From fb5a030eece368cb089899382bb6c60a9dd6b4f7 Mon Sep 17 00:00:00 2001 From: Stepan Zakharov Date: Fri, 5 Jan 2024 16:37:05 +0300 Subject: [PATCH] Update documentation --- .buildinfo | 2 +- _images/adaptive_2_0.svg | 115 - _images/adaptive_6_0.svg | 500 -- _images/adaptive_rungekutta_2_0.svg | 355 -- .../baydin-2018-diff-approaches-overview.png | Bin 0 -> 228401 bytes _images/bisection_regula_falsi_4_0.svg | 133 - _images/cubic_spline_2_0.svg | 162 - _images/cubic_spline_4_0.svg | 169 - _images/cubic_spline_6_0.svg | 113 - _images/euler_2_0.svg | 153 - _images/ex_2_0.svg | 232 - _images/graph-backward-first-traverse.svg | 541 ++ _images/graph-backward-general.svg | 365 ++ _images/graph-binary.svg | 176 + _images/graph-cross-example.svg | 329 ++ _images/graph-example.svg | 421 ++ _images/graph-forward-auxillary-values.svg | 569 ++ _images/graph-forward-general.svg | 407 ++ _images/graph-unary.svg | 127 + _images/newton_cotes_2_0.svg | 356 -- _images/newton_cotes_4_0.svg | 301 - _images/newton_cotes_6_0.svg | 162 - _images/newton_secant_4_0.svg | 143 - _images/newton_secant_6_0.svg | 129 - _images/polynomial_10_0.svg | 111 - _images/polynomial_12_0.svg | 137 - _images/polynomial_2_0.svg | 161 - _images/polynomial_4_0.svg | 155 - _images/polynomial_6_0.svg | 129 - _images/polynomial_8_0.svg | 133 - _images/pwlinear_2_0.svg | 336 -- _images/pwlinear_4_0.svg | 161 - _images/pwlinear_6_0.svg | 164 - _images/pwlinear_8_0.svg | 112 - _images/ridders_4_0.svg | 195 - _images/rungekutta_2_0.svg | 398 -- _images/rungekutta_4_0.svg | 149 - ...-main.c949a650a448cc0ae9fd3441c0e17fb0.css | 1 - ...ables.06eb56fa6e07937060861dad626602ad.css | 7 - _sources/appendix/genindex.md | 1 - _sources/autodiff/backwardmode.md | 269 + _sources/autodiff/compgraph.md | 108 + _sources/autodiff/complexstep.md | 146 + _sources/autodiff/dualnumbers.md | 422 ++ _sources/autodiff/ex.md | 21 + _sources/autodiff/forwardmode.md | 203 + _sources/autodiff/index.md | 55 + _sources/autodiff/oja_problem.md | 51 + _sources/bibliography.md | 4 - _sources/index.md | 34 +- _sources/integration/adaptive.ipynb | 927 ---- _sources/integration/adaptive.md | 14 +- _sources/integration/ex.md | 6 + _sources/integration/gauss.md | 12 +- _sources/integration/index.md | 6 + _sources/integration/newton_cotes.ipynb | 1386 ----- _sources/integration/newton_cotes.md | 19 +- _sources/integration/romberg.md | 6 + _sources/interpolation/cubic_spline.ipynb | 972 ---- _sources/interpolation/cubic_spline.md | 12 +- _sources/interpolation/ex.ipynb | 302 - _sources/interpolation/ex.md | 33 +- _sources/interpolation/index.md | 8 + _sources/interpolation/polynomial.ipynb | 1286 ----- _sources/interpolation/polynomial.md | 12 +- _sources/interpolation/pwlinear.ipynb | 1265 ----- _sources/interpolation/pwlinear.md | 12 +- _sources/intro/cond.ipynb | 274 - _sources/intro/cond.md | 15 +- _sources/intro/ex.md | 56 - _sources/intro/float.ipynb | 782 --- _sources/intro/float.md | 14 +- _sources/intro/index.md | 6 + _sources/intro/julia.md | 2236 -------- _sources/julia/arrays.md | 12 +- _sources/julia/controlflow.md | 6 + _sources/julia/ex.md | 33 +- _sources/julia/functions.md | 6 + _sources/julia/index.md | 80 +- _sources/julia/install.md | 20 +- _sources/julia/julia.md | 242 - _sources/julia/linearalgebra.md | 8 +- _sources/julia/modules.md | 6 + _sources/julia/numbers.md | 6 + _sources/julia/run.md | 6 + _sources/julia/strings.md | 6 + _sources/julia/types_methods_dispatch.md | 6 + _sources/julia/typesystem.md | 333 -- _sources/nlroot/bisection_regula_falsi.ipynb | 428 -- _sources/nlroot/bisection_regula_falsi.md | 12 +- _sources/nlroot/ex.ipynb | 456 -- _sources/nlroot/ex.md | 20 +- _sources/nlroot/index.md | 6 + _sources/nlroot/itp.ipynb | 239 - _sources/nlroot/itp.md | 12 +- _sources/nlroot/newton_secant.ipynb | 593 -- _sources/nlroot/newton_secant.md | 13 +- _sources/nlroot/ridders.ipynb | 507 -- _sources/nlroot/ridders.md | 17 +- _sources/nlroot/simpleiter.ipynb | 301 - _sources/nlroot/simpleiter.md | 16 +- _sources/ode/adaptive_rungekutta.ipynb | 649 --- _sources/ode/adaptive_rungekutta.md | 14 +- _sources/ode/euler.ipynb | 429 -- _sources/ode/euler.md | 18 +- _sources/ode/ex.md | 6 + _sources/ode/index.md | 8 +- _sources/ode/rungekutta.ipynb | 998 ---- _sources/ode/rungekutta.md | 31 +- _sources/optim/bfgs.md | 30 +- _sources/optim/ex.md | 8 +- _sources/optim/index.md | 8 +- _sources/optim/intro.md | 6 + _sources/optim/linesearch.md | 41 +- _sources/optim/newton.md | 7 + _sources/ptsplit/index.md | 6 + _sources/ptsplit/problem.md | 8 +- _sources/ptsplit/problem_as_min.md | 127 - _sources/ptsplit/solution.md | 8 +- _sources/ptstability/algorithm.md | 6 + _sources/ptstability/criterion.md | 60 - _sources/ptstability/exercise.md | 7 +- _sources/ptstability/index.md | 6 + _sources/ptstability/problem.md | 6 + _sources/ptstability/vanderwaals.md | 6 + _sources/syslinear/conditioning.md | 6 + _sources/syslinear/decompose_overview.ipynb | 173 - _sources/syslinear/decompose_overview.md | 12 +- _sources/syslinear/ex.md | 6 + _sources/syslinear/index.md | 6 + _sources/syslinear/lu.ipynb | 670 --- _sources/syslinear/lu.md | 13 +- _sources/syslinear/plu.ipynb | 903 --- _sources/syslinear/plu.md | 12 +- _sources/syslinear/triangular.ipynb | 123 - _sources/syslinear/triangular.md | 6 + _sources/sysnonlinear/ex.md | 6 + _sources/sysnonlinear/index.md | 6 + _sources/sysnonlinear/newton.ipynb | 346 -- _sources/sysnonlinear/newton.md | 12 +- _sources/sysnonlinear/quasinewton.ipynb | 577 -- _sources/sysnonlinear/quasinewton.md | 16 +- ...e.4045f2051d55cab465a707391d5b2007.min.css | 2 +- _static/__init__.py | 0 _static/__pycache__/__init__.cpython-38.pyc | Bin 188 -> 0 bytes .../_sphinx_javascript_frameworks_compat.js | 134 + _static/basic.css | 54 +- _static/copybutton.css | 3 +- _static/copybutton.js | 44 +- _static/copybutton_funcs.js | 17 +- _static/css/blank.css | 2 - ...index.ff1ffe594081f20da1ef19478df9384b.css | 6 - _static/css/theme.css | 120 - ...e.4045f2051d55cab465a707391d5b2007.min.css | 2 +- _static/doctools.js | 480 +- _static/documentation_options.js | 6 +- _static/{jquery-3.5.1.js => jquery-3.6.0.js} | 227 +- _static/jquery.js | 4 +- _static/js/index.be7d3bbb2ef33a8344ce.js | 32 - _static/language_data.js | 100 +- _static/locales/ar/LC_MESSAGES/booktheme.mo | Bin 0 -> 1541 bytes _static/locales/ar/LC_MESSAGES/booktheme.po | 76 +- _static/locales/bg/LC_MESSAGES/booktheme.mo | Bin 0 -> 1708 bytes _static/locales/bg/LC_MESSAGES/booktheme.po | 76 +- _static/locales/bn/LC_MESSAGES/booktheme.mo | Bin 0 -> 1646 bytes _static/locales/bn/LC_MESSAGES/booktheme.po | 55 +- _static/locales/ca/LC_MESSAGES/booktheme.mo | Bin 0 -> 1246 bytes _static/locales/ca/LC_MESSAGES/booktheme.po | 57 +- _static/locales/cs/LC_MESSAGES/booktheme.mo | Bin 0 -> 1405 bytes _static/locales/cs/LC_MESSAGES/booktheme.po | 76 +- _static/locales/da/LC_MESSAGES/booktheme.mo | Bin 0 -> 1304 bytes _static/locales/da/LC_MESSAGES/booktheme.po | 76 +- _static/locales/de/LC_MESSAGES/booktheme.mo | Bin 0 -> 1388 bytes _static/locales/de/LC_MESSAGES/booktheme.po | 76 +- _static/locales/el/LC_MESSAGES/booktheme.mo | Bin 0 -> 1722 bytes _static/locales/el/LC_MESSAGES/booktheme.po | 76 +- _static/locales/eo/LC_MESSAGES/booktheme.mo | Bin 0 -> 1337 bytes _static/locales/eo/LC_MESSAGES/booktheme.po | 76 +- _static/locales/es/LC_MESSAGES/booktheme.mo | Bin 0 -> 1396 bytes _static/locales/es/LC_MESSAGES/booktheme.po | 76 +- _static/locales/et/LC_MESSAGES/booktheme.mo | Bin 0 -> 1341 bytes _static/locales/et/LC_MESSAGES/booktheme.po | 76 +- _static/locales/fi/LC_MESSAGES/booktheme.mo | Bin 0 -> 1368 bytes _static/locales/fi/LC_MESSAGES/booktheme.po | 76 +- _static/locales/fr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1412 bytes _static/locales/fr/LC_MESSAGES/booktheme.po | 76 +- _static/locales/hr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1402 bytes _static/locales/hr/LC_MESSAGES/booktheme.po | 76 +- _static/locales/id/LC_MESSAGES/booktheme.mo | Bin 0 -> 1323 bytes _static/locales/id/LC_MESSAGES/booktheme.po | 76 +- _static/locales/it/LC_MESSAGES/booktheme.mo | Bin 0 -> 1403 bytes _static/locales/it/LC_MESSAGES/booktheme.po | 76 +- _static/locales/iw/LC_MESSAGES/booktheme.mo | Bin 0 -> 1445 bytes _static/locales/iw/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ja/LC_MESSAGES/booktheme.mo | Bin 0 -> 1471 bytes _static/locales/ja/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ko/LC_MESSAGES/booktheme.mo | Bin 0 -> 1375 bytes _static/locales/ko/LC_MESSAGES/booktheme.po | 76 +- _static/locales/lt/LC_MESSAGES/booktheme.mo | Bin 0 -> 1413 bytes _static/locales/lt/LC_MESSAGES/booktheme.po | 76 +- _static/locales/lv/LC_MESSAGES/booktheme.mo | Bin 0 -> 1404 bytes _static/locales/lv/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ml/LC_MESSAGES/booktheme.mo | Bin 0 -> 1883 bytes _static/locales/ml/LC_MESSAGES/booktheme.po | 57 +- _static/locales/mr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1674 bytes _static/locales/mr/LC_MESSAGES/booktheme.po | 57 +- _static/locales/ms/LC_MESSAGES/booktheme.mo | Bin 0 -> 1213 bytes _static/locales/ms/LC_MESSAGES/booktheme.po | 57 +- _static/locales/nl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1356 bytes _static/locales/nl/LC_MESSAGES/booktheme.po | 76 +- _static/locales/no/LC_MESSAGES/booktheme.mo | Bin 0 -> 1317 bytes _static/locales/no/LC_MESSAGES/booktheme.po | 76 +- _static/locales/pl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1371 bytes _static/locales/pl/LC_MESSAGES/booktheme.po | 76 +- _static/locales/pt/LC_MESSAGES/booktheme.mo | Bin 0 -> 1364 bytes _static/locales/pt/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ro/LC_MESSAGES/booktheme.mo | Bin 0 -> 1390 bytes _static/locales/ro/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ru/LC_MESSAGES/booktheme.mo | Bin 0 -> 1722 bytes _static/locales/ru/LC_MESSAGES/booktheme.po | 76 +- _static/locales/sk/LC_MESSAGES/booktheme.mo | Bin 0 -> 1393 bytes _static/locales/sk/LC_MESSAGES/booktheme.po | 76 +- _static/locales/sl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1374 bytes _static/locales/sl/LC_MESSAGES/booktheme.po | 76 +- _static/locales/sr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1679 bytes _static/locales/sr/LC_MESSAGES/booktheme.po | 76 +- _static/locales/sv/LC_MESSAGES/booktheme.mo | Bin 0 -> 1349 bytes _static/locales/sv/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ta/LC_MESSAGES/booktheme.mo | Bin 0 -> 1928 bytes _static/locales/ta/LC_MESSAGES/booktheme.po | 57 +- _static/locales/te/LC_MESSAGES/booktheme.mo | Bin 0 -> 1806 bytes _static/locales/te/LC_MESSAGES/booktheme.po | 57 +- _static/locales/tg/LC_MESSAGES/booktheme.mo | Bin 0 -> 1628 bytes _static/locales/tg/LC_MESSAGES/booktheme.po | 76 +- _static/locales/th/LC_MESSAGES/booktheme.mo | Bin 0 -> 1766 bytes _static/locales/th/LC_MESSAGES/booktheme.po | 76 +- _static/locales/tl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1273 bytes _static/locales/tl/LC_MESSAGES/booktheme.po | 57 +- _static/locales/tr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1373 bytes _static/locales/tr/LC_MESSAGES/booktheme.po | 76 +- _static/locales/uk/LC_MESSAGES/booktheme.mo | Bin 0 -> 1681 bytes _static/locales/uk/LC_MESSAGES/booktheme.po | 76 +- _static/locales/ur/LC_MESSAGES/booktheme.mo | Bin 0 -> 1462 bytes _static/locales/ur/LC_MESSAGES/booktheme.po | 57 +- _static/locales/vi/LC_MESSAGES/booktheme.mo | Bin 0 -> 1431 bytes _static/locales/vi/LC_MESSAGES/booktheme.po | 76 +- .../locales/zh_CN/LC_MESSAGES/booktheme.mo | Bin 0 -> 1310 bytes .../locales/zh_CN/LC_MESSAGES/booktheme.po | 81 +- .../locales/zh_TW/LC_MESSAGES/booktheme.mo | Bin 0 -> 1341 bytes .../locales/zh_TW/LC_MESSAGES/booktheme.po | 86 +- ...9c37c29e427902b24a333a5f9fcb2f0b3ac41.css} | 742 ++- ...-main.c949a650a448cc0ae9fd3441c0e17fb0.css | 1 - ...ables.06eb56fa6e07937060861dad626602ad.css | 7 - _static/pygments.css | 226 +- _static/scripts/bootstrap.js | 3 + _static/scripts/bootstrap.js.LICENSE.txt | 5 + _static/scripts/bootstrap.js.map | 1 + _static/scripts/pydata-sphinx-theme.js | 34 +- _static/scripts/pydata-sphinx-theme.js.map | 1 + _static/scripts/sphinx-book-theme.js | 2 +- _static/scripts/sphinx-book-theme.js.map | 2 +- _static/searchtools.js | 784 +-- _static/sphinx-book-theme.css | 5 - ...-theme.d59cb220de22ca1c485ebbdc042f0030.js | 22 - ...theme.e2363ea40746bee74734a24ffefccd78.css | 5 - _static/styles/bootstrap.css | 6 + _static/styles/bootstrap.css.map | 1 + _static/styles/pydata-sphinx-theme.css | 8 +- _static/styles/pydata-sphinx-theme.css.map | 1 + _static/styles/sphinx-book-theme.css | 2 +- _static/styles/theme.css | 132 - _static/tabs.css | 110 - _static/tabs.js | 21 - _static/underscore-1.12.0.js | 2027 ------- _static/vendor/fontawesome/5.13.0/LICENSE.txt | 34 - .../vendor/fontawesome/5.13.0/css/all.min.css | 5 - .../5.13.0/webfonts/fa-brands-400.eot | Bin 133034 -> 0 bytes .../5.13.0/webfonts/fa-brands-400.svg | 3570 ------------ .../5.13.0/webfonts/fa-brands-400.ttf | Bin 132728 -> 0 bytes .../5.13.0/webfonts/fa-brands-400.woff | Bin 89824 -> 0 bytes .../5.13.0/webfonts/fa-brands-400.woff2 | Bin 76612 -> 0 bytes .../5.13.0/webfonts/fa-regular-400.eot | Bin 34390 -> 0 bytes .../5.13.0/webfonts/fa-regular-400.svg | 803 --- .../5.13.0/webfonts/fa-regular-400.ttf | Bin 34092 -> 0 bytes .../5.13.0/webfonts/fa-regular-400.woff | Bin 16800 -> 0 bytes .../5.13.0/webfonts/fa-regular-400.woff2 | Bin 13584 -> 0 bytes .../5.13.0/webfonts/fa-solid-900.eot | Bin 202902 -> 0 bytes .../5.13.0/webfonts/fa-solid-900.svg | 4938 ----------------- .../5.13.0/webfonts/fa-solid-900.ttf | Bin 202616 -> 0 bytes .../5.13.0/webfonts/fa-solid-900.woff | Bin 103300 -> 0 bytes .../5.13.0/webfonts/fa-solid-900.woff2 | Bin 79444 -> 0 bytes _static/vendor/fontawesome/6.1.2/LICENSE.txt | 165 + .../vendor/fontawesome/6.1.2/css/all.min.css | 5 + .../vendor/fontawesome/6.1.2/js/all.min.js | 2 + .../6.1.2/js/all.min.js.LICENSE.txt | 5 + .../6.1.2/webfonts/fa-brands-400.ttf | Bin 0 -> 181264 bytes .../6.1.2/webfonts/fa-brands-400.woff2 | Bin 0 -> 105112 bytes .../6.1.2/webfonts/fa-regular-400.ttf | Bin 0 -> 60236 bytes .../6.1.2/webfonts/fa-regular-400.woff2 | Bin 0 -> 24028 bytes .../6.1.2/webfonts/fa-solid-900.ttf | Bin 0 -> 389948 bytes .../6.1.2/webfonts/fa-solid-900.woff2 | Bin 0 -> 154840 bytes .../6.1.2/webfonts/fa-v4compatibility.ttf | Bin 0 -> 10084 bytes .../6.1.2/webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4776 bytes _static/webpack-macros.html | 22 +- appendix/bibliography.html | 1200 ++-- appendix/cholesky.html | 1110 ++-- appendix/genindex.html | 753 --- appendix/materials.html | 1085 ++-- appendix/solvecubic.html | 1120 ++-- autodiff/backwardmode.html | 832 +++ autodiff/compgraph.html | 694 +++ autodiff/complexstep.html | 800 +++ autodiff/dualnumbers.html | 1074 ++++ autodiff/ex.html | 639 +++ autodiff/forwardmode.html | 774 +++ autodiff/index.html | 644 +++ autodiff/oja_problem.html | 634 +++ bibliography.html | 712 --- genindex.html | 964 ++-- index.html | 1046 ++-- integration/adaptive.html | 1514 ++--- integration/ex.html | 1103 ++-- integration/gauss.html | 1225 ++-- integration/index.html | 1038 ++-- integration/newton_cotes.html | 1677 +++--- integration/romberg.html | 1191 ++-- interpolation/cubic_spline.html | 1525 +++-- interpolation/ex.html | 1264 ++--- interpolation/index.html | 1037 ++-- interpolation/polynomial.html | 1614 +++--- interpolation/pwlinear.html | 1584 +++--- intro/cond.html | 1155 ++-- intro/ex.html | 771 --- intro/float.html | 1252 ++--- intro/index.html | 1038 ++-- intro/julia.html | 3093 ----------- julia/arrays.html | 1319 ++--- julia/controlflow.html | 1181 ++-- julia/ex.html | 1150 ++-- julia/functions.html | 1233 ++-- julia/index.html | 1177 ++-- julia/install.html | 1138 ++-- julia/julia.html | 1028 ---- julia/linearalgebra.html | 1088 ++-- julia/modules.html | 1301 ++--- julia/numbers.html | 1159 ++-- julia/run.html | 1166 ++-- julia/strings.html | 1054 ++-- julia/types_methods_dispatch.html | 1337 ++--- julia/typesystem.html | 1110 ---- nlroot/bisection_regula_falsi.html | 1366 ++--- nlroot/ex.html | 1276 ++--- nlroot/index.html | 1042 ++-- nlroot/itp.html | 1239 ++--- nlroot/newton_secant.html | 1349 +++-- nlroot/ridders.html | 1305 ++--- nlroot/simpleiter.html | 1177 ++-- objects.inv | Bin 3933 -> 5350 bytes ode/adaptive_rungekutta.html | 1540 ++--- ode/euler.html | 1319 ++--- ode/ex.html | 1115 ++-- ode/index.html | 1046 ++-- ode/rungekutta.html | 1572 +++--- optim/bfgs.html | 1209 ++-- optim/ex.html | 1040 ++-- optim/index.html | 1050 ++-- optim/intro.html | 1052 ++-- optim/linesearch.html | 1277 ++--- optim/newton.html | 1189 ++-- ptsplit/index.html | 1042 ++-- ptsplit/problem.html | 1103 ++-- ptsplit/problem_as_min.html | 893 --- ptsplit/solution.html | 1107 ++-- ptstability/algorithm.html | 1166 ++-- ptstability/criterion.html | 771 --- ptstability/exercise.html | 1139 ++-- ptstability/index.html | 1040 ++-- ptstability/problem.html | 1130 ++-- ptstability/vanderwaals.html | 1146 ++-- search.html | 975 ++-- searchindex.js | 2 +- syslinear/conditioning.html | 1091 ++-- syslinear/decompose_overview.html | 1189 ++-- syslinear/ex.html | 1135 ++-- syslinear/index.html | 1040 ++-- syslinear/lu.html | 1253 ++--- syslinear/plu.html | 1351 ++--- syslinear/triangular.html | 1087 ++-- sysnonlinear/ex.html | 1097 ++-- sysnonlinear/index.html | 1038 ++-- sysnonlinear/newton.html | 1205 ++-- sysnonlinear/quasinewton.html | 1343 ++--- 392 files changed, 51277 insertions(+), 94084 deletions(-) delete mode 100644 _images/adaptive_2_0.svg delete mode 100644 _images/adaptive_6_0.svg delete mode 100644 _images/adaptive_rungekutta_2_0.svg create mode 100644 _images/baydin-2018-diff-approaches-overview.png delete mode 100644 _images/bisection_regula_falsi_4_0.svg delete mode 100644 _images/cubic_spline_2_0.svg delete mode 100644 _images/cubic_spline_4_0.svg delete mode 100644 _images/cubic_spline_6_0.svg delete mode 100644 _images/euler_2_0.svg delete mode 100644 _images/ex_2_0.svg create mode 100644 _images/graph-backward-first-traverse.svg create mode 100644 _images/graph-backward-general.svg create mode 100644 _images/graph-binary.svg create mode 100644 _images/graph-cross-example.svg create mode 100644 _images/graph-example.svg create mode 100644 _images/graph-forward-auxillary-values.svg create mode 100644 _images/graph-forward-general.svg create mode 100644 _images/graph-unary.svg delete mode 100644 _images/newton_cotes_2_0.svg delete mode 100644 _images/newton_cotes_4_0.svg delete mode 100644 _images/newton_cotes_6_0.svg delete mode 100644 _images/newton_secant_4_0.svg delete mode 100644 _images/newton_secant_6_0.svg delete mode 100644 _images/polynomial_10_0.svg delete mode 100644 _images/polynomial_12_0.svg delete mode 100644 _images/polynomial_2_0.svg delete mode 100644 _images/polynomial_4_0.svg delete mode 100644 _images/polynomial_6_0.svg delete mode 100644 _images/polynomial_8_0.svg delete mode 100644 _images/pwlinear_2_0.svg delete mode 100644 _images/pwlinear_4_0.svg delete mode 100644 _images/pwlinear_6_0.svg delete mode 100644 _images/pwlinear_8_0.svg delete mode 100644 _images/ridders_4_0.svg delete mode 100644 _images/rungekutta_2_0.svg delete mode 100644 _images/rungekutta_4_0.svg delete mode 100644 _panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css delete mode 100644 _panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css delete mode 100644 _sources/appendix/genindex.md create mode 100644 _sources/autodiff/backwardmode.md create mode 100644 _sources/autodiff/compgraph.md create mode 100644 _sources/autodiff/complexstep.md create mode 100644 _sources/autodiff/dualnumbers.md create mode 100644 _sources/autodiff/ex.md create mode 100644 _sources/autodiff/forwardmode.md create mode 100644 _sources/autodiff/index.md create mode 100644 _sources/autodiff/oja_problem.md delete mode 100644 _sources/bibliography.md delete mode 100644 _sources/integration/adaptive.ipynb delete mode 100644 _sources/integration/newton_cotes.ipynb delete mode 100644 _sources/interpolation/cubic_spline.ipynb delete mode 100644 _sources/interpolation/ex.ipynb delete mode 100644 _sources/interpolation/polynomial.ipynb delete mode 100644 _sources/interpolation/pwlinear.ipynb delete mode 100644 _sources/intro/cond.ipynb delete mode 100644 _sources/intro/ex.md delete mode 100644 _sources/intro/float.ipynb delete mode 100644 _sources/intro/julia.md delete mode 100644 _sources/julia/julia.md delete mode 100644 _sources/julia/typesystem.md delete mode 100644 _sources/nlroot/bisection_regula_falsi.ipynb delete mode 100644 _sources/nlroot/ex.ipynb delete mode 100644 _sources/nlroot/itp.ipynb delete mode 100644 _sources/nlroot/newton_secant.ipynb delete mode 100644 _sources/nlroot/ridders.ipynb delete mode 100644 _sources/nlroot/simpleiter.ipynb delete mode 100644 _sources/ode/adaptive_rungekutta.ipynb delete mode 100644 _sources/ode/euler.ipynb delete mode 100644 _sources/ode/rungekutta.ipynb delete mode 100644 _sources/ptsplit/problem_as_min.md delete mode 100644 _sources/ptstability/criterion.md delete mode 100644 _sources/syslinear/decompose_overview.ipynb delete mode 100644 _sources/syslinear/lu.ipynb delete mode 100644 _sources/syslinear/plu.ipynb delete mode 100644 _sources/syslinear/triangular.ipynb delete mode 100644 _sources/sysnonlinear/newton.ipynb delete mode 100644 _sources/sysnonlinear/quasinewton.ipynb rename _static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css => _sphinx_design_static/design-style.4045f2051d55cab465a707391d5b2007.min.css (56%) delete mode 100644 _static/__init__.py delete mode 100644 _static/__pycache__/__init__.cpython-38.pyc create mode 100644 _static/_sphinx_javascript_frameworks_compat.js delete mode 100644 _static/css/blank.css delete mode 100644 _static/css/index.ff1ffe594081f20da1ef19478df9384b.css delete mode 100644 _static/css/theme.css rename _sphinx_design_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css => _static/design-style.4045f2051d55cab465a707391d5b2007.min.css (56%) rename _static/{jquery-3.5.1.js => jquery-3.6.0.js} (98%) delete mode 100644 _static/js/index.be7d3bbb2ef33a8344ce.js create mode 100644 _static/locales/ar/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/bg/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/bn/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ca/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/cs/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/da/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/de/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/el/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/eo/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/es/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/et/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/fi/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/fr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/hr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/id/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/it/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/iw/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ja/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ko/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/lt/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/lv/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ml/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/mr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ms/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/nl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/no/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/pl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/pt/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ro/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ru/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sk/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sv/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ta/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/te/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tg/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/th/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/uk/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ur/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/vi/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/zh_CN/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/zh_TW/LC_MESSAGES/booktheme.mo rename _static/{mystnb.css => mystnb.4510f1fc1dee50b3e5859aac5469c37c29e427902b24a333a5f9fcb2f0b3ac41.css} (87%) delete mode 100644 _static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css delete mode 100644 _static/panels-variables.06eb56fa6e07937060861dad626602ad.css create mode 100644 _static/scripts/bootstrap.js create mode 100644 _static/scripts/bootstrap.js.LICENSE.txt create mode 100644 _static/scripts/bootstrap.js.map create mode 100644 _static/scripts/pydata-sphinx-theme.js.map delete mode 100644 _static/sphinx-book-theme.css delete mode 100644 _static/sphinx-book-theme.d59cb220de22ca1c485ebbdc042f0030.js delete mode 100644 _static/sphinx-book-theme.e2363ea40746bee74734a24ffefccd78.css create mode 100644 _static/styles/bootstrap.css create mode 100644 _static/styles/bootstrap.css.map create mode 100644 _static/styles/pydata-sphinx-theme.css.map delete mode 100644 _static/tabs.css delete mode 100644 _static/tabs.js delete mode 100644 _static/underscore-1.12.0.js delete mode 100644 _static/vendor/fontawesome/5.13.0/LICENSE.txt delete mode 100644 _static/vendor/fontawesome/5.13.0/css/all.min.css delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.eot delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.svg delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.ttf delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.woff delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.woff2 delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.eot delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.svg delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.ttf delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.woff delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-regular-400.woff2 delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.eot delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.svg delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.ttf delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.woff delete mode 100644 _static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.woff2 create mode 100644 _static/vendor/fontawesome/6.1.2/LICENSE.txt create mode 100644 _static/vendor/fontawesome/6.1.2/css/all.min.css create mode 100644 _static/vendor/fontawesome/6.1.2/js/all.min.js create mode 100644 _static/vendor/fontawesome/6.1.2/js/all.min.js.LICENSE.txt create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-brands-400.ttf create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-brands-400.woff2 create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-regular-400.ttf create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-regular-400.woff2 create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-solid-900.ttf create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-solid-900.woff2 create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-v4compatibility.ttf create mode 100644 _static/vendor/fontawesome/6.1.2/webfonts/fa-v4compatibility.woff2 delete mode 100644 appendix/genindex.html create mode 100644 autodiff/backwardmode.html create mode 100644 autodiff/compgraph.html create mode 100644 autodiff/complexstep.html create mode 100644 autodiff/dualnumbers.html create mode 100644 autodiff/ex.html create mode 100644 autodiff/forwardmode.html create mode 100644 autodiff/index.html create mode 100644 autodiff/oja_problem.html delete mode 100644 bibliography.html delete mode 100644 intro/ex.html delete mode 100644 intro/julia.html delete mode 100644 julia/julia.html delete mode 100644 julia/typesystem.html delete mode 100644 ptsplit/problem_as_min.html delete mode 100644 ptstability/criterion.html diff --git a/.buildinfo b/.buildinfo index 3cfaa84..8505ed7 100644 --- a/.buildinfo +++ b/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 9a8226f5f1b042dae718dd1c5fb170b5 +config: 46e60af904d03c0364121ceed7c97fe4 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_images/adaptive_2_0.svg b/_images/adaptive_2_0.svg deleted file mode 100644 index dcf001b..0000000 --- a/_images/adaptive_2_0.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/adaptive_6_0.svg b/_images/adaptive_6_0.svg deleted file mode 100644 index b1ad92b..0000000 --- a/_images/adaptive_6_0.svg +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/adaptive_rungekutta_2_0.svg b/_images/adaptive_rungekutta_2_0.svg deleted file mode 100644 index ed12762..0000000 --- a/_images/adaptive_rungekutta_2_0.svg +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/baydin-2018-diff-approaches-overview.png b/_images/baydin-2018-diff-approaches-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..ef6d8e3003ee6f7f8806202c60bc01ea0537b812 GIT binary patch literal 228401 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�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 literal 0 HcmV?d00001 diff --git a/_images/bisection_regula_falsi_4_0.svg b/_images/bisection_regula_falsi_4_0.svg deleted file mode 100644 index 66672b0..0000000 --- a/_images/bisection_regula_falsi_4_0.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/cubic_spline_2_0.svg b/_images/cubic_spline_2_0.svg deleted file mode 100644 index 5aed518..0000000 --- a/_images/cubic_spline_2_0.svg +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/cubic_spline_4_0.svg b/_images/cubic_spline_4_0.svg deleted file mode 100644 index 8234032..0000000 --- a/_images/cubic_spline_4_0.svg +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/cubic_spline_6_0.svg b/_images/cubic_spline_6_0.svg deleted file mode 100644 index cdf3b17..0000000 --- a/_images/cubic_spline_6_0.svg +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/euler_2_0.svg b/_images/euler_2_0.svg deleted file mode 100644 index 4f1a832..0000000 --- a/_images/euler_2_0.svg +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/ex_2_0.svg b/_images/ex_2_0.svg deleted file mode 100644 index d08db6b..0000000 --- a/_images/ex_2_0.svg +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/graph-backward-first-traverse.svg b/_images/graph-backward-first-traverse.svg new file mode 100644 index 0000000..e0c10b9 --- /dev/null +++ b/_images/graph-backward-first-traverse.svg @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/graph-backward-general.svg b/_images/graph-backward-general.svg new file mode 100644 index 0000000..8b9bc3e --- /dev/null +++ b/_images/graph-backward-general.svg @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + f + + + + + + + + + + + + + diff --git a/_images/graph-binary.svg b/_images/graph-binary.svg new file mode 100644 index 0000000..3d4f9a3 --- /dev/null +++ b/_images/graph-binary.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/graph-cross-example.svg b/_images/graph-cross-example.svg new file mode 100644 index 0000000..1fff3d7 --- /dev/null +++ b/_images/graph-cross-example.svg @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/graph-example.svg b/_images/graph-example.svg new file mode 100644 index 0000000..d51cd59 --- /dev/null +++ b/_images/graph-example.svg @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/graph-forward-auxillary-values.svg b/_images/graph-forward-auxillary-values.svg new file mode 100644 index 0000000..72283d1 --- /dev/null +++ b/_images/graph-forward-auxillary-values.svg @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/graph-forward-general.svg b/_images/graph-forward-general.svg new file mode 100644 index 0000000..228e263 --- /dev/null +++ b/_images/graph-forward-general.svg @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + f + + + + + + + + + + + + diff --git a/_images/graph-unary.svg b/_images/graph-unary.svg new file mode 100644 index 0000000..6efaba1 --- /dev/null +++ b/_images/graph-unary.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/newton_cotes_2_0.svg b/_images/newton_cotes_2_0.svg deleted file mode 100644 index c696429..0000000 --- a/_images/newton_cotes_2_0.svg +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/newton_cotes_4_0.svg b/_images/newton_cotes_4_0.svg deleted file mode 100644 index cce61e7..0000000 --- a/_images/newton_cotes_4_0.svg +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/newton_cotes_6_0.svg b/_images/newton_cotes_6_0.svg deleted file mode 100644 index 2c21c71..0000000 --- a/_images/newton_cotes_6_0.svg +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/newton_secant_4_0.svg b/_images/newton_secant_4_0.svg deleted file mode 100644 index 83d039c..0000000 --- a/_images/newton_secant_4_0.svg +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/newton_secant_6_0.svg b/_images/newton_secant_6_0.svg deleted file mode 100644 index 701eb33..0000000 --- a/_images/newton_secant_6_0.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_10_0.svg b/_images/polynomial_10_0.svg deleted file mode 100644 index a2b9b7b..0000000 --- a/_images/polynomial_10_0.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_12_0.svg b/_images/polynomial_12_0.svg deleted file mode 100644 index ce9a0fc..0000000 --- a/_images/polynomial_12_0.svg +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_2_0.svg b/_images/polynomial_2_0.svg deleted file mode 100644 index 2b11951..0000000 --- a/_images/polynomial_2_0.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_4_0.svg b/_images/polynomial_4_0.svg deleted file mode 100644 index a3a6ec0..0000000 --- a/_images/polynomial_4_0.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_6_0.svg b/_images/polynomial_6_0.svg deleted file mode 100644 index 3c68785..0000000 --- a/_images/polynomial_6_0.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/polynomial_8_0.svg b/_images/polynomial_8_0.svg deleted file mode 100644 index 50b0335..0000000 --- a/_images/polynomial_8_0.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/pwlinear_2_0.svg b/_images/pwlinear_2_0.svg deleted file mode 100644 index baaf973..0000000 --- a/_images/pwlinear_2_0.svg +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/pwlinear_4_0.svg b/_images/pwlinear_4_0.svg deleted file mode 100644 index 7e65538..0000000 --- a/_images/pwlinear_4_0.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/pwlinear_6_0.svg b/_images/pwlinear_6_0.svg deleted file mode 100644 index 066c902..0000000 --- a/_images/pwlinear_6_0.svg +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/pwlinear_8_0.svg b/_images/pwlinear_8_0.svg deleted file mode 100644 index 2e95c69..0000000 --- a/_images/pwlinear_8_0.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/ridders_4_0.svg b/_images/ridders_4_0.svg deleted file mode 100644 index 0d76e0a..0000000 --- a/_images/ridders_4_0.svg +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/rungekutta_2_0.svg b/_images/rungekutta_2_0.svg deleted file mode 100644 index 73cbd03..0000000 --- a/_images/rungekutta_2_0.svg +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/rungekutta_4_0.svg b/_images/rungekutta_4_0.svg deleted file mode 100644 index 3917e5d..0000000 --- a/_images/rungekutta_4_0.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css b/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css deleted file mode 100644 index fc14abc..0000000 --- a/_panels_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css +++ /dev/null @@ -1 +0,0 @@ -details.dropdown .summary-title{padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.dropdown:hover{cursor:pointer}details.dropdown .summary-content{cursor:default}details.dropdown summary{list-style:none;padding:1em}details.dropdown summary .octicon.no-title{vertical-align:middle}details.dropdown[open] summary .octicon.no-title{visibility:hidden}details.dropdown summary::-webkit-details-marker{display:none}details.dropdown summary:focus{outline:none}details.dropdown summary:hover .summary-up svg,details.dropdown summary:hover .summary-down svg{opacity:1}details.dropdown .summary-up svg,details.dropdown .summary-down svg{display:block;opacity:.6}details.dropdown .summary-up,details.dropdown .summary-down{pointer-events:none;position:absolute;right:1em;top:.75em}details.dropdown[open] .summary-down{visibility:hidden}details.dropdown:not([open]) .summary-up{visibility:hidden}details.dropdown.fade-in[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out;animation:panels-fade-in .5s ease-in-out}details.dropdown.fade-in-slide-down[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out}@keyframes panels-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes panels-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.octicon{display:inline-block;fill:currentColor;vertical-align:text-top}.tabbed-content{box-shadow:0 -.0625rem var(--tabs-color-overline),0 .0625rem var(--tabs-color-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.tabbed-content>:first-child{margin-top:0 !important}.tabbed-content>:last-child{margin-bottom:0 !important}.tabbed-content>.tabbed-set{margin:0}.tabbed-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.tabbed-set>input{opacity:0;position:absolute}.tabbed-set>input:checked+label{border-color:var(--tabs-color-label-active);color:var(--tabs-color-label-active)}.tabbed-set>input:checked+label+.tabbed-content{display:block}.tabbed-set>input:focus+label{outline-style:auto}.tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.tabbed-set>label{border-bottom:.125rem solid transparent;color:var(--tabs-color-label-inactive);cursor:pointer;font-size:var(--tabs-size-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .tabbed-set>label:hover{color:var(--tabs-color-label-active)} diff --git a/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css b/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css deleted file mode 100644 index adc6166..0000000 --- a/_panels_static/panels-variables.06eb56fa6e07937060861dad626602ad.css +++ /dev/null @@ -1,7 +0,0 @@ -:root { ---tabs-color-label-active: hsla(231, 99%, 66%, 1); ---tabs-color-label-inactive: rgba(178, 206, 245, 0.62); ---tabs-color-overline: rgb(207, 236, 238); ---tabs-color-underline: rgb(207, 236, 238); ---tabs-size-label: 1rem; -} \ No newline at end of file diff --git a/_sources/appendix/genindex.md b/_sources/appendix/genindex.md deleted file mode 100644 index 77ee4ba..0000000 --- a/_sources/appendix/genindex.md +++ /dev/null @@ -1 +0,0 @@ -# Указатель diff --git a/_sources/autodiff/backwardmode.md b/_sources/autodiff/backwardmode.md new file mode 100644 index 0000000..36cc178 --- /dev/null +++ b/_sources/autodiff/backwardmode.md @@ -0,0 +1,269 @@ +```{eval-rst} +.. meta:: + :description: Данный раздел посвящён автоматическому дифференцированию назад (backward mode). + :keywords: автоматическое дифференцирование назад, backward mode, reverse accumulation, autodiff, forwarddiff, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +# Автоматическое дифференцирование назад + +```{index} дифференцирование; автоматическое назад +``` +**Автоматическое дифференцирование назад** (обратное, backward mode, reverse accumulation) это вид автоматического дифференцирования, в котором вычисления производных распространяются от результата функции к её аргументам. +С историей открытия и авторства этого метода дифференцирования можно ознакомиться в работе {cite}`Griewank2012`. + +Мы приведём общий случай позже, а сейчас продемонстрируем алгоритм на примере функции из {numref}`Раздела %s `. + +```{math} +f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3} +``` + +```{figure} static/graph-example.svg +--- +name: fig:autodiff:graph-example-backward +--- + +Граф вычислений функции $f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3$. +``` + +В отличие от {ref}`дифференцирования вперёд `, поставим задачу вычисления не одной, а сразу всех частных производных функции $f$ по аргументам (т.е. найдём градиент) +```{math} +\nabla f (x_1, x_2, x_3) = \begin{bmatrix} +\partial f / \partial x_1 +\\ \partial f / \partial x_2 +\\ \partial f / \partial x_3 +\end{bmatrix}. +``` + +Будем считать функцию $f$ сложной (композитной) функцией промежуточных значений $x_j$ ($j = 1, \dots, 7$) и воспользуемся правилом дифференцирования сложной функции. +Чтобы найти градиент $\nabla f$, нам понадобится найти все частные производные вида +```{math} +\frac{\partial f}{\partial x_j}, \quad j = 1, \dots, 7, +``` +при $j = 1, 2, 3$ искомые производные составляют градиент. + +**Шаг 0.** +Совершим обход графа вычислений ({numref}`Рисунок %s `) для нахождения (только) промежуточных значений +```{math} +x_1, \dots, x_7. +``` +На {numref}`Рисунке %s ` показан результат этого обхода при вычислении $f(1, 2, 3)$. + +```{figure} static/graph-backward-first-traverse.svg +--- +name: fig:autodiff:graph-backward-first-traverse +--- + +Прямой обход графа вычислений $f(1, 2, 3)$ для нахождения промежуточных значений (подписаны рядом с вершинами). +``` + +Запомним промежуточные значения $x_j$ и _запомним граф вычислений_, он понадобится далее. +На этом первый этап вычислений завершается. + +````{warning} +В дальнейшем мы будем "переопределять" функцию $f$ для упрощения нотации. +Более корректным было бы вводить новую функцию (со своим именем) на каждом шаге. +Например, при вычислении $\partial f / \partial x_3$ на шаге 5 было бы корректней определить функцию $g$ +```{math} +g = g(x_5(x_3), x_7(x_3)) = g(x_3), +``` +производная которой совпадает с производной $\partial f / \partial x_3$. +Вместо записи выше мы используем запись +```{math} +f = f(x_5(x_3), x_7(x_3)). +``` +```` + +**Шаг 1.** +Мы будем искать производные "справа-налево". +Произведём инициализацию алгоритма и вычислим одну (тривиальную) производную +```{math} +\frac{\partial f}{\partial x_7} = 1. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_7}(1, 2, 3) = 1. +``` + +**Шаг 2.** +Найдём производную $\partial f / \partial x_6$. +Значение $x_6$ явно влияет только на $x_7 = x_6 / x_3$, поэтому (для вычисления производной) посчитаем, что $f$ это сложная функция вида +```{math} +f = f(x_7(x_6)), +``` +тогда +```{math} +\frac{\partial f}{\partial x_6} += \frac{\partial f}{\partial x_7} \frac{\partial x_7}{\partial x_6} += 1 \times \frac{1}{x_3} += \frac{1}{x_3} +. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_6}(1, 2, 3) = \frac{1}{3}. +``` +Здесь производная $\partial f / \partial x_7$ нам известна с шага 1, а производная $\partial x_7 / \partial x_6$ определяется из явной связи $x_7 = x_6 / x_3$. +Отметим, что эта явная связь нам известна из графа вычислений, сохранённом на шаге 0. + +**Шаг 3.** +Найдём производную $\partial f / \partial x_5$. +Значение $x_5$ явно влияет только на $x_6$, поэтому представим $f$ в виде +```{math} +f = f(x_6(x_5)), +``` +тогда +```{math} +\frac{\partial f}{\partial x_5} += \frac{\partial f}{\partial x_6} \frac{\partial x_6}{\partial x_5} += \frac{1}{x_3} \times 1 += \frac{1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_5}(1, 2, 3) = \frac{1}{3}. +``` +Значение производной $\partial f / \partial x_6$ нам известно с шага 2. +В свою очередь, связь $x_6 = x_4 + x_5$ хранится в графе вычислений, что позволяет вычислить производную $\partial x_6 / \partial x_5 = 1$. + +**Шаг 4.** +Найдём производную $\partial f / \partial x_4$. +Значение $x_4$ явно влияет только на $x_6 = x_4 + x_5$, и этот шаг аналогичен шагу 3. +```{math} +\begin{align} +f &= f(x_6(x_4)) +\\ +\frac{\partial f}{\partial x_4} +&= \frac{\partial f}{\partial x_6} \frac{\partial x_6}{\partial x_4} += \frac{1}{x_3} \times 1 += \frac{1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_4}(1, 2, 3) = \frac{1}{3}. +\end{align} +``` + + +**Шаг 5.** +Найдём производную $\partial f / \partial x_3$. +Значение $x_3$ явно влияет на $x_5$ и $x_7$, поэтому для вычисления производной представим $f$ в виде +```{math} +f = f(x_5(x_3), x_7(x_3)), +``` +тогда производная имеет вид +```{math} +\frac{\partial f}{\partial x_3} += \frac{\partial f}{\partial x_5} \frac{\partial x_5}{\partial x_3} + + \frac{\partial f}{\partial x_7} \frac{\partial x_7}{\partial x_3} += \frac{1}{x_3} \times \cos{x_3} + 1 \times \bigg[ - \frac{x_6}{x^2_3} \bigg] += \frac{\cos{x_3}}{x_3} - \frac{x_6}{x^2_3}. +\\ +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_3}(1, 2, 3) = \frac{\cos{3}}{3} - \frac{2 + \sin{3}}{9}. +``` +Здесь мы воспользовались правилом дифференцирования сложной функции. +Значения производных $\partial f / \partial x_5$ и $\partial f / \partial x_7$ известны с шагов 3 и 1, соответственно. +Для нахождения производных $\partial x_5 / \partial x_3$ и $\partial x_7 / \partial x_3$ мы пользуемся графом вычислений, в котором хранятся явные связи $x_5 = \sin{x_3}$ и $x_7 = x_6 / x_3$. +Значение $x_6$ известно с шага 0. + + +**Шаг 6.** +Найдём производную $\partial f / \partial x_2$. +Значение $x_2$ явно влияет только на $x_4$, поэтому для нахождения производной представим $f$ в виде +```{math} +f = f(x_4(x_2)), +``` +тогда производная имеет вид +```{math} +\frac{\partial f}{\partial x_2} += \frac{\partial f}{\partial x_4} \frac{\partial x_4}{\partial x_2} += \frac{1}{x_3} \times x_1 += \frac{x_1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_2}(1, 2, 3) = \frac{1}{3} +``` +Значение производной $\partial f / \partial x_4$ известно с шага 4, а связь $x_4 = x_1 x_2$ хранится в графе вычислений, что позволяет посчитать $\partial x_4 / \partial x_2 = x_1$. + + +**Шаг 7.** +Последний шаг, вычислим производную $\partial f / \partial x_1$. +Значение $x_1$ влияет только на $x_4$ и этот шаг аналогичен шагу 6. +```{math} +\begin{align} +f &= f(x_4(x_1)) +\\ +\frac{\partial f}{\partial x_1} +&= \frac{\partial f}{\partial x_4} \frac{\partial x_4}{\partial x_1} += \frac{1}{x_3} \times x_2 += \frac{x_2}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_1}(1, 2, 3) = \frac{2}{3} +\end{align} +``` + +Итак, задача вычисления градиента в некоторой (одной) точке решена. +Отметим, что она решалась в два прохода по графу вычислений: прямому и обратному. +При обратном проходе мы интенсивно пользовались только одним правилом --- правилом дифференцирования сложной функции. + + +## Общий случай + +В общем случае для вычисления градиента функции вида $f: \real^n \to \real$ ставится вычислить производные вида +```{math} +:label: eq:autodiff:backward-gradient-problem + +\frac{\partial f}{\partial x_j}, \quad j = 1, \dots, V,\ V \ge n, +``` +где $x_j$ это промежуточные значения (вершины графа вычислений). +Первые $n$ штук $x_j$ совпадают с аргументами функции $f$, а последний $x_V \equiv f$. + +Для вычисления одной производной $\partial f / \partial x_j$ функция $f$ представляется в виде +```{math} +f = f(\{ x_k(x_j) \}_{k \in K}), +``` +где $\{ x_k(x_j) \}_{k \in K}$ это вершины, зависящие _явно_ от $x_j$ (а $K$ множество индексов таких вершин). +На графе вычислений $x_k$ соответствуют тем вершинам, у которых есть сток (ребро) из $x_j$ в $x_k$ (см. {numref}`Рисунок %s `). + +```{figure} static/graph-backward-general.svg +--- +name: fig:autodiff:graph-backward-general +--- + +Общая схема графа вычислений производной $\partial f / \partial x_j$ в автоматическом дифференцировании назад. +Явные связи между вершинами (т.е. дуги графа) показаны прямыми стрелками, а неявные --- волнистыми. +``` + +В этом представлении производная $\partial f / \partial x_j$ вычисляется следующим образом +```{math} +\frac{\partial f}{\partial x_j} += \sum_{k \in K} \frac{\partial f}{\partial x_k} \frac{\partial x_k}{\partial x_j}. +``` +Производные $\partial f / \partial x_k$ известны с предыдущих шагов обратного прохода по графу. +В свою очередь, производные $\partial x_k / \partial x_j$ вычисляются на шаге по явным связям $x_k(x_j)$, хранящимся в графе вычислений. + + +## Быстродействие и применимость + +Рассмотрим два крайних случая. + +В задаче вычисления градиента функции вида $f: \real^n \to \real$ {eq}`eq:autodiff:backward-gradient-problem` автоматическому дифференцированию назад требуется два прохода. +По этой причине дифференцирование назад предпочтительней дифференцирования вперёд для вычисления градиента. + +Напротив, в задаче вычисления производных вида $\partial f_i / \partial x$ (строки матрицы Якоби) для функции $f: \real \to \real^m$ автоматическому дифференцированию назад требуется уже $m + 1$ проходов. +Один прямой проход и по проходу на каждую производную. + +В общем случае функции вида $f: \real^n \to \real^m$ автоматическое дифференцирование назад эффективно для вычисления матрицы Якоби при $n \gg m$. + +Кроме того, дифференцированию назад требуется хранить граф вычислений, поэтому возникает требование к памяти. +Остро это требование проявляется в задачах с большими графами вычислений, например, при минимизации функции ошибки в машинном обучении. + +```{note} +Воспользоваться автоматическим дифференцированием назад в Julia можно, например, с помощью пакетов +[Zygote.jl](https://github.com/FluxML/Zygote.jl) {cite}`Innes2018` +или [ReverseDiff.jl](https://github.com/JuliaDiff/ReverseDiff.jl). +``` diff --git a/_sources/autodiff/compgraph.md b/_sources/autodiff/compgraph.md new file mode 100644 index 0000000..9fa08e6 --- /dev/null +++ b/_sources/autodiff/compgraph.md @@ -0,0 +1,108 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 +kernelspec: + display_name: Julia 1.9.4 + language: julia + name: julia-1.9 +--- + +```{eval-rst} +.. meta:: + :description: В данном разделе мы определяем понятие графа вычислений, которое понадобится для классификации видов автоматического дифференцирования. + :keywords: граф вычислений, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +(sec:autodiff:compgraph)= +# Граф вычислений + +```{index} граф; вычислений +``` +Для общего представления автоматического дифференцирования нам понадобится **граф вычислений**. +Это ориентированный граф для представления последовательности вычислений, скажем, функции $f$. + +Обычно вершинами графа являются операции или их аргументы, а рёбра связывают операции с аргументами. +Мы же воспользуемся упрощённым описанием, которого хватит для наших целей. +Так, в вершины графа мы будем помещать значения, возникающие в ходе вычислений (включая аргументы $f$ и итоговое значение), а рёбра (дуги) графа будут соединять аргументы операции с её результатом. + +Рассмотрим несколько примеров. + +```{figure} static/graph-unary.svg +--- +name: fig:autodiff:graph-unary +--- + +Граф вычислений $f(x) = \sin x$. +``` + +На {numref}`Рисунке %s ` показан граф вычисления унарной функции (функции одного аргумента). +В этом случае $x_1 \equiv x$, а $x_2 \equiv f(x)$. + + +```{figure} static/graph-binary.svg +--- +name: fig:autodiff:graph-binary +--- + +Граф вычислений для операции суммы. +``` + +На {numref}`Рисунке %s ` показан граф вычисления суммы $x_1 + x_2$ с хранением результата в $x_3$. +С формальной точки зрения, операцию сложения можно представить в виде функции двух аргументов (бинарной функции). +В таком случае стоки вершины $x_3$ соединяют её с аргументами операции, а саму операцию мы будем подписывать рядом с вершиной-результатом. + + +```{figure} static/graph-example.svg +--- +name: fig:autodiff:graph-example +--- + +Граф вычислений функции $f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3$. +``` + +На {numref}`Рисунке %s ` показан граф вычисления функции трёх переменных + +```{math} +f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3}, +``` + +которую мы будем в качестве примера в последующих разделах. +Значения $x_1$, $x_2$ и $x_3$ являются аргументами функции, а $x_7$ --- значением функции в точке $[x_1, x_2, x_3]^\top$. +Промежуточные значения функции приведены ниже. + +```{code-cell} +function f(x₁, x₂, x₃) + @show x₁ + @show x₂ + @show x₃ + @show x₄ = x₁ * x₂ + @show x₅ = sin(x₃) + @show x₆ = x₄ + x₅ + @show x₇ = x₆ / x₃ + return x₇ +end + +f(1, 2, 3) +``` + +Те же промежуточные значения $x_4$, $x_5$, $x_6$, $x_7$ создаёт компилятор языка. +Они обозначаются как `%номер` в Julia. + +```{code-cell} +f2(x₁, x₂, x₃) = (x₁ * x₂ + sin(x₃)) / x₃ +@code_lowered f2(1, 2, 3) +``` + +В нашем случае `x₄ = %1`, `x₅ = %2`, `x₆ = %3` и `x₇ = %4`. + +Для создания машинного (или промежуточного представления) кода из исходного компилятор строит синтаксическое дерево. +Если не вдаваться в технические детали, синтаксическое дерево напоминает граф вычислений, который мы описывали выше. +Однако, в синтаксическом дереве содержатся не только "привычные" математические операции, но и операторы языка, например, операторы ветвления, циклов или вызова функций. +Кроме того, на разных платформах (железе или операционной системе) машинный код может быть разным, но синтаксические деревья (и исходный код) могут совпадать ввиду более высокого уровня абстракции вычисления. + +В следующих разделах мы воспользуемся графом вычисления, показанном на {numref}`Рисунке %s `, для классификации методов автоматического дифференцирования. diff --git a/_sources/autodiff/complexstep.md b/_sources/autodiff/complexstep.md new file mode 100644 index 0000000..04666d6 --- /dev/null +++ b/_sources/autodiff/complexstep.md @@ -0,0 +1,146 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 +kernelspec: + display_name: Julia 1.9.4 + language: julia + name: julia-1.9 +--- + +```{eval-rst} +.. meta:: + :description: Численное дифференцирование методом комплексного шага. + :keywords: дифференцирование, производная, метод комплескного шага, complex step, вычислительная математика, вычматы +``` + +(sec:autodiff:complex_step)= +# Метод комплексного шага + +**Метод комплексного шага** (complex step method) {cite}`Martins2003, KochenderferWheeler2019` относится к численным методам дифференцирования (наряду с методом конечных разностей). +Однако, арифметика, стоящая за методом, роднит его с методом автоматического дифференцирования вперёд. + +```{index} метод; комплескного шага +``` +Заключается метод в следующем. +Вычислим функцию $f$ один раз в точке $x + i h$ ($i h$ и есть комплексный шаг). +Разложение Тейлора для $f(x + ih)$ имеет вид +```{math} +f(x + i h) += f(x) + i h f'(x) - h^2 \frac{f''(x)}{2!} - i h^3 \frac{f'''(x)}{3!} + \dots +``` +Мнимая часть разложения +```{math} +\operatorname{Im}(f(x + i h)) = h f'(x) - h^3 \frac{f'''(x)}{3!} + \dots += h f'(x) + O(h^3) +``` +позволяет вычислить производную $f'(x)$ с точностью $O(h^2)$ +```{math} +:label: complex_step_derivative +f'(x) = \frac{\operatorname{Im}(f(x + i h))}{h} + O(h^2). +``` +В свою очередь, действительная часть разложения +```{math} +\operatorname{Re}(f(x + i h)) += f(x) - h^2 \frac{f''(x)}{2!} + \dots += f(x) + O(h^2) +``` +содержит значение $f(x)$ с той же точностью, $O(h^2)$ +```{math} +f(x) = \operatorname{Re}(f(x + i h)) + O(h^2). +``` + +Метод комплексного шага прост в реализации. + +::::{proof:function} diff_complexstep + +**Метод комплексного шага** + +:::julia +""" + diff_complexstep(f, x; h=1e-16) + +Производная скалярной функции `f` в точке `x` методом комплексного шага, +размер шага `h`. +""" +diff_complexstep(f, x; h=1e-16) = imag(f(x + im * h)) / h +::: +:::: + +Как видно из реализации, метод можно применять к любой функции, вычислимой от комплекcного аргумента. +При этом от программиста требуется определить только дифференцируемую функцию (скажем, уравнение состояния), а её производные можно вычислить, выполнив вычисление от комплексного числа. + + +В демонстрации ниже показан пример вычисления производной функции методом комплексного шага, а также сравнивается точность этого метода с парой методов конечных разностей. + +```{proof:demo} +``` +```{raw} html +

+``` + +Рассмотрим три численных метода дифференцирования: методы конечных разностей (прямой и центральный вариант) и метод комплексного шага. + +```{code-cell} +:tags: [remove-output] + +diff_complexstep(f, x, h=1e-16) = imag(f(x + im * h)) / h +diff_forward(f, x, h=1e-8) = (f(x + h) - f(x)) / h +diff_central(f, x, h=1e-6) = (f(x + h/2) - f(x - h/2)) / h +``` + +Сравним точности методов на примере вычисления производной синуса в точке $x = 1/3$. + +```{code-cell} +:tags: [remove-output] + +f(x) = sin(x) +df(x) = cos(x) + +x = 1/3 +h = [2.0^i for i in -52:0] + +err_complex = @. abs(1 - diff_complexstep(f, x, h)/df(x)) +err_forward = @. abs(1 - diff_forward(f, x, h)/df(x)) +err_central = @. abs(1 - diff_central(f, x, h)/df(x)) +``` + +График зависимости невязки от размера шага $h$ выглядит следующим образом ($\log-\log$ шкала). + +```{code-cell} +using Plots + +plot(; + xaxis=:log10, + yaxis=:log10, + xlabel="Размер шага h", + ylabel="Норма относительной невязки", + leg_title="Метод", leg=:top +) + +plot!(h[err_complex .> 0], err_complex[err_complex .> 0]; label="комплексный шаг") +plot!(h, err_forward; label="разность вперёд") +plot!(h, err_central; label="центральная разность") + +xticks!([10.0^i for i in -14:2:0]) +``` + +При этом значения невязки для метода комплексного шага при шагах менее $1.5 \times 10^{-8}$ получились нулевыми (поэтому они не насенены на график в логарифмической шкале). + +```{code-cell} +[h err_complex][err_complex .== 0, :] +``` + +Так, метод комплексного шага более устойчив, чем методы конечных разностей, к ошибкам округления, возникающих в арифметике с конечной точностью. +Устойчивость кроется в избегании эффекта {ref}`subtractive cancellation ` за счёт вычисления функции один раз (вместо двух). +```{raw} html +
+``` + +Метод комплескного шага гораздо лучше устойчив к численным эффектам, чем методы конечных разностей. +Тем не менее, его точность аналитически ограничена {eq}`complex_step_derivative`. +Далее мы увидим, что можно получить точное значение производной, если вычислить функцию не от комплексного, а от дуального числа. diff --git a/_sources/autodiff/dualnumbers.md b/_sources/autodiff/dualnumbers.md new file mode 100644 index 0000000..02719b4 --- /dev/null +++ b/_sources/autodiff/dualnumbers.md @@ -0,0 +1,422 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 +kernelspec: + display_name: Julia 1.9.4 + language: julia + name: julia-1.9 +--- + +```{eval-rst} +.. meta:: + :description: Численное дифференцирование методом комплексного шага. + :keywords: дуальное число, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +(sec:autodiff:dualnumbers)= +# Дуальные числа + +Дуальные числа тесно связаны с дифференцированием, а на основе арифметики с ними можно создать алгоритм автоматического дифференцирования вперёд. + +```{index} число; дуальное +``` +````{proof:definition} Множество дуальных чисел +Дуальные числа $\dualset$ расширяют[^hypercomplexnumbers] действительные числа $\real$ числом $\dual$, для которого определяются следующие правила + +```{math} +\dual{} \neq 0, \quad \dual{} \times 0 = 0, \quad \text{но} \quad \dual{} \times \dual{} = \dual{}^2 = 0. +``` + +[^hypercomplexnumbers]: Расширение множества действительных чисел называют гиперкомплексными числами. Комплексные, дуальные числа, и, например, квартерионы являются гиперкомплексными числами. +```` + +Например, в дуальных числах уравнение $x^2 = 0$ имеет множество корней: $0, \dual{}^2, \dual{}^3,\dots$ + +Определим запись дуальных чисел аналогично записи комплексных +```{math} + a + b \dual, \quad a, b \in \real, +``` +где $a$ назовём действительной частью (компонентой) числа, а $b$ --- дуальной. + +Сложение и вычитание чисел определяется интуитивно, покомпонентно +```{math} +\begin{align} +\begin{split} + (a + b \dual) + (c + d \dual) = (a + c) + (b + d)\dual, + \\ + (a + b \dual) - (c + d \dual) = (a - c) + (b - d)\dual. +\end{split} +\end{align} +``` + +При произведении проявляется природа числа $\dual$ +```{math} +(a + b \dual)(c + d \dual) = ac + a d \dual + b c \dual + \cancel{b d \dual^2} += ac + (a d + b c)\dual. +``` +Такое поведение может напомнить пренебрежение квадратичными поправками. +Например, можно считать, что $b\dual$ и $d\dual$ являются погрешностями значений $a$ и $c$. +Тогда $b d \dual^2$ мало по сравнению с остальными слагаемыми, и пренебрегается. + +Деление дуальных чисел можно представить домножением числителя и знаменателя на сопряжённое к знаменателю (при этом знаменатель ненулевой, $c + d\dual \neq 0$) +```{math} +\frac{a + b\dual}{c + d\dual} += \frac{(a + b\dual)(c - d \dual)}{(c + d\dual)(c - d\dual)} += \frac{ac + (-ad + bc)\dual}{c^2} += \frac{a}{c} + \frac{bc - ad}{c^2}\dual. +``` + +(sec:autodiff:dual_arithmetic)= +````{proof:definition} Арифметика дуальных чисел +Сложение, вычитание, произведение и деление дуальных чисел определяются следующим образом. + +```{math} +:label: eq:dual_sumsub +(a + b \dual) \pm (c + d \dual) = (a \pm c) + (b \pm d)\dual. +``` + +```{math} +:label: eq:dual_mul +(a + b \dual)(c + d \dual) = ac + (a d + b c)\dual. +``` + +```{math} +:label: eq:dual_div +\frac{a + b\dual}{c + d\dual} = \frac{a}{c} + \frac{bc - ad}{c^2}\dual. +``` +```` + + +## Связь с дифференцированием + +Попробуем вычислить функцию $f$ от дуального числа $a + b\dual{}$. +Для этого воспользуемся разложением Тейлора +```{math} +f(x) = \sum_{k=0}^{\infty} \frac{f^{(k)}(x_0)}{k!} (x - x_0)^k +``` +и применим его к $f(a + b\dual{})$ +```{math} +\begin{split} +f(a + b\dual) &= \sum_{k=0}^{\infty} \frac{f^{(k)}(a)}{k!} (a + b\dual - a)^k += \sum_{k=0}^{\infty} \frac{f^{(k)}(a) b^k \dual^k}{k!} +\\ &= f(a) + b f'(a) \dual + \sum_{k=2}^\infty \frac{f^{(k)}(a) b^k \dual^k}{k!} +\\ &= f(a) + b f'(a) \dual + \dual^2 \sum_{k=2}^\infty \frac{f^{(k)}(a) b^k \dual^{k-2}}{k!} +\\ &= f(a) + b f'(a) \dual. +\end{split} +``` + +Значит, вычислив функцию от дуального числа, получаем дуальное число, в действительной части которого содержится значение функции, а в дуальной содержится её производится. +(Сравните с {ref}` методом комплексного шага `.) + +Итак, дуальные числа обладают свойством, непосредственно связанным с дифференцированием. + +::::{proof:proposition} Значение функции от дуального числа + +```{math} +:label: eq:funcofdual + +f(a + b\dual) = f(a) + b f'(a)\dual, \quad a, b \in \real. +``` +:::: + +Отметим, что соотношение {eq}`eq:funcofdual` выполняется _аналитически_ точно. + +::::{proof:example} + +Ниже показаны примеры вычисления функций от дуального числа $3 + 2\dual$. +Чтобы показать определение функции и точку вычисления использована запись $[\text{тело функции}](\text{аргумент})$. +Например, $[x^2 + 3](4)$ означает вычисление $f(x) = x^2 + 3$ в точке 4, т.е. $[x^2 + 3](4) = 4^2 + 3 = 19$. + +- Константа +```{math} +\begin{align*} +f(x) &= 5, +\\ f(3 + 2\dual) &= [5](3) + 2 \times [0](3) \dual = 5. +\end{align*} +``` +- Полином +```{math} +\begin{align*} +f(x) &= 4x^3 + x, +\\ f(3 + 2 \dual) &= [4 x^3 + x](3) + 2 \times [12 x^2 + 1](3) \times \dual +\\ &= 111 + 2 \times 109 \times \dual = 111 + 218 \dual. +\end{align*} +``` +- Логарифм +```{math} +:label: eq:example_log +\begin{split} +f(x) &= \log x, +\\ f(3 + 2 \dual) &= [\log x](3) + 2 \times [1/x](3) \times \dual + = \log 3 + \frac{2}{3} \dual. +\end{split} +``` +:::: + +Рассмотрим арифметические операции с функциями. +Для этого воспользуемся свойством {eq}`eq:funcofdual` и определениями арифметических операций с дуальными числами {eq}`eq:dual_sumsub`, {eq}`eq:dual_mul` и {eq}`eq:dual_div`. +Начнём рассмотрение со значения суммы функций в точке $a + b\dual$ +```{math} +\begin{split} +f(a + b \dual) + g(a + b \dual) +&= (f(a) + b f'(a) \dual) + (g(a) + b g'(a) \dual) +\\ &= (f(a) + g(a)) + b (f'(a) + g'(a)) \dual. +\end{split} +``` +В действительной части мы получили сумму функций, а в дуальной присутствует сумма их производных. +Положим $b = 1$ и получим +```{math} +f(a + \dual) + g(a + \dual) = (f(a) + g(a)) + (f'(a) + g'(a)) \dual. +``` +Теперь в дуальной части находится сумма производных функций, она же является производной суммы $(f + g)' = f' + g'$. +То есть, +```{math} +[f + g](a + \dual) = [f + g](a) + [f + g]'(a) \times \dual. +``` + +Итак, мы получили согласие с правилом дифференцирования суммы функций от действительного числа $a$. +Действительная часть соответствует сумме функций в $a$, а дуальная --- производной суммы функций в $a$. +Естественно, аналогичное верно и для вычитания. + +Проверим теперь произведение функций +```{math} +\begin{split} +f(a + \dual) \times g(a + \dual) &= (f(a) + f'(a) \dual) \times (g(a) + g'(a) \dual) +\\ &= f(a) g(a) + (f'(a) g(a) + f(a) g'(a)) \dual. +\end{split} +``` +И снова есть соответствие. +В действительной части мы получили произведение функций, а в дуальной --- производную произведения функций $(fg)' = f'g + fg'$ в точке $a$ +```{math} +[f \times g](a + \dual) = [f \times g](a) + [f \times g]'(a) \times \dual. +``` + +Наконец, проверим деление функций +```{math} +\begin{split} +\frac{f(a + \dual)}{g(a + \dual)} &= \frac{f(a) + f'(a) \dual}{g(a) + g'(a) \dual} +\\ &= \frac{f(a)}{g(a)} + \frac{f'(a) g(a) - f(a) g'(a)}{g^2(a)} \dual. +\end{split} +``` +И снова наблюдается соответствие. +Действительная часть является делением функций, а дуальная --- производной деления функций $(f/g)' = (f'g - f g')/g^2$ в точке $a$ +```{math} +[f / g](a + \dual) = [f / g](a) + [f / g]'(a) \dual. +``` + +Последнее, что осталось проверить, это вычисление сложной (составной) функции +```{math} +g(f(a + \dual)) = g(f(a) + f'(a)\dual) = g(f(a)) + g'(f(a)) f'(a)\dual. +``` +Как видно, наблюдается соответствие с правилом дифференцирования сложной функции $(g(f(x)))' = g'(f(x)) f'(x)$ +```{math} +[g \circ f](a + \dual) = [g \circ f](a) + [g \circ f]'(a) \times \dual. +``` + + +## Автоматическое дифференцирование скалярной функции + +Теперь у нас есть все инструменты для вычисления производной функции. +Так, чтобы вычислить производную функции в точке $f'(x)$, необходимо реализовать вычисление функции от дуального числа $f(x + \dual)$. +В дуальной части $f(x + \dual)$ будет содержаться значение производной $f'(x)$, согласно {eq}`eq:funcofdual`. + +Рассмотрим конкретный пример. +Задача: вычислить производную функции $f(x) = 3 + x \log{x^2}$ в точке $x = 5$. +Чтобы верифицировать будущие вычисления, приведём выражение для производной $f'(x)$ + +```{math} +f'(x) = \log{x^2} + 2, \quad x \neq 0, +``` + +и зададим функцию и её производную в коде. + +```{code-cell} +:tags: [remove-output] +f(x) = 3 + x * log(x^2) +df(x) = log(x^2) + 2 +``` + +В точке $x = 5$ мы ожидаем следующие значения функции и её производной + +```{code-cell} +f(5), df(5) +``` + +Теперь перейдём к реализации метода автоматического дифференцирования. +Во-первых, определим новый тип данных `Dual` для представления дуального числа. + +```{code-cell} +struct Dual{T<:Real} + a::T + b::T +end +``` + +В структуре `Dual` всего два поля: поле `a` хранит действительную часть числа, а поле `b` хранит дуальную. +Кроме того, мы потребовали, чтобы типы полей были одинаковыми. + +Теперь реализуем {ref}`арифметику дуальных чисел `. +Для этого перегрузим операторы сложения и умножения. +(В $f(x)$ отсутствуют вычитание и деление, их реализовывать не будем.) + +```{code-cell} +Base.:+(x::Dual, y::Dual) = Dual(x.a + y.a, x.b + y.b) +Base.:*(x::Dual, y::Dual) = Dual(x.a * y.a, x.b * y.a + x.a * y.b) +``` + +В нашем примере есть ещё две операции: возведение числа в целую степень и логарифмирование. +Для этих операций понадобится реализовать свойство {eq}`eq:funcofdual`. +Как известно из матанализа +```{math} +\begin{align} +(x^n)' &= n x^{n-1}, \quad x \in \real, n \in \integer, +\\ (\log{x})' &= 1 / x, \quad\quad x \in \real, x \neq 0. +\end{align} +``` +Воспользуемся этими правилами дифференцирования и добавим методы для оператора `^` и функции натурального логарифма `log`. + +```{code-cell} +Base.:^(x::Dual, n::Int) = Dual(x.a^n, x.b * n * x.a^(n-1)) +Base.log(x::Dual) = Dual(log(x.a), x.b / x.a) +``` + +Все операции определены и можно провести вычисление с дуальными числами. +Константу 3 представляем в виде $3 \equiv 3 + 0\times\dual$, а вычисление производим в точке $x = 5 + \dual$. + +```{code-cell} +d = Dual(3, 0) + Dual(5, 1) * log(Dual(5, 1)^2) +f(5) == d.a, df(5) == d.b +``` + +Как видно, действительная часть числа `d` совпадает с `f(5)`, а дуальная часть совпадает с производной в точке 5 `df(5)`. +Отметим, что эти равенства выполняются точно. + +Проводить вычисления функции `f` с дуальными числами пока нельзя. +Дело в том, что в `f` присутствует сложение `3::Int` с дуальным числом `(x * log(x^2))::Dual{Float64}`, это сложение мы ещё не определили. + +```{code-cell} +:tags: [raises-exception] + +f(Dual(5, 1)) +``` + +Есть два способа доопредилить сложение. +Первый состоит в добавлении метода `+(::Int, ::Dual)` и нам бы его хватило для примера. +Мы же поступим более общим для языка Julia способом. +Мы уже знакомы с функцией `promote(xs...)`, которая возвращает значения аргументов, приведённых к "общему" типу. + +```{code-cell} +promote(1, 2.5, 1//3) +``` + +Воспользуемся ей, чтобы определить сложение `Real` чисел с дуальными `Dual`. + +```{code-cell} +Base.:+(x::Dual, y::Real) = +(promote(x, y)...) +Base.:+(x::Real, y::Dual) = +(promote(x, y)...) +``` + +Однако, мы ещё не определили правила, по которым приводить `Real`-числа к `Dual`-числам. +Для этого надо знать, как работает функция `promote(x::T, y::S)`. +В общих чертах, `promote` выясняет "общий" для `T` и `S` тип `U` с помощью `promote_type`, а затем конвертирует к типу `U` свои аргументы. + +```julia +function promote(x::T, y::S) where {T, S} + U = promote_type(T, S) + return (convert(U, x), convert(U, y)) +end +``` + +Начнём с конвертации. + +```{code-cell} +Base.convert(::Type{Dual{T}}, x::Dual) where {T} = Dual{T}(x.a, x.b) +Base.convert(::Type{Dual{T}}, x::S) where {T, S<:Real} = Dual{T}(x, zero(x)) +``` + +В первой строчке мы определили конвертацию `Dual`-чисел между собой. +Фактически, при конвертации мы создаём новое `Dual` число, у которого поля имеют желаемый тип `T`. +Во второй строчке мы определили конвертацию `Real`-числа к `Dual{T}`-числу. +Как нам известно, действительное число это дуальное с нулевой дуальной частью. + +Теперь перейдём к определению `promote_type` для дуальных чисел. +Саму функцию `promote_type` переопределять не рекомендуется. +Вместо этого добавляется метод к функции `promote_rule(T1, T2)`, которая для пары типов `T1` и `T2` (явно) задаёт общий. +В свою очередь, `promote_type` использует `promote_rule`, применяя её попарно ко всем своим аргументам. +Кроме того, `promote_type` заботится о симметрии аргументов, поэтому `promote_rule` достаточно определить для пары аргументов один раз, т.е. пара неупорядоченная. + +```{code-cell} +Base.promote_rule(::Type{Dual{T}}, ::Type{Dual{S}}) where {T, S} = Dual{promote_type(T, S)} +Base.promote_rule(::Type{Dual{T}}, ::Type{S}) where {T, S<:Real} = Dual{promote_type(T, S)} +``` + +В первой строчке мы определяем общий тип для двух дуальных. +Поскольку `T` и `S` это подтипы `Real` (см. выше определение `struct Dual`), то мы можем воспользоваться `promote_type` для них. +Для `Real` чисел `promote_type` уже определён в Julia. +Во второй строчке для `Dual` и `Real` числа мы задаём `Dual` как общий тип. + +Теперь `promote` работает с нашим типом `Dual`. + +```{code-cell} +promote(1, 2.5, 1//3, Dual(1, 2)) +``` + +```{code-cell} +promote(1//3, Dual(1, 2)) +``` + +Наконец, всё готово для вычисления производной 🎉 + +```{code-cell} +f(Dual(5, 1)) +``` + +## Заключение + +Ниже представлен полный код из примера выше. + +```julia +struct Dual{T<:Real} + a::T + b::T +end + +Base.convert(::Type{Dual{T}}, x::Dual) where {T} = Dual{T}(x.a, x.b) +Base.convert(::Type{Dual{T}}, x::S) where {T, S<:Real} = Dual{T}(x, zero(x)) + +Base.promote_rule(::Type{Dual{T}}, ::Type{Dual{S}}) where {T, S} = Dual{promote_type(T, S)} +Base.promote_rule(::Type{Dual{T}}, ::Type{S}) where {T, S<:Real} = Dual{promote_type(T, S)} + +Base.:+(x::Dual, y::Real) = +(promote(x, y)...) +Base.:+(x::Real, y::Dual) = +(promote(x, y)...) + +Base.:+(x::Dual, y::Dual) = Dual(x.a + y.a, x.b + y.b) +Base.:*(x::Dual, y::Dual) = Dual(x.a * y.a, x.b * y.a + x.a * y.b) +Base.:^(x::Dual, n::Int) = Dual(x.a^n, x.b * n * x.a^(n-1)) + +Base.log(x::Dual) = Dual(log(x.a), x.b / x.a) +``` + +Этот код позволяет автоматически дифференцировать не только функцию $3 + x \log{x^2}$, но и вообще любую скалярную функцию, состоящую из операций сложения, произведения, возведения в целую степень и логарифмирования. +Чтобы распространить метод на больший класс функций, необходимо доопределить оставшиеся операции, например, вычитание, сравнение или $\sin$. +Кроме того, понадобится доопределить нематематические функции, например, выделение памяти. + +Дифференцирование с использованием дуальных чисел обощается на случаи частных производных и производных высших порядков. +Такой вид дифференцирования реализован в пакете [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl). +С помощью ForwardDiff производную для нашего примера можно вычислить так. + +```{code-cell} +using ForwardDiff + +f(x) = 3 + x * log(x^2) +df(x) = ForwardDiff.derivative(f, x) +df(5) +``` + +Реализованный нами способ дифференцирования называется _автоматическим дифференцированием вперёд_. +Смысл слова "вперёд" связан с направленностью цепочки вычислений производной и разъясняется в следующих разделах. diff --git a/_sources/autodiff/ex.md b/_sources/autodiff/ex.md new file mode 100644 index 0000000..e15d2bb --- /dev/null +++ b/_sources/autodiff/ex.md @@ -0,0 +1,21 @@ +```{eval-rst} +.. meta:: + :description: Задания на тему автоматического дифференцирования. + :keywords: задача, задание, упражнение, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +# Задания + +## Автоматическое дифференцирование вперёд + +Вам необходимо реализовать автоматическое дифференцирование вперёд для функций `f(x)`, используя дуальные числа. +В задании должна присутствовать проверка правильности вычислений производной. +Для этого сравните производную по реализованному алгоритму в трёх разных `x` с аналитическими значениями, либо используя [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) или [Zygote.jl](https://github.com/FluxML/Zygote.jl). + +Примеры `f(x)` приведены ниже + +1. `2 + exp(x) * sin(x)` +1. `4 * cos(x^2) / x` +1. `log(sqrt(x)) - exp(x)` +1. `cbrt(cos(x^2)) / x^4` +1. `log(1 + tan(x)) / 8.5` diff --git a/_sources/autodiff/forwardmode.md b/_sources/autodiff/forwardmode.md new file mode 100644 index 0000000..bb702d5 --- /dev/null +++ b/_sources/autodiff/forwardmode.md @@ -0,0 +1,203 @@ +```{eval-rst} +.. meta:: + :description: Данный раздел посвящён автоматическому дифференцированию вперёд (forward mode). + :keywords: дуальное число, автоматическое дифференцирование вперед, forward mode, forward accumulation, autodiff, forwarddiff, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +(sec:autodiff:forwardmode)= +# Автоматическое дифференцирование вперёд + +```{index} дифференцирование; автоматическое вперёд +``` +**Автоматическое дифференцирование вперёд** (прямое, forward mode, forward accumulation) является видом автоматического дифференцирования, в котором вычисления производных распространяются от аргументов функции к её результату. +Впервые этот метод дифференцирования был представлен R.E. Wengert {cite}`Wengert1964`. + +Сначала мы продемонстируем работу алгоритма на частном примере функции из {numref}`Раздела %s `, а затем опишем общий случай. +Ниже показана функция из примера и её граф вычисления. + +```{math} +f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3} +``` + +```{figure} static/graph-example.svg +--- +name: fig:autodiff:graph-example-forward +--- + +Граф вычислений функции $f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3$. +``` + +Поставим задачу вычисления первой частной производной $\partial f / \partial x_1$. +Будем считать, что $f$ это сложная (композитная) функция от промежуточных значений. +Например, можно сказать, что $f$ _явно_ зависит от $x_3$ и $x_6$, которые, в свою очередь, _неявно_ зависят (или не зависят) от $x_1$. +Это позволит нам воспользоваться правилом дифференцирования сложной функции и, в конечном итоге, получить производную $\partial f / \partial x_1$. + +Итак, наша задача найти все частные производные вида +```{math} +\frac{\partial x_j}{\partial x_1}, \quad j = 1, \dots, 7. +``` +Часть этих производных нулевые, а при $j = 7$ мы получим $\partial x_7 / \partial x_1 \equiv \partial f / \partial x_1$, т.е. искомую частную производную. + +**Шаг 1.** +Произведём инициализацию алгоритма. +Нам известны значения аргументов $x_1$, $x_2$, $x_3$ и их частные производные по $x_1$ +```{math} +\frac{\partial x_1}{\partial x_1} = 1, +\quad \frac{\partial x_2}{\partial x_1} += \frac{\partial x_3}{\partial x_1} += 0. +``` +Запомним их. + +**Шаг 2.** +Найдём производную $\partial x_4 / \partial x_1$. +Для этого считаем $x_4$ сложной функцией в соответствии с графом вычисления (см. аргументы вычисления $x_4$ на {numref}`Рисунке %s `) +```{math} +x_4 = x_4(x_1, x_2) = x_1 \times x_2(x_1) = x_4(x_1) +``` +и получим +```{math} +\frac{\partial x_4}{\partial x_1} += \frac{\partial x_1}{\partial x_1} x_2 + x_1 \frac{\partial x_2}{\partial x_1} += 1 \times x_2 + x_1 \times 0 += x_2. +``` +Здесь мы воспользовались правилом дифференцирования произведения. +Производные $\partial x_1 / \partial x_1 = 1$ и $\partial x_2 / \partial x_1 = 0$ нам известны с шага 1. +В конце шага запомним не только производную $\partial x_4 / \partial x_1$, но и значение $x_4 = x_1 x_2$. + +**Шаг 3.** +Найдём производную $\partial x_5 / \partial x_1$. +Поступая также, как на шаге 2, посчитаем $x_5$ сложной функцией от $x_3$ +```{math} +x_5 = x_5(x_3) = \sin{x_3(x_1)} = x_5(x_1), +``` +тогда +```{math} +\frac{\partial x_5}{\partial x_1} += \frac{\partial x_5}{\partial x_3} \frac{\partial x_3}{\partial x_1} += \cos{x_3} \times 0 += 0. +``` +Здесь мы воспользовались правилом дифференцирования сложной функции и производной функции синуса. +Производная $\partial x_3 / \partial x_1 = 0$ известна с шага 1. +Как и на шаге 2, запомним $x_5 = \sin{x_3}$ и $\partial x_5 / \partial x_1$. + +**Шаг 4.** +Найдём производную $\partial x_6 / \partial x_1$. +Значение $x_6$ явно вычисляется по $x_4$ и $x_5$ +```{math} +x_6 = x_6(x_4, x_5) = x_4(x_1) + x_5(x_1) = x_6(x_1), +``` +тогда +```{math} +\frac{\partial x_6}{\partial x_1} += \frac{\partial x_4}{\partial x_1} + \frac{\partial x_5}{\partial x_1} += x_2 + 0 += x_2 +``` +Здесь мы воспользовались правилом дифференцирования суммы функций и значениями производных, полученных на шагах 2 и 3. +Запомним значение $x_6 = x_4 + x_5 = x_1 x_2 + \sin{x_3}$ и производную $\partial x_6 / \partial x_1$. + +**Шаг 5.** +Последний шаг, найдём производную $\partial x_7 / \partial x_1 \equiv \partial f / \partial x_1$. +Значение $x_7$ явно определяется по значениям $x_3$ и $x_6$ +```{math} +x_7 = x_7(x_3, x_6) = \frac{x_6(x_1)}{x_3(x_1)}, +``` +а производная по $x_1$ имеет вид +```{math} +\frac{\partial x_7}{\partial x_1} += \frac{ (\partial x_6 / \partial x_1 ) \times x_3 - x_6 \times (\partial x_3 / \partial x_1) }{ x^2_3 } += \frac{x_1 \times x_3 - x_6 \times 0}{x^2_3} += \frac{x_1}{x_3} +, \quad x_3 \neq 0. +``` +Здесь мы воспользовались правилом дифференцирования деления функций и значениями производных с шагов 1 и 4. +Таким образом, мы вычислили значение первой компоненты градиента функции $\partial f / \partial x_1$. + +Отметим, что все промежуточные значения и производные выражались на протяжении алгоритма через значения аргументов функции $x_1$, $x_2$ и $x_3$. +При этом промежуточные значения и производные мы получали в направлении "слева-направо" по графу вычислений, т.е. от аргументов к результату $x_7 \equiv f$. +На {numref}`Рисунке %s ` показан граф вычисления значения функции $f$ и её производной $\partial f / \partial x_1$ в точке $[1, 2, 3]^\top$. + +```{figure} static/graph-forward-auxillary-values.svg +--- +name: fig:autodiff:graph-forward-aux +--- + +Граф вычисления $f(1, 2, 3)$ и $\partial f / \partial x_1 (1, 2, 3)$. +Вычисления распространяются "слева-направо". +У каждой вершины подписаны значение промежуточной величины $x_i$ и производной $\partial x_i / \partial x_1$. +Напоминает {ref}`дуальные числа `? +``` + + +## Общий случай + +В общем случае задача автоматического дифференцирования сводится к поиску всех производных вида + +```{math} +\frac{\partial x_j}{\partial x_i}, \quad j = 1,\dots,V,\ i = 1,\dots,n,\ V \ge n, +``` +где $x_1$, ..., $x_n$ это аргументы функции, а $x_1$, ..., $x_V$ промежуточные значения в графе вычислений. +В примере выше аргументов было $n = 3$, а промежуточных значений $V = 7$. + +Автоматическое дифференцирование по-разному пользуется правилом дифференцирования сложной (композитной) функции. +В случае дифференцирования вперёд промежуточное значение $x_j$ представляется в виде функции +```{math} +:label: eq:forwarddiff:general_xj + +x_j = x_j( \{ x_k(x_i) \}_{k \in K} ) = x_j(x_i), +``` +где $\{x_k\}_{k \in K}$ это промежуточные значения, от которых $x_j$ зависит явно, непосредственно (а $K$ это множество индексов таких вершин). +Т.е. на графе вычислений $\{x_k\}_{k \in K}$ это вершины, которые связаны с $x_j$ стоком. + +```{figure} static/graph-forward-general.svg +--- +name: fig:autodiff:graph-forward-general +--- + +Общая схема графа вычислений $\partial x_j / \partial x_i$ для автоматического дифференцирования вперёд. +Явные связи (дуги графа) показаны прямыми стрелками, а неявные связи показаны волнистыми стрелками. +``` + +Применяя к представлению функции $x_j$ в виде {eq}`eq:forwarddiff:general_xj` правило дифференцирования сложной функции, получаем +```{math} +\frac{\partial x_j}{\partial x_i} += \sum_{k \in K} \frac{\partial x_j}{\partial x_k} \frac{\partial x_k}{\partial x_i}, +``` +где производные $\partial x_k / \partial x_i$ известны с предыдущих шагов обхода графа вычислений. +В свою очередь, производные $\partial x_j / \partial x_k$ вычисляются на текущем шаге обхода по явной связи $x_j(\{ x_k \}_{k \in K})$. + + +## Быстродействие и применимость + +Пусть стоит задача вычисления градиента функции вида $f: \real^n \to \real$ +```{math} +\frac{\partial f}{\partial x_i},\ i = 1, \dots, n. +``` +В этой задаче автоматическому дифференцированию вперёд требуется $n$ проходов графа вычислений, по одному проходу на каждую производную. + +Если же стоит задача найти производные функции $f: \real \to \real^m$, т.е. +```{math} +\frac{\partial f_j}{\partial x},\ j = 1, \dots, m, +``` +то автоматическому дифференцированию вперёд требуется всего один проход графа вычислений. + +В общем случае функции вида $f: \real^n \to \real^m$ автоматическое дифференцирование вперёд эффективно для вычисления матрицы Якоби при $n \ll m$. + +Кроме того, автоматическое дифференцирование вперёд не требует хранения графа вычислений в явном виде, поскольку проход(ы) по графу происходит только в одну сторону. +Другими словами, на практике для реализации нужен не сам граф вычислений, а лишь последовательность инструкций, которые строит компилятор. +Особенно удобно реализовывать дифференцирование вперёд на языках программирования, в которых можно перегрузить операторы и функции. +В этом мы убедились в {numref}`Разделе {number} ({name}) `. + +Возможность не хранить граф вычислений актуальна для задач с большим количеством параметров, например, при минимизации функции ошибки. +В этом случае ограничение по памяти проще удовлетворить. + +Итак, автоматическое дифференцирование вперёд эффективно по памяти, быстро работает для вычисления строк матрицы Якоби, но медленно для вычисления её столбцов или градиента функции. +Однако, строки матрицы Якоби не так часто нужны на практике, как градиенты функций. +Поэтому для автоматического вычисления градиентов чаще используется дифференцирование назад, о котором речь пойдёт в следующем разделе. + +```{note} +Воспользоваться автоматическим дифференцированием вперёд в Julia можно, например, с помощью пакета [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl), {cite}`RevelsLubinPapamarkou2016`. +``` diff --git a/_sources/autodiff/index.md b/_sources/autodiff/index.md new file mode 100644 index 0000000..9f4ac4d --- /dev/null +++ b/_sources/autodiff/index.md @@ -0,0 +1,55 @@ +```{eval-rst} +.. meta:: + :description: Данный раздел посвящён автоматическому дифференцированию. + :keywords: дуальное число, автоматическое дифференцирование вперед, автоматическое дифференцирование назад, backward mode, reverse accumulation, forward mode, forward accumulation, autodiff, forwarddiff, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +# Автоматическое дифференцирование + +```{index} дифференцирование; автоматическое +``` +**Автоматическое дифференцирование** является способом вычисления производных функции, заданной программно. +Этот вид дифференцирования опирается на правило дифференцирования сложной функции, представление функции в виде последовательности элементарных операций и перегрузке программных инструкций (функций, операторов). + +Автоматическое дифференцирование не является численным дифференцированием. +Численное дифференцирование _приближает_ производную на основе её определения $f'(x) \approx (f(x) + f(x + \delta x)) / \delta x$. +В то время как автоматическое дифференцирование не требует введения шага $\delta x$, а производная вычисляется точно (в пределах машинной арифметики). + +Автоматическое дифференцирование не является символьным дифференцированием. +Символьное дифференцирование преобразовывает выражения и применяет правила дифференцирования, чтобы получить _выражение_ производной $f'(x)$. +Впоследствии полученное выражение можно _вычислить_ (и даже создать исходный код для производной). +В автоматическом дифференцировании отсутствует программное представление функции в виде математического (символьного) выражения. + +Сравнение способов дифференцирования показано на {numref}`Рисунке %s `. + +```{figure} static/baydin-2018-diff-approaches-overview.png +--- +name: autodiff:overview +width: 640px +--- + +Способы дифференцирования. +Символьное вычисление даёт точный результат, но требует преобразования кода `f` к closed-form; +численное дифференцирование неточно ввиду погрешностей метода и округления; +автоматическое дифференцирование точно и позволяет использовать управляющие конструкции языка. +Источник: {cite}`Baydin2015`. +``` + +```{note} +С автоматическим дифференцированием связано понятие "дифференцируемого" программирования (differential programming). +Это подход к написанию кода, который учитывает возможность автоматически дифференцировать запрограммированные функции. +``` + +В данной главе изложены темы дуальных чисел, графа вычислений, а также автоматического дифференцирования вперёд и назад. +Чтение главы вы можете начать с {numref}`Раздела {number} ({name}) `, пропустив {numref}`Раздел {number} ({name}) `. + +```{tip} +Подробнее с автоматическим дифференцированием вы можете ознакомиться в следующих работах. + +- {cite:ts}`KochenderferWheeler2019`. +- Дмитрий Кропотов. + Автоматическое дифференцирование. + ВМК МГУ, кафедра математических методов прогнозирования. + https://youtu.be/za2LgI8JFCw. +- {cite:ts}`Baydin2015`. +``` diff --git a/_sources/autodiff/oja_problem.md b/_sources/autodiff/oja_problem.md new file mode 100644 index 0000000..ae92a89 --- /dev/null +++ b/_sources/autodiff/oja_problem.md @@ -0,0 +1,51 @@ +```{eval-rst} +.. meta:: + :description: Данный раздел вкратце освещает задачу оптимального вычисления матрицы Якоби (optimal Jacobian accumulation). + :keywords: автоматическое дифференцирование, оптимальное вычисление, матрица якоби, autodiff, cross mode, mixed mode, optimal jacobian accumulation, автоматическое дифференцирование, производная, вычислительная математика, вычматы +``` + +# Оптимальное вычисление матрицы Якоби + +Напоследок, мы без подробностей затронем задачу оптимального вычисления матрицы Якоби (optimal Jacobian accumulation). + +Пусть дана функция $f: \real^n \to \real^m$ и стоит задача вычисления её матрицы Якоби +```{math} +J_{i j} = \frac{\partial f_i}{\partial x_j}(x_1, \dots, x_n), \quad i = 1, \dots, m,\ j = 1, \dots, n, +``` +за минимальное число операций. +Как нам уже известно, при $n \gg m$ эффективней по быстродействию использовать автоматическое дифференцирование назад, а в обратном случае $n \ll m$ --- дифференцирование вперёд. + +В общем случае можно учитывать структуру (топологию) графа вычислений и уменьшить количество вычислительной нагрузки. +Например, можно разделить весь граф вычислений на подграфы, каждый из которых определяет "часть" функции $f$. +Затем на каждом из участков графа использовать тот вид дифференцирования, который на нём эффективен. +В конце же остаётся "сшить" результаты вычислений, используя правило дифференцирования сложной функции. + +Мы продемонстрируем эту идею на функции с (очень) специфическим графом вычислений, показанном на {numref}`Рисунке %s `. + +```{figure} static/graph-cross-example.svg +:name: autodiff:cross:example + +Пример графа вычисления, для которого эффективно использовать оба вида дифференцирования. +Промежуточное значение $g$ является точкой сочленения. +``` + +В этом случае разумно использовать оба вида дифференцирования. +Для этого представим исходную функцию $\mathbf{f}$ в виде +```{math} +f_i = f_i(g(x_1, \dots, x_n)), \quad i = 1, \dots, m, +``` +где промежуточное значение $g$ является функцией $\real^n \to \real$. +Тогда производные (элементы матрицы Якоби) имеют вид + +```{math} +J_{i j} += \frac{\partial f_i}{\partial x_j} += \frac{\partial f_i}{\partial g} \frac{\partial g}{\partial x_j} +. +``` + +Производные $\partial g / \partial x_j$ эффективно вычисляются дифференцированием назад, поскольку $n \gg 1$. +В свою очередь, производные $\partial f_i / \partial g$ эффективно вычисляются дифференцированием вперёд ($1 \ll m$). + +Так, автоматические способы дифференцирования вперёд и назад являются лишь крайними вариантами обхода графа вычислений в соответствии с правилом дифференцирования сложной функции. + diff --git a/_sources/bibliography.md b/_sources/bibliography.md deleted file mode 100644 index 3ae5b44..0000000 --- a/_sources/bibliography.md +++ /dev/null @@ -1,4 +0,0 @@ -# Литература - -```{bibliography} -``` diff --git a/_sources/index.md b/_sources/index.md index 82cc6c7..3e21107 100644 --- a/_sources/index.md +++ b/_sources/index.md @@ -1,4 +1,20 @@ -# Предмет практикума +```{eval-rst} +.. meta:: + :description: В курсе рассматривается ряд задач теплофизики и необходимые для их решения вычислительные методы. Все задачи мы сопровождаем практикой, то есть, программированием. + :keywords: теплофизика, термодинамика, фазовое равновесие, вычислительная математика, вычматы, программирование, алгоритмы, julia +``` + + +# О практикуме + +```{epigraph} +Sapere aude (Дерзай знать) + +-- Девиз Московского Физико-Технического Института +``` + +**Практикум по вычислительной теплофизики** читается на кафедре физики высокотемпературных процессов [Московского Физико-Технического Института](https://mipt.ru/). +Авторы курса [Степан Захаров](https://scholar.google.ru/citations?user=xvp7Z9oAAAAJ) и [Василий Писарев](https://scholar.google.ru/citations?user=ZLTxwC8AAAAJ). В области ответственности теплофизики находится целый ряд задач. @@ -12,7 +28,8 @@ **Коэффициенты переноса.** Расчёт коэффициентов переноса для конкретных веществ или смесей. Примеры коэффициентов: теплопроводность, вязкость, диффузия, скорость звука, поверхностное натяжение. Без этих коэффициентов, как правило, не обходятся задачи гидродинамики. Без них также сложно оценить, какие течения преобладают, например, диффузивное или конвективное, ламинарное или турбулентное. -В свою очередь, каждая из этих задач имеет аналитическую постановку. Вот несколько задач, к которым так или иначе сводятся вышеперечисленные. +В свою очередь, каждая из этих задач имеет аналитическую постановку. +Вот несколько задач, к которым так или иначе сводятся вышеперечисленные. - Решение нелинейного скалярного уравнения $f(x) = 0$; - Интегрирование функции $\int f \diff x$; @@ -23,6 +40,15 @@ - Решение уравнений и систем уравнений в частных производных $f_t + f_x = 0$, $f_t + (\kappa f_x)_x = 0$, $f_{xx} = g(x)$; - Задача условной и безусловной оптимизации $\mathbf{x}^*\in\Omega: f(\mathbf{x}^*) = \min_\Omega f(\mathbf{x})$. -*Однако, есть трудность*: реальные системы описываются нелинейными уравнениями и зависимостями, поэтому только в редких частных случаях можно аналитически решить задачи выше. В общем случае, эти задачи решаются вычислительными (дискретными) методами. +*Однако, есть трудность*: реальные системы описываются нелинейными уравнениями и зависимостями, поэтому только в редких частных случаях можно аналитически решить задачи выше. +В общем случае, эти задачи решаются вычислительными (дискретными) методами. + +В курсе мы рассмотрим некоторые задачи теплофизики и необходимые для их решения вычислительные методы. +Все задачи мы сопровождаем практикой, то есть, программированием. + + +```{tip} +Сообщить об ошибке в материалах курса можно через [Телеграмм](https://red_deer.t.me) или GitHub {guilabel}`Иконка сверху → Open issue`. -Именно вычислительным методам посвящён настоящий практикум. При этом мы будем делать упор на реализацию методов и применение их к теплофизическим задачам. +Если вы хотите воспользоваться материалами курса не в учебных целях, то обратитесь к авторам курса. +``` diff --git a/_sources/integration/adaptive.ipynb b/_sources/integration/adaptive.ipynb deleted file mode 100644 index dcc67dd..0000000 --- a/_sources/integration/adaptive.ipynb +++ /dev/null @@ -1,927 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "4ba7fa53", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "8b30a5f2", - "metadata": {}, - "source": [ - "(chapter_integration_adaptive)=\n", - "# Адаптивное интегрирование\n", - "\n", - "Рассмотренные ранее методы интегрирования, не считая метода Гаусса, используют равномерные сетки. Взглянем на следующий пример.\n", - "\n", - "(demo_adapt_badcase)=\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Допустим, нам нужно проинтегрировать функцию $x \\sin(2x/(x-2))$. Её график выглядит следующим образом" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "ff968b64", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/integration/adaptive_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = x * sin(2x/(x-2))\n", - "plot(foo, 0, 1.85; xlabel=L\"x\", ylabel=L\"f(x)\", label=\"\")" - ] - }, - { - "cell_type": "markdown", - "id": "e74e82bc", - "metadata": {}, - "source": [ - "Видно, что данная функция по-разному \"изменчива\" на разных участках:\n", - "\n", - "- справа разрешение колебания требует мелкую сетку, причём, чем ближе к $x=2$, тем мельче;\n", - "- слева же функция меняется плавно, поэтому подойдёт и крупная сетка. \n", - "\n", - "Применение метода, основанного на равномерной сетке, при высокой точности приводит к перевычислениям.\n", - "Например, для метода Ромберга получим" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d5b68712", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "((-0.3865423776775579, 7), (0.043384162370539096, 12), (-0.3420434608094782, 13))" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = x * sin(2x/(x-2))\n", - "r01 = rombergwstep(foo, 0, 1; atol=1e-6)\n", - "r12 = rombergwstep(foo, 1, 1.999; atol=1e-6)\n", - "r02 = rombergwstep(foo, 0, 1.999; atol=1e-6)\n", - "r01, r12, r02" - ] - }, - { - "cell_type": "markdown", - "id": "62e219fc", - "metadata": {}, - "source": [ - "`rombergwstep` отличается от {numref}`Функции {number} (romberg) ` только тем, что возвращает кортеж `(I[1, i], i)`. То есть, вычисления слева можно было бы закончить уже после 7 разбиений, однако при вычислении на всём участке потребовалось уже 13 разбиений.\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "```{index} алгоритм; адаптивный\n", - "```\n", - "Алгоритмы, которые обнаруживают подобное поведение и подбирают сетку автоматически, называются **адаптивными**.\n", - "\n", - "## Идея\n", - "\n", - "Изложенную здесь идею подробнее можно почитать, например, здесь {cite}`SamarskiyGulin1989`, {cite}`fnc2017`.\n", - "\n", - "Допустим, мы вычисляем часть интеграла на отрезке $\\int_{x_{i-1}}^{x_i} f\\diff x$. Чтобы понять, нужно ли дробить отрезок для повышения точности, можно рассмотреть два приближения интеграла и сравнить их. Если разница не удовлетворяет заданной \"точности\", то отрезок $[x_{i-1}, x_i]$ дробится пополам, а вычисления по *тем же* квадратурам происходят уже на более мелких отрезках.\n", - "\n", - "Два приближения вычислим по формулам Симпсона {eq}`simp_final` на разных сетках\n", - "\n", - "```{math}\n", - "\\begin{align}\n", - "S_f(h/2) &= \\frac{1}{3}\\big[4T_f(h/2) - T_f(h)\\big],\\\\\n", - "S_f(h/4) &= \\frac{1}{3}\\big[4T_f(h/4) - T_f(h/2)\\big],\\\\\n", - "h &= x_i - x_{i-1}.\n", - "\\end{align}\n", - "```\n", - "\n", - "Всего на шаге интегрирования потребуется 5 вычислений функции $f$ в точках $x_{i-1}$, $x_{i-1} + h/4$, $x_{i-1} + h/2$, $x_{i-1} + 3h/4$, $x_i$ для получения $T_f(h)$, $T_f(h/2)$ и $T_f(h/4)$.\n", - "\n", - "```{margin}\n", - "Формула Ромберга получается из экстраполяции Ричардсона.\n", - "```\n", - "Формула Симпсона имеет четвёртный порядок сходимости, а следующая за ней в экстраполяции формула Ромберга $R_f$\n", - "\n", - "```{math}\n", - "R_f(h/4) = \\frac{1}{15}\\big[16 S_f(h/4) - S_f(h/2) \\big]\n", - "```\n", - "\n", - "имеет уже шестой порядок сходимости.\n", - "\n", - "Приближениями $S_f(h/4)$, $R_f(h/4)$ воспользуемся для апостериорной оценки погрешности\n", - "\n", - "```{math}\n", - "E = R_f(h/4) - S_f(h/4) = \\frac{S_f(h/4) - S_f(h/2)}{15},\n", - "```\n", - "\n", - "которую и будем использовать для критерия разбиения отрезка.\n", - "\n", - "*Критерий разбиения* нужно выбирать аккуратно. Дело в том, что по значению входных данных (т.е. функции $f$ и отрезка) нельзя оценить величину интеграла: будет ли она маленькой или большой. Поэтому полагаться нужно сразу на относительную $\\delta_r$ и абсолютную $\\delta_a$ \"точности\"\n", - "\n", - "```{math}\n", - ":label: int_adaptive_criterion\n", - "\n", - "|E| < \\delta_a + \\delta_r |S_f(h/4)|.\n", - "```\n", - "\n", - "Если приближение к интегралу $S_f \\approx 0$ мало, то работает абсолютная погрешность $\\delta_a$. Если же $S_f$ велико, то {eq}`int_adaptive_criterion` требует, чтобы разница приближений $|E|$ составляла меньше некоторой части $\\delta_r$ от приближения $|S_f|$.\n", - "\n", - "## Реализация\n", - "\n", - ":::{proof:function} intadapt\n", - "\n", - "**Адаптивное интегрирование**\n", - "\n", - "```julia\n", - "\"\"\"\n", - " intadapt(f, a, b, tol[, xtol=eps()])\n", - "\n", - "Адаптивно вычисляет ∫`f`dx на отрезке [`a`, `b`]. Точность приближения `E` на подотрезке \n", - "контролируется `tol`. Участок сетки не может быть мельче `xtol`.\n", - "Возвращает величину интеграла и сетку. Если точность не может быть достигнута,\n", - "вызывает ошибку.\n", - "\"\"\"\n", - "function intadapt(f, a, b, tol, xtol=eps(), fa=f(a), fb=f(b), m=(b-a)/2, fm=f(m))\n", - " if a > b; a, b = b, a; end\n", - " \n", - " xl = (a + m)/2; fl = f(xl) # расположение:\n", - " xr = (m + b)/2; fr = f(xr) # a -- xl -- m -- xr -- b\n", - " \n", - " T = Vector{Float64}(undef, 3)\n", - " h = b - a\n", - " T[1] = h * (fa + fb)/2\n", - " T[2] = T[1]/2 + h/2 * fm\n", - " T[3] = T[2]/2 + h/4 * (fl + fr)\n", - " S = (4*T[2:end] - T[1:2]) / 3\n", - "\n", - " err = (S[2] - S[1]) / 15\n", - " \n", - " if abs(err) < tol * (1 + tol * abs(S[2]))\n", - " Q = S[2]\n", - " nodes = [a, xl, m, xr, b]\n", - " else\n", - " b - a ≤ xtol && error(\"Достигнут предел точности отрезка интегрирования `xtol`.\")\n", - " Ql, nodesl = intadapt(f, a, m, tol, xtol, fa, fm, xl, fl)\n", - " Qr, nodesr = intadapt(f, m, b, tol, xtol, fm, fb, xr, fr)\n", - " Q = Ql + Qr\n", - " nodes = [nodesl; nodesr[2:end]]\n", - " end\n", - " return (Q, nodes)\n", - "end\n", - "```\n", - ":::\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Посмотрим, как наш алгоритм справляется с ситуацией из {numref}`Демонстрации {number} `" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "b2d5aeab", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/integration/adaptive_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "a, b = 0, 1.85\n", - "foo(x) = x * sin(2x/(x-2))\n", - "Q, nodes = intadapt(foo, a, b, 1e-4)\n", - "plot(; layout=(2,1), xlabel=L\"x\", leg=:topleft, linewidth=2)\n", - "plot!(foo, a, b; label=\"функция\", linewidth=2, linecolor=:red)\n", - "plot!(nodes, foo.(nodes);\n", - " label=\"узлы интегрирования\",\n", - " seriestype=:sticks,\n", - " marker=(:o, 2, :lightblue),\n", - " linecolor=:blue,\n", - ")\n", - "histogram!(nodes;\n", - " label=\"распределение числа узлов\",\n", - " subplot=2,\n", - " bins=range(a, b; length=9),\n", - " link=:x,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "18a6bdf8", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 33, - 36, - 46, - 52, - 165, - 183 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/integration/adaptive.md b/_sources/integration/adaptive.md index a7829ae..2f455d9 100644 --- a/_sources/integration/adaptive.md +++ b/_sources/integration/adaptive.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим адаптивное численное интегрирование. + :keywords: адаптивное интегрирование, неравномерная сетка, численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -184,4 +192,4 @@ histogram!(nodes; ```{raw} html -``` \ No newline at end of file +``` diff --git a/_sources/integration/ex.md b/_sources/integration/ex.md index 1b20e49..0706637 100644 --- a/_sources/integration/ex.md +++ b/_sources/integration/ex.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему численного интегрирования. + :keywords: задачи, упражнения, численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + # Задания ## Вычислите интеграл diff --git a/_sources/integration/gauss.md b/_sources/integration/gauss.md index e3e114e..f05b25d 100644 --- a/_sources/integration/gauss.md +++ b/_sources/integration/gauss.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Численное интегрирование по квадратурным формулам Гаусса, Кронрода и Лобатто. + :keywords: кронрод, лобатто, метод гаусса, численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + # Формулы Гаусса В {numref}`Разделе {number} ` мы видели, что веса квадратуры $\{w_i\}$ с известными узлами $\{x_i\}$ могут быть найдены решением линейной системы уравнений @@ -69,9 +75,11 @@ f \cdot g = \int\limits_{-1}^{1} f(x) g(x) \diff x. ``` Как известно из матанализа, для многочленов ортонормированный базис составляют *многочлены Лежандра* +```{index} многочлен Лежандра +``` ```{math} -L_k(x) = \frac{1}{2^n n!} \frac{d^k}{dx^k}(x^2 - 1)^k. +L_k(x) = \frac{1}{2^k\ k!} \frac{d^k}{dx^k}(x^2 - 1)^k. ``` Значит, в качестве $\Omega_N$ возьмём $L_N$, чтобы удовлетворить {eq}`gauss_orthogonal` для полиномов $q_{M-N}$ как можно более высокой степени. Тогда, если степень $q_{M-N}$ не превосходит $M-N \le N-1$, т.е. $M \le 2N-1$, то {eq}`gauss_orthogonal` выполнится, т.е. @@ -275,4 +283,4 @@ L_{M+1}(x) = \frac{2M + 1}{M + 1} x L_M(x) - \frac{M}{M + 1} L_{M-1}(x), \int\limits_{-5}^{5} \frac{\diff x}{1 + x^2} ``` при помощи формул Гаусса по 7 точкам ($G_7$) и Гаусса-Кронрода по 15 точкам ($K_{15}$). - Даёт ли величина $\vert G_7 - K_{15}\vert$ хорошую оценку погрешности численного интегрирования? \ No newline at end of file + Даёт ли величина $\vert G_7 - K_{15}\vert$ хорошую оценку погрешности численного интегрирования? diff --git a/_sources/integration/index.md b/_sources/integration/index.md index 594c52a..30750f9 100644 --- a/_sources/integration/index.md +++ b/_sources/integration/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу численного интегрирования функции и основные методы её решения. + :keywords: численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + # Численное интегрирование В математическом анализе рассматривается задача нахождения определённого интеграла diff --git a/_sources/integration/newton_cotes.ipynb b/_sources/integration/newton_cotes.ipynb deleted file mode 100644 index 1888cdb..0000000 --- a/_sources/integration/newton_cotes.ipynb +++ /dev/null @@ -1,1386 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "dc0f6c6d", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "83ec018d", - "metadata": {}, - "source": [ - "(chapters:integration:newton-cotes)=\n", - "# Формулы Ньютона-Котса\n", - "\n", - "Рассмотрим задачу приближения интеграла\n", - "```{math}\n", - "I = \\int\\limits_{0}^{1} f(x) \\diff x\n", - "```\n", - "\n", - "Очевидный способ -- ввести равномерную сетку $\\{x_i = \\frac{i-1}{N-1}, i = 1, \\dots, N\\}$ или $\\{x_i = \\frac{i - 1/2}{N}, i = 1, \\dots, N\\}$, вычислить полиномиальную интерполяцию подынтегральной функции по значениям в этих точках и взять значение интеграла от полиномиальной интерполяции за приближение к интегралу $I$.\n", - "\n", - "```{index} формула; Ньютона-Котса\n", - "```\n", - "Получаемые таким образом квадратурные формулы называются **формулами Ньютона-Котса**. Два выбора узлов интерполяции соответствуют *закрытым* (концы отрезка входят в множество узлов) и *открытым* (концы отрезка не входят во множество узлов) формулам.\n", - "\n", - "Веса формул Ньютона-Котса определяются из условия, что формула с $N$ узлами должна давать точное значение интеграла для всех многочленов степени ниже $N$, в частности, для \"чистых\" степеней $x^p$:\n", - "\n", - "```{math}\n", - "\\sum\\limits_{i=1}^{N} w_i x_i^p = \\int\\limits_{0}^{1} x^p \\diff x = \\frac{1}{p + 1} \\quad\\forall p \\in \\{0, \\dots, N-1\\}\n", - "```\n", - "\n", - "Это условие дает линейную систему:\n", - "\n", - "```{math}\n", - ":label: NewtonCotesGeneral\n", - "\n", - "\\left(\n", - "\\begin{array}{cccc}\n", - " 1 & 1 & \\dots & 1 \\\\\n", - "x_1 & x_2 & \\dots & x_N \\\\\n", - "x_1^2 & x_2^2 & \\dots & x_N^2 \\\\\n", - "\\vdots & \\vdots& & \\vdots\\\\\n", - "x_1^{N-1} & x_2^{N-1} & \\dots & x_N^{N-1}\n", - "\\end{array}\n", - "\\right) \n", - "\\left(\n", - "\\begin{array}{c}\n", - "w_1 \\\\\n", - "w_2 \\\\\n", - "w_3 \\\\\n", - "\\vdots \\\\\n", - "w_N\n", - "\\end{array}\n", - "\\right) = \n", - "\\left(\n", - "\\begin{array}{c}\n", - "1 \\\\\n", - "1 / 2 \\\\\n", - "1 / 3 \\\\\n", - "\\vdots \\\\\n", - "1 / N\n", - "\\end{array}\n", - "\\right)\n", - "```\n", - "\n", - "```{index} квадратура; алгебраический порядок\n", - "```\n", - "Говорят, что квадратурная формула имеет **алгебраический порядок** $p$, если она точна для всех многочленов степени $p$ и меньше. Из формулы для вычисления весов видно, что квадратура Ньютона-Котса с $N$ узлами имеет алгебраический порядок как минимум $N-1$. Однако из симметрии задачи легко показать, что веса удовлетворяют условию $w_i = w_{N-i+1}$. Это приводит к тому, что формулы с нечетным $N$ приобретают \"дополнительный\" порядок точности и имеют алгебраический порядок $N$ (это легко видеть, заметив, что для отрезка $[-1; 1]$ квадратурная формула дает ноль для нечётных функций, т.е. интегрирует их точно, а функция $f(x) = x^N$ -- нечётная при нечётном $N$). \n", - "\n", - "Кажется, что точность формул Ньютона-Котса растет с повышением порядка, но при расчетах с конечной точностью это не так. При повышении степени в этих формулах появляются отрицательные веса, что приводит к численной неустойчивости. Поэтому в основном применяются формулы Ньютона-Котса низких порядков. В этом случае лучше брать закрытые формулы, т.к. конечная точка одного подотрезка является начальной точкой следующего, что экономит одно вычисление подынтегральной функции по сравнению с открытыми формулами того же порядка точности. Тем не менее, если на одном из концов отрезка функция имеет особенность, применение открытых формул позволяет избежать её вычисления в этой точке.\n", - "\n", - "Ниже приведены некоторые составные квадратурные формулы Ньютона-Котса.\n", - "\n", - "## Формула прямоугольников\n", - "\n", - "Для открытой формулы с 1 узлом (т.е. подынтегральная функция приближается константой):\n", - "\n", - "```{index} формула; средних прямоугольников\n", - "```\n", - "```{margin}\n", - "Существуют также формулы левых и правых прямоугольников, но у них хуже точность.\n", - "```\n", - "```{math}\n", - "\\int_{x_{i-1}}^{x_i} f(x)\\diff x \\approx (x_i - x_{i-1})f(x_{i-1/2}),\\quad x_{i-1/2} = \\frac{x_{i-1} + x_i}{2}.\n", - "```\n", - "\n", - "Эту формулу называют формулой **средних прямоугольников** (*midpoint rule*).\n", - "\n", - "**Составная формула прямоугольников** имеет вид\n", - "\n", - "```{math}\n", - "\\int_a^b f(x)\\diff x \\approx \\sum_{i=1}^n h \\cdot f(x_i),\\quad x_i = a + (i - 1/2)h, \\quad h = \\frac{b - a}{n}.\n", - "```\n", - "\n", - "```{margin}\n", - "`start:step:stop` означает диапазон точек с шагом `step`, начинающийся со `start`, последнее значение в котором меньше или равно `stop`.\n", - "\n", - "`sum(f, x)` вычисляет сумму значений функции `f` на массиве `x`.\n", - "```\n", - ":::{proof:function} midpoint\n", - "\n", - "**Формула прямоугольников**\n", - "\n", - "```julia\n", - "\"\"\"\n", - "Вычисляет по формуле прямоугольников интеграл ∫`f`dx на отрезке [`a`, `b`]\n", - "с равномерной сеткой из `n` интервалов.\n", - "Возвращает значение интеграла, узлы и значения функции в узлах.\n", - "\"\"\"\n", - "function midpoint(f, a, b, n)\n", - " h = (b - a) / n\n", - " x = range(a + h/2, b; step=h)\n", - " int = h * sum(f, x)\n", - " return int\n", - "end\n", - "```\n", - ":::\n", - "\n", - ":::{proof:demo}\n", - ":::\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Ниже представлены графики численного интеграла\n", - "\n", - "```{math}\n", - "\\int_0^3 x e^{\\sin 2x}\n", - "```\n", - "\n", - "для разного числа точек." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "85a0e946", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/integration/newton_cotes_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = x * exp(sin(2x))\n", - "plt = plot(layout=(3,1), leg=:none, xlabel=L\"x\")\n", - "for (i, n) in enumerate((1, 4, 8))\n", - " plot!(foo, 0, 3; subplot=i, linewidth=2, linecolor=:red)\n", - " \n", - " h = 3/n\n", - " x = [h/2 + i * h for i in 0:n-1]\n", - " y = foo.(x)\n", - " for (px, py) in zip(x, y)\n", - " h = 3 / n\n", - " plot!([px-h/2, px+h/2], [py, py];\n", - " subplot=i, fill=(0, 0.1, :blue), linecolor=:blue, linewidth=2\n", - " )\n", - " end\n", - " scatter!(x, y; subplot=i, marker=:o, markercolor=:lightblue)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "a62662f1", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Можно показать {cite}`SamarskiyGulin1989`, что составная формула прямоугольников имеет *второй порядок сходимости*\n", - "\n", - "```{math}\n", - "|\\tau_f(h)| \\le \\frac{h^2(b-a)}{24} \\max_{x\\in [a,b]} |f''(x)| \\sim O(h^2).\n", - "```\n", - "\n", - "При этом отсюда видно, что ошибка становится *нулевой* для линейных функций (для них $f'' \\equiv 0$).\n", - "\n", - "## Формула трапеций\n", - "\n", - "Если аппроксимировать функцию на отрезке $[x_{i-1}, x_{i}]$ прямой, проходящей через значения на концах отрезка, то получим **формулу трапеций** (*trapezoidal rule*)\n", - "\n", - "```{index} формула; трапеций\n", - "```\n", - "```{math}\n", - "\\int_{x_{i-1}}^{x_i} f(x)\\diff x \\approx \\frac{f(x_{i-1}) + f(x_i)}{2} h.\n", - "```\n", - "\n", - "Та же формула получается из {eq}`NewtonCotesGeneral`, если взять узлы $x_1=0$ и $x_2=1$:\n", - "```{math}\n", - "\\left(\n", - "\\begin{array}{cc}\n", - " 1 & 1 \\\\\n", - " 0 & 1\n", - "\\end{array}\n", - "\\right)\n", - "\\left(\n", - "\\begin{array}{c}\n", - "w_1 \\\\\n", - "w_2\n", - "\\end{array}\n", - "\\right) = \n", - "\\left(\n", - "\\begin{array}{c}\n", - "1 \\\\\n", - "1 / 2\n", - "\\end{array}\n", - "\\right) \\Rightarrow\n", - "\\left(\n", - "\\begin{array}{c}\n", - "w_1 \\\\\n", - "w_2\n", - "\\end{array}\n", - "\\right) = \n", - "\\left(\n", - "\\begin{array}{c}\n", - "1 / 2 \\\\\n", - "1 / 2\n", - "\\end{array}\n", - "\\right)\n", - "```\n", - "```{index} формула; трапеций (составная)\n", - "```\n", - "Просуммировав {eq}`quadrature_composite`, получим **составную формулу трапеций** для отрезка $[a, b]$:\n", - "\n", - "```{math}\n", - "\\int_a^b f(x)\\diff x \\approx T_f = h \\left(\\frac{1}{2} f(x_0) + f(x_1) + f(x_2) + ... + f(x_{n-1}) + \\frac{1}{2}f(x_n)\\right).\n", - "```\n", - "\n", - "Из формулы трапеций выводятся многие усовершенствованные методы. Ниже дана реализация.\n", - "\n", - "(function-trapezoid)=\n", - ":::{proof:function} trapezoid\n", - "\n", - "**Формула трапеций**\n", - "\n", - "```julia\n", - "\"\"\"\n", - "Вычисляет по формуле трапеций интеграл ∫`f`dx на отрезке [`a`, `b`]\n", - "с равномерной сеткой из `n` интервалов.\n", - "Возвращает значение интеграла.\n", - "\"\"\"\n", - "function trapezoid(f, a, b, n)\n", - " x = range(a, b; length=n+1)\n", - " h = step(x)\n", - " if isone(n)\n", - " int = h * (f(x[1]) + f(x[2])) / 2\n", - " else\n", - " @views int = h * (sum(f, x[2:n]) + (f(x[1]) + f(x[n+1])) / 2)\n", - " end\n", - " return int\n", - "end\n", - "```\n", - "```{note}\n", - ":class: dropdown\n", - "\n", - "Макрос `@view x[m:n]` создаёт вместо среза массива объект-подмассив, ссылающийся на ту же область памяти, что и `x` (см. [Views](https://docs.julialang.org/en/v1/base/arrays/#Views-(SubArrays-and-other-view-types))).\n", - "\n", - "Макрос `@views expr` преобразовывает все \"срезы\" внутри выражения `expr` во view-объекты.\n", - "\n", - "Чтобы избежать ветвления, можно написать `int = h * (sum(f, x) - (f(x[1]) + f(x[2])) / 2)`.\n", - "```\n", - ":::\n", - "\n", - ":::{proof:demo}\n", - ":::\n", - "```{raw} html\n", - "
\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0cb7933c", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/integration/newton_cotes_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = x * exp(sin(2x))\n", - "a, b = 0, 3\n", - "plt = plot(layout=(3,1), leg=:none, xlabel=L\"x\")\n", - "for (i, n) in enumerate((1, 4, 8))\n", - " x = range(a, b; length=n+1)\n", - " y = foo.(x)\n", - " plot!(foo, a, b; subplot=i,linewidth=2, linecolor=:red)\n", - " plot!(x, y; subplot=i, fill=(0, 0.1, :blue), linecolor=:blue, linewidth=2)\n", - " scatter!(x, y; subplot=i, marker=:o, markercolor=:lightblue)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "017a52f1", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Для составной формулы трапеций можно показать {cite}`SamarskiyGulin1989`, что\n", - "\n", - "```{math}\n", - "|I - T_f| \\le \\frac{h^2(b-a)}{12} \\max_{x\\in[a,b]} f''(x) \\sim O(h^2).\n", - "```\n", - "\n", - "Таким образом, она обладает вторым порядком точности, как и формула прямоугольников. И также точно приближает интеграл от линейной функции.\n", - "\n", - "(sec:quadrature_simpson)=\n", - "## Формула Симпсона\n", - "\n", - "Формулу Симпсона несложно получить, решив {eq}`NewtonCotesGeneral` для $x_1 = 0, x_2 = 1/2, x_3 = 1$, \n", - "что соответствует интерполяции $f(x)$ параболой по трём точкам.\n", - "Однако можно взглянуть на вывод этой формулы с другой стороны, на основе экстраполяции Ричардсона.\n", - "\n", - "Для формулы трапеций на основе разложения Тейлора можно показать, что\n", - "\n", - "```{math}\n", - ":label: simp_step1\n", - "\n", - "I = T_f(h) + c_1 h^2 + O(h^4),\n", - "```\n", - "\n", - "где $c_1$ не зависит от $h$.\n", - "\n", - "Если мы проведём расчёт на сетке вдвое мельче, то получим\n", - "\n", - "```{math}\n", - ":label: simp_step2\n", - "\n", - "I = T_f(h/2) + c_1 \\left(\\frac{h}{2}\\right)^2 + O(h^4).\n", - "```\n", - "\n", - "Комбинируя выражения {eq}`simp_step1` и {eq}`simp_step2` так, чтобы исключить главный член погрешности $c_1 h^2$, получим\n", - "\n", - "```{math}\n", - ":label: simp_bigo\n", - "I = \\frac{1}{3} \\big[4 T_f(h/2) - T_f(h)\\big] + O(h^4).\n", - "```\n", - "\n", - "Таким образом получена уточнённая оценка интеграла. Если сумма $T_f(h)$ вычислена для $h = b - a$, то\n", - "```{index} формула; Симпсона\n", - "```\n", - "```{math}\n", - ":label: simp_final\n", - "\\begin{split}\n", - "S_f(h) &= \\frac{1}{3} \\big[4 T_f\\left(\\frac{h}{2}\\right) - T_f(h)\\big] \\\\\n", - "&= \\frac{1}{3} \\left[\n", - "4 \\left(\\frac{\\tilde{f}(0)}{2} + \\tilde{f}\\left(\\frac{h}{2}\\right) + \\frac{\\tilde{f}(h)}{2}\\right)\\frac{h}{2} - \n", - "h\\frac{\\tilde{f}(0) + \\tilde{f}(h)}{2}\n", - "\\right] \\\\\n", - "&= \\frac{h}{6} \\big[ \\tilde{f}(0) + 4 \\tilde{f}\\left(\\frac{h}{2}\\right) + \\tilde{f}(h)\\big],\n", - "\\end{split}\n", - "```\n", - "\n", - "где введено обозначение\n", - "\n", - "```{math}\n", - "\\tilde{f}(x) = f(a + x).\n", - "```\n", - "\n", - "Веса в {eq}`simp_final` в точности совпадают с решением {eq}`NewtonCotesGeneral` для $x_1 = 0, x_2 = 1/2, x_3 = 1$. \n", - "Полученное приближение называется **квадратурной формулой Симпсона** (*Simpson's rule*). Из вывода {eq}`simp_step1`--{eq}`simp_bigo` видно, \n", - "что она имеет чётвертый порядок сходимости. Более точная оценка {cite}`SamarskiyGulin1989`\n", - "\n", - "```{math}\n", - "|I - S_f(h)| \\le \\frac{h^4 (b-a)}{2880} \\sup_{x\\in [a,b]} f^{IV}(x) \\sim O(h^4).\n", - "```\n", - "\n", - "Отсюда видно, что формула Симпсона приближает точно интеграл от многочленов степени не выше третьей.\n", - "```{index} формула; Симпсона (составная)\n", - "```\n", - "Приведём также явный вид **составной формулы Симпсона**\n", - "\n", - "```{margin}\n", - "Можно избавиться от дробных индексов, если ввести сетку $x_i = a_i + 0.5 h i$, $i=0,..,2n$.\n", - "```\n", - "```{math}\n", - "\\begin{align}\n", - "\\int_a^b f(x) \\diff x \\approx S_f(h) &= \\sum\\limits_{i=1}^{n} \\frac{h}{6}(f_{i-1} + 4 f_{i-1/2} + f_i) \\\\\n", - "&= \\frac{h}{6}\\big[f_0 + f_n + 2 (f_1 + f_2 + ... + f_{n-1}) + 4 (f_{1/2} + f_{3/2} + ... + f_{n-1/2}) \\big].\n", - "\\end{align}\n", - "```\n", - "\n", - "Ниже дана реализация на основе {numref}`Функции {number} `.\n", - "\n", - ":::{proof:function} simpson\n", - "\n", - "**Формула Симпсона**\n", - "\n", - "```julia\n", - "\"\"\"\n", - "Вычисляет по формуле Симпсона интеграл ∫`f`dx на отрезке [`a`, `b`]\n", - "с равномерной сеткой из `n` (чётное) интервалов.\n", - "Возвращает значение интеграла.\n", - "\"\"\"\n", - "function simpson(f, a, b, n)\n", - " return (1/3) * (4*trapezoid(f, a, b, n) - trapezoid(f, a, b, n÷2))\n", - "end\n", - "```\n", - ":::\n", - "\n", - ":::{proof:demo}\n", - ":::\n", - "```{raw} html\n", - "
\n", - "```\n", - "**Сравнение формул**\n", - "\n", - "Ниже представлены графики численного интеграла\n", - "\n", - "```{math}\n", - "\\int_0^3 x e^{\\sin 2x}\n", - "```\n", - "\n", - "в зависимости от числа интервалов $n$ для разных формул." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "eb42085d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/integration/newton_cotes_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = x * exp(sin(2x))\n", - "a, b = 0, 3\n", - "simp(n) = simpson(foo, a, b, n)\n", - "trap(n) = trapezoid(foo, a, b, n)\n", - "midp(n) = midpoint(foo, a, b, n)\n", - "n = 4:2:26\n", - "plot(n, trap.(n); marker=:o, label=\"формула трапеций\", xlabel=\"число отрезков\", ylabel=\"интеграл\")\n", - "plot!(n, simp.(n); marker=:o, label=\"формула Симпсона\")\n", - "plot!(n, midp.(n); marker=:o, label=\"формула прямоугольников\")" - ] - }, - { - "cell_type": "markdown", - "id": "7de51956", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Упражения\n", - "\n", - "1. Ниже приведена заготовка функции, находящей узлы и коэффициенты формулы Ньютона-Котса, точной для многочлена степени $p$.\n", - " Заполните пропуски `⟨...⟩`\n", - "\n", - " ```{code-block} julia\n", - " :emphasize-lines: 8,10,12\n", - "\n", - " \"\"\"\n", - " Находит узлы и веса формулы Ньютона-Котса с числом узлов `nnodes` на отрезке `[0; 1]`.\n", - " Если аргумент `closed=true` (по умолчанию), то расчет делается для \n", - " закрытых квадратурных формул, иначе - для открытых\n", - " \"\"\"\n", - " function newton_cotes_nodes_weights(nnodes::Integer; closed::Bool=true)\n", - " if closed\n", - " nodes = range(⟨...⟩)\n", - " else\n", - " nodes = range(⟨...⟩)\n", - " end\n", - " rhp = ⟨...⟩\n", - " w = (vandermonde(nodes))' \\ rhp\n", - " return (nodes=nodes, weights=w)\n", - " end\n", - " ```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 140, - 158, - 262, - 274, - 396, - 406 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/integration/newton_cotes.md b/_sources/integration/newton_cotes.md index 73a11df..60b259e 100644 --- a/_sources/integration/newton_cotes.md +++ b/_sources/integration/newton_cotes.md @@ -4,17 +4,26 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Численное интегрирование методами Ньютона (Ньютона-Котса) и Симпсона, а также по формулам прямоугольника и трапеций. + :keywords: метод ньютона, метод ньютона-котса, формула прямоугольников, метод трапеций, формула симпсона, метод Симпсона, экстраполяция Ричардсона, численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] include("../src.jl") ``` + (chapters:integration:newton-cotes)= # Формулы Ньютона-Котса @@ -156,6 +165,7 @@ for (i, n) in enumerate((1, 4, 8)) end plt ``` + ```{raw} html ``` @@ -259,6 +269,7 @@ end ```{raw} html
``` + ```{code-cell} foo(x) = x * exp(sin(2x)) a, b = 0, 3 @@ -272,6 +283,7 @@ for (i, n) in enumerate((1, 4, 8)) end plt ``` + ```{raw} html
``` @@ -404,6 +416,7 @@ plot(n, trap.(n); marker=:o, label="формула трапеций", xlabel="ч plot!(n, simp.(n); marker=:o, label="формула Симпсона") plot!(n, midp.(n); marker=:o, label="формула прямоугольников") ``` + ```{raw} html ``` @@ -431,4 +444,4 @@ plot!(n, midp.(n); marker=:o, label="формула прямоугольнико w = (vandermonde(nodes))' \ rhp return (nodes=nodes, weights=w) end - ``` \ No newline at end of file + ``` diff --git a/_sources/integration/romberg.md b/_sources/integration/romberg.md index 5cc6f67..0e04337 100644 --- a/_sources/integration/romberg.md +++ b/_sources/integration/romberg.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Численное интегрирование методом Ромберга. + :keywords: метод ромберга, экстраполяция ричардсона, численное интегрирование, квадратура, квадратурная формула, вычислительная математика, вычматы +``` + # Метод Ромберга *Метод Ромберга* (*Romberg's method*) позволяет быстро интегрировать с заданной точностью. Метод основывается на применении экстраполяции Ричардсона к формуле трапеций при удвоении числа узлов. diff --git a/_sources/interpolation/cubic_spline.ipynb b/_sources/interpolation/cubic_spline.ipynb deleted file mode 100644 index 79c3c4d..0000000 --- a/_sources/interpolation/cubic_spline.ipynb +++ /dev/null @@ -1,972 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "eb1592ae", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: Precompiling Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]\n", - "└ @ Base loading.jl:1342\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: Precompiling PrettyTables [08abe8d2-0d0c-5749-adfa-8a2ac140af0d]\n", - "└ @ Base loading.jl:1342\n" - ] - }, - { - "data": { - "text/plain": [ - "spinterp" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"interpolation.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "c235f659", - "metadata": {}, - "source": [ - "# Кубические сплайны\n", - "\n", - "Кусочно-линейный интерполянт непрерывен, но имеет разрывную производную. Можно построить интерполянт с более гладкими свойствами.\n", - "\n", - "```{index} интерполяция; кубическим сплайном\n", - "```\n", - "```{index} кубический сплайн\n", - "```\n", - "(definition_cubicspline)=\n", - "```{proof:definition} Кубический сплайн\n", - "**Кубический сплайн** $S(x)$ это кусочно-кубическая функция, при этом дважды непрерывно-дифференцируемая на всём интервале интерполяции.\n", - "```\n", - "\n", - "Допустим, задана $n+1$ абсцисса $t_0 < t_1 < ... < t_n$ с соответствующими значениями $y_0, y_1, ..., y_n$. На каждом из $n$ отрезков $[t_{k-1}, t_k]$ сплайн $S_k(x)$ имеет вид\n", - "\n", - "```{math}\n", - ":label: spline\n", - "\n", - "S_k(x) = a_k + (x-t_{k-1})b_k + (x-t_{k-1})^2 c_k + (x-t_{k-1})^3 d_k, \\quad k = 1,...,n.\n", - "```\n", - "\n", - "Таким образом, для построения сплайна необходимо знать $4n$ коэффициентов $a_k$, $b_k$, $c_k$ и $d_k$.\n", - "\n", - "Из {numref}`Определения {number} ` сплайна можно составить систему уравнений из условий на\n", - "\n", - "1. Значения сплайна в узлах;\n", - "2. Гладкость первой производной;\n", - "3. Гладкость второй производной.\n", - "\n", - "Также, как оказывается, понадобятся ещё граничные условия. Ниже приведён вывод системы {cite}`fnc2017`.\n", - "\n", - "## Условия непрерывности сплайна\n", - "\n", - "**1. Непрерывность в узлах интерполяции.**\n", - "\n", - "Сама задача интерполяции требует $S(t_k) = y_k$, $k=0,...,n$. Это условие достигается при $S_k(t_{k-1}) = y_{k-1}$, $S_k(t_k) = y_k$, где $k=1,...,n$.\n", - "\n", - "**1.а.** Условие $S_k(t_{k-1}) = y_{k-1}$ при подстановке в {eq}`spline` приводит к\n", - "\n", - "```{math}\n", - "a_k = y_{k-1}, \\quad k = 1, ..., n.\n", - "```\n", - "\n", - "Матричный вид этого условия\n", - "\n", - "```{math}\n", - ":label: spline_nodes_a\n", - "\n", - "\\begin{bmatrix}\n", - "\\mathbf{I} & \\mathbf{0} & \\mathbf{0} & \\mathbf{0}\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "\\mathbf{a} \\\\ \\mathbf{b} \\\\ \\mathbf{c} \\\\ \\mathbf{d}\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "y_0 \\\\ y_1 \\\\ \\vdots \\\\ y_{n-1}\n", - "\\end{bmatrix},\n", - "```\n", - "где $\\mathbf{I}$ единичная $n\\times n$ матрица, $\\mathbf{0}$ нулевая $n\\times n$ матрица; $\\mathbf{a}$, $\\mathbf{b}$, $\\mathbf{c}$ и $\\mathbf{d}$ векторы $n\\times 1$ искомых коэффициентов $a_k$, $b_k$, $c_k$ и $d_k$ соответственно.\n", - "\n", - "**1.б.** Условие $S_k(t_k) = y_k$ приводит к \n", - "\n", - "```{math}\n", - "a_k + h_k b_k + h^2_k c_k + h^3_k d_k = y_k,\\quad h_k = t_k - t_{k-1},\\: k=1,...,n.\n", - "```\n", - "\n", - "В матричном виде\n", - "\n", - "```{math}\n", - ":label: spline_nodes_b\n", - "\n", - "\\begin{bmatrix}\n", - "\\mathbf{I} & \\mathbf{H} & \\mathbf{H}^2 & \\mathbf{H}^3\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "\\mathbf{a} \\\\ \\mathbf{b} \\\\ \\mathbf{c} \\\\ \\mathbf{d}\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "y_1 \\\\ y_2 \\\\ \\vdots \\\\ y_n\n", - "\\end{bmatrix},\n", - "```\n", - "где $\\mathbf{H} = \\diag(h_1, h_2, ..., h_n)$ – диагольная матрица из $h_k$.\n", - "\n", - "Итак, системы {eq}`spline_nodes_a` и {eq}`spline_nodes_b` дают $2n$ уравнений.\n", - "\n", - "**2. Непрерывность первой производной.**\n", - "\n", - "Чтобы добиться гладкости первой производной $S(x)$ сплайна, потребуем сшивку производных в узловых точках для соседних кусков $S'_k(t_k) = S'_{k+1}(t_k)$. Тогда, из {eq}`spline` получим\n", - "\n", - "```{math}\n", - "b_k + 2 h_k\\cdot c_k + 3h^2_k\\cdot d_k = b_{k+1},\\quad k=1,...,n-1.\n", - "```\n", - "\n", - "В явном матричном виде это записывается так\n", - "\n", - "```{math}\n", - "\\left[\n", - "\\begin{array}{ccc|cccc|ccc|ccc}\n", - "0 & & & 1 & -1 & & & 2h_1 & & & 3h^2_1 & & \\\\\n", - " & \\ddots & & & \\ddots & \\ddots & & & \\ddots & & & \\ddots & \\\\\n", - " & & 0 & & & 1 & -1 & & & 2h_{n-1} & & & 3h^2_{n-1}\n", - "\\end{array}\n", - "\\right]\n", - "\\begin{bmatrix}\n", - "a_1 \\\\ \\vdots \\\\ a_{n-1} \\\\ b_1 \\\\ \\vdots \\\\ b_n \\\\ c_1 \\\\ \\vdots \\\\ c_{n-1} \\\\ d_1 \\\\ \\vdots \\\\ d_{n-1}\n", - "\\end{bmatrix}\n", - "=\n", - "\\mathbf{0}_{(n-1)\\times 1}\n", - "```\n", - "\n", - "Блоки в этой матрице имеют по $n-1$ строк, второй блок имеет $n$ столбцов, а остальные $n-1$ столбцов. В векторе неизвестных отстутствуют $a_n$, $c_n$ и $d_n$. Чтобы встроить эту систему в общую, мы формально увеличим матрицы до размера $n\\times n$, а вектор неизвестных до $4n$. Чтобы получить эквивалентную систему, нужно будет только \"удалить\" $n$-ую строку\n", - "\n", - "```{math}\n", - ":label: spline_deriv\n", - "\n", - "\\mathbf{E}\n", - "\\begin{bmatrix}\n", - "\\mathbf{0} & \\mathbf{J} & 2 \\mathbf{H} & 3 \\mathbf{H}^2\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "\\mathbf{a} \\\\ \\mathbf{b} \\\\ \\mathbf{c} \\\\ \\mathbf{d}\n", - "\\end{bmatrix}\n", - "=\n", - "\\mathbf{0}_{(n-1)\\times 1},\n", - "```\n", - "\n", - "здесь блочные матрицы уже размера $n\\times n$, а матрица $\\mathbf{E}$ \"удаляет\" последнюю строку произведения $[\\mathbf{0}\\:\\mathbf{J}\\:2\\mathbf{H}\\:3 \\mathbf{H}^2][\\mathbf{a}^\\top\\:\\mathbf{b}^\\top\\:\\mathbf{c}^\\top\\:\\mathbf{d}^\\top]^\\top$. Матрица $\\mathbf{E}$ имеет размер $(n-1)\\times n$ и выглядит как единичная без последней строки\n", - "\n", - "```{math}\n", - "\\mathbf{E}_{(n-1)\\times n} =\n", - "\\begin{bmatrix}\n", - "1 & 0 & \\cdots & \\cdots & 0 \\\\\n", - "0 & \\ddots & & & \\vdots \\\\\n", - "\\vdots & & \\ddots & & \\vdots \\\\\n", - "0 & \\cdots & 0 & 1 & 0\n", - "\\end{bmatrix}.\n", - "```\n", - "\n", - "Матрица $\\mathbf{J}$ двудиагональная, размера $n\\times n$\n", - "\n", - "```{math}\n", - "\\mathbf{J}_{n\\times n} = \n", - "\\begin{bmatrix}\n", - "1 & -1 & & \\\\\n", - " & \\ddots & \\ddots & \\\\\n", - " & & \\ddots & -1 \\\\\n", - " & & & 1\n", - "\\end{bmatrix}.\n", - "```\n", - "\n", - "Итак, система {eq}`spline_deriv` содержит $n-1$ уравнение.\n", - "\n", - "**3. Непрерывность второй производной.**\n", - "\n", - "Аналогично условию на первую производную, требуем для второй $S''_k(t_k) = S''_{k+1}(t_k)$. Из определения $S_k$ {eq}`spline` получаем\n", - "\n", - "```{math}\n", - "2 c_k + 6h_k d_k = 2 c_{k+1},\\quad k=1,...,n-1.\n", - "```\n", - "\n", - "Матричный вид системы\n", - "\n", - "```{math}\n", - ":label: spline_dderiv\n", - "\n", - "\\mathbf{E}\n", - "\\begin{bmatrix}\n", - "\\mathbf{0} & \\mathbf{0} & \\mathbf{J} & 3 \\mathbf{H}\n", - "\\end{bmatrix}\n", - "=\n", - "\\mathbf{0}_{(n-1)\\times 1}.\n", - "```\n", - "\n", - "В итоге получаем $n-1$ уравнение.\n", - "\n", - "## Граничные условия\n", - "\n", - "```{index} кубический сплайн; not-a-knot\n", - "```\n", - "На данном этапе у нас есть $4n$ неизвестных и $2n + 2(n-1) = 4n - 2$ уравнения. Чтобы замкнуть систему, понадобятся граничные условия. Бывает так, что они известны, т.е. известны $S'$ и/или $S''$ на концах отрезка. Если они не известны, то популярными являются условия *not-a-knot*\n", - "\n", - "```{math}\n", - "S'''_1(t_1) = S_2'''(t_1),\\quad S'''_{n-1}(t_{n-1}) = S'''_n(t_{n-1}).\n", - "```\n", - "\n", - "Что приводит к уравнениям\n", - "\n", - "```{math}\n", - ":label: spline_edge\n", - "\n", - "d_1 = d_2, \\quad d_{n-1} = d_n.\n", - "```\n", - "\n", - "Которым можно сопоставить соответствующие строки, и встроить их в уже существующую систему.\n", - "\n", - "Итак, уравнения {eq}`spline_nodes_a`, {eq}`spline_nodes_b`, {eq}`spline_deriv`, {eq}`spline_dderiv` и {eq}`spline_edge` формируют систему для $4n$ неизвестных, с квадратной матрицей размера $(4n) \\times (4n)$. В отличие от кусочно-линейной интерполяции, интерполяция сплайнами требует решения линейной системы. Оказывается, для сплайнов всё-таки можно найти базис, но он не будет обладать свойством {eq}`cardinality`.\n", - "\n", - "## Реализация\n", - "\n", - ":::{proof:function} polynomial\n", - "\n", - "**Полином общего вида** $c_1 + c_2 x + c_3 x^2 + ...$ **.**\n", - "\n", - "```julia\n", - "\"Возвращает полином вида `c[1] + c[2]*x + c[3]*x^2 + ...`.\"\n", - "polynomial(c) = x -> horner(c, x)\n", - "```\n", - ":::\n", - "\n", - ":::{proof:function} pwlininterp\n", - "\n", - "**Кубический сплайн** $S(x)$\n", - "\n", - "Создание блочной матрицы смотрите в {numref}`Демонстрации {number} `.\n", - "\n", - "```julia\n", - "\"Возвращает кубический сплайн, проходящий через точки (`t[i]`, `y[i]`)\"\n", - "function spinterp(t, y)\n", - " n = size(t, 1) - 1\n", - " \n", - " In = I(n)\n", - " E = In[1:end-1, :]\n", - " J = diagm(0 => ones(n), 1 => -ones(n-1)) \n", - " Z = zeros(n, n)\n", - " h = [t[k+1] - t[k] for k in 1:n]\n", - " H = diagm(0 => h)\n", - " \n", - " # 1.а Значения на левой границе\n", - " AL = [In Z Z Z]\n", - " vL = y[1:end-1]\n", - " \n", - " # 1.б Значения на правой границе\n", - " AR = [In H H^2 H^3]\n", - " vR = y[2:end]\n", - " \n", - " # 2. Непрерывность первой производной\n", - " A1 = E * [Z J 2*H 3*H^2]\n", - " v1 = zeros(n-1)\n", - "\n", - " # 3. Непрерывность второй производной\n", - " A2 = E * [Z Z J 6*H]\n", - " v2 = zeros(n-1)\n", - " \n", - " # 4. Not-a-knot\n", - " nakL = [zeros(1, 3*n) 1 -1 zeros(1, n-2)] # слева\n", - " nakR = [zeros(1, 3*n) zeros(1, n-2) 1 -1] # справа\n", - " \n", - " # Собираем систему и решаем\n", - " A = [AL; AR; A1; A2; nakL; nakR]\n", - " v = [vL; vR; v1; v2; 0; 0]\n", - " coefs = A \\ v\n", - " \n", - " # Разбираем коэффициенты\n", - " a = coefs[1:n]\n", - " b = coefs[n+1:2*n]\n", - " c = coefs[2*n+1:3*n]\n", - " d = coefs[3*n+1:4*n]\n", - " \n", - " S = [polynomial([a[k], b[k], c[k], d[k]]) for k in 1:n]\n", - " \n", - " return function (x)\n", - " if x < first(t) || x > last(t)\n", - " return NaN\n", - " elseif x == first(t)\n", - " return first(y)\n", - " else\n", - " k = findlast(x .> t) # k такое, что x ∈ (tₖ₋₁, tₖ)\n", - " return S[k](x - t[k])\n", - " end\n", - " end\n", - "end\n", - "```\n", - ":::\n", - "\n", - "## Сходимость\n", - "\n", - "В случае сплайнов, подобно кусочно-линейной интерполяции, справедливо утверждение\n", - "\n", - "```{index} сходимость; кубического сплайна\n", - "```\n", - "```{proof:proposition} Cходимость кубического сплайна\n", - "\n", - "Для функции $f(x)$, имеющей четвёртую непрерывную производную на отрезке $[a,b]$ и её кубического сплайна $S_h(x)$, узлы которого определены на равномерной сетке $\\omega_h$, найдётся число $C$, такое что, справедлива оценка\n", - "\n", - "$$\n", - "\\|f - S_h\\|_\\infty \\le C h^4.\n", - "$$\n", - "\n", - "Т.е. кубический сплайн сходится к функции с *четвёртым* порядком.\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Функция $f(x)=\\exp(\\sin(2x)) + 0.05\\sin(15x)$.\n", - "\n", - "Построение по 7 выбранным точкам." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "5cb177c6", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/cubic_spline_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = [1.0, 1.5, 3.0, 3.5, 4.1, 4.5, 5.5]\n", - "\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = spinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:top, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x)) + 0.05*sin(15x)\")\n", - "plot!(xs, interpolant.(xs); label=\"кубический сплайн\")" - ] - }, - { - "cell_type": "markdown", - "id": "5bef5e3d", - "metadata": {}, - "source": [ - "**Случай равноотстоящих точек**" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "08f2e89c", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/cubic_spline_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(1, 5.5; length=15)\n", - "\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = spinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:topleft, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x)) + 0.05*sin(15x)\")\n", - "plot!(xs, interpolant.(xs); label=\"кубический сплайн\")" - ] - }, - { - "cell_type": "markdown", - "id": "5b789687", - "metadata": {}, - "source": [ - "**Оценка порядка сходимости**\n", - "\n", - "В этом случае мы ожидаем увидеть прямую с наклоном 4 в log-log осях." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "85c6144a", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/cubic_spline_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "a, b = [1, 5.5]\n", - "xs = range(a, b; length=10000)\n", - "mesh_h = []\n", - "err = []\n", - "for n in (20, 40, 400, 1000, 2000)\n", - " ts = range(a, b; length=n)\n", - " h = (b - a) / (n - 1)\n", - " ys = foo.(ts)\n", - " interpolant = spinterp(ts, ys)\n", - " Δ = norm(foo.(xs) - interpolant.(xs), Inf)\n", - " push!(mesh_h, h)\n", - " push!(err, Δ)\n", - "end\n", - "plot(log10.(mesh_h), log10.(err);\n", - " m=:o, label=\"ошибка\", leg=:left, xlabel=L\"h\", ylabel=L\"||f-S_h||_\\infty\",\n", - ")\n", - "plot!([-2.5, -0.7], [-10, -2.8]; line=:dash, label=L\"O(h^4)\")\n", - "xticks!(\n", - " [-2.5, -2, -1.5, -1.0],\n", - " [L\"5\\times10^{-3}\", L\"10^{-2}\", L\"5\\times10^{-2}\", L\"10^{-1}\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "d498e01b", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 323, - 335, - 339, - 351, - 357, - 380 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/interpolation/cubic_spline.md b/_sources/interpolation/cubic_spline.md index eadaf67..ae5bed0 100644 --- a/_sources/interpolation/cubic_spline.md +++ b/_sources/interpolation/cubic_spline.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим интерполяцию кубическим сплайном и её реализацию на языке Julia. + :keywords: сплайн, кубический сплайн, интерполяция, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/interpolation/ex.ipynb b/_sources/interpolation/ex.ipynb deleted file mode 100644 index b5eb826..0000000 --- a/_sources/interpolation/ex.ipynb +++ /dev/null @@ -1,302 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "d6273c45", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "spinterp" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"interpolation.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "84d4df25", - "metadata": {}, - "source": [ - "# Задания\n", - "\n", - "## Вязкость разреженного газа\n", - "\n", - "%%% bib\n", - "\n", - "Многие корреляционные модели вязкости (например, {cite}`Assael1992`) предоставляют формулу для вычислений\n", - "\n", - "```{math}\n", - "\\eta_{\\text{c}}(\\upsilon, T),\n", - "```\n", - "\n", - "где $\\upsilon$ молярный объём и $T$ температура. Индекс $\\text{c}$ отражает тот факт, что внутри формула параметризована для конкретного вещества. Как правило, параметризация производится по экспериментальным данным, а набор параметров для некоторых веществ приводится вместе с моделью.\n", - "\n", - "Подобные корреляции включают в свою модель вязкость разреженного газа $\\eta_{0\\text{c}}$ как низкоплотный предел\n", - "\n", - "```{math}\n", - "\\eta_{\\text{c}}(\\upsilon, T) \\to \\eta_{0\\text{c}}(T), \\quad \\upsilon \\to \\infty.\n", - "```\n", - "\n", - "В свою очередь, низкоплотные пределы исследуются *аналитически*. В этом задании вам предстоит реализовать одну такую модель.\n", - "\n", - "**Модель разреженного газа.**\n", - "\n", - "%%% bib\n", - "\n", - "Модель ниже приводится из {cite}`GolubevGnezdilov1971`.\n", - "\n", - "Уравнение модели получено из физической кинетики. Выведено для низкоплотного состояния неполярного газа. Модель учитывает кинетическое взаимодействие и взаимодействие по [потенциалу Ленарда-Джонса](https://en.wikipedia.org/wiki/Lennard-Jones_potential) (Л-Ж) между частицами вещества.\n", - "\n", - "Модель даёт уравнение\n", - "\n", - "```{math}\n", - ":label: dilute\n", - "\n", - "\\eta_{0\\text{c}}(T) = 8.44107\\times 10^{-5}\\cdot\\frac{\\sqrt{M T}f_\\eta(T^*)}{\\sigma^2 \\Omega^{(2,2)*}(T^*)},\n", - "```\n", - "\n", - "где\n", - "\n", - "- $\\eta_{0\\text{c}}$ -- вязкость разреженного газа [Па с];\n", - "- $T$ -- температура газа [К];\n", - "- $M$ -- молярная масса газа [кг моль⁻¹];\n", - "- $T^*$ -- приведённая температура, $T^* = kT / \\varepsilon$, где $\\varepsilon/k$ [K]\n", - " + $\\varepsilon$ -- энергетический параметр в Л-Ж потенциале\n", - " + $k$ -- постоянная Больцмана;\n", - "- $f_\\eta(T^*)$ -- уточняющий фактор;\n", - "- $\\sigma$ -- пространственный параметр в потенциале Л-Ж [Å];\n", - "- $\\Omega^{(2,2)*}(T^*)$ -- приведённый интеграл столкновения;\n", - "- численный множитель получается после подстановки значений физических констант.\n", - "\n", - "В уравнении {eq}`dilute` вещество $\\text{c}$ определяется тремя параметрами $M$, $\\sigma$ и $\\varepsilon/k$.\n", - "\n", - "Функции $f_\\eta(T^*)$ и $\\Omega^{(2,2)*}(T^*)$ в {cite}`GolubevGnezdilov1971` приводятся в табличном виде, ссылки на таблицы приведены ниже\n", - "\n", - "- $f_\\eta(T^*)$: **{{ url_feta_table }}**;\n", - "- $\\Omega^{(2,2)*}(T^*)$: **{{ url_omega22_table }}**.\n", - "\n", - "Таким образом, при реализации модели {eq}`dilute` возникает задача интерполяции.\n", - "\n", - "**Задание.**\n", - "\n", - "Вам необходимо реализовать модель разреженного газа {eq}`dilute` и посчитать вязкости для веществ из таблицы ниже в диапазоне температур $T\\in[T_\\min, T_\\max]$." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "772587c2", - "metadata": { - "tags": [ - "remove-input" - ] - }, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
ВеществоM, г/мольσ, Åε/k, KTmin, KTmax, KNIST
CO₂44.0093.9961903001000
CH₄16.0433.822137100600
O₂31.9993.4331131001000
\n", - "\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "CO₂url = \"https://webbook.nist.gov/cgi/fluid.cgi?D=0.001&TLow=220&THigh=1000&TInc=20&Applet=on&Digits=5&ID=C124389&Action=Load&Type=IsoChor&TUnit=K&PUnit=bar&DUnit=kg%2Fm3&HUnit=kJ%2Fmol&WUnit=m%2Fs&VisUnit=uPa*s&STUnit=N%2Fm&RefState=DEF\"\n", - "\n", - "CH₄url = \"https://webbook.nist.gov/cgi/fluid.cgi?D=0.001&TLow=100&THigh=600&TInc=10&Applet=on&Digits=5&ID=C74828&Action=Load&Type=IsoChor&TUnit=K&PUnit=bar&DUnit=kg%2Fm3&HUnit=kJ%2Fmol&WUnit=m%2Fs&VisUnit=uPa*s&STUnit=N%2Fm&RefState=DEF\"\n", - "\n", - "O₂url = \"https://webbook.nist.gov/cgi/fluid.cgi?D=0.001&TLow=60&THigh=1000&TInc=20&Applet=on&Digits=5&ID=C7782447&Action=Load&Type=IsoChor&TUnit=K&PUnit=bar&DUnit=kg%2Fm3&HUnit=kJ%2Fmol&WUnit=m%2Fs&VisUnit=uPa*s&STUnit=N%2Fm&RefState=DEF\"\n", - "\n", - "data = [\n", - " \"CO₂\" 44.009 3.996 190 300 1000 Markdown.parse(\"[[ссылка]]($(CO₂url))\");\n", - " \"CH₄\" 16.043 3.822 137 100 600 Markdown.parse(\"[[ссылка]]($CH₄url)\");\n", - " \"O₂\" 31.999 3.433 113 100 1000 Markdown.parse(\"[[ссылка]]($O₂url)\");\n", - "]\n", - "\n", - "pretty_table(data;\n", - " header=[\"Вещество\", \"M, г/моль\", \"σ, Å\", \"ε/k, K\", \"Tmin, K\", \"Tmax, K\", \"NIST\"],\n", - " backend=:html,\n", - " alignment=:c\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "307552b2", - "metadata": {}, - "source": [ - "В качестве ответа вам необходимо предоставить следующее.\n", - "\n", - "1. Julia-пакет, реализующий описанную выше модель разреженного газа, имеющий следующий интерфейс\n", - " - Структура для задания вещества;\n", - " - Функция вычисления вязкости по структуре и температуре $T$.\n", - "2. С помощью разработанного пакета подсчитать вязкости для веществ из таблицы в указанных диапазонах температур с шагом в 1 Кельвин;\n", - "3. Построить по графику $\\eta_{0\\text{c}}(T)$ для каждого вещества (форматы .jpg, .png или .pdf). На график нанести\n", - " - Подсчитанную вязкость вещества из модели\n", - " - Данные NIST по вязкости для вещества (5-6 точек). (Ссылка указана в таблице, необходимо только поменять ось Y на \"Viscosity (μ Pa \\* s)\".)\n", - "\n", - "Структура ответа\n", - "\n", - "```\n", - "- Julia-пакет/\n", - "- Output data/\n", - " - co2.tsv\n", - " - co2.nist.tsv\n", - " - ...\n", - "- Output plots/\n", - " - co2.{jpg|png|pdf}\n", - " - ...\n", - "- Скрипты, по которым подсчитаны данные (и построены графики)\n", - "- ...\n", - "```\n", - "\n", - "```{note}\n", - "The National Institute of Standards and Technology (NIST) Сhemistry Webbook [[ссылка]](https://webbook.nist.gov/chemistry/) является базой данных по свойствам веществ. Часть данных экспериментальная, другая часть построена по корреляциям. Страница вещества с данными содержит список источников, где это можно уточнить.\n", - "```\n", - "\n", - "```{admonition} Подсказки\n", - ":class: dropdown\n", - "\n", - "Сгенерировать пакет можно с помощью команды `pkg> generate `. Основной модуль будет лежать в директории `/src/.jl`.\n", - "\n", - "Для работы с табличными данными есть встроенная библиотека `DelimitedFiles`.\n", - "\n", - "Для генерации сеток см. `range`.\n", - "\n", - "Для броадкаста по собственной структуре данных см. {ref}`broadcasting`.\n", - "\n", - "Для построения графиков можно. (1) Записать в файл данные и построить график какой-нибудь программой (табличный процессор или, например, gnuplot). (2) Воспользоваться [Plots.jl](https://docs.juliaplots.org/stable/).\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 16, - 20, - 86, - 106 - ], - "substitutions": { - "url_feta_table": "
[ссылка]", - "url_omega22_table": "[ссылка]" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/interpolation/ex.md b/_sources/interpolation/ex.md index 74a36b0..615c662 100644 --- a/_sources/interpolation/ex.md +++ b/_sources/interpolation/ex.md @@ -4,15 +4,24 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 -substitutions: - url_omega22_table: "[ссылка]" - url_feta_table: "[ссылка]" + name: julia-1.9 +myst: + substitutions: + url_omega22_table: "pdf" + url_feta_table: "pdf" --- +```{eval-rst} +.. meta:: + :description: Задачи и упражения на интерполяцию. + :keywords: задачи, упражнения, интерполяция, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -23,8 +32,6 @@ include("interpolation.jl") ## Вязкость разреженного газа -%%% bib - Многие корреляционные модели вязкости (например, {cite}`Assael1992`) предоставляют формулу для вычислений ```{math} @@ -72,10 +79,10 @@ include("interpolation.jl") В уравнении {eq}`dilute` вещество $\text{c}$ определяется тремя параметрами $M$, $\sigma$ и $\varepsilon/k$. -Функции $f_\eta(T^*)$ и $\Omega^{(2,2)*}(T^*)$ в {cite}`GolubevGnezdilov1971` приводятся в табличном виде, ссылки на таблицы приведены ниже +Функции $f_\eta(T^*)$ и $\Omega^{(2,2)*}(T^*)$ в {cite}`GolubevGnezdilov1971` задаются в табличном виде, ссылки на таблицы приведены ниже -- $f_\eta(T^*)$: **{{ url_feta_table }}**; -- $\Omega^{(2,2)*}(T^*)$: **{{ url_omega22_table }}**. +- табличное определение функции $f_\eta(T^*)$, {{ url_feta_table }}; +- табличное определение функции $\Omega^{(2,2)*}(T^*)$, {{ url_omega22_table }}. Таким образом, при реализации модели {eq}`dilute` возникает задача интерполяции. @@ -100,8 +107,8 @@ data = [ pretty_table(data; header=["Вещество", "M, г/моль", "σ, Å", "ε/k, K", "Tmin, K", "Tmax, K", "NIST"], - backend=:html, - alignment=:c + backend=Val(:html), + alignment=:c, ) ``` @@ -143,7 +150,7 @@ The National Institute of Standards and Technology (NIST) Сhemistry Webbook [[ Для генерации сеток см. `range`. -Для броадкаста по собственной структуре данных см. {ref}`broadcasting`. +Для броадкаста по собственной структуре данных см. {ref}`sec:julia:broadcast`. Для построения графиков можно. (1) Записать в файл данные и построить график какой-нибудь программой (табличный процессор или, например, gnuplot). (2) Воспользоваться [Plots.jl](https://docs.juliaplots.org/stable/). ``` diff --git a/_sources/interpolation/index.md b/_sources/interpolation/index.md index cef2e55..65f2113 100644 --- a/_sources/interpolation/index.md +++ b/_sources/interpolation/index.md @@ -1 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу интерполяции функции и некоторые методы её решения. + :keywords: интерполяция, вычислительная математика, вычматы +``` + # Интерполяция + +В этом разделе мы рассмотрим задачу интерполяции функции и некоторые методы её решения. diff --git a/_sources/interpolation/polynomial.ipynb b/_sources/interpolation/polynomial.ipynb deleted file mode 100644 index 361fc7d..0000000 --- a/_sources/interpolation/polynomial.ipynb +++ /dev/null @@ -1,1286 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "4f2d8462", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "spinterp" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"interpolation.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "9802e9ed", - "metadata": {}, - "source": [ - "# Полиномиальная интерполяция\n", - "\n", - "```{index} интерполяция; полиномиальная\n", - "```\n", - ":::{proof:definition} Полиномиальная интерполяция\n", - "**Полиномиальная интерполяция** по точкам $(t_1, y_1), (t_2,y_2), ..., (t_n, y_n)$, где все $t_i$ различны, заключается в построении полинома $p(x)$ степени не выше $n$, проходящего через все данные точки, т.е.\n", - "\n", - "```{math}\n", - ":label: polyinterpcond\n", - "p(t_i)=y_i,\\quad i=1, ..., n.\n", - "```\n", - ":::\n", - "\n", - "Такой полином можно получить, рассматривая задачу интерполяции как линейную систему. Однако, существуют и другие способы, например, построение полинома в форме Лагранжа или Ньютона.\n", - "\n", - "Полинома степени не выше $n$ имеет вид\n", - "\n", - "```{math}\n", - ":label: polyinterppoly\n", - "p(x) = c_1 + c_2 x + c_3 x^2 + ... + c_n x^{n-1}.\n", - "```\n", - "\n", - "Воспользуемся условием {eq}`polyinterpcond` и получим систему на коэффициенты $c_i$\n", - "\n", - "```{math}\n", - "\\begin{align*}\n", - "c_1 + c_2 t_1 + c_3 t^2_1 + ... + c_n t^{n-1}_1 &= y_1\\\\\n", - "c_1 + c_2 t_2 + c_3 t^2_2 + ... + c_n t^{n-1}_2 &= y_2\\\\\n", - "&\\vdots\\\\\n", - "c_1 + c_2 t_i + c_3 t^2_i + ... + c_n t^{n-1}_i &= y_i\\\\\n", - "&\\vdots\\\\\n", - "c_1 + c_2 t_n + c_3 t^2_n + ... + c_n t^{n-1}_n &= y_n\\\\\n", - "\\end{align*}\n", - "```\n", - "\n", - "Данная система записывается в виде $\\mathbf{V}\\mathbf{c}=\\mathbf{y}$\n", - "\n", - "```{math}\n", - ":label: polyinterpsys\n", - "\\begin{bmatrix}\n", - "1 & t_1 & ... & t_1^{n-2} & t_1^{n-1} \\\\\n", - "1 & t_2 & ... & t_2^{n-2} & t_2^{n-1} \\\\\n", - "\\vdots & \\vdots & & \\vdots & \\vdots \\\\\n", - "1 & t_{n-1} & ... & t_{n-1}^{n-2} & t_{n-1}^{n-1}\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "c_1 \\\\c_2 \\\\ \\vdots \\\\ c_n\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "y_1 \\\\ y_2 \\\\ \\vdots \\\\ y_n\n", - "\\end{bmatrix}.\n", - "```\n", - "\n", - "```{index} матрица; Вандермонда\n", - "```\n", - "Матрица $\\mathbf{V}$ называется [матрицей Вандермонда](https://en.wikipedia.org/wiki/Vandermonde_matrix).\n", - "\n", - "Итак, для решения задачи полиномиальной интерполяции, необходимо\n", - "\n", - "1. Составить систему {eq}`polyinterpsys`;\n", - "2. Решить систему {eq}`polyinterpsys`, таким образом, получив коэффициенты $c_i$;\n", - "3. Решением же задачи будет функция {eq}`polyinterppoly`. \n", - "\n", - "## Реализация\n", - "\n", - "(function-polyinterp)=\n", - ":::{proof:function} polyinterp\n", - "**Полиномиальная интерполяция**\n", - "```julia\n", - "\"Возвращает полиномиальный интерполянт, проходящий через точки (`t[i]`, `y[i]`).\"\n", - "function polyinterp(t, y)\n", - " V = vandermonde(t)\n", - " c = V \\ y\n", - " return x -> horner(c, x)\n", - "end\n", - "```\n", - ":::\n", - "(function-vandermonde)=\n", - ":::{proof:function} vandermonde\n", - "```julia\n", - "\"Возвращает матрицу Вандермонда.\"\n", - "function vandermonde(x)\n", - " V = zeros(eltype(x), size(x, 1), size(x, 1))\n", - " for j in 1:size(V, 2)\n", - " V[:, j] .= x .^ (j-1)\n", - " end\n", - " return V\n", - "end\n", - "```\n", - ":::\n", - "(function-horner)=\n", - ":::{proof:function} horner\n", - "```julia\n", - "\"Вычисляет полином `c[1] + c[2]*x + c[3]*x^2 + ...` алгоритмом Горнера.\"\n", - "function horner(c, x)\n", - " ans = last(c)\n", - " for i in lastindex(c)-1:-1:1\n", - " ans = (ans * x) + c[i]\n", - " end\n", - " return ans\n", - "end\n", - "```\n", - ":::\n", - "\n", - "{numref}`Функция {number} ` `polyinterp` вычисляет коэффициенты `c` полинома {eq}`polyinterppoly`, а затем создаёт и возвращает анонимную функцию, которая при вызове вычисляет значение полинома {eq}`polyinterppoly` с помощью {numref}`Функции {number} ` `horner`. Поскольку здесь реализуется [замыкание](https://en.wikipedia.org/wiki/Closure_(computer_programming)), то вектор коэффициентов вычисляется только один раз, при вызове `polyinterp`.\n", - "\n", - "{numref}`Функция {number} ` `vandermonde` строит матрицу Вандермонда для системы {eq}`polyinterpsys`. В теле её цикла вектор `x` поэлементно возводится в степень, а затем присваивается в `j`-ый столбец матрицы `V`.\n", - "\n", - "Наконец, {numref}`Функция {number} ` `horner` вычисляет полином [методом Горнера](https://ru.wikipedia.org/wiki/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%93%D0%BE%D1%80%D0%BD%D0%B5%D1%80%D0%B0)\n", - "\n", - "\n", - "```{proof:demo} Полиномиальная интерполяция\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Для примера мы посмотрим на полиномиальную интерполяцию известной нам функции `foo(x)`, в реальных же данных `foo(x)` неизвестна." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "3513e1ea", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x))\n", - "ts = [1.0, 1.5, 3.0, 3.5, 4.5, 5.5]\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = polyinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:top, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x))\")\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "96ce1e46", - "metadata": {}, - "source": [ - "В целом выглядит неплохо, однако стоит добавить одну точку $t_i = 4.1$ во входные данные, и интерполянт сильно поменяется." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "33d0b7ec", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x))\n", - "ts = [1.0, 1.5, 3.0, 3.5, 4.1, 4.5, 5.5]\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = polyinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:top, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x))\")\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "324fcda7", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "```{proof:observation}\n", - "Сильная зависимость от расположения точек требует дополнительных проверок, иначе можно с большой ошибкой задать табличные данные. Ошибку интерполяции стоит оценивать хотя бы на глаз.\n", - "\n", - "Так, можно заложить в модель не только крупные численные ошибки, но и *качественные*, например, нефизическое поведение.\n", - "```\n", - "\n", - "(poly_equalspaced)=\n", - "## Случай равноотстоящих точек\n", - "\n", - "```{proof:proposition}\n", - "Полиномиальная интерполяция **плохо обусловлена** в случае равноотстоящих узлов интерполяции.\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Возьмём функцию из предыдущего примера, но добавим в неё небольшой шум. В реальных данных этот шум вносится погрешностями измерений." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "b6037ca3", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(-1, 2; length=7)\n", - "ys = foo.(ts)\n", - "\n", - "scatter(ts, ys; label=\"данные\", legend=:topleft, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x)) + 0.05*sin(15x)\")" - ] - }, - { - "cell_type": "markdown", - "id": "a5c3d61e", - "metadata": {}, - "source": [ - "Посмотрим на интерполянт." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "d1910cfb", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_8_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(-1, 2; length=5)\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = polyinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"данные\", legend=:topleft, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "7c6808d5", - "metadata": {}, - "source": [ - "Что будет, если взять 15 точек? Данные с шумом не сильно изменились: это всё тот же \"холм\"." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "5b754b0a", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 6, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_10_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(-1, 2; length=15)\n", - "ys = foo.(ts)\n", - "\n", - "scatter(ts, ys; label=\"данные\", legend=:topleft, xlabel=L\"x\")" - ] - }, - { - "cell_type": "markdown", - "id": "e518c3b5", - "metadata": {}, - "source": [ - "Но интерполянт выглядит так." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "02b691af", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 7, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/polynomial_12_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(-1, 2; length=15)\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = polyinterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"данные\", legend=:topleft, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "8be9512b", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "```{proof:observation}\n", - "Таким образом, если полиномиальная интерполяция и используется на практике, то применяются полиномы не больших степеней, при этом узлы интерполяции тщательно выбираются, если есть возможность.\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 140, - 151, - 155, - 166, - 194, - 202, - 206, - 216, - 220, - 226, - 230, - 240 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/interpolation/polynomial.md b/_sources/interpolation/polynomial.md index 31be45a..40b5a5f 100644 --- a/_sources/interpolation/polynomial.md +++ b/_sources/interpolation/polynomial.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим простейший вид интерполяции - полиномиальную. + :keywords: полиномиальная интерполяция, матрица вандермонда, обусловленность, интерполяция, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/interpolation/pwlinear.ipynb b/_sources/interpolation/pwlinear.ipynb deleted file mode 100644 index 3d38c69..0000000 --- a/_sources/interpolation/pwlinear.ipynb +++ /dev/null @@ -1,1265 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "6370efb8", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "spinterp" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"interpolation.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "a45ac5f8", - "metadata": {}, - "source": [ - "# Кусочно-линейная интерполяция\n", - "\n", - "Что самое простое можно сделать с набором точек? Соединить отрезками. В этом и состоит кусочно-линейная интерполяция.\n", - "\n", - "```{index} интерполяция; кусочно-линейная\n", - "```\n", - ":::{proof:definition} Кусочно-линейная интерполяция\n", - "\n", - "На каждом отрезке $[t_k, t_{k+1}]$ **кусочно-линейный интерполянт** является отрезком прямой, соединяющей точки $(t_k, y_k)$ и $(t_{k+1}, y_{k+1})$\n", - "\n", - "```{math}\n", - ":label: pwlin\n", - "\n", - "p(x) = y_k + \\frac{y_{k+1} - y_k}{t_{k+1} - t_k} (x - t_k),\\quad x \\in [t_k, t_{k+1}]\n", - "```\n", - ":::\n", - "\n", - "Простой способ реализации формулы {eq}`pwlin` заключается в поиске отрезка $[t_k, t_{k+1}]$, которому принадлежит $x$, а затем уже в применении {eq}`pwlin`.\n", - "\n", - "Мы же поступим более общим способом {cite}`LeVeque2002`.\n", - "\n", - "## Hat-функции\n", - "\n", - "Искомый интерполянт лишь одна из *непрерывных кусочно-линейных* функций, которые образуют *линейное пространство*. В этом пространстве функция выражается в виде\n", - "\n", - "```{math}\n", - ":label: pwlin_decomp\n", - "\n", - "p(x) = \\sum_{k=1}^n c_k \\varphi_k(x),\\quad x \\in [t_1, t_n].\n", - "```\n", - "\n", - "Где набор функций $\\{\\varphi_k(x)\\}_{k=1}^n$ является *базисом* пространства, а коэффициенты (веса, координаты) $c_k$ однозначно задают $p(x)$. В качестве такого базиса широко используются hat-функции.\n", - "\n", - "```{index} функция; hat-функция\n", - "```\n", - "```{index} hat-функция\n", - "```\n", - ":::{proof:definition} Hat-функция\n", - "\n", - "**Полная hat-функция** $\\varphi_k$ это функция треугольного вида, задающаяся аналитически в виде\n", - "\n", - "```{math}\n", - ":label: hatfunc\n", - "\n", - "\\varphi_k(x) = \\begin{cases}\n", - "\\dfrac{x-t_{k-1}}{t_k - t_{k-1}},& x \\in [t_k, t_{k-1}],\\\\\n", - "\\dfrac{t_{k+1}-x}{t_{k+1} - t_k},& x \\in [t_k, t_{k+1}],\\\\\n", - "0, & иначе.\n", - "\\end{cases},\\quad k = 2,...,n-1.\n", - "```\n", - "\n", - "```{index} hat-функция; половинчатая\n", - "```\n", - "**Половинчатые hat-функции** задаются на краях и имеют вид\n", - "\n", - "```{math}\n", - ":label: hatfunchalf\n", - "\n", - "\\varphi_1 = \\begin{cases}\n", - "\\dfrac{t_2-x}{t_2 - t_1},& x \\in [t_1, t_2],\\\\\n", - "0, & иначе.\n", - "\\end{cases}\n", - "\\quad\n", - "\\varphi_n(x) = \\begin{cases}\n", - "\\dfrac{x-t_n}{t_{n-1} - t_n},& x \\in [t_{n-1}, t_n],\\\\\n", - "0, & иначе.\n", - "\\end{cases}\n", - "```\n", - ":::\n", - "\n", - "Реализуем hat-функции через замыкание.\n", - "\n", - "(function_hatfunc)=\n", - ":::{proof:function} hatfunc\n", - "\n", - "**Hat-функция** $\\varphi_k(x)$\n", - "\n", - "```julia\n", - "\"\"\"\n", - "Возращает hat-функцию φ_k(x) для отсортированной сетки абсцисс `t`.\n", - "Индекс `k ∈ [1, size(t, 1)]`.\n", - "\"\"\"\n", - "function hatfunc(t, k)\n", - " n = size(t, 1)\n", - " return function (x)\n", - " if k ≥ 2 && t[k-1] ≤ x ≤ t[k]\n", - " return (x - t[k-1]) / (t[k] - t[k-1])\n", - " elseif k ≤ n-1 && t[k] ≤ x ≤ t[k+1]\n", - " return (t[k+1] - x) / (t[k+1] - t[k])\n", - " else # x вне [t[1], t[end]] или неподходящий k\n", - " return zero(x)\n", - " end\n", - " end\n", - "end\n", - "```\n", - ":::\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Допустим, интерполяция производится по четырём точкам $t_1 = 1.0, t_2 = 1.3, t_3 = 3.1, t_4 = 4.0$ (абсциссы), соответствующий базис имеет вид." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "aaa8939b", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/pwlinear_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "ts = [1.0, 1.3, 3.1, 4.0]\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plt = plot(layout=(4,1),xlabel=L\"x\", ylims=[-0.1,1.1], ytick=[1], leg=:outertopleft)\n", - "for k in 1:size(ts, 1)\n", - " φ_k = hatfunc(ts, k)\n", - " plot!(xs, φ_k.(xs); label=\"φ_$k\", subplot=k)\n", - " scatter!(ts, φ_k.(ts); label=\"\", subplot=k)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "563ec363", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Интерполяция\n", - "\n", - "```{proof:observation}\n", - "Определение интерполянта $p(x)$ в виде {eq}`pwlin_decomp` делает нахождение коэффициентов $c_k$ и базиса $\\varphi_k(x)$ *независимыми* задачами.\n", - "```\n", - "\n", - "Поскольку hat-функции обладают свойством\n", - "\n", - "```{math}\n", - ":label: cardinality\n", - "\n", - "\\varphi_k(t_l) = \\begin{cases}\n", - "1, & k = l,\\\\\n", - "0, & k \\ne l.\n", - "\\end{cases}\n", - "```\n", - "\n", - "То коэффициенты $c_k$ в разложении {eq}`pwlin_decomp` равняются $y_k$\n", - "\n", - "```{math}\n", - "p(x) = \\sum_{k=1}^n y_k \\varphi_k(x),\\quad x \\in [t_1, t_n].\n", - "```\n", - "\n", - ":::{proof:function} pwlininterp\n", - "\n", - "**Кусочно-линейная интерполяция**\n", - "\n", - "```julia\n", - "\"Возвращает кусочно-линейный интерполянт для точек (`t[i]`, `y[i]`).\"\n", - "function pwlininterp(t, y)\n", - " basis = [hatfunc(t, k) for k in 1:size(t, 1)]\n", - " return x -> sum(y[k]*basis[k](x) for k in 1:size(y, 1))\n", - "end\n", - "```\n", - "```{admonition} Пояснение по синтаксису\n", - ":class: dropdown tip\n", - "\n", - "> `basis = [hatfunc(t, k) for k in 1:size(t, 1)]`\n", - "\n", - "Создание вектора из функций с помощью [Array comprehensions](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions).\n", - "\n", - "> `sum(y[k]*basis[k](x) for k in 1:size(y, 1))`\n", - "\n", - "- Внутри `sum` стоит [генератор](https://docs.julialang.org/en/v1/manual/arrays/#Generator-Expressions), что очень похоже на Array Comprehension, но не аллоцирует массив;\n", - "- `basis[k](x)` стоит читать как `(basis[k])(x)`: извлечение `k`-го элемента массива `basis`, что является функцией и затем вызов этой функции с аргументом `x`.\n", - "```\n", - ":::\n", - "\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим пример кусочно-линейной интерполяции на функции из раздела {ref}`poly_equalspaced`." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "bdc004ab", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/pwlinear_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = [1.0, 1.5, 3.0, 3.5, 4.1, 4.5, 5.5]\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = pwlininterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:top, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x)) + 0.05*sin(15x)\")\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "3c81737f", - "metadata": {}, - "source": [ - "Возьмём большее число точек, на этот раз равноотстоящих." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "9d700c84", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/pwlinear_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "ts = range(1.0, 5.5; length=15)\n", - "ys = foo.(ts)\n", - "\n", - "interpolant = pwlininterp(ts, ys)\n", - "\n", - "scatter(ts, ys; label=\"узлы интерполяции\", legend=:top, xlabel=L\"x\")\n", - "xs = range(first(ts), last(ts); length=200)\n", - "plot!(xs, foo.(xs); label=\"exp(sin(2x)) + 0.05*sin(15x)\")\n", - "plot!(xs, interpolant.(xs); label=\"интерполянт\")" - ] - }, - { - "cell_type": "markdown", - "id": "15798fbb", - "metadata": {}, - "source": [ - "Похоже, интерполянт стремится к некоторому пределу...\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Сходимость\n", - "\n", - "Можно рассмотреть, как меняется ошибка приближения функции интерполянтом в зависимости от количества использующихся точек. Нам понадобятся несколько инструментов.\n", - "\n", - "```{index} норма; ∞-норма функции \n", - "```\n", - "```{index} функция; ∞-норма \n", - "```\n", - ":::{proof:definition} $\\infty$-норма функции\n", - "Для измерения величины ошибки введём $\\infty$-**норму функции**. Эта норма показывает насколько сильно отклоняется функция $f$ от нуля на отрезке $[a, b]$\n", - "\n", - "```{math}\n", - "\\|f\\|_\\infty = \\max_{x\\in[a,b]} |f(x)|.\n", - "```\n", - ":::\n", - "\n", - "```{index} сетка; равномерная одномерная\n", - "```\n", - ":::{proof:definition} Равномерная одномерная сетка\n", - "\n", - "Введём также *равномерную* **сетку** из узлов\n", - "\n", - "```{math}\n", - "\\omega_h = \\{t_i\\!: \\: t_i = a + (i-1) h, \\: h = (b-a)/n, \\: i=1,...,n\\},\n", - "```\n", - "\n", - "```{index} сетка; размер\n", - "```\n", - "```{index} сетка; мелкость\n", - "```\n", - "где число $n$ называют **размером сетки**, а $h$ её **мелкостью** (или шагом).\n", - ":::\n", - "\n", - "Каждой сетке $\\omega_h$ поставим в соответствие интерполянт $p_h(x)$ функции $f(x)$:\n", - "\n", - "```{math}\n", - "p_h(t_i) = f(t_i), t_i \\in \\omega_h.\n", - "```\n", - "\n", - "Теперь есть всё, чтобы представить утверждение.\n", - "\n", - "```{index} сходимость; кусочно-линейной интерполяции\n", - "```\n", - "```{proof:proposition} Cходимость кусочно-линейной интерполяции\n", - "\n", - "Дважды непрерывно-дифференцируемую на $[a, b]$ функцию $f(x)$ кусочно-линейный интерполянт $p_h(x)$ приближает с оценкой\n", - "\n", - "$$\n", - "\\|f - p_h\\|_\\infty = \\max_{x\\in[a,b]}|f(x) - p_h(x)| \\le M h^2,\\quad M = \\|f''\\|_\\infty.\n", - "$$\n", - "```\n", - "\n", - "При уменьшении шага сетки $h \\to 0$ ошибка интерполяции составляет $O(h^2)$.\n", - "\n", - "```{index} сходимость; порядок\n", - "```\n", - "```{proof:definition} Сходимость и порядок сходимости\n", - "Если ошибка приближения составляет $O(h^m)$ при $h \\to 0$, то говорят о **сходимости** приближения с **порядком** $m$.\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Функция $f(x)=\\exp(\\sin(2x)) + 0.05\\sin(15x)$.\n", - "\n", - "Сгенерируем несколько равномерных сеток $\\omega_h$, построим на них интерполянт и посчитаем норму ошибки. Тогда, поскольку $\\|f - p_h \\|_\\infty \\approx C h^2$, то \n", - "\n", - "```{math}\n", - "\\log \\|f - p_h \\|_\\infty \\approx 2\\cdot\\log h + \\log C.\n", - "```\n", - "А значит на графике зависимости ошибки от $h$ в log-log осях мы должны наблюдать прямую с наклоном 2." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "bc410017", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 5, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/interpolation/pwlinear_8_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "foo(x) = exp(sin(2x)) + 0.05*sin(15x)\n", - "a, b = (1, 5.5)\n", - "xs = range(a, b; length=10000)\n", - "mesh_h = []\n", - "err = []\n", - "for n in (500, 1000, 2000, 3500)\n", - " ts = range(a, b; length=n)\n", - " h = (b - a) / (n - 1)\n", - " ys = foo.(ts)\n", - " interpolant = pwlininterp(ts, ys)\n", - " Δ = norm(foo.(xs) - interpolant.(xs), Inf)\n", - " push!(mesh_h, h)\n", - " push!(err, Δ)\n", - "end\n", - "plot(log10.(mesh_h), log10.(err);\n", - " m=:o, label=\"ошибка\", leg=:left, xlabel=L\"h\", ylabel=L\"||f-p_h||_\\infty\" \n", - ")\n", - "plot!([-3, -2], [-6, -4]; line=:dash, label=L\"O(h^2)\")\n", - "xticks!(\n", - " [-3.0, -2.5, -2, -1.5],\n", - " [L\"10^{-3}\", L\"5\\times10^{-3}\", L\"10^{-2}\", L\"5\\times10^{-2}\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "be0e8c87", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 125, - 135, - 199, - 210, - 214, - 225, - 309, - 332 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/interpolation/pwlinear.md b/_sources/interpolation/pwlinear.md index ddc9a6a..4c9a38b 100644 --- a/_sources/interpolation/pwlinear.md +++ b/_sources/interpolation/pwlinear.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим кусочно-линейную интерполяцию функции. + :keywords: кусочно-линейная интерполяция, hat-функция, интерполяция, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/intro/cond.ipynb b/_sources/intro/cond.ipynb deleted file mode 100644 index 388b513..0000000 --- a/_sources/intro/cond.ipynb +++ /dev/null @@ -1,274 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "a7b54f00", - "metadata": {}, - "source": [ - "# Обусловленность задач\n", - "\n", - "Рассмотрим простую вычислительную задачу.\n", - "Необходимо вычислить значение функции\n", - "\n", - "```{math}\n", - "f(x) = x + 1.\n", - "```\n", - "\n", - "```{margin}\n", - "При этом не рассматривается погрешность, связанная со сложением.\n", - "```\n", - "Поскольку вычисления осуществляются в числах с плавающей точкой, то в реальности получится вычислить не $f(x)$, а $y(x)$ следующего вида\n", - "\n", - "```{math}\n", - "y(x) = \\float(x) + 1 = (x + \\delta x) + 1,\n", - "```\n", - "\n", - "единица при этом представима точно.\n", - "\n", - "Теперь рассмотрим относительную ошибку вычисления $f(x)$\n", - "\n", - "```{math}\n", - "\\frac{|f(x) - y(x)|}{|f(x)|} = \\frac{|(x + 1) - (x + \\delta x + 1)|}{|x+1|} = \\frac{|\\delta x|}{|x+1|}.\n", - "```\n", - "\n", - "Отсюда видно, что относительная ошибка возрастает, если значение $x$ близко к $-1$.\n", - "\n", - "Подобные ошибки являются следствием конечной точности используемых чисел $x \\to \\float(x)$. Если вычисления ведутся в таких числах, то этих ошибок не избежать *независимо от используемого алгоритма*. Поэтому, ещё до его написания можно оценить области входных данных, на которых алгоритм даёт большие ошибки.\n", - "\n", - "Кроме того, в случае `Float64`, несмотря на точность в 16 десятичных знаков, не все они репрезентативны в конечном результате.\n", - "\n", - "Таким образом, задачам (и алгоритмам) можно сопоставить их чувствительность к входным данным. У некоторых задач теоретически сильная чувствительность (большая обусловленность), что в паре с вычислительной погрешностью приводит к ошибкам в расчётах. Для оценки чувствительности вводится число обусловленности.\n", - "\n", - "## Число обусловленности\n", - "\n", - "... **скалярных функций**\n", - "\n", - "```{index} число; обусловленности скалярной функции\n", - "```\n", - "```{index} обусловленность; число\n", - "```\n", - ":::{proof:definition} Число обусловленности скалярной функции\n", - "\n", - "Относительным **числом обусловленности** называют предел отношения относительного изменения значения функции к относительному изменению значения аргумента.\n", - "\n", - "```{math}\n", - ":label: condscalar\n", - "\n", - "\\kappa_f(x) = \\lim_{\\delta x \\to 0} \\frac{ \\dfrac{ |f(x+\\delta x)-f(x)| }{|f(x)|} }{ \\dfrac{|\\delta x|}{|x|} }.\n", - "```\n", - ":::\n", - "\n", - "В случае дифференциируемой функции $f$ из {eq}`condscalar` получаем\n", - "\n", - "```{math}\n", - ":label: condscalardiff\n", - "\n", - "\\kappa_f(x) = \\left| \\frac{x f'(x)}{f(x)}\\right|.\n", - "```\n", - "\n", - "Число обусловленности сложной функции $h(x) = f(g(x))$ имеет вид\n", - "```{math}\n", - "\\kappa_h(x) = \\kappa_f(g(x))\\cdot\\kappa_g(x),\n", - "```\n", - "\n", - "что показывает, как могут распространяться ошибки в алгоритмах.\n", - "\n", - ":::{proof:example}\n", - "\n", - "Сложение $\\text{add}(x) = x + c$ порождает ошибки из-за конечной точности\n", - "\n", - "$$\n", - "\\kappa_\\text{add}(x) = \\left|\\frac{(x)(1)}{x+c}\\right| = \\left|\\frac{x}{x+c}\\right|\n", - "$$\n", - "\n", - "около точек $x \\approx -c$.\n", - "\n", - "Умножение $\\text{mul}(x) = cx$ не порождает новых, но \"протаскивает\" существующие\n", - "\n", - "$$\n", - "\\kappa_\\text{mul}(x) = \\left| \\frac{(x)(c)}{cx} \\right| = 1.\n", - "$$\n", - "\n", - "А вот, скажем, извлечение корня $\\text{sqrt}(x) = \\sqrt x$\n", - "\n", - "$$\n", - "\\kappa_\\text{sqrt}(x) = \\left| \\frac{(x)(1/(2\\sqrt x))}{\\sqrt x} \\right| = \\frac{1}{2}\n", - "$$\n", - "\n", - "теоретически должно уменьшать ошибку в вычислениях, однако, на практике $\\text{sqrt}(x)$ реализован программно, и при его вычислении происходят операции, порождающие ошибки. Либо, в конечном итоге, произойдёт ошибка округления входных данных. Поэтому, на практике меньшее единицы число обусловленности $\\kappa_f < 1$ можно \"округлять\" до единицы.\n", - ":::\n", - "\n", - "## Оценка ошибок\n", - "\n", - "Из определения числа обусловленности {eq}`condscalar` следует, что при малом $\\delta x$\n", - "\n", - "```{math}\n", - ":label: conderr\n", - "\\frac{ |f(x+\\delta x) - f(x)| }{|f(x)|} \\approx \\kappa_f(x) \\frac{|\\delta x|}{|x|}.\n", - "```\n", - "\n", - "Другими словами, это соотношение позволяет оценить возмущение в значении функции по возмущению входных данных.\n", - "\n", - "Например, в случае $\\kappa_f \\approx 10^d$ можно ожидать, что $d$ десятичных знаков (мантиссы) потеряны при вычислении $f(x)$ из $x$. Таким образом, если $\\kappa_f\\approx 1/\\macheps$, то вычислить $f$ в числах с точностью $\\macheps$ не получится.\n", - "\n", - "```{index} обусловленность; плохая\n", - "```\n", - ":::{proof:definition} Плохая обусловленность задачи\n", - "Если задача имеет большое число обусловленности при некотором $x$, то говорят, что задача **плохо обусловлена** при этом $x$. В таких случаях ошибка в получаемом ответе уже *превышает ошибку округления*.\n", - ":::\n", - "\n", - ":::{proof:demo}\n", - ":::\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Вычисление детерминанта является плохо обусловленной задачей для почти сингулярных матриц.\n", - "Рассмотрим пример\n", - "\n", - "```{math}\n", - "A(x) = \\begin{bmatrix}\n", - "1 + x & 2 \\\\\n", - "4 & 5\n", - "\\end{bmatrix},\n", - "\\quad \\det(A(x)) = 5x - 3,\n", - "\\quad \\kappa_\\det(x) = \\left|\\frac{x}{x - 0.6}\\right|.\n", - "```\n", - "\n", - "Эта матрица сингулярна при $x^* = 0.6$, а число обусловленности возрастает при $x^* $.\n", - "\n", - "```{margin}\n", - "Здесь использована функция детерминанта `det` из стандартного пакета `LinearAlgebra`.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b9f0f9b2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "A = [1.0 + x 2.0; 4.0 5.0] = [1.601 2.0; 4.0 5.0]\n", - "det(A) = " - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.004999999999999005\n" - ] - } - ], - "source": [ - "using LinearAlgebra: det;\n", - "x = 0.601;\n", - "@show A = [1.0 + x 2.0; 4.0 5.0]; # 1.601 представимо точно\n", - "@show det(A);" - ] - }, - { - "cell_type": "markdown", - "id": "513870b8", - "metadata": {}, - "source": [ - "По цифрам в мантиссе видно, что детерминант вычислен с ошибкой (точное значение $0.005$). Посмотрим на относительную ошибку вычислений `err`" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "778fad0d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1.9897278269453977e-13" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "err = abs(det(A) - 0.005) / 0.005" - ] - }, - { - "cell_type": "markdown", - "id": "d655fd83", - "metadata": {}, - "source": [ - "Число обусловленности в точке $x=0.601$ равняется $\\kappa_\\det = 601$. Если теперь возмутить входные данные $x$ на погрешность, вносимую $\\float(x)$, т.е. на машинную точность $\\delta x = $ `eps(x)` вблизи $x$, получим" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "86ac5825", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "err_estimate = 601.0 * (eps(x) / x) = 1.1102230246251565e-13\n" - ] - } - ], - "source": [ - "@show err_estimate = 601.0 * (eps(x) / x);" - ] - }, - { - "cell_type": "markdown", - "id": "8872dca8", - "metadata": {}, - "source": [ - "Видно, что ошибка вычислений `err` совпадает с оценкой ошибки `err_estimate` по выражению {eq}`conderr`.\n", - "\n", - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 11, - 149, - 154, - 158, - 160, - 164, - 166 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/intro/cond.md b/_sources/intro/cond.md index 7fcbdd8..96c9a84 100644 --- a/_sources/intro/cond.md +++ b/_sources/intro/cond.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Обусловленность задач и число обусловленности. + :keywords: вычислительная математика, вычматы, обусловленность задач, число обусловленности +``` + # Обусловленность задач Рассмотрим простую вычислительную задачу. @@ -146,6 +154,7 @@ A(x) = \begin{bmatrix} ```{margin} Здесь использована функция детерминанта `det` из стандартного пакета `LinearAlgebra`. ``` + ```{code-cell} using LinearAlgebra: det; x = 0.601; @@ -169,4 +178,4 @@ err = abs(det(A) - 0.005) / 0.005 ```{raw} html -``` \ No newline at end of file +``` diff --git a/_sources/intro/ex.md b/_sources/intro/ex.md deleted file mode 100644 index 7291ae5..0000000 --- a/_sources/intro/ex.md +++ /dev/null @@ -1,56 +0,0 @@ -# Задания - -## Точки - -- *Задание предназначено для изучения языка Julia*. -- *Задание можно выполнять в парах. В таком случае один человек в команде реализует интерфейс для `CartesianPoint`, а второй для `PolarPoint`*. - -Создайте модуль `Points`, предназначенный для работы с точками на плоскости. Реализуйте описанные ниже структуры данных и интерфейс к ним. - -Создайте две структуры данных для точки на плоскости - -1. Композитный тип `CartesianPoint`: хранит декартовы координаты точки; -2. Композитный тип `PolarPoint`: хранит полярные координаты точки. - -Оба типа должны быть подтипом абстрактного типа `AbstractPoint`. - -К каждой структуре данных имплементируйте следующий интерфейс - -Сложение `p + q` -: Вовзращает новую точку как результат векторного сложения точек `p::T` и `q::T`. - -Вычитание `p - q` -: Возвращает новую точку как результат векторного вычитания из точки `p::T` точки `q::T`. - -Длина `norm(p)` -: Вовзращает длину радиус-вектора точки `p`. - -Аргумент `arg(p)` -: Возвращает угол (в радианах) между радиус вектором точки и осью абсцисс. - -Угол между радиус-векторами `angle(p::AbstractPoint, q::AbstractPoint)` -: Возвращает угол между радиус-векторами точек `p` и `q`. - -Скалярное произведение радиус-векторов `dot(p::AbstractPoint, q::AbstractPoint)` -: Возвращает скалярное произведение радиус-векторов точек `p` и `q`. - -Растяжение `α * p` -: Возвращает новую точку, получающуюся в результате центрального растяжения (`α > 1`) или сжатия (`0 < α < 1`) радиус вектора точки `p` в `α::Real` раз. Например, точка `(5, 6)` при `α = 2.5` переходит в точку `(12.5, 15.0)`. - -Поворот `rotate(p, φ)` -: Возвращает новую точку, получающуюся поворотом точки `p` на угол `φ` против часовой стрелки. - -*Заметьте, в случае функций `angle` и `dot` точки могут иметь разный тип.* - -Также имплементируйте интерфейс перевода из точки из одного типа во второй (см. **[[url]](https://docs.julialang.org/en/v1/manual/constructors/#man-outer-constructor-methods)**) - -`CartesianPoint(p::PolarPoint)` -: Создает соответствующую точку типа `CartesianPoint` из точки типа `PolarPoint`. - -`PolarPoint(p::CartesianPoint)` -: Создает соответствующую точку типа `PolarPoint` из точки типа `CartesianPoint`. - -В качестве ответа требуется: - -- исходные файлы модуля `Points`; -- файл, импортирующий модуль `Points` и демонстрирующий весь рабочий интерфейс. diff --git a/_sources/intro/float.ipynb b/_sources/intro/float.ipynb deleted file mode 100644 index ac9ad44..0000000 --- a/_sources/intro/float.ipynb +++ /dev/null @@ -1,782 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "156f1827", - "metadata": {}, - "source": [ - "# Числа с плавающей точкой\n", - "\n", - "Множество действительных чисел $\\real$ неограничено и непрерывно. Однако, в вычислительной практике используется множество *чисел с плавающей точкой* $\\floatset\\subset\\real$, которое ограничено и дискретно. Это множество имеет арифметику, отличающуюся от арифметики в действительных чисел.\n", - "\n", - "## Множество чисел с плавающей точкой\n", - "\n", - "```{index} число; с плавающей точкой\n", - "```\n", - "```{index} see: экспонента; число с плавающей точкой\n", - "```\n", - "```{index} see: мантисса; число с плавающей точкой\n", - "```\n", - "\n", - ":::{proof:definition} Число с плавающей точкой\n", - "\n", - "Множество **чисел с плавающей точкой** $\\floatset$ состоит из нуля и чисел вида\n", - "\n", - "```{math}\n", - ":label: floatpoint\n", - "\\pm (1 + f) \\times 2^n,\n", - "```\n", - "\n", - "где целое число $n\\in\\integer$ называют **экспонентой**, а $1+f$ **мантиссой**, при этом $f$ имеет вид\n", - "\n", - "```{math}\n", - ":label: mantissa\n", - "f = \\sum_{i=1}^d b_i \\, 2^{-i}, \\quad b_i\\in\\{0,1\\},\n", - "```\n", - "\n", - "где натуральное $d$ называют (в данном случае) двоичной **точностью**.\n", - "\n", - "Можно сказать, что $f$ {eq}`mantissa` является дробной частью мантиссы.\n", - ":::\n", - "\n", - "Используя нотацию из позиционных систем счисления, можно записать *в двоичной системе*\n", - "\n", - "```{math}\n", - "1 + f = 1 + 0.\\overline{b_1 b_2 ... b_d} = 1.\\overline{b_1 b_2 ... b_d} \\in [1,2).\n", - "```\n", - "\n", - "Отсюда видно, что ближайшие мантисcы отстоят друг от друга на $2^{-d}$ (последний бит $b_d$).\n", - "Поэтому, между числами $2^n$ и $2^{n+1}$ находится $2^d$ равномерно распределённых чисел.\n", - "В свою очередь, отсюда следует, что числа с плавающей точной *распределены неравномерно* на числовой оси.\n", - "\n", - ":::{proof:example}\n", - "\n", - "Рассмотрим числа с точностью $d = 3$. Для $n=0$ получим $8$ чисел\n", - "\n", - "$$\n", - "1, \\: 1 + \\frac{1}{8}, \\: 1 + \\frac{1}{4}, \\: 1 + \\frac{1}{4} + \\frac{1}{8}, \\:\n", - "1 + \\frac{1}{2}, \\: 1 + \\frac{1}{2} + \\frac{1}{8}, \\: 1 + \\frac{1}{2} + \\frac{1}{4}, \\:\n", - "1 + \\frac{1}{2} + \\frac{1}{4} + \\frac{1}{8} = 1 + \\frac{7}{8}.\n", - "$$\n", - "\n", - "которые заключены в полуинтервале $[1,2)$ с промежутком $2^0 2^{-3} = 1/8$.\n", - "\n", - "В свою очередь, для $n=1$ получим $8$ чисел в полуинтервале $[2, 4)$ с промежутком $2^1 2^{-3} = 1/4$\n", - "\n", - "$$\n", - "(1+0)\\times 2^1 = 2, \\quad \\bigg(1 + \\frac{1}{8}\\bigg) \\times 2^1 = 2 + \\frac{1}{4}\n", - ", \\quad ..., \\quad \\bigg(1 + \\frac{1}{2} + \\frac{1}{4} + \\frac{1}{8}\\bigg) \\times 2^1 = 3 + \\frac{3}{4}.\n", - "$$\n", - "\n", - "Аналогично, для $n=-1$ получим $8$ чисел в полуинтервале $[1/2,1)$ с промежуком $2^{-1}2^{-3}=1/16$.\n", - "\n", - ":::\n", - "\n", - "```{margin}\n", - "Для чисел с плавающей точкой верно равенство $1 + \\macheps / 2 = 1$.\n", - "```\n", - "```{index} машинный ноль\n", - "```\n", - "```{index} see: машинный нуль; машинный ноль\n", - "```\n", - "Из примера видно, что наименьшее число с плавающей точкой, большее $1$ это $1 + 2^{-d}$. Разницу между этими числами $2^{-d}$ называют **машинным нулём** (машинным эпсилон, машинной точностью) $\\macheps$.\n", - "\n", - "Поскольку числа с плавающей точкой имеют конечную точность, сделаем оценку лучшего приближения.\n", - "Пусть $\\float(x)\\in\\floatset$ ближайшее к действительному $x\\in\\real$ число с плавающей точкой. Расстояние для чисел в промежутке $[2^n, 2^{n+1})$ равняется $2^n \\macheps = 2^{n-d}$. Поэтому число $x$ находится не далее, чем на $2^{n-d} / 2 = 2^{n-d-1}$ от $\\float(x)$. Относительная ошибка приближения тогда\n", - "\n", - "```{math}\n", - "\\frac{|\\float(x)-x|}{|x|} \\le \\frac{2^{n-d-1}}{2^n} \\le \\frac{1}{2}\\macheps.\n", - "```\n", - "\n", - "## Числа двойной точности\n", - "```{index} число; двойной точности\n", - "\n", - "```\n", - "```{margin}\n", - "Последняя версия стандарта – IEEE 754-2019.\n", - "\n", - "Поскольку в двоичном представлении первая цифра мантиссы нормализованного числа всегда 1, то её смысла хранить нет.\n", - "```\n", - "Число с плавающей точкой двойной точности `Float64` определил стандарт IEEE 754-1985.\n", - "Для `Float64` всего отводится 64 бита: один под знак числа, 11 под экспоненту и 52 под дробную часть мантиссы $f$.\n", - "\n", - "\n", - "```\n", - " s eeeeeeeeeee mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n", - " ↑ экспонента мантисса\n", - "знак\n", - "1 бит 11 бит 52 бита\n", - "```\n", - "\n", - "Таким образом для `Float64` $d=52$ {eq}`mantissa`, а машинная точность $\\macheps$ составляет\n", - "\n", - "```{math}\n", - ":label: macheps_float64\n", - "\\macheps = 2^{-52} \\approx 2.2 \\times 10^{-16}.\n", - "```\n", - "\n", - "Экспонента $n$ {eq}`floatpoint` принимает значения $-1022 \\le n \\le 1023$. Максимальное значение в ` Float64` составляет почти $2^{1024} \\approx 2 \\times 10^{308}$. Числа крупнее принимают специальное значение-бесконечность `Inf`. Наименьшим положительным числом является $2^{-1022} \\approx 2 \\times 10^{-308}$, меньшие его становятся нулём. Отрицательные аналоги работают схожим образом.\n", - "\n", - "Стоит отметить, что нулей в `Float64`, как и бесконечностей, два: `+0` и `-0`.\n", - "\n", - "```{margin}\n", - "Да, на ноль делить можно.\n", - "```\n", - "Кроме того, существует ещё одно специальное значение **Not a Number**, `NaN`. Оно появляется в результате неопределённых операций: `±0/±0`, `±Inf/±Inf` и операций, в которых участвует `NaN`, что приводит к распространению `NaN` в вычислениях.\n", - "\n", - ":::{proof:demo}\n", - ":::\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "% todo: график распределение float64 на числовой прямой\n", - "\n", - "**`Float64` в Julia**\n", - "\n", - "Битовое представление `Float64`" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "3de000a0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "typeof(2.784) = Float64\n" - ] - } - ], - "source": [ - "@show typeof(2.784);" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c1d2cc86", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"0100000000000110010001011010000111001010110000001000001100010010\"" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bitstring(2.784)" - ] - }, - { - "cell_type": "markdown", - "id": "bb33477f", - "metadata": {}, - "source": [ - "Функции `nextfloat` и `prevfloat` возвращают ближайшие следующее и предыдущее числа" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "5cb320e6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3-element Vector{String}:\n", - " \"0011111111101111111111111111111111111111111111111111111111111111\"\n", - " \"0011111111110000000000000000000000000000000000000000000000000000\"\n", - " \"0011111111110000000000000000000000000000000000000000000000000001\"" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[bitstring(prevfloat(1.0)), bitstring(1.0), bitstring(nextfloat(1.0))]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "c98aebc4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3-element Vector{Float64}:\n", - " 0.9999999999999999\n", - " 1.0\n", - " 1.0000000000000002" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[prevfloat(1.0), 1.0, nextfloat(1.0)]" - ] - }, - { - "cell_type": "markdown", - "id": "2e2c4dda", - "metadata": {}, - "source": [ - "Определённые в {eq}`floatpoint` экспоненту и мантиссу также можно получить" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "b541e76e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(sign(x), exponent(x), significand(x)) = (1.0, 1, 1.392)\n" - ] - } - ], - "source": [ - "x = 2.784\n", - "@show sign(x), exponent(x), significand(x);" - ] - }, - { - "cell_type": "markdown", - "id": "8d229d1f", - "metadata": {}, - "source": [ - "Расстояние между числами в диапазоне $[2^n, 2^{n+1})$ можно получить с помощью функции `eps(x)`.\n", - "По умолчанию, `eps()` возвращает значение для единицы `1.0`, что является машинным нулём $\\macheps$" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "f4f31cb6", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "eps() = 2.220446049250313e-16\n", - "log2(eps()) = -52.0\n" - ] - } - ], - "source": [ - "@show eps();\n", - "@show log2(eps());" - ] - }, - { - "cell_type": "markdown", - "id": "942e910c", - "metadata": {}, - "source": [ - "Пример вызова для для числа, отличного от `1.0`" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "5ed1872e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "eps(3.0) = 4.440892098500626e-16\n", - "prevfloat(3.0) = 2.9999999999999996\n", - "nextfloat(3.0) = 3.0000000000000004\n" - ] - } - ], - "source": [ - "@show eps(3.0);\n", - "@show prevfloat(3.0);\n", - "@show nextfloat(3.0);" - ] - }, - { - "cell_type": "markdown", - "id": "b0ae81bf", - "metadata": {}, - "source": [ - "Однако, стоит отметить, что `eps(x)` определяется как\n", - "\n", - "```julia\n", - "eps(x) == max(x-prevfloat(x), nextfloat(x)-x)\n", - "```\n", - "\n", - "например, для числа `2.0` проявится то, что оно находится на границе диапазонов $[1, 2), [2, 4)$" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "a3384959", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "eps(2.0) = 4.440892098500626e-16\n", - "prevfloat(2.0) = 1.9999999999999998\n", - "nextfloat(2.0) = 2.0000000000000004\n" - ] - } - ], - "source": [ - "@show eps(2.0);\n", - "@show prevfloat(2.0);\n", - "@show nextfloat(2.0);" - ] - }, - { - "cell_type": "markdown", - "id": "98c434ad", - "metadata": {}, - "source": [ - "Наименьшее и наибольшее числа (но не `Inf` или `0`) получить можно так" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "99193203", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(floatmin(), floatmax()) = (2.2250738585072014e-308, 1.7976931348623157e308)\n" - ] - } - ], - "source": [ - "@show floatmin(), floatmax();" - ] - }, - { - "cell_type": "markdown", - "id": "55d4496a", - "metadata": {}, - "source": [ - "Специальные значения можно получить с помощью констант `Inf` и `NaN`" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "c8100fa9", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3-element Vector{String}:\n", - " \"0111111111110000000000000000000000000000000000000000000000000000\"\n", - " \"1111111111110000000000000000000000000000000000000000000000000000\"\n", - " \"0111111111111000000000000000000000000000000000000000000000000000\"" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[bitstring(Inf), bitstring(-Inf), bitstring(NaN)]" - ] - }, - { - "cell_type": "markdown", - "id": "f80e112b", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Особенности арифметики чисел с плавающей точкой\n", - "\n", - "Конечная точность чисел с плавающей точкой приводит к **ошибкам округления**.\n", - "Рассмотрим на примерах ниже.\n", - "\n", - ":::{proof:example}\n", - "\n", - "**Oшибки округления**\n", - "\n", - "Пусть требуется сложить $2.25 + 1.125$ c двоичной точностью $d=3$\n", - "Тогда сложение представится в виде\n", - "\n", - "$$\n", - "\\float(2.25) + \\float(1.125) = \\bigg(1+\\frac{1}{8}\\bigg)\\times 2^1 + \\bigg(1+\\frac{1}{8}\\bigg)\\times 2^0.\n", - "$$\n", - "\n", - "Чтобы его выполнить, необходимо сначала выравнять экспоненты слагаемых\n", - "\n", - "$$\n", - "\\require{cancel}\n", - "\\bigg(1+\\frac{1}{8}\\bigg)\\times 2^1 + \\bigg(\\frac{1}{2}+\\cancel{\\frac{1}{16}}\\bigg)\\times 2^1.\n", - "$$\n", - "\n", - "На этом этапе происходит обрезание $1/16$, поскольку $1/16$ меньше точности $1/8$, с которой можно задать мантиссу.\n", - "\n", - "Когда экспонентны выравнены, можно сложить мантиссы $(1 + 1/8) + (1/2)$. Получаем результат\n", - "\n", - "$$\n", - "\\bigg(1+ \\frac{1}{2}+\\frac{1}{8}\\bigg)\\times 2^1 = 3.25,\n", - "$$\n", - "\n", - "который не равен сложению в действительныйх числах $2.25 + 1.125 = 3.375$.\n", - ":::\n", - "\n", - "В случае `Float64` демонстрация ошибок округления может быть такой" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "c50954ac", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.0 + nextfloat(1.0) = 3.0\n", - "nextfloat(1.0) = 1.0000000000000002\n" - ] - } - ], - "source": [ - "@show 2.0 + nextfloat(1.0);\n", - "@show nextfloat(1.0);" - ] - }, - { - "cell_type": "markdown", - "id": "16d42ce5", - "metadata": {}, - "source": [ - "Ошибки округления копятся, например, можно вычислить\n", - "\n", - "$$\n", - "\\frac{k}{10} - \\sum_{i=1}^{k} 0.1\n", - "$$" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "be0471e2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Σ = [sum((0.1 for _ = 1:k)) for k = ks] = [0.9999999999999999, 9.99999999999998, 99.9999999999986, 1000.0000000001588]\n", - "exact = 0.1 .* ks = [1.0, 10.0, 100.0, 1000.0]\n" - ] - } - ], - "source": [ - "ks = [10.0, 100.0, 1000.0, 10000.0]\n", - "@show Σ = [sum(0.1 for _ in 1:k) for k in ks]\n", - "@show exact = 0.1 .* ks;" - ] - }, - { - "cell_type": "markdown", - "id": "256f3c2e", - "metadata": {}, - "source": [ - "При этом относительная ошибка копится" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "c4438b84", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Float64}:\n", - " 1.1102230246251565e-16\n", - " 1.9539925233402757e-15\n", - " 1.4068746168049984e-14\n", - " -1.588205122970976e-13" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(exact .- Σ) ./ exact" - ] - }, - { - "cell_type": "markdown", - "id": "0efc96d7", - "metadata": {}, - "source": [ - "% TODO\n", - "% Хороший график можно накодить\n", - "% https://stackoverflow.com/questions/249467/what-is-a-simple-example-of-floating-point-rounding-error\n", - "\n", - "```{margin}\n", - "Так и поступают для вычисления рядов, например, $e^x = \\sum_{n=0}^\\infty x^n /n!$.\n", - "```\n", - "\n", - "```{margin}\n", - "Также, см. [алгоритм Кэхэна](https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9A%D1%8D%D1%85%D1%8D%D0%BD%D0%B0).\n", - "```\n", - "Ошибку округления можно уменьшить, если изменить порядок сложения" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "3a71226b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.9999999999999999\n", - "(0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1) = 1.0\n" - ] - } - ], - "source": [ - "@show 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;\n", - "@show (0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1) + (0.1 + 0.1);" - ] - }, - { - "cell_type": "markdown", - "id": "1205f3be", - "metadata": {}, - "source": [ - "Более прикладным примером является работа с числами разных порядков" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "e7b7a02e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1.0 + ϵ) ^ 2 = 1.000002000001\n", - "1.0 + 2.0ϵ + ϵ ^ 2 = 1.0000020000010001\n", - "1.0 + (2.0ϵ + ϵ ^ 2) = 1.000002000001\n" - ] - } - ], - "source": [ - "ϵ = 1e-6\n", - "@show (1.0 + ϵ)^2;\n", - "@show 1.0 + 2.0*ϵ + ϵ^2;\n", - "@show 1.0 + (2.0*ϵ + ϵ^2);" - ] - }, - { - "cell_type": "markdown", - "id": "54c60d2d", - "metadata": {}, - "source": [ - "Машинный ноль {eq}`macheps_float64` на практике означает, что при сложении чисел двойной точности, отличающихся примерно в $10^{16}$ раз или более, одно из слагаемых потеряется" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "9aede5dc", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1.0 + 1.0e-15 = 1.000000000000001\n", - "1.0 + 1.0e-16 = 1.0\n", - "1.0 + 1.0e15 = 1.000000000000001e15\n", - "1.0 + 1.0e16 = 1.0e16\n" - ] - } - ], - "source": [ - "@show 1.0 + 1e-15;\n", - "@show 1.0 + 1e-16;\n", - "@show 1.0 + 1e15;\n", - "@show 1.0 + 1e16;" - ] - }, - { - "cell_type": "markdown", - "id": "c322bb37", - "metadata": {}, - "source": [ - "Ещё один пример неассоциативности. Он возникает на границе $2^n$ диапазонов $[2^{n-1}, 2^n)$ и $[2^n,2^{n+1})$\n", - "\n", - "```{margin}\n", - "В англоязычной литературе см. *subtractive cancellation*.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "131cdada", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1.0 + eps() / 2) - 1.0 = 0.0\n", - "1.0 + (eps() / 2 - 1.0) = 1.1102230246251565e-16\n" - ] - } - ], - "source": [ - "@show (1.0 + eps()/2) - 1.0;\n", - "@show 1.0 + (eps()/2 - 1.0);" - ] - }, - { - "cell_type": "markdown", - "id": "3fb73340", - "metadata": {}, - "source": [ - "## Меры предосторожности и практика работы с float-числами\n", - "\n", - "**Точность представления чисел**\n", - "\n", - "```julia-repl\n", - "julia> 0.1 + 0.2 # Float64\n", - "0.30000000000000004\n", - "\n", - "julia> 0.1f0 + 0.2f0 # Float32\n", - "0.3f0\n", - "```\n", - "\n", - "Не все числа представимы в float точно, в реальности программист имеет дело с ближайшим к действительному float-числу. Сложение float-чисел может быть выполнено точно, например, результат 0.30000000000000004 верный, просто сложение происходило для приближений, а не исходных чисел. В разных представлениях могут быть разные результаты, так для `Float32` те же числа складываются иначе.\n", - "\n", - "**Сравнение чисел**\n", - "\n", - "Когда необходимо сравнивать числа, используйте неточное сравнение `isapprox`, при этом лучше использовать относительную погрешность, а не абсолютную.\n", - "\n", - "Будьте аккуратнее в точных сравнениях. Например, вам необходимо найти отрицательную энергию, тогда сравнение вида `E < 0` иногда не подходит, поскольку `E` может быть порядка $-\\macheps$: считать ли такое значение значение физически отрицательным -- решать вам.\n", - "\n", - "**Числа сильно разных точностей**\n", - "\n", - "Работая с `Float64`, старайтесь не допускать сложений чисел, отличающихся примерно в $10^{16}$ раз или более.\n", - "\n", - "**Сложение неассоциативно**\n", - "\n", - "Малое складывать с малым, а крупное с крупным.\n", - "\n", - "Осторожнее с\n", - "\n", - "- С суммами большого числа слагаемых (ряды, циклы);\n", - "- Возведением в степень.\n", - "\n", - "**Subtractive cancellation**\n", - "\n", - "Осторожнее с вычитанием чисел близких по значению. Примеры из [Википедии](https://en.wikipedia.org/wiki/Catastrophic_cancellation#In_numerical_algorithms). Операции происходят с конечной точностью, поэтому иногда ошибка вычитания приближений может сильно превышать вычитание точных чисел. Алгебраические преобразования с вычисляемым выражением могут помочь снизить ошибку." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 11, - 144, - 148, - 150, - 154, - 158, - 160, - 164, - 167, - 172, - 175, - 179, - 183, - 193, - 197, - 201, - 203, - 207, - 209, - 251, - 254, - 262, - 266, - 270, - 272, - 287, - 290, - 294, - 299, - 303, - 308, - 315, - 318 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/intro/float.md b/_sources/intro/float.md index f3df417..d500b12 100644 --- a/_sources/intro/float.md +++ b/_sources/intro/float.md @@ -4,12 +4,21 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Основы арифметики чисел с плавающей точкой (float). + :keywords: float, floating point arithmetic, арифметика, плавающая точка +``` + +(section-float-numbers)= # Числа с плавающей точкой Множество действительных чисел $\real$ неограничено и непрерывно. Однако, в вычислительной практике используется множество *чисел с плавающей точкой* $\floatset\subset\real$, которое ограничено и дискретно. Это множество имеет арифметику, отличающуюся от арифметики в действительных чисел. @@ -312,6 +321,7 @@ ks = [10.0, 100.0, 1000.0, 10000.0] ```{margin} В англоязычной литературе см. *subtractive cancellation*. ``` + ```{code-cell} @show (1.0 + eps()/2) - 1.0; @show 1.0 + (eps()/2 - 1.0); diff --git a/_sources/intro/index.md b/_sources/intro/index.md index 41f825c..e9f9f78 100644 --- a/_sources/intro/index.md +++ b/_sources/intro/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Основы арифметики чисел с плавающей точкой (float) и обусловленность численных задач. + :keywords: float, floating point arithmetic, арифметика, плавающая точка, обусловленность задач, число обусловленности +``` + # Введение Данный раздел включает следующие темы diff --git a/_sources/intro/julia.md b/_sources/intro/julia.md deleted file mode 100644 index 0ff6325..0000000 --- a/_sources/intro/julia.md +++ /dev/null @@ -1,2236 +0,0 @@ ---- -substitutions: - urldownload: "https://julialang.org/downloads/" - wintermdwnld: "\"⊞\" [Windows Terminal](https://aka.ms/terminal)" - julia_logo: "" ---- - -# Основы языка программирования Julia - -```{epigraph} -Julia: come for the syntax, stay for the speed - --- *[Nature](https://www.nature.com/articles/d41586-019-02310-3)* -``` - -**Почему {{ julia_logo }} Julia?** - -Язык [Julia](https://julialang.org/) создавался как решение *two-languages problem* в научной и вычислительной среде {cite}`Julia2017`. На одних языках просто писать программы, но они медленно исполняются (например, на Python), с другой стороны, в языках с быстрым исполнением программ сложный синтаксис (например, C/C++, Fortran). - -Так, язык Julia созданный в 2012 году, развивается с фокусом на математические вычисления при сохранении удобного синтаксиса. В языке богатая стандартная библиотека, которая легко расширяется под пользовательские структуры данных. - -**Кто уже пользуется?** - -Julia продолжает набирать популярность. Этот язык уже используется в физике, машинном обучении, финансовых моделях, биологии, медицине, геофизике... А в список пользователей входят: MIT, Princeton, NASA, CISCO, IBM, Adobe...[^usage_proof] - -[^usage_proof]: https://juliacomputing.com/case-studies/, https://en.wikipedia.org/wiki/Julia_(programming_language)#Notable_uses - -**Как изучить?** - -В данном разделе излагаются основные инструменты языка Julia, которые понадобятся в практикуме. Дополнительные материалы по изучению языка находятся в Приложении {ref}`materials_julia`. - -## Инструкция по установке - -Ниже расположены краткие инструкции по установке исполнителя языка Julia для Linux-based операционных систем (ОС), MacOS и Windows. При возникновении неясностей, обратитесь к [официальной инструкции](https://julialang.org/downloads/platform/) для вашей ОС. - -```{admonition} Инструкция для пользователей Linux-based ОС -:class: dropdown - -**1. Скачать последнюю версию интерпретатора** - -На сайте загрузок {{ urldownload }} найти в таблице свою систему и архитектуру -(скорее всего, это {guilabel}`Generic Linux on x86 → 64-bit`). - -:::{warning} -Использовать пакеты `julia` из репозитория дистрибутива настоятельно не рекомендуется, поскольку в репозиториях сборка часто неверно сконфигурирована, из-за чего сторонние библиотеки для Julia могут отказаться работать. -::: - -**2. Распаковать скачанный архив** - -(предполагаем, что скачанный архив лежит непосредственно в домашней директории) - -:::console -$ tar -xzf julia-1.6.2-linux-x86_64.tar.gz -::: - -(здесь и далее команды в терминале помечаются `$`) - -После этого в домашней директории должна появиться директория {file}`julia-1.6.2`, где находится исполняемый файл интерпретатора и необходимые для его работы библиотеки. - -**3. Добавление ссылки для удобного вызова** - -Рекомендуется вместо добавления в `PATH` директории, в которой лежит исполняемый файл, добавить символьную ссылку на этот файл в директорию, которая уже в `PATH`. В большинстве дистрибутивов директория {file}`~/bin`, если она существует, автоматически добавляется в `PATH`, что позволяет добавить ссылку, даже не имея прав администратора. Если директории {file}`~/bin` нет, то её сначала нужно создать: - -:::console -$ mkdir ~/bin -::: - -Затем делаем там символьную ссылку на исполняемый файл интерпретатора - -:::console -$ ln -s ~/julia-1.6.2/bin/julia ~/bin/julia -::: - -Теперь интерпретатор можно запускать, просто набрав `julia` в командной строке (возможно, нужно начать новую сессию в терминале). - -Можно вместо домашней директории сделать символьную ссылку в системной директории (нужны права администратора): - -:::console -# ln -s ~/julia-1.6.2/bin/julia /usr/local/bin/julia -::: -``` - -```{admonition} Инструкция для пользователей MacOS -:class: dropdown - -**1. Скачайте последнюю версию интерпретатора** - -Скачайте .dmg-пакет с официального сайта загрузок {{ urldownload }}, {guilabel}`MacOS → 64-bit`; - -**2. Установить интерпретатор** - -Стандартно для .dmg-пакетов установите (перетащить .app-файл в директорию Applications). - -Julia уже установлена, её можно вызвать стандартным способом, но лучше настроить работу через Terminal.app. - -Откройте Terminal.app и вызовите Julia по абсолютному пути (далее команды терминала помечаются `%`, инструкция для Julia 1.6, для других версий аналогично): - -:::console -% /Applications/Julia-1.6.app/Contents/Resources/julia/bin/julia --version -::: - -Если вы получили в ответ `julia version 1.6.2`, то всё в порядке. - -**3. Настройка для быстрого вызова интерпретатора** - -Чтобы в будущем доступаться до Julia по короткой команде `julia`, можно добавить либо [ссылку](https://julialang.org/downloads/platform/#macos), либо создать для Julia alias в rc-файле командной оболочки. - -Ниже показан способ с alias. - -::::{admonition} Как найти rc-файл -:class: dropdown - -Узнайте ваш `shell` - -:::console -% echo $SHELL -/bin/zsh -::: - -- Если это `zsh`, то файл для настройки {file}`~/.zshrc`. - - Если файл отсутствует, создайте его `touch ~/.zshrc`. -- Если это `bash`, то файл для настройки {file}`~/.bashrc`. - - Если файл отсутствует, создайте его `touch ~/.bashrc`. -:::: - -Добавление `alias` (для `bash` аналогично): - -:::console -% open ~/.zshrc -::: - -В открывшемся редакторе будет содержимое {file}`~/.zshrc`, добавьте в файл строчку - -:::console -# Alias для быстрого доступа к julia -alias julia='/Applications/Julia-1.6.app/Contents/Resources/julia/bin/julia' -::: - -и сохраните {file}`~/.zshrc`. Далее сделайте завершение настройки. - -:::console -% source ~/.zshrc -% julia --version -julia version 1.6.2 -::: -``` - -```{admonition} Инструкция для пользователей ОС Windows 10 -:class: dropdown - -**1. Скачайте последнюю версию интерпретатора** - -На сайте загрузок {{ urldownload }} найти в таблице свою систему и архитектуру -(скорее всего, подойдет {guilabel}`Windows → 64-bit (installer)`) - -**2. Установить интерпретатор** - -Следуйте инструкциям установщика. По умолчанию установка идёт в пользовательскую директорию. Если хочется установить в {file}`C:\Program Files`, не забудьте запустить установщик через {guilabel}`ПКМ → Запуск от имени администратора`. - -В конце установки отметить галочкой пункт **Add Julia to `PATH`**. - -**3. Запуск** - -Теперь интерпретатор можно запускать из командной строки командой `julia`. -*Рекомендуется* в качестве командной строки использовать современный {{ wintermdwnld }}. -``` - -(repl_guide)= -## Интерактивный режим - -```{margin} -Это аналогично интерактивному режиму работы в Python. -``` -Знакомство языка начнём с интерактивного режима. Для этого необходимо запустить Julia REPL (Read-Evaluate-Print-Loop). - -```{margin} -`GNOME Terminal`, `Terminal.app`, `iTerm.app`, `Windows Terminal`, `cmd`... -``` -В терминале необходимо набрать команду `julia` - -```console -% julia - _ - _ _ _(_)_ | Documentation: https://docs.julialang.org - (_) | (_) (_) | - _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. - | | | | | | |/ _` | | - | | |_| | | | (_| | | Version 1.6.2 (2021-07-14) - _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release -|__/ | - -julia> -``` - -Строки до `julia>` это приветственное сообщение. Здесь есть ссылка на документацию к языку. Команды для получения помощи и версия релиза. - -Julia REPL обладает четыремя режимами работы - -- Интерпретатор; -- Помощь; -- Менеджер пакетов; -- Командная оболочка. - -При запуске запускается режим интерпретатора. Из него можно переключиться в другие режимы, а чтобы вернуться в режим интерпретатора из любого другого, нужно очистить строку {kbd}`Ctrl+E`, {kbd}`Ctrl+U` и нажать {kbd}`← Backspace`. - -Чтобы выйти из REPL, очистите строку и нажмите {kbd}`Ctrl+D`. - -::::{tab-set} - -:::{tab-item} Интерпретатор - -В нём вы можете исполнять команды языка и переходить в другие режимы. Prompt-сообщение `julia>`. - -```julia-repl -julia> println("Hello, world") -Hello, world - -julia> -``` -::: - -:::{tab-item} Помощь -Здесь можно получить помощь и документацию к коду. Переход по нажатию {kbd}`?`. Prompt-сообщение `help?>`. - -```julia-repl -julia> ? - -help?> println -search: println printstyled print sprint isprint - - println([io::IO], xs...) - - Print (using print) xs followed by a newline. If io is not supplied, prints to stdout. - - ... -``` -::: - -:::{tab-item} Менеджер пакетов - -Посвящён работе c окружениями и со сторонними пакетами [^pkgenv]. Команда перехода {kbd}`]`. Prompt-сообщение `(@v1.6) pkg>`. Этот режим нам пока не понадобится. Для знакомых с Python, этот режим обладает функционалом pip и virtualenv. - -[^pkgenv]: Программный пакет *package* это библиотека кода. Окружение *environment* позволяет исполнить код только с необходимыми пакетами, что уменьшает количество конфликтов версий между ними. - -```julia-repl -julia> ] - -(v1.6) pkg> help - Welcome to the Pkg REPL-mode. To return to the julia> prompt, ... -``` - -::: - -:::{tab-item} Командная оболочка - -В этом режиме можно работать с командной оболочкой, не выходя из Julia REPL. Команда перехода {kbd}`;`. Prompt-сообщение `shell>`. - -```julia-repl -julia> ; - -shell> echo 'Привет, мир!' -Привет, мир! -``` -::: - -:::: - -## Исполнение программ - -Исходный код программы в Julia это текстовый файл, стандартное расширение `.jl`. Сохраняйте исходный код в UTF кодировке. - -Чтобы опробовать, создайте текстовый файл с названием `hello.jl` с содержимым - -```julia -using Random - -maze_width = 50 -maze_height = 10 - -for i in 1:maze_height - println(join(rand(1:4) > 2 ? "+" : " " for i in 1:maze_width)) -end -``` - -Программа запускается командой `julia` с указанием полного пути до файла с исходным кодом. Перейдите в терминале в директорию, где вы сохранили `hello.jl` и выполните команду `julia hello.jl` - -```console -% julia hello.jl - + + ++++ +++ + + ++ + +++++ + ++ + + + + ++ ++ -+ ++ + +++ + + + ++ +++++ +++ + + + - + ++ ++++++ + ++ ++ ++ + + +++ + ++ + +++ - + + + ++++ +++ ++ + + + + ++++ ++ - ++ ++ ++ + + + + +++ ++ ++ ++ + + ++ - + ++ + ++ ++++ ++ + + + ++ ++ + + -+ ++ ++ ++ +++ ++++ + ++ + + +++++++ + -+ + + +++ + + ++++++ ++++ + + + + ++ -+ + ++ + ++++++ + + + + +++ + +++ -+ + + + + ++++ + +++ ++++ + + ++ ++ + ++ + -``` - -У интерпретатора много полезных опций. Например, с опцией `-i` интерпретатор переходит в интерактивный режим после исполения программы. - -```console -% julia -i hello.jl - + +++ ++++ +++ +++ +++ + + +++++ +++ ++ -+ + ++ + + ++ +++ + ++ ++ ++ +++ ++ +++ -++++ + + + + +++++ ++ +++ +++ +++++ - + + ++ ++ + + + + ++ + + ++ + + + +++ -+++ ++ + + + + + ++++++ ++++ + ++ + + + + -+ ++ ++++ ++ ++++ + ++ + ++ + +++ +++ -+ +++ ++++ +++ ++ ++++ + + + ++++++++ + - + + + +++ + + ++++ +++ + +++ +++ + -++ +++++ + ++++ ++ ++ + + ++ ++++++ ++ +++ - + +++++ + ++ + +++ ++++ + + +++ +++ + ++++ - _ - _ _ _(_)_ | Documentation: https://docs.julialang.org - (_) | (_) (_) | - _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. - | | | | | | |/ _` | | - | | |_| | | | (_| | | Version 1.6.2 (2021-07-14) - _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release -|__/ | - -julia> maze_height -10 -``` - -## Числа и переменные - -```{tip} -Данный раздел является *кратким* обзором следующих разделов манула - -- Variables **[[url]](https://docs.julialang.org/en/v1/manual/variables/)**; -- Integers and Floating-Point Numbers **[[url]](https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/)**; -- Mathematical Operations and Elementary Functions **[[url]](https://docs.julialang.org/en/v1/manual/mathematical-operations/)**; -- Complex and Rational Numbers **[[url]](https://docs.julialang.org/en/v1/manual/complex-and-rational-numbers/)**. -``` - -В Julia богатая система встроенных числовых типов, узнать тип переменной или литерала можно с помощью функции `typeof(x)`. - -```julia-repl -julia> typeof(5) -Int64 - -julia> typeof(5.0) -Float64 - -julia> typeof(5im) -Complex{Int64} - -julia> typeof(2.3 + 5.0im) -ComplexF64 (alias for Complex{Float64}) - -julia> typeof(2//3) -Rational{Int64} - -julia> typeof(1//3 + 2//3im) -Complex{Rational{Int64}} - -``` - -Синтаксис присвоения значения переменной стандартный, также поддерживается параллельное присваивание и каскадное. - -```julia-repl -julia> x = 5 -5 - -julia> x, y = 1, 2 -(1, 2) - -julia> x -1 - -julia> y -2 - -julia> x = y = 1 -1 - -julia> x, y -(1, 1) - -julia> (x = (y = 2) + (z = 3)) -5 - -julia> x, y, z -(5, 2, 3) -``` - -В исполнительном режиме REPL печатает возращаемое значение, его можно опустить с помощью `;` в конце выражения. - -```julia-repl -julia> x = 10; - -julia> x -10 -``` - -```{margin} -Список поддерживаемых для набора в REPL Unicode символов **[[url]](https://docs.julialang.org/en/v1/manual/unicode-input/)**. -``` -В имена переменных могут входить любые [Unicode](https://ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4) символы. -REPL позволяет набирать часто употребляемые с помощью LaTeX-подобного синтаксиса и {kbd}`Tab ⇥`, например, так выглядит набор символов `α₁`: - -```julia-repl -julia> \alpha # потом нажмите ``, и ввод сменится на α - α - α\_1 # `` - α₁ -``` - -```{list-table} Некоторые операторы и функции. -:header-rows: 1 - -* - Описание - - Синтаксис -* - Бинарные операторы `+`, `-`, `*`, `/` - - `x + y`, `x - y`, `x * y`, `x / y` -* - Функции `+`, `-`, `*`, `/` - - `+(x, y,..)`, `-(x, y)`, `*(x, y,..)`, `/(x, y)` -* - Унарный минус - - `-x` или `-(x)` -* - Частное от деления целых - - `x ÷ y` или `÷(x, y)` или `div(x, y)` -* - Остаток от деления целых - - `x % y` или `%(x, y)` или `rem(x, y)` -* - Возведение в степень $x^y$ - - `x ^ y` или `^(x, y)` -* - Логарифмы $\ln(x)$, $\log_2(x)$, $\log_{10}(x)$ - - `log(x)`, `log2(x)`, `log10(x)` -* - Тригонометрия $\sin(x)$, $\cos(x)$ - - `sin(x)`, `cos(x)` -* - Квадратный корень $\sqrt{x}$ - - `sqrt(x)` -``` - -Математические константы - -```julia-repl -julia> π # \pi -π = 3.1415926535897... - -julia> ℯ # \euler -ℯ = 2.7182818284590... - -julia> typeof(ℯ) -Irrational{:ℯ} -``` - -При применении операций к разным типам аргументов тип результата интуитивен: число из типа, соответствующего, математически "меньшему" множеству конвертируется в тип математически "большего" множества. Затем операция выполняется для одинаковых типов. Система типов в Julia это её позвоночник, см. раздел {ref}`type_system`. - -Редко требуется аргумент подать в явном типе, например, - -```julia-repl -julia> sqrt(-1.0) -ERROR: DomainError with -1.0: -sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)). -... - -julia> sqrt(-1.0 + 0im) -0.0 + 1.0im -``` - -```{admonition} Почему? -:class: dropdown -Во-первых, функция корня в математике определяется на разных множествах. - -Во-вторых, так удаётся сохранять *стабильность типов*: т.е. когда по типам аргументов функции можно определить тип возвращаемого значения. Если бы функция корня, извлекая из `Float64`, возвращала иногда `Float64`, а иногда `Complex{Float64}`, то предсказать тип возвращаемого значения было бы невозможно. Предсказание типов позволяет *компилировать* функции и методы, не уступающие по скорости аналогам кода на статически типизируемых языках, например, `C/C++`. -``` - -## Логические типы и сравнение величин - -В Julia один логический тип `Bool`, имеющий два значения: `true` и `false`. -Операторы сравнения как правило возвращают тип `Bool` и используются в логических конструкциях. - -```{list-table} Некоторые логические операторы и операторы сравнения (функциональные форма не приведена). -:header-rows: 1 - -* - Описание - - Синтаксис -* - Логическое отрицание - - `!a` -* - Логическое И (short-circuit) - - `a && b` -* - Логическое ИЛИ (short-circuit) - - `a || b` -* - Равенство по значению - - `x == y`, `isequal(x, y)` (не взаимозаменяемы) -* - Identity - - `x === y`, `x ≡ y` -* - Неточное равенство по значению - - `x ≈ y`, `isapprox(x, y[; kwargs...])` -* - Меньше, чем - - `x < y` и `x <= y`, `x ≤ y` -* - Больше, чем - - `x > y` и `x >= y`, `x ≥ y` -``` - -Кроме того, существует тип `Missing` со единственным значением `missing`. Он используюется с операторами `&` и `|`, реализующую троичную логику на `true`, `false` и `missing`. - -## Строки - -```{tip} -Подробнее о строках в мануале **[[url]](https://docs.julialang.org/en/v1/manual/strings/)**. -``` - -В Julia богатая поддержка работы с текстом, встроенные текстовые типы работают с Unicode. -Основные типы: `Char`, `String` и `SubString`. - -Тип `Char` используется для работы с отдельными символами, его литерал две одинарные кавычки `'`. - -% здесь почему-то julia-repl не работает. Убрал, чтобы jb build не ругался -``` -julia> 'a' -'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) - -julia> 'α' -'α': Unicode U+03B1 (category Ll: Letter, lowercase) - -julia> 'aa' -ERROR: syntax: character literal contains multiple characters -Stacktrace: - [1] top-level scope - @ none:1 -``` - -Тип `String` предназначен для строк, его литерал двойные кавычки `"`. - -```julia-repl -julia> "a" -"a" - -julia> "a" == 'a' -false - -julia> "aaaa" -"aaaa" - -julia> typeof("aaaa") -String -``` - -Escape специальных символов производится привычным `\`, например `'\n'`, `'\t'`. - -```{list-table} Часто используемые операции над строками. -:header-rows: 1 - -* - Описание - - Cинтаксис - - Пример - - Результат -* - Конкатенация - - `x * y` - - `"ab" * "b"` - - `"abb"` -* - Дублирование - - `x ^ i` - - `"a" ^ 6` - - `"aaaaaa"` -* - Интерполяция значения переменной - - `"$x"` - - `y = 1.0; x = "$y"` - - `x` будет `"1.0"` -* - Интерполяция результата выражения - - `"$(expr)"` - - `"$(sin(π/2))"` - - `"1.0"` -* - Разбиение строки - - `split(x)` - - `split("a b\nc\td")` - - `["a", "b", "c", "d"]` (массив) -* - Сбор строки - - `join(x [, delim])` - - `join([25, "февраля", 1936], " ")` - - `"25 февраля 1936"` -* - Удаление whitespace окружения - - `strip(x)` - - `strip(" \ta ba\n")` - - `"a ba"` -* - Форматированная строка (`using Printf`) - - `@sprintf "fmt" x...` - - `@sprintf "π ≈ %.2f, ℯ ≈ %.2f" π ℯ` - - `"π ≈ 3.14, ℯ ≈ 2.72"` -* - Печать в stdout - - `println(x,..)` - - `println("A = ", 10)` - - Печатает в stdout "A = 10" -* - Чтение из stdin - - `readline()` - - `readline()` - - Ожидание ввода -* - Парсинг строки - - `parse(T, x)` - - `parse(Float64, "1.564")` - - `1.564` -``` - -Строки в Julia являются неизменяемыми объектами. -Однако, часто требуется поработать с каким-то участком строки. -Для этого, чтобы экономить память и время, в Julia существует тип `SubString`, который указывает на часть строки, но при этом ведёт себя как `String`. - -```julia-repl -julia> split(strip(" 1.0 2.0 3.0 ")) -3-element Vector{SubString{String}}: - "1.0" - "2.0" - "3.0" - -julia> parse.(Float64, ans) # ans -- внутренняя переменная REPL, хранящая результат последнего вычисления -3-element Vector{Float64}: - 1.0 - 2.0 - 3.0 -``` - -## Управляющие конструкции - -```{tip} -Подробнее в мануале **[[url]](https://docs.julialang.org/en/v1/manual/control-flow/)**. -Здесь освещены не все конструкции и не так подробно. -``` - -### Составные выражения - -Блок `begin-end` позволяет объединять несколько выражений в одно, составное выражение (*compound expression*). Результат выражения это результат последнего вычисления в выражении. - -```julia-repl -julia> z = begin - x = 1 - y = 2 - x + y - end -3 - -julia> x, y -(1, 2) -``` - -Как видно из примера, `begin-end` исполняется во внешнем пространстве имён. Его двойник блок `let-end` создаёт собственное пространство имён. Внутри `let-end` можно пользоваться именами извне, но если происходит присвоение, то имя создаётся внутри видимости `let-end`. - -```julia-repl -julia> x, y = 1, 2 -(1, 2) - -julia> let - x = 10 - y = 20 - x + y - end -30 - -julia> x, y -(1, 2) -``` - -С помощью `;` можно поместить несколько выражений на одной строке, что часто используется для коротких составных выражений или депривации вывода в REPL. - -```julia-repl -julia> z = (x = 1; y = 2; x + y) -3 - -julia> z = begin x = 1; y = 2; x + y end -3 -``` - -Предназначение `;` аналогично его предназначению в C-подобных языках, но в Julia не требуется ставить `;` после каждой инструкции. - -### Ветвление - -Основная конструкция это `if-elseif-else` блок. - -```julia-repl -julia> x, y = 10, 20; - -julia> if x < y - "x is less than y" - elseif x > y - "x is greater than y" - else - "x is equal to y" - end -"x is less than y" -``` - -- В `if` и `elseif` должно стоять boolean выражение; -- Количество `elseif` не ограничено. - -Блок `if-elseif-else`, как и `begin-end` является выражением и возвращает значение. В примере выше возвращается результат первой ветви исполнения -- строка "x is less than y". - -Также в вашем распоряжении тернарный оператор `cond ? whentrue : whenfalse`. - -```julia-repl -julia> count = 24; - -julia> "$count apple$(count > 1 ? "s" : "")" -"24 apples" -``` - -Помимо этого, в Julia есть `try/catch` для обработки программных исключений. - -### Циклы - -Julia предоставляет два цикла: `while` и `for`. - -```julia-repl -julia> i = 1; - -julia> while i <= 5 - println(i) - i += 1 - end -1 -2 -3 -4 -5 -``` - -Цикл `while` создаёт собственное пространство имён, что может вызвать фрустрацию. В REPL всё пространство имён глобальное, поэтому пример выше работает. Если же вы используете `while`-цикл в глобальном пространстве скрипта, то при обращении к переменной `i` будет ошибка. В этом случае можно внутри цикла указать `global i`, чтобы внутри `while` она была видна. Более лучший вариант это обернуть пример выше в функцию, функции создают собственное пространство имён и конфликта со вложенным в неё `while` не будет. - -У `for`-цикла следующий синтаксис. - -```julia -for item in iterator - ... -end -``` - -Переменная цикла `item` создаётся внутри видимости цикла `for` автоматически. После исполнения цикла она недоступна, если не была объявлена во внешней области видимости. - -```julia-repl -julia> for j in 1:3 - println(j) - end -1 -2 -3 - -julia> j -ERROR: UndefVarError: j not defined -``` - -Здесь использован *range operator* `start:stop`, создающий генератор арифметической прогрессии. - -```julia-repl -help?> 1:3 - (:)(start, [step], stop) - - Range operator. a:b constructs a range from a to b with a step size of 1 (a UnitRange), - and a:s:b is similar but uses a step size of s(a StepRange). -``` - -Итерировать можно и по коллекциям. Ниже пример для кортежа `Tuple`. - -```julia-repl -julia> for j in (1, 2, "hello") - println(j) - end -1 -2 -hello -``` - -Доступно множество утилит для итерирования: `zip`, `enumerate`, `drop`, `rest`... - -```julia-repl -julia> for (i, val) in enumerate((1, 2, "hello")) - println("$i: $val") - end -1: 1 -2: 2 -3: hello -``` - -Для циклов доступны стандартные команды досрочного завершения итерации `continue` и всего цикла `break`. - -Циклы могут быть вложенными. Для вложенного `for`-цикла существует альтернативный вариант синтаксиса. - -::::{tab-set} -:::{tab-item} Вложенный `for` -```julia-repl -julia> for j in 1:2 - for i in 3:4 - println("i = $i, j = $j") - end - end -i = 3, j = 1 -i = 4, j = 1 -i = 3, j = 2 -i = 4, j = 2 -``` -::: -:::{tab-item} Альтернативный синтаксис -```julia-repl -julia> for j in 1:2, i in 3:4 - println("i = $i, j = $j") - end -i = 3, j = 1 -i = 4, j = 1 -i = 3, j = 2 -i = 4, j = 2 -``` -::: -:::: - -## Функции - -```{tip} -Больше информации в мануале **[[url]](https://docs.julialang.org/en/v1/manual/functions/)**. -``` - -Основной синтаксис для функций в Julia - -```julia-repl -julia> function f(x, y) - return sqrt(x^2 + y^2) - end -f (generic function with 1 method) -``` - -Строго говоря, команда `return` необязательна: функция в Julia возвращает результат последнего выражения, однако, мы будем придерживаться [![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle). - -```{margin} -Раз есть тип `Nothing`, есть и `Something`! -``` -В теле функции может находиться несколько команд `return`, в этом случае при вызове сработает только одна из них. -Если необходимо, чтобы функция ничего не возвращала, тогда используется `return nothing`. -Тип `Nothing` имеет лишь одно значение `nothing`, представляющее в Julia отутствие значения. - -Зачастую пригождается более краткий синтаксис создания функции (*assignment form*) - -```julia-repl -julia> f(x, y) = sqrt(x^2 + y^2) -f (generic function with 1 method) -``` - -В этом случае справа от `=` может находиться составное выражение (*compound expression*) `begin-end`. - -```julia-repl -julia> g(x, y) = begin # или g(x, y) = begin z = f(x, y); return 2*z end - z = f(x, y) - return 2*z - end -g (generic function with 1 method) -``` - -Синтаксис вызова интуитивен - -```julia-repl -julia> f(3, 4) -5.0 - -julia> g(3, 4) -10.0 -``` - -В Julia аргументы передаются по принципу *pass-by-sharing*. Т.е. аргументы функции внутри тела ведут себя как новые переменные. Однако, у изменяемых *mutable* аргументов (например, массив), можно поменять значения, и они будут видны извне. По соглашению, если функция меняет свой аргумент, то в её имя добавляется `!` в конце, например, `map!(f, A, B)`, `push!(A, x)` (исключение составляют функции, работающие с вводом-выводом `print`, `write`,..). - -Функции являются **first-class** объектами. Ими можно "распоряжаться", как переменными: присваивать их другим переменным, передавать как аргумент... - -```julia-repl -julia> φ = f; - -julia> φ(3, 4) -5.0 -``` - -Важно, что операторы в Julia также являются функциями - -```julia-repl -julia> +(1, 2, 3) == 1 + 2 + 3 -true -``` - -Языковые конструкции, вроде доступа к элементу массива (`A[i]`) или полю структуры (`S.x`) являются операторами c функциональными аналогами. - -Можно создавать анонимные функции - -```julia-repl -julia> x -> 2x # короткий синтаксис -#1 (generic function with 1 method) - -julia> f4 = x -> 2x # анонимная функция x -> 2x присвоена переменной f4 -#3 (generic function with 1 method) - -julia> f4(8) -16 - -julia> function (x) # длинный синтаксис - return 3x - end -#5 (generic function with 1 method) - -julia> map(x -> 3x, 1:4) # пример применения -4-element Vector{Int64}: # map здесь создает массив - 3 # из утроенных значений - 6 # арифм. прогрессии от 1 до 4 - 9 - 12 -``` - -В Julia тип, соответствующий аргументам функции, является кортежем `Tuple`. Кортеж неизменная коллекция. - -```julia-repl -julia> tup = (3, 4) -(3, 4) - -julia> tup[1] -3 - -julia> (3,) # tuple из одного значения -(3,) -``` - -Функция, конечно, может и возращать `Tuple`, т.е. возвращать несколько значений. Если абстрагироваться, функция в Julia создаёт из одного кортежа значений другой кортеж. - -```julia-repl -julia> function addmul(x, y) - return x + y, x * y - end -addmul (generic function with 1 method) - -julia> a, b = addmul(3, 4) -(7, 12) - -julia> a -7 - -julia> b -12 -``` - -Также существует именованный кортеж `NamedTuple`, хранящий пары ключ-значение. На его основе создаются функции, принимающие аргументы по ключу. - -И можно присваивать аргументам значения по умолчанию. - -```julia -# x - позиционный, p - именованный со значением по умолчанию -julia> f(x; p=10) = p * x -f (generic function with 1 method) - -julia> f(1) -10 - -julia> f(2; p=20) -40 -``` - - -(type_system)= -## Система типов -```{tip} -Подробнее, как всегда, в мануале к языку **[[url]](https://docs.julialang.org/en/v1/manual/types/)**. -``` - -В Julia **сильная динамическая** система типов. Система типов и методы функций являются фундаментом по повторному использованию кода. - -```{margin} -Однако, стоит избегать и потенциально предугадывать места, в которых переменная меняет свой тип. Компилятор вас поощрит. -``` -Поскольку в Julia динамическая типизация, то переменная может менять свой тип в процессе работы программы. - -```julia-repl -julia> x = 5 -5 - -julia> typeof(x) -Int64 - -julia> x = 5.0 -5.0 - -julia> typeof(x) -Float64 -``` - -В Julia нельзя указать, чтобы переменная имела постоянное значение, но можно указать, что переменная *не меняет свой тип* - -```julia-repl -julia> const y = 10 -10 - -julia> y = 10.0 -ERROR: invalid redefinition of constant y -Stacktrace: - [1] top-level scope - @ REPL[6]:1 - -julia> y = 20 -WARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors. -20 -``` - -Julia не допустила присвоение `y = 10.0`, потому что оно меняет тип переменной `y::Int64`. Однако, присваивать значения `Int64` переменной `y` всё-таки можно, но не стоит этого делать. - -### Декларация типов - -С помощью оператора `::` вы можете *декларировать* тип объекта. Обычно это делается для - -- переменных; -- аргументов функции; -- возвращаемого функцией значения; -- полей композитных типов (структур). - -```{margin} -Конвертацию делает функция `convert(T, x)`. Правила конвертации можно задавать. -``` -Например, вы можете декларировать тип переменной внутри функции (или другой локальной области видимости). В таком случае при присвоении значения происходит конвертация. - -```julia-repl -julia> function foo() - x::Int8 = 100 - return x - end -foo (generic function with 1 method) - -julia> x = foo() -100 - -julia> typeof(x) -Int8 - -julia> typeof(100) -Int64 -``` - -Также вы можете декларировать тип возвращаемого значения функцией (хотя, делается это редко, поскольку компилятор выводит типы, если возможно). - -```julia-repl -julia> bar()::Int8 = 100 -bar (generic function with 1 method) - -julia> bar() -100 - -julia> typeof(bar()) -Int8 -``` - -### Какие бывают типы - -Типы в Julia классифицируются по следующим признакам (указаны не все) - -- абстрактный *abstract* (`AbstractFloat`) и конкретный *concrete* (`Float64`); -- примитивный *primitive* (`Float64`) и композитный *composite* (`Complex{Float64}`); -- параметрический *parametric* (`Complex{Float64}`); -- изменяемый (`Vector{Float64}`) и неизменяемый (`Tuple{Float64,Float64}`); -- ... - -В Julia система типов является деревом, корень которого тип `Any`. Листьями дерева типов являются **конкретные типы**. У значения такого типа известна структура в памяти. **Абстрактные** типы нужны в качестве промежуточных узлов дерева типов, выстраивая иерархию. - -```{note} -:class: dropdown - -Кроме того, объявление неабстрактного параметрического типа `T1{T2}` создаёт **UnionAll** тип `T1`. Последний ведёт себя как супертип (родительский) для параметризованных потомков. - -Например, `Rational{T}` порождает UnionAll `Rational`, и `Rational` будет супертипом для всех `Rational{T}`: `Rational{Int64}`, `Rational{Int8}`... - -В дереве ниже `UnionAll` типы помещены в параллелограммы. -``` - -Например, так выглядит часть дерева с числовыми и строчными типами, при этом - -- конкретные типы указаны в округлённых рамках; -- абстрактные в прямоугольных. - -```{mermaid} -flowchart TB - Any --> Number --> Real --> Integer - Any --> AbstractString --> String([String]) - AbstractString --> SubString[/SubString/] - Number --> Complex[/Complex/] - Real --> AbstractFloat - Real --> Rational[/Rational/] - Rational --> RationalInt64(["Rational{Int64}"]) - Rational --> RationalInt32(["Rational{Int32}"]) - Integer --> Int64([Int64]) - Integer --> Int32([Int32]) - Integer --> Int16([Int16]) - Integer --> Int8([Int8]) -``` - -Несколько функций для интроспекции системы типов - -- `subtypes(T)`: подтипы типа `T`; -- `isabstracttype(T)`: является ли тип `T` абстрактным; -- `isprimitivetype(T)`: является ли тип `T` примитивным; -- `ismutable(x)`: является ли значение `x` изменяемым. - -```{margin} -С точки зрения дерева, можно ли из `Ty` добраться до `Tx`. -``` -Также с помощью subtype-оператора `Tx <: Ty` можно проверять "является ли тип `Tx` подтипом типа `Ty`". - -```julia-repl -julia> Int64 <: Number -true -``` - -**Примитивные** типы представляются в виде набора бит. Примерами являются `Int`-ы и `Float`-ы. - -```{note} -Создание собственных абстрактных и примитивных типов здесь не разбирается. -``` - -(julia_composite)= -### Композитные типы - -**Композитный** тип имеет более сложную структуру в памяти, чем примитивный тип. Этот тип является набором именованных полей, а экземпляром такого типа можно манипулирвовать как одним значением. В других языках им соответствуют объекты (*objects*) или структуры (*structs*). Примерами встроенных композитых типов являются `Complex{T}`, `Rational{T}`, `Tuple`, `String`, `Array`, `IO`... - -Классический пример – структура для точки на плоскости. - -```julia-repl -julia> struct Point - x - y::Int64 # так указывается тип (можно и абстрактный) - end - -julia> p1 = Point(1.0, 2) -Point(1.0, 2) - -julia> typeof(p1) -Point - -julia> p1.x -1.0 - -julia> p1.x = 9 -ERROR: setfield! immutable struct of type Point cannot be changed -... -``` - -Присвоение можно разрешить, сделав структуру изменяемой (`mutable`). - -```julia-repl -julia> mutable struct MPoint - x - y - end - -julia> mp1 = MPoint(1, 2) -MPoint(1, 2) - -julia> mp1.x = 10 -10 - -julia> mp1 -MPoint(10, 2) -``` - -Иногда это может приводить к замедлению работы, поскольку `mutable struct` выделяется в куче, а не на стеке. - -Тем не менее, в поле обычной структуры можно хранить значение изменяемого типа. В таком случае поле хранит *ссылку на изменяемый объект*. Объект поменять можно, а ссылку – нет. Например, так хранятся массивы внутри структур. - -Конструктор (*constructor*) `Point(x, y)` для композитного типа можно поменять. Более того, можно создать несколько конструкторов. - -### Параметрические композитные типы - -```{margin} -Абстрактные параметрические типы тоже существуют. -``` -**Параметрический** тип это тип, который в своём объявлении содержит дополнительную информацию. Например, тип `Complex` в языке объявлен следующим образом **[[source]](https://github.com/JuliaLang/julia/blob/1326e4b00e6f27a4120c30eb12b578a6cee28039/base/complex.jl#L3)**. - -```julia -struct Complex{T<:Real} <: Number - re::T - im::T -end -``` - -Это объявление значит - -```{margin} -`Complex` в данном случае ни абстрактный, ни конкретный. -``` -- создать UnionAll-тип `Complex`, который будет вести себя как супертип для `Complex{T}`; -- создать параметрический тип `Complex{T}`, -- где параметр `T` является подтипом типа `Real`, -- при этом типы `Complex` и `Complex{T}` являются подтипами `Number`; -- у `Complex{T}` два поля: `re` и `im`, каждое из них имеет тип `T`. - -```{margin} -Это не значит, что массив в Julia может хранить только значения одного типа. Ведь есть абстрактные типы: `Any`, `Number`... -``` -В качестве параметров могут быть типы и значения примитивных типов. Например, в Julia объявлен тип для массивов ` AbstractArray{T,N}`, где под `T` подразумевается тип значений, а под `N` размерность массива (1 для векторов, 2 для матриц...). - -Параметрические типы порождают целое семейство типов. Член такого семейства – *любая комбинация разрешенных значений* параметров типа. - -Таким образом, с помощью параметризации композитного типа мы можем дать подсказки для компилятора, чтобы тот создавал оптимизированный код. - -#### Пример - -Рассмотрим две версии `Point` - -```julia-repl -julia> struct APoint - x - y - end - -julia> struct TPoint{T} - x::T - y::T - end -``` - -Создадим функцию, вычисляющую расстояние от точки до начала координат - -```julia-repl -julia> dist(p) = sqrt(p.x^2 + p.y^2) -dist (generic function with 1 method) -``` - -Заметьте, в этой функции нет никаких ограничений на тип `p`. - -Создадим два массива случайных точек - -```julia-repl -julia> AA = [APoint(rand(2)...) for _ in 1:1_000_000]; - -julia> TA = [TPoint(rand(2)...) for _ in 1:1_000_000]; - -julia> typeof(AA), typeof(TA) -(Vector{APoint}, Vector{TPoint{Float64}}) -``` - -Про массив `TA` компилятор явно знает больше, судя по `typeof`. - -Измерим время работы. Точный бенчмарк показывает разницу времени работы в два порядка. - -```julia-repl -julia> using BenchmarkTools - -julia> @btime dist.(AA); - 117.766 ms (4999502 allocations: 83.92 MiB) - -julia> @btime dist.(TA); - 1.290 ms (5 allocations: 7.63 MiB) -``` - -```{tip} -:class: dropdown - -Поисследовать, может ли компилятор предугадать типы в теле вызова можно с помощью макроса `@code_warntype` - -:::julia-repl -julia> @code_warntype dist(APoint(1, 2)) -Variables - #self#::Core.Const(dist) - p::APoint - -Body::Any -1 ─ %1 = Base.getproperty(p, :x)::Any -│ %2 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %3 = (%2)()::Core.Const(Val{2}()) -│ %4 = Base.literal_pow(Main.:^, %1, %3)::Any -│ %5 = Base.getproperty(p, :y)::Any -│ %6 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %7 = (%6)()::Core.Const(Val{2}()) -│ %8 = Base.literal_pow(Main.:^, %5, %7)::Any -│ %9 = (%4 + %8)::Any -│ %10 = Main.sqrt(%9)::Any -└── return %10 - -julia> @code_warntype dist(TPoint(1, 2)) -Variables - #self#::Core.Const(dist) - p::TPoint{Int64} - -Body::Float64 -1 ─ %1 = Base.getproperty(p, :x)::Int64 -│ %2 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %3 = (%2)()::Core.Const(Val{2}()) -│ %4 = Base.literal_pow(Main.:^, %1, %3)::Int64 -│ %5 = Base.getproperty(p, :y)::Int64 -│ %6 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %7 = (%6)()::Core.Const(Val{2}()) -│ %8 = Base.literal_pow(Main.:^, %5, %7)::Int64 -│ %9 = (%4 + %8)::Int64 -│ %10 = Main.sqrt(%9)::Float64 -└── return %10 -::: -``` - -## Методы и multiple dispatch - -Для каждой функции в Julia можно определить сколько угодно методов (*methods*). Это способ полиформизма в языке. Вы уже с ним сталкивались, например, `1 + 2` и `1.0 + 2.0` совершенно разные вызовы. В первом случае вызывается метод `+(x, y)` для `Int64`, а во втором метод `+(x, y)` для сложения `Float64`. - -У сложения `+` в Julia 1.6.2 190 методов. - -```julia-repl -julia> methods(+) -# 190 methods for generic function "+": -[1] +(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:87 -[2] +(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigInt) in Base.GMP at gmp.jl:528 -[3] +(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) in Base.GMP at gmp.jl:534 -... -``` - -Узнать, какой метод вызвался можно макросом `@which`. - -```julia-repl -julia> @which 1 + 2 -+(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:87 - -julia> @which 1.0 + 2.0 -+(x::Float64, y::Float64) in Base at float.jl:326 - -julia> @which 1.0 + 2 -+(x::Number, y::Number) in Base at promotion.jl:321 -``` - -Можно сказать, что функция определяет дефолтное действие с аргументами. А методы функции содержат частные реализации этих действий на случаи тех или иных аргументов. Например, метод `sum` для вектора сложит все элементы и это займёт линейное время, а `sum` для арифметической прогрессии займёт константное время, используя формулу. При этом с точки зрения пользователя сигнатура вызова одна и та же: `sum(A)`. - -Процесс выбора нужного метода называется **диспетчеризацией** (*dispatch*). В Julia диспетчеризация производится **по типам *всех* позиционных аргументов функции**. Этот механизм называется *multiple dispatch*. Он гибче и продуктивнее, нежели диспетчеризация по одному типу, например, как в Python (`type(x).__add__(x, y)`). При этом, в отличие от языков со статической типизацией, нет необходимости указывать типы аргументов. - -Строго говоря, *generic function* единственна, а методов у неё много. Однако, всё же принято называть методы функциями, если контекст позволяет. - -Методы создаются как функции, но с указанием типа хотя бы одного аргумента. - -```julia-repl -julia> f(x, y) = 2x + y -f (generic function with 1 method) - -julia> f(x::Float64, y::Float64) = 3x + y -f (generic function with 2 methods) - -julia> methods(f) -# 2 methods for generic function "f": -[1] f(x::Float64, y::Float64) in Main at REPL[28]:1 -[2] f(x, y) in Main at REPL[26]:1 -``` - -Здесь же посмотрим на диспетчеризацию -```julia-repl -julia> f(1, 1) -3 - -julia> f(1.0, 1.0) # два Float64, подходит f(x::Float64, y::Float64) -4.0 - -julia> f(1.0, 1) # Float64 и Int64, подходит f(x, y) -3.0 -``` - -Конечно, использование не конкретных типов разрешено - -```julia-repl -julia> f(x::Complex, y::Complex) = 5x + y*im -f (generic function with 3 methods) - -julia> f(1.5im, 2.5im) --2.5 + 7.5im - -julia> f(1.5im, 2.5) -2.5 + 3.0im -``` - -При диспетчеризации может возникать коллизия: два или более метода подходят для вызова. В этом случае Julia выдаст ошибку `MethodError`. - -**Как создаётся быстрый код?** При запуске функции или метода от данного набора аргументов в первый раз, Julia - -- Запоминает типы аргументов при вызове (типы могут быть и абстрактные); -- Выводит типы переменных в теле функции (*type inference*), для которых это возможно; -- Компилирует функцию для данного набора типов аргументов и сохраняет машинный код, если все типы переменных **стабильны**, т.е. не зависят от *значений* аргументов; -- При дальнейших вызовах функции с теми же типами аргументов будет использоваться компилированная (быстрая) версия. - -Кроме того, до запуска скрипта (*compilation time*) Julia просматривает методы и некоторые из них может прекомпилировать. - -Методы могут быть параметрическими, и в их теле вам будет доступен тип аргумента на этапе компиляции (`typeof(x)` не нужен). - -```{tip} -:class: dropdown - -На методах основаны интерфейсы в языке. Например, вы можете создавать собственные структуры данных, у которых будет поведение массивов. Как только вы объявите методы интерфейса для своего типа, вы сможете пользоваться всеми функциями, определенными для `AbstractArray{T,N}`. Или, скажем, вы можете встроить свои структуры данных в интерфейс цикла `for`. - -С помощью методов также создаются типы, ведущие себя как функции: их можно вызывать (*callable*). На этом основаны замыкания (*closures*) в Julia. - -Изобретено множество дизайн-паттернов с использованием методов и типов. За подробностями по теме методов обращайтесь в мануал **[[url]](https://docs.julialang.org/en/v1/manual/methods/)**. Много паттернов описано в книге {cite}`Kwong2020`. -``` - -## Массивы - -### Массивы - -В Julia для массивов существует абстрактный тип `AbstractArray{T,N}`, где `T` тип элемента массива (`Int64`, `String`, `Complex{Int64}`, `Number`, `Any`...), а `N` размерность. При написании собственных типов с поведением массива в объявлении следует указать, что ваш тип является подтипом `AbstractArray`. - -Встроенным типом для массивом является `Array{T,N}`. Это изменяемый массив динамического размера с *column-major* хранением элементов. - -:::{note} -Поскольку в Julia массивы хранятся постолбично, то для быстродействия вложенный цикл должен проходится по строке, а внешний по столбцу. Вообще, если есть массив `A[i, j, k]`, то цикл должен выглядить так: - -```julia -for k in eachindex(A, 3) - for j in eachindex(A, 2) - for i in eachindex(A, 1) - ... - end - end -end -``` -::: - -Существуют два часто используемых синонима - -- `Vector{T} == Array{T,1}` для одномерных вектор-столбцов; -- `Matrix{T} == Array{T,2}` для матриц и вектор-строк. - -Литералом `Array{T,N}` являются квадратные скобки `[]`, при этом можно явно указать тип `T[]` (`Int[1, 2]`, `Float64[1, 2]`). Создание массива с помощью литерала осуществляется посредством вертикальной и горизонтальной *конкатенации*. - -Для **вертикальной конкатенации** используется `;` или новая строка. - -::::{tab-set} -:::{tab-item} Вектор из скаляров -```julia-repl -julia> [1, 2, 3] -3-element Vector{Int64}: - 1 - 2 - 3 -``` -::: -:::{tab-item} Вертикальная конкатенация -```julia-repl -julia> [[1, 2, 3]; [7, 8]] -5-element Vector{Int64}: - 1 - 2 - 3 - 7 - 8 -``` -::: -:::: - -Для **горизонтальной конкатенации** используется пробел ` ` или табуляция. Запятая `,` означает отсутствие конкатенации. - -::::{tab-set} -:::{tab-item} Вектор-строка -```julia-repl -julia> [1 2 3 4] -1×4 Matrix{Int64}: - 1 2 3 4 -``` -::: -:::{tab-item} Горизонтальная конкатенация -```julia-repl -julia> [[1, 2] [3, 4]] -2×2 Matrix{Int64}: - 1 3 - 2 4 -``` -::: -:::: - -Если конкатенация не нужна, используйтся запятая `,`. В примере ниже показано создание вектора векторов. - -```julia-repl -julia> [[1, 2, 3], [7, 8]] -2-element Vector{Vector{Int64}}: - [1, 2, 3] - [7, 8] -``` - -На первый взгляд, синтаксис может показаться запутанным. Однако, он позволяет создавать блочные матрицы и тензоры. - -(demo_create_block_matrix)= -```{proof:demo} Создание блочной матрицы - -Скажем, задана блочная матрица - -:::{math} -\mathcal{M} = \left[\begin{array}{ccc|ccc} -1 & 2 & 3 & 1 & 0 & 0 \\ -4 & 5 & 6 & 0 & 1 & 0 \\ -7 & 8 & 9 & 0 & 0 & 1 \\ \hline -0 & 0 & 0 & 10 & 11 & 12 \\ -\end{array}\right] -= \left[\begin{array}{c|c} -A & I \\ \hline -0^\top & b^\top -\end{array}\right] -::: - -Соответствующий код будет - -:::julia-repl -julia> A = [1 2 3; 4 5 6; 7 8 9] -3×3 Matrix{Int64}: - 1 2 3 - 4 5 6 - 7 8 9 - -julia> I = [1 0 0; 0 1 0; 0 0 1] -3×3 Matrix{Int64}: - 1 0 0 - 0 1 0 - 0 0 1 - -julia> zero = [0, 0, 0] -3-element Vector{Int64} - 0 - 0 - 0 - -julia> b = [10, 11, 12] -3-element Vector{Int64}: - 10 - 11 - 12 - -julia> M = [A I; zero' b'] -4×6 Matrix{Int64}: - 1 2 3 1 0 0 - 4 5 6 0 1 0 - 7 8 9 0 0 1 - 0 0 0 10 11 12 -::: - -Оператор `'` (одинарная кавычка) выполняет [транспонирование](arrays_linops). -``` - -### Индексирование - -В Julia встроено два вида индексов. - -Синтаксис первого `A[i]`, это линейный индекс `LinearIndex`. Он позволяет получить `i`-ый *по счёту в памяти* элемент массива. Например, для вектора `A[4]` это $A_4$, а для матрицы размера $2 \times 3$ это $A_{1, 3}$. - -Синтаксис второго `A[i, j, k,..]`, это декартов индекс `CartesianIndex`. Данный индекс учитывает размерность массива. Например, для матрицы элемент `A[i, j]` это элемент $A_{i,j}$ ($i$-ая строка, $j$-ый столбец). - -Индексом может быть и коллекция элементов, что позволяет обращаться к целым строкам, столцам, их пересечению, или просто некоторому набору элементов. Часто для этого используется *range operator* `start:[step:]stop`. - -%Например, для матрицы, обращение `A[I, J]` порождает матрицу из элементов `A[I[1], J[1]]`, `A[I[1], J[2]]`, `A[I[2], J[1]]`, т.е. подматрицу из $A_{ij}, i\in I, j\in J$. - -Ниже показано несколько примеров для матрицы. - -```julia-repl -julia> A = [1 2 3; 4 5 6; 7 8 9] -3×3 Matrix{Int64}: - 1 2 3 - 4 5 6 - 7 8 9 -``` - -::::{tab-set} -:::{tab-item} Один элемент -```julia-repl -julia> A[6] # линейный индекс -8 - -julia> A[3, 2] # декартов индекс -8 - -julia> A[end, end] -9 -``` -::: -:::{tab-item} Целая строка/столбец - -Строка. -```julia -julia> A[1, :] # A[строка 1, все столбцы] -3-element Vector{Int64}: - 1 - 2 - 3 -``` - -Столбец. -```julia-repl -julia> A[:, 2] # A[все строки, столбец 2] -3-element Vector{Int64}: - 2 - 5 - 8 -``` -::: -:::{tab-item} Подматрица - -"Пересечение" строк 1 и 2 со столбцами 2 и 3. -```julia-repl -julia> A[1:2, 2:3] -2×2 Matrix{Int64}: - 2 3 - 5 6 -``` - -Угольные элементы. - -```julia-repl -julia> A[[1, end], [1, end]] -2×2 Matrix{Int64}: - 1 3 - 7 9 -``` - -::: -:::{tab-item} Диагонали - -Главная диагональ. - -```julia-repl -julia> A[1:4:end] -3-element Vector{Int64}: - 1 - 5 - 9 -``` - -Побочная диагональ. - -```julia-repl -julia> A[3:2:7] -3-element Vector{Int64}: - 7 - 5 - 3 -``` -::: -:::: - -### Присваивание значений - -Массив `Array{T,N}` изменяемый тип, можно перезаписывать его элементы. Это делается с помощью оператора присваивания `=`, при этом по обе стороны должны находиться объекты одинаковых размерностей. - -```julia-repl -julia> A = [1 2 3; 4 5 6; 7 8 9]; - -julia> A[:, 1] = [7, 4, 1]; - -julia> A -3×3 Matrix{Int64}: - 7 2 3 - 4 5 6 - 1 8 9 - -julia> A[1, :] = [-1, 0, 1]; - -julia> A -3×3 Matrix{Int64}: - -1 0 1 - 4 5 6 - 1 8 9 - -julia> A[1, 2] = 10; - -julia> A -3×3 Matrix{Int64}: - -1 10 1 - 4 5 6 - 1 8 9 -``` - -При присваивании можно использовать [векторизацию](broadcasting). - -```julia-repl -julia> A[1, :] .= 11; - -julia> A -3×3 Matrix{Int64}: - 11 11 11 - 4 5 6 - 1 8 9 -``` - -### Вспомогательные функции - -Интроспекция массива - -- `length(A)`: количество элементов; -- `ndims(A)`: размерность; -- `size(A)`: кортеж из размеров каждой размерности `(число_строк, число_столбцов)`; -- `size(A, n)`: размер размерности `n`; -- `eachindex(A)`: итератор из индексов массива. - -Создание массивов - -- `collect(c)`: создание массива из коллекции; -- `zeros([T=Float64,] dims...)`: массив из нулей типа `T` размерности `dims...`; -- `ones([T=Float64,] dims...)`: аналогично `zeros`, но массив из единиц; -- `copy(A)`: нерекурсивная копия массива; -- `similar(A)`: неинициализированный массив той же размерности и типа, что `A`; -- `rand([T=Float64,] dims...)`: массив из равномерно-распределённых случайных чисел; -- `fill(x, dims...)`: массив размера `dims...` из `x`; -- `map(f, c)`: создание массива на основе применения функции `f` к каждому элементу коллекции `c`. - -Другие операции - -- `push!(A, x...)`: добавление в конец `A` элемента `x`; -- `pop!(A)`: извлечение элемента с конца `A`. - -Для чтения и записи в файл массивов в форматах с сепаратором (.csv, .tsv,..) есть встроенная библиотека [DelimitedFiles](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/). - -(arrays_linops)= -### Линейная алгебра - -```{tip} -Больше информации тут **[[url]](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/)**. -``` - -В Julia богатая стандартная библиотека операций линейной алгебры. Часто используемые инструменты доступны сразу. - -Ниже представлены примеры операций для этих векторов и матриц. - -```julia-repl -julia> a = [1, 2, 3]; b = [4, 5, 6]; - -julia> A = [1 2; 3 4]; B = [-1 -2; -3 -4]; -``` - -::::{tab-set} -:::{tab-item} Линейные -```julia-repl -julia> c = 2*a + b - a / 2 -3-element Vector{Float64}: - 5.5 - 8.0 - 10.5 - -julia> A/2 + 2*B -2×2 Matrix{Float64}: - -1.5 -3.0 - -4.5 -6.0 -``` -::: -:::{tab-item} Матричное умножение -```julia-repl -julia> A * [1, 2] -2-element Vector{Int64}: - 5 - 11 - -julia> A * B -2×2 Matrix{Int64}: - -7 -10 - -15 -22 -``` -::: -:::{tab-item} Транспонирование -```julia-repl -julia> a' -1×3 adjoint(::Vector{Int64}) with eltype Int64: - 1 2 3 - -julia> a' * b -32 - -julia> A * A' -2×2 Matrix{Int64}: - 5 11 - 11 25 -``` -Для комплексных матриц `'`-оператор выполняет эрмитово сопряжение. -::: -:::{tab-item} Решение СЛАУ -Решается система $A x = [1, 2]^\top$, `inv(A)`$= A^{-1}$. -```julia-repl -julia> x = A \ [1, 2] -2-element Vector{Float64}: - 0.0 - 0.5 - -julia> A * x -2-element Vector{Float64}: - 1.0 - 2.0 - -julia> inv(A) * [1, 2] == x -true -``` -::: -:::: - -Дополнительный набор инструментов импортируется из стандартной библиотеки `LinearAlgebra`. - -```julia-repl -julia> using LinearAlgebra - -julia> det(A), tr(A), norm(a) # детерминант, след, норма -(-2.0, 5, 3.7416573867739413) - -julia> a ⋅ b, A ⋅ B # скалярное умножение (dot) -(32, -30) - -julia> a × b # векторное умножение -3-element Vector{Int64}: - -3 - 6 - -3 -``` - -`LinearAlgebra` также содержит - -- типы для матриц специального вида; -- решатели СЛАУ; -- разложения матриц; -- функции над матрицами; -- низкоуровневые операции; -- [BLAS](https://ru.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms)-функции; -- обёртку над [LAPACK](https://ru.wikipedia.org/wiki/LAPACK). - -(broadcasting)= -## Векторизация функций - -```{tip} -Соответствующий раздел мануала **[[url]](https://docs.julialang.org/en/v1/manual/arrays/#man-array-and-vectorized-operators-and-functions)**. -``` - -В Julia *любая функция* может быть векторизована. Т.е. вы можете создать функцию для скаляров и автоматически получаете её векторизованный аналог. Векторизация осуществляется через механизм *broadcasting*. При этом достаточно в конце имени функции дописать точку `.` (*dot-syntax*). - -```julia-repl -julia> x = [0, π/6, π/3]; - -julia> sin(x) -ERROR: MethodError: no method matching sin(::Vector{Float64}) - ... - -julia> sin.(x) -3-element Vector{Float64}: - 0.0 - 0.49999999999999994 - 0.8660254037844386 -``` - -Механизм векторизации "насыщен" (*fused*). Для программиста это означает, что сложный вызов, например, `sin.(cos.(x))` *не медленнее* цикла, в котором к каждому элементу вектора `x` применили `sin(cos(x[i]))`. - -Автоматически векторизуются и пользовательские функции над стандартными типами. - -```julia-repl -julia> f(x) = x^2 + 1 -f (generic function with 1 method) - -julia> f.([1, 2, 3]) -3-element Vector{Int64}: - 2 - 5 - 10 - -julia> g(x, y) = f(x) + f(y) -g (generic function with 1 method) - -julia> g.([1, 2], [3, 4]) -2-element Vector{Int64}: - 12 - 22 - -julia> g.([1, 2], 3) -2-element Vector{Int64}: - 12 - 15 - -julia> parse.(Float64, ["1", "2.5", "-1.2e-9"]) -3-element Vector{Float64}: - 1.0 - 2.5 - -1.2e-9 -``` - -Для собственных типов нужно объявлять правила векторизации. Однако, если ваш тип должен вести себя как скаляр, можно воспользоваться `Ref(x)`. Ниже определяется модель идеального газа и его давление. Затем, с помощью `Ref` и векторизации вычисляется давление кислорода при фиксированной плотности для ряда температур. - -```julia-repl -julia> struct IdealGasComponent - name::String - molarmass::Float64 - end - -julia> pressure(c::IdealGasComponent, ρ, T) = ρ * 8.314 * T / c.molarmass -pressure (generic function with 1 method) - -julia> oxygen = IdealGasComponent("oxygen", 0.016) -IdealGasComponent("oxygen", 0.016) - -julia> pressure(oxygen, 500, 300) -7.794375e7 - -julia> pressure.(Ref(oxygen), 500, [300, 350, 400]) -3-element Vector{Float64}: - 7.794375e7 - 9.0934375e7 - 1.03925e8 -``` - -Операторы тоже функции. Так, broadcast порождает, например, поэлементные операции над векторами и матрицами (`.+`, `.*`, ...). - -```julia-repl -julia> 2 * sin.(x) .* cos.(x) == sin.(2 * x) -true -``` - -```{proof:observation} Полиморфизм -В этом примере несколько поэлементых видов умножений. - -- `2 * x`: умножение скаляра на вектор, оно и без броадкаста действует поэлементно; -- `x .* y`: поэлементное умножение векторов. -``` - -Если вам надоедает ставить точки везде, воспользуйтесь макросом `@.` - -```julia-repl -julia> x = [0, π/6, π/3]; - -julia> @. 2 * sin(x) * cos(x) -3-element Vector{Float64}: - 0.0 - 0.8660254037844386 - 0.8660254037844388 -``` - -Ещё одно важное применение броадкаста: *in-place* присваивание. Оно делает вашу программу менее прожорливой по памяти, а сборщик мусора не будет добавлять времени работы. - -```julia-repl -julia> x = rand(100); y = rand(100); - -julia> @allocated z = x + y; # первый вызов включает компиляцию - -julia> @allocated z = x + y -896 - -julia> z = similar(x); # выделили память под `z` один раз - -julia> @allocated z .= x .+ y; # первый вызов включает компиляцию - -julia> @allocated z .= x .+ y -64 -``` - -```{proof:demo} (Ещё один) бенчмарк -На аллокации требуется время, а ещё время требуется для работы сборщика мусора. На данных небольшого размера время сборщика мусора существенно по сравнению с временем исполнения. - -Так, сложение двух векторов размера 100 с аллокацией требует в тесте в среднем 85 нс, а с использованием *in-place* операций 22 нс. Причём разницу, судя по бенчмарку, занимает сборщик мусора (*garbage collector*, *GC*). - -:::julia-repl -julia> using BenchmarkTools - -julia> x = rand(100); y = rand(100); z = similar(x); - -julia> @benchmark $z = $x + $y -BenchmarkTools.Trial: 10000 samples with 973 evaluations. - Range (min … max): 75.194 ns … 619.990 ns ┊ GC (min … max): 0.00% … 0.00% - Time (median): 78.805 ns ┊ GC (median): 0.00% - Time (mean ± σ): 85.932 ns ± 41.564 ns ┊ GC (mean ± σ): 5.88% ± 9.87% - - █▄▁ ▁ - █████▇█▇▅▅▅▅▄█▇▄▃▃▅▄▁▄▃▃▁▁▄▄▁▄▁▁▁▁▁▁▁▁▁▁▁▁▁▄▁▁▃▁▃▃▁▁▄▅▆▅▇▆▇▆ █ - 75.2 ns Histogram: log(frequency) by time 365 ns < - - Memory estimate: 896 bytes, allocs estimate: 1. - -julia> @benchmark $z .= $x .+ $y -BenchmarkTools.Trial: 10000 samples with 997 evaluations. - Range (min … max): 20.640 ns … 398.402 ns ┊ GC (min … max): 0.00% … 0.00% - Time (median): 20.930 ns ┊ GC (median): 0.00% - Time (mean ± σ): 22.264 ns ± 8.109 ns ┊ GC (mean ± σ): 0.00% ± 0.00% - - █▃▁▁▁ ▁ - █████▇▆▆▇▇▆▆▆▆▆▆▆▆▅▅▅▆▆▆▆▆▇▇▇▇▇▇▆▇▇▆▇▇▇▆▅▆▆▆▆▄▄▅▅▄▄▄▄▄▅▃▁▄▁▄ █ - 20.6 ns Histogram: log(frequency) by time 45 ns < - - Memory estimate: 0 bytes, allocs estimate: 0. -::: - -Повторим тест для больших векторов, возьмём их размером 1000000. - -:::julia-repl -julia> x = rand(1_000_000); y = rand(1_000_000); z = similar(x); - -julia> @benchmark $z = $x + $y -BenchmarkTools.Trial: 2902 samples with 1 evaluation. - Range (min … max): 901.201 μs … 6.733 ms ┊ GC (min … max): 0.00% … 46.36% - Time (median): 1.275 ms ┊ GC (median): 0.00% - Time (mean ± σ): 1.713 ms ± 976.100 μs ┊ GC (mean ± σ): 26.05% ± 25.78% - - ██▄▁ ▁▄▄▂▁ ▁ - ▃▁▁▁▁▅████▇▄▇▅▃▃▁▃▁▁▄▃▁▁▁▃▁▃▃▁▃▁▁▁▃▁▁▁▁▁▁▁▁▁▃▃▁▁▁▁▁▁▁▅██████▇ █ - 901 μs Histogram: log(frequency) by time 470 ms < - - Memory estimate: 7.63 MiB, allocs estimate: 2. - -julia> @benchmark $z .= $x .+ $y -BenchmarkTools.Trial: 5360 samples with 1 evaluation. - Range (min … max): 789.767 μs … 5.811 ms ┊ GC (min … max): 0.00% … 0.00% - Time (median): 832.923 μs ┊ GC (median): 0.00% - Time (mean ± σ): 921.733 μs ± 295.907 μs ┊ GC (mean ± σ): 0.00% ± 0.00% - - ▅█▆▃▃▂▁▁▁▁▁▁▁▁ ▁ - ██████████████████▇█▇▇▆▆▇▆▅▆▅▆▆▅▆▅▅▅▄▄▄▄▄▄▄▃▄▅▅▄▅▅▁▄▃▄▅▄▄▄▄▄▅ █ - 790 μs Histogram: log(frequency) by time 2.42 ms < - - Memory estimate: 0 bytes, allocs estimate: 0. -::: - -На векторах размера 100 разница среднего времени исполнения составляла $\approx 4$ раза, а на больших векторах уменьшилась до $\approx 2$ раз. -``` - -## Модули - -```{tip} -Подробнее в секции мануала **[url](https://docs.julialang.org/en/v1/manual/modules/)**. -``` - -В Julia можно разбивать исходный код программы на модули (*modules*). Модуль создаёт собственное пространство имён и может быть прекомпилирован. - -Основной синтаксис выглядит так. - -```julia -module Points - -using LinearAlgebra - -export dist, Point - -include("types.jl") -include("functions.jl") - -private_foo() = println("Hello!") - -end # module -``` - -Всё, что между командами `module ... end` представляет собой модуль. В данном примере создаётся модуль `Points`. - -Инструкция `using LinearAlgebra` импортирует публичные имена из модуля `LinearAlgebra`. При таком вызове, например, функция `LinearAlgebra.norm` из модуля доступна просто по имени `norm`. Фактически, программист так указывает зависимости модуля. - -Модуль `Points` также делает имена `dist` и `Point` публичными. Т.е., когда кто-нибудь импортирует `Points` командой `using`, то ему будут доступны имена `dist` и `Point`. Точно также где-то в исходном коде модуля `LinearAlgebra` происходит экспорт имени `norm`. - -Функция `include("")` делает подстановку содержимого файла в модуль. В Julia позднее связывание имён, поэтому вы можете спокойно экспортировать что-то, а объявить где-то позднее. - -Помимо этого, при импортировании есть следующие опции. - -```{list-table} -:header-rows: 1 - -* - Команда импорта - - Какие имена доступны -* - `using Points` - - `Points`, `dist`, `Point`, остальные через точку: `Points.private_foo` -* - `using Points: dist` - - `dist` -* - `using Points: dist as d` - - `d` -* - `import Points` - - `Points`, остальные через точку -* - `import Points as Pnts` - - `Pnts`, остальные через точку -``` - -### Пример разработки модуля - -Ниже показана разработка модуля в несколько этапов. В нём привычная структура `Point{T}`, а её интерфейс оборачивается в модуль. Затем, для примера, структура встраивается в существующую экосистему языка: можно скалярно умножать точки, складывать или умножать на скаляр. - -::::{tab-set} - -:::{tab-item} Базовая разработка - -{file}`Points.jl` - -```julia -module Points - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -end # module -``` - -{file}`script.jl` - -```julia -include("path/to/Points.jl") -using .Points - -println(dist(Point(3, 4))) -println(Points.random_point()) -``` -::: - -:::{tab-item} Скалярное произведение - -{file}`Points.jl` - -```julia -module Points - -import LinearAlgebra # для добавления метода к скалярному произведению - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -# Добавление метода к скалярному произведению LinearAlgebra.dot -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -end # module -``` - -{file}`script.jl` - -```julia -include("path/to/Points.jl") -using .Points -using LinearAlbgebra # Для dot(x, y) - -println(dot(Point(-1, 2), Point(-2, -3))) -``` -::: - -:::{tab-item} Линейные операции - -{file}`Points.jl` - -```julia -module Points - -import LinearAlgebra - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -# Расширяение стандартной библиотеки языка, модуля Base -# `+` коммутативно -Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y) -# `*` не коммутативно -Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y) -Base.:*(p::Point, α::Number) = α * p - -end # module -``` - - -{file}`script.jl` -```julia -include("path/to/Points.jl") -using .Points - -println(Point(1, 2) + Point(3.0, 4.1)) -println(2 * Point(1, 2)) -println(Point(1, 2) * 2.0) -``` -::: -:::: - -### Разбиение исходного файла - -Функция `include("filename.jl")` вставляет содержимое {file}`filename.jl` в исходный код туда, где `include` был вызван. - -```{margin} -От реальной структуры отличается только отстутсвием файла с зависимостями пакета. -``` -Ниже показана типичная структура исходного когда библиотеки. - -::::{grid} 2 - -:::{grid-item-card} Структура библиотеки и {file}`Points.jl` - -Структура директории. -``` -src/ - operators.jl - interface.jl - types.jl - Points.jl -``` - -Код модуля {file}`src/Points.jl`. - -```julia -module Points - -import LinearAlgebra - -export dist -export Point - -include("types.jl") -include("interface.jl") -include("operators.jl") - -end # module -``` - -::: - -:::{grid-item-card} Остальной код - -{file}`src/types.jl` -```julia -struct Point{T} - x::T - y::T -end -``` - -{file}`src/interface.jl` - -```julia -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) -``` - -{file}`src/operators.jl` - -```julia -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y) - -Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y) -Base.:*(p::Point, α::Number) = α * p -``` -::: -:::: diff --git a/_sources/julia/arrays.md b/_sources/julia/arrays.md index 3c44c66..21ee5c6 100644 --- a/_sources/julia/arrays.md +++ b/_sources/julia/arrays.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Массивы и векторизация (broadcast) операций в Julia. + :keywords: julia, программирование, массив, array, vector, matrix, векторизация, broadcast +``` + # Массивы и broadcast В Julia для массивов существует абстрактный тип `AbstractArray{T,N}`, где `T` тип элемента массива (`Int64`, `String`, `Complex{Int64}`, `Number`, `Any`...), а `N` размерность. При написании собственных типов с поведением массива в объявлении следует указать, что ваш тип является подтипом `AbstractArray`. @@ -138,7 +144,7 @@ julia> M = [A I; zero' b'] 0 0 0 10 11 12 ::: -Оператор `'` (одинарная кавычка) выполняет [транспонирование](arrays_linops). +Оператор `'` (одинарная кавычка) выполняет {ref}`транспонирование `. ``` ## Индексирование @@ -275,7 +281,7 @@ julia> A 1 8 9 ``` -При присваивании можно использовать [векторизацию](broadcasting). +При присваивании можно использовать {ref}`векторизацию `. ```julia-repl julia> A[1, :] .= 11; @@ -316,7 +322,7 @@ julia> A Для чтения и записи в файл массивов в форматах с сепаратором (.csv, .tsv,..) есть встроенная библиотека [DelimitedFiles](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) и сторонний пакет [CSV.jl](https://github.com/JuliaData/CSV.jl). -(broadcasting)= +(sec:julia:broadcast)= ## Векторизация функций ```{tip} diff --git a/_sources/julia/controlflow.md b/_sources/julia/controlflow.md index 7f65cc0..eb2d8a0 100644 --- a/_sources/julia/controlflow.md +++ b/_sources/julia/controlflow.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Julia. Ветвление if-elseif-else и циклы for и while. + :keywords: julia, программирование, ветвление, циклы, if, if-else, if-else-if, for, while +``` + # Управляющие конструкции Подробнее в мануале **[[url]](https://docs.julialang.org/en/v1/manual/control-flow/)**. Здесь освещены не все конструкции и не так подробно. diff --git a/_sources/julia/ex.md b/_sources/julia/ex.md index 3efdcf3..64ae804 100644 --- a/_sources/julia/ex.md +++ b/_sources/julia/ex.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Упражнения для освоения базового синтаксиса языка Julia. + :keywords: julia, программирование, упражнения +``` + # Задания ## Упражнения @@ -18,20 +24,37 @@ Напишите функцию, подсчитывающую количество способов добраться из клетки с номером 1 до клетки с номером `n > 1`. 3\. -Напишите функцию, которая принимает на вход массив из чисел. -А возвращает новый массив, состоящий из положительных чисел исходного массива с сохранением порядка. +Напишите функцию, которая принимает на вход массив из чисел и возвращает _новый массив_, состоящий из положительных чисел исходного массива с сохранением порядка. +Пример входных и выходных данных: + +```julia +filterpositive([8, 0, -1, 2, -10]) == [8, 2] +``` 4\. Функция принимает на вход массив из целых неотрицательных чисел. -Функция создаёт новый массив из исходного, в котором сначала отсортированы по возрастанию нечётные числа, а затем, по возрастанию, чётные. +Функция _создаёт массив_ из исходного, в котором сначала отсортированы по возрастанию нечётные числа, а затем, по возрастанию, чётные. +Пример входных и выходных данных: + +```julia +sortoddeven([7, 4, 2, 9, 0, 1]) == [1, 7, 9, 0, 2, 4] +``` 5\. -Напишите функцию, подсчитывающую проекцию вектора $x$ на направление $d$. +Напишите функцию, подсчитывающую векторную проекцию вектора $\mathbf{x}$ на направление $\mathbf{d}$. +Пример входных и выходных данных: + +```julia +# x = d = +projection([1, 1], [2, 0]) == [1, 0] +``` 6\. Подсчитайте давление $P_r = P / P_c$ газа ван дер Ваальса вдоль изотерм $T_r = T / T_c = 0.85, 1.0, 1.15$. Уравнение состояния имеет вид $P_r = 8 T_r / (3 V_r - 1) - 3 / V_r^2$, где $V_r = V / V_c$. -Уравнение состояния должно быть оформлено в виде функции `pressurevdw(Vr, Tr)`. + +- Уравнение состояния должно быть оформлено в виде функции `pressurevdw(Vr, Tr)`; +- При подсчёте изотерм давления используйте объёмы из полуинтервала $V_r \in (1/3, 5]$. ## Создание пакета diff --git a/_sources/julia/functions.md b/_sources/julia/functions.md index c80031e..8ed0947 100644 --- a/_sources/julia/functions.md +++ b/_sources/julia/functions.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Julia. Определение и вызов функций, виды аргументов, операторы и кортежи. + :keywords: julia, программирование, функция, function, аргумент, argument, операторы, operator, кортеж, tuple +``` + # Функции Функция в Julia один из основных инструментов повторного использования кода. diff --git a/_sources/julia/index.md b/_sources/julia/index.md index 61491a8..ff5dd0a 100644 --- a/_sources/julia/index.md +++ b/_sources/julia/index.md @@ -1,8 +1,26 @@ --- -substitutions: - julia_logo: "" +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 +kernelspec: + display_name: Julia 1.9.4 + language: julia + name: julia-1.9 +myst: + substitutions: + julia_logo: "" --- +```{eval-rst} +.. meta:: + :description: Введение в программирование на языке Julia. + :keywords: julia, программирование, введение, учебник +``` + # Основы языка программирования Julia ```{epigraph} @@ -26,3 +44,61 @@ Julia продолжает набирать популярность. Этот **Как изучить?** В данном разделе излагаются основные инструменты языка Julia, которые понадобятся в практикуме. Дополнительные материалы по изучению языка находятся в Приложении {ref}`materials_julia`. + +```{proof:demo} Синтаксис Julia +``` + +```{raw} html +
+``` + +Ниже показано решение уравнения $\exp{x} + \log{x} - 2 = 0$ методом деления пополам. +Можете оценить синтаксис Julia по этому короткому примеру. + +```{code-cell} +:tags: [remove-output] + +function bisection(f, xl, xr; xtol=eps(), ftol=eps()) + @assert xl < xr + + yl, yr = f.((xl, xr)) + @assert sign(yl) != sign(yr) + + abs(yl) < ftol && return xl + abs(yl) < ftol && return xr + + maxiter = ceil(Int, log2((xr-xl)/xtol)) + + for i in 1:maxiter + xmid = (xr + xl) / 2 + ymid = f(xmid) + + if sign(yr) == sign(ymid) + xr, yr = xmid, ymid + elseif sign(yl) == sign(ymid) + xl, yl = xmid, ymid + else + return xmid + end + abs(ymid) < ftol && return xmid + end + return (xr + xl)/2 +end +``` + +```{code-cell} +f(x) = exp(x) + log(x) - 2 +xsol = bisection(f, 0.1, 2) +``` + +```{code-cell} +using Plots +using LaTeXStrings + +plot(f; label=L"\exp\ x + \log\ x - 2", xlim=(0, 1.5), ylim=(-6, 6), xlabel=L"x", ylabel=L"f(x)") +scatter!([xsol], [f(xsol)]; label="метод бисекции, корень $(round(xsol; digits=5))") +``` + +```{raw} html +
+``` diff --git a/_sources/julia/install.md b/_sources/julia/install.md index 164d3bc..b08e6f3 100644 --- a/_sources/julia/install.md +++ b/_sources/julia/install.md @@ -1,14 +1,26 @@ --- -substitutions: - urldownload: "https://julialang.org/downloads/" - wintermdwnld: "\"⊞\" [Windows Terminal](https://aka.ms/terminal)" - julia_logo: "" +myst: + substitutions: + urldownload: "https://julialang.org/downloads/" + wintermdwnld: "\"⊞\" [Windows Terminal](https://aka.ms/terminal)" + julia_logo: "" --- +```{eval-rst} +.. meta:: + :description: Установка языка компилятора языка Julia на Windows, Linux-системы и MacOS. + :keywords: julia, установка, инструкция +``` + # Установка Ниже расположены краткие инструкции по установке исполнителя языка Julia для Linux-based операционных систем (ОС), MacOS и Windows. При возникновении неясностей, обратитесь к [официальной инструкции](https://julialang.org/downloads/platform/) для вашей ОС. +```{warning} +Инструкция ниже написана для версии языка `1.6.2`. +Скорее всего, вам потребуется изменить некоторые команды, заменив в них `1.6.2` на скачанную вами версию языка. +``` + ## Linux-based ОС **1. Скачать последнюю версию интерпретатора** diff --git a/_sources/julia/julia.md b/_sources/julia/julia.md deleted file mode 100644 index 85662e0..0000000 --- a/_sources/julia/julia.md +++ /dev/null @@ -1,242 +0,0 @@ -## Модули - -```{tip} -Подробнее в секции мануала **[url](https://docs.julialang.org/en/v1/manual/modules/)**. -``` - -В Julia можно разбивать исходный код программы на модули (*modules*). Модуль создаёт собственное пространство имён и может быть прекомпилирован. - -Основной синтаксис выглядит так. - -```julia -module Points - -using LinearAlgebra - -export dist, Point - -include("types.jl") -include("functions.jl") - -private_foo() = println("Hello!") - -end # module -``` - -Всё, что между командами `module ... end` представляет собой модуль. В данном примере создаётся модуль `Points`. - -Инструкция `using LinearAlgebra` импортирует публичные имена из модуля `LinearAlgebra`. При таком вызове, например, функция `LinearAlgebra.norm` из модуля доступна просто по имени `norm`. Фактически, программист так указывает зависимости модуля. - -Модуль `Points` также делает имена `dist` и `Point` публичными. Т.е., когда кто-нибудь импортирует `Points` командой `using`, то ему будут доступны имена `dist` и `Point`. Точно также где-то в исходном коде модуля `LinearAlgebra` происходит экспорт имени `norm`. - -Функция `include("")` делает подстановку содержимого файла в модуль. В Julia позднее связывание имён, поэтому вы можете спокойно экспортировать что-то, а объявить где-то позднее. - -Помимо этого, при импортировании есть следующие опции. - -```{list-table} -:header-rows: 1 - -* - Команда импорта - - Какие имена доступны -* - `using Points` - - `Points`, `dist`, `Point`, остальные через точку: `Points.private_foo` -* - `using Points: dist` - - `dist` -* - `using Points: dist as d` - - `d` -* - `import Points` - - `Points`, остальные через точку -* - `import Points as Pnts` - - `Pnts`, остальные через точку -``` - -### Пример разработки модуля - -Ниже показана разработка модуля в несколько этапов. В нём привычная структура `Point{T}`, а её интерфейс оборачивается в модуль. Затем, для примера, структура встраивается в существующую экосистему языка: можно скалярно умножать точки, складывать или умножать на скаляр. - -::::{tab-set} - -:::{tab-item} Базовая разработка - -{file}`Points.jl` - -```julia -module Points - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -end # module -``` - -{file}`script.jl` - -```julia -include("path/to/Points.jl") -using .Points - -println(dist(Point(3, 4))) -println(Points.random_point()) -``` -::: - -:::{tab-item} Скалярное произведение - -{file}`Points.jl` - -```julia -module Points - -import LinearAlgebra # для добавления метода к скалярному произведению - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -# Добавление метода к скалярному произведению LinearAlgebra.dot -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -end # module -``` - -{file}`script.jl` - -```julia -include("path/to/Points.jl") -using .Points -using LinearAlbgebra # Для dot(x, y) - -println(dot(Point(-1, 2), Point(-2, -3))) -``` -::: - -:::{tab-item} Линейные операции - -{file}`Points.jl` - -```julia -module Points - -import LinearAlgebra - -export dist -export Point - -struct Point{T} - x::T - y::T -end - -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) - -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -# Расширяение стандартной библиотеки языка, модуля Base -# `+` коммутативно -Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y) -# `*` не коммутативно -Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y) -Base.:*(p::Point, α::Number) = α * p - -end # module -``` - - -{file}`script.jl` -```julia -include("path/to/Points.jl") -using .Points - -println(Point(1, 2) + Point(3.0, 4.1)) -println(2 * Point(1, 2)) -println(Point(1, 2) * 2.0) -``` -::: -:::: - -### Разбиение исходного файла - -Функция `include("filename.jl")` вставляет содержимое {file}`filename.jl` в исходный код туда, где `include` был вызван. - -```{margin} -От реальной структуры отличается только отстутсвием файла с зависимостями пакета. -``` -Ниже показана типичная структура исходного когда библиотеки. - -::::{grid} 2 - -:::{grid-item-card} Структура библиотеки и {file}`Points.jl` - -Структура директории. -``` -src/ - operators.jl - interface.jl - types.jl - Points.jl -``` - -Код модуля {file}`src/Points.jl`. - -```julia -module Points - -import LinearAlgebra - -export dist -export Point - -include("types.jl") -include("interface.jl") -include("operators.jl") - -end # module -``` - -::: - -:::{grid-item-card} Остальной код - -{file}`src/types.jl` -```julia -struct Point{T} - x::T - y::T -end -``` - -{file}`src/interface.jl` - -```julia -dist(p::Point) = sqrt(p.x^2 + p.y^2) -random_point() = Point(rand(2)...) -``` - -{file}`src/operators.jl` - -```julia -LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y - -Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y) - -Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y) -Base.:*(p::Point, α::Number) = α * p -``` -::: -:::: diff --git a/_sources/julia/linearalgebra.md b/_sources/julia/linearalgebra.md index 506f556..b917b52 100644 --- a/_sources/julia/linearalgebra.md +++ b/_sources/julia/linearalgebra.md @@ -1,4 +1,10 @@ -(arrays_linops)= +```{eval-rst} +.. meta:: + :description: Julia. Операции линейной алгебры и модуль LinearAlgebra. + :keywords: julia, программирование, линейная алгебра, linearalgebra, транспонирование, норма, матричное умножение +``` + +(sec:julia:linear-algebra)= # Линейная алгебра ```{tip} diff --git a/_sources/julia/modules.md b/_sources/julia/modules.md index 1b6b5f5..28b2690 100644 --- a/_sources/julia/modules.md +++ b/_sources/julia/modules.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Julia. Создание модулей, библиотек кода и пакетов. + :keywords: julia, программирование, модуль, пакет, библиотека, package, export, include, using, import +``` + # Модули и пакеты ## Модули diff --git a/_sources/julia/numbers.md b/_sources/julia/numbers.md index fbdf676..aac3879 100644 --- a/_sources/julia/numbers.md +++ b/_sources/julia/numbers.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Julia. Числовые типы, переменные, математические операции и логические типы. + :keywords: julia, программирование, основы, переменные +``` + # Числа, переменные, Bool Данный раздел является кратким обзором следующих разделов манула diff --git a/_sources/julia/run.md b/_sources/julia/run.md index f42d16e..427771c 100644 --- a/_sources/julia/run.md +++ b/_sources/julia/run.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Мы рассмотрим запуск Julia программ, работу с режимами Julia REPL и работу в ноутбуках Jupyter и Pluto. + :keywords: julia, учебник, repl, pluto, jupyter +``` + # Запуск программ Программы в Julia можно запускать в интерактивном (REPL) или скриптовом режиме. diff --git a/_sources/julia/strings.md b/_sources/julia/strings.md index 80186c8..2cb516c 100644 --- a/_sources/julia/strings.md +++ b/_sources/julia/strings.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Julia. Работа со строками и текстом. + :keywords: julia, программирование, основы, строки, текст +``` + # Строки Подробнее о строках в мануале **[[url]](https://docs.julialang.org/en/v1/manual/strings/)**. diff --git a/_sources/julia/types_methods_dispatch.md b/_sources/julia/types_methods_dispatch.md index 34cf40f..487a45c 100644 --- a/_sources/julia/types_methods_dispatch.md +++ b/_sources/julia/types_methods_dispatch.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Мы рассмотрим краегольный камень дизайна языка Julia - систему типов, multiple dispatch и методы. + :keywords: julia, программирование, функция, function, тип, type, дерево типов, метод, methods, диспатч, multiple dispatch +``` + # Типы, методы и multiple dispatch В Julia типы упорядочены в *дерево*, образуя систему. diff --git a/_sources/julia/typesystem.md b/_sources/julia/typesystem.md deleted file mode 100644 index 16897d0..0000000 --- a/_sources/julia/typesystem.md +++ /dev/null @@ -1,333 +0,0 @@ -(type_system)= -# Система типов - -В Julia **сильная динамическая** система типов. Система типов и методы функций являются фундаментом по повторному использованию кода. - -Подробнее в мануале к языку **[[url]](https://docs.julialang.org/en/v1/manual/types/)**. - -:::{margin} -Однако, стоит избегать и потенциально предугадывать места, в которых переменная меняет свой тип. Компилятор вас поощрит. -::: -Поскольку в Julia динамическая типизация, то переменная может менять свой тип в процессе работы программы. - -```julia-repl -julia> x = 5 -5 - -julia> typeof(x) -Int64 - -julia> x = 5.0 -5.0 - -julia> typeof(x) -Float64 -``` - -В Julia нельзя указать, чтобы переменная имела постоянное значение, но можно указать, что переменная *не меняет свой тип* - -```julia-repl -julia> const y = 10 -10 - -julia> y = 10.0 -ERROR: invalid redefinition of constant y -Stacktrace: - [1] top-level scope - @ REPL[6]:1 - -julia> y = 20 -WARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors. -20 -``` - -Julia не допустила присвоение `y = 10.0`, потому что оно меняет тип переменной `y::Int64`. Однако, присваивать значения `Int64` переменной `y` всё-таки можно, но не стоит этого делать. - -## Декларация типов - -С помощью оператора `::` вы можете *декларировать* тип объекта. Обычно это делается для - -- переменных; -- аргументов функции; -- возвращаемого функцией значения; -- полей композитных типов (структур). - -```{margin} -Конвертацию делает функция `convert(T, x)`. Правила конвертации можно задавать. -``` -Например, вы можете декларировать тип переменной внутри функции (или другой локальной области видимости). В таком случае при присвоении значения происходит конвертация. - -```julia-repl -julia> function foo() - x::Int8 = 100 - return x - end -foo (generic function with 1 method) - -julia> x = foo() -100 - -julia> typeof(x) -Int8 - -julia> typeof(100) -Int64 -``` - -Также вы можете декларировать тип возвращаемого значения функцией (хотя, делается это редко, поскольку компилятор выводит типы, если возможно). - -```julia-repl -julia> bar()::Int8 = 100 -bar (generic function with 1 method) - -julia> bar() -100 - -julia> typeof(bar()) -Int8 -``` - -## Какие бывают типы - -Типы в Julia классифицируются по следующим признакам (указаны не все) - -- абстрактный *abstract* (`AbstractFloat`) и конкретный *concrete* (`Float64`); -- примитивный *primitive* (`Float64`) и композитный *composite* (`Complex{Float64}`); -- параметрический *parametric* (`Complex{Float64}`); -- изменяемый (`Vector{Float64}`) и неизменяемый (`Tuple{Float64,Float64}`); -- ... - -В Julia система типов является деревом, корень которого тип `Any`. Листьями дерева типов являются **конкретные типы**. У значения такого типа известна структура в памяти. **Абстрактные** типы нужны в качестве промежуточных узлов дерева типов, выстраивая иерархию. - -```{note} -:class: dropdown - -Кроме того, объявление неабстрактного параметрического типа `T1{T2}` создаёт **UnionAll** тип `T1`. Последний ведёт себя как супертип (родительский) для параметризованных потомков. - -Например, `Rational{T}` порождает UnionAll `Rational`, и `Rational` будет супертипом для всех `Rational{T}`: `Rational{Int64}`, `Rational{Int8}`... - -В дереве ниже `UnionAll` типы помещены в параллелограммы. -``` - -Например, так выглядит часть дерева с числовыми и строчными типами, при этом - -- конкретные типы указаны в округлённых рамках; -- абстрактные в прямоугольных. - -```{mermaid} -flowchart TB - Any --> Number --> Real --> Integer - Any --> AbstractString --> String([String]) - AbstractString --> SubString[/SubString/] - Number --> Complex[/Complex/] - Real --> AbstractFloat - Real --> Rational[/Rational/] - Rational --> RationalInt64(["Rational{Int64}"]) - Rational --> RationalInt32(["Rational{Int32}"]) - Integer --> Int64([Int64]) - Integer --> Int32([Int32]) - Integer --> Int16([Int16]) - Integer --> Int8([Int8]) -``` - -Несколько функций для интроспекции системы типов - -- `subtypes(T)`: подтипы типа `T`; -- `isabstracttype(T)`: является ли тип `T` абстрактным; -- `isprimitivetype(T)`: является ли тип `T` примитивным; -- `ismutable(x)`: является ли значение `x` изменяемым. - -```{margin} -С точки зрения дерева, можно ли из `Ty` добраться до `Tx`. -``` -Также с помощью subtype-оператора `Tx <: Ty` можно проверять "является ли тип `Tx` подтипом типа `Ty`". - -```julia-repl -julia> Int64 <: Number -true -``` - -**Примитивные** типы представляются в виде набора бит. Примерами являются `Int`-ы и `Float`-ы. - -```{note} -Создание собственных абстрактных и примитивных типов здесь не разбирается. -``` - -(julia_composite)= -## Композитные типы - -**Композитный** тип имеет более сложную структуру в памяти, чем примитивный тип. Этот тип является набором именованных полей, а экземпляром такого типа можно манипулирвовать как одним значением. В других языках им соответствуют объекты (*objects*) или структуры (*structs*). Примерами встроенных композитых типов являются `Complex{T}`, `Rational{T}`, `Tuple`, `String`, `Array`, `IO`... - -Классический пример – структура для точки на плоскости. - -```julia-repl -julia> struct Point - x - y::Int64 # так указывается тип (можно и абстрактный) - end - -julia> p1 = Point(1.0, 2) -Point(1.0, 2) - -julia> typeof(p1) -Point - -julia> p1.x -1.0 - -julia> p1.x = 9 -ERROR: setfield! immutable struct of type Point cannot be changed -... -``` - -Присвоение можно разрешить, сделав структуру изменяемой (`mutable`). - -```julia-repl -julia> mutable struct MPoint - x - y - end - -julia> mp1 = MPoint(1, 2) -MPoint(1, 2) - -julia> mp1.x = 10 -10 - -julia> mp1 -MPoint(10, 2) -``` - -Иногда это может приводить к замедлению работы, поскольку `mutable struct` выделяется в куче, а не на стеке. - -Тем не менее, в поле обычной структуры можно хранить значение изменяемого типа. В таком случае поле хранит *ссылку на изменяемый объект*. Объект поменять можно, а ссылку – нет. Например, так хранятся массивы внутри структур. - -Конструктор (*constructor*) `Point(x, y)` для композитного типа можно поменять. Более того, можно создать несколько конструкторов. - -## Параметрические композитные типы - -```{margin} -Абстрактные параметрические типы тоже существуют. -``` -**Параметрический** тип это тип, который в своём объявлении содержит дополнительную информацию. Например, тип `Complex` в языке объявлен следующим образом **[[source]](https://github.com/JuliaLang/julia/blob/1326e4b00e6f27a4120c30eb12b578a6cee28039/base/complex.jl#L3)**. - -```julia -struct Complex{T<:Real} <: Number - re::T - im::T -end -``` - -Это объявление значит - -```{margin} -`Complex` в данном случае ни абстрактный, ни конкретный. -``` -- создать UnionAll-тип `Complex`, который будет вести себя как супертип для `Complex{T}`; -- создать параметрический тип `Complex{T}`, -- где параметр `T` является подтипом типа `Real`, -- при этом типы `Complex` и `Complex{T}` являются подтипами `Number`; -- у `Complex{T}` два поля: `re` и `im`, каждое из них имеет тип `T`. - -```{margin} -Это не значит, что массив в Julia может хранить только значения одного типа. Ведь есть абстрактные типы: `Any`, `Number`... -``` -В качестве параметров могут быть типы и значения примитивных типов. Например, в Julia объявлен тип для массивов ` AbstractArray{T,N}`, где под `T` подразумевается тип значений, а под `N` размерность массива (1 для векторов, 2 для матриц...). - -Параметрические типы порождают целое семейство типов. Член такого семейства – *любая комбинация разрешенных значений* параметров типа. - -Таким образом, с помощью параметризации композитного типа мы можем дать подсказки для компилятора, чтобы тот создавал оптимизированный код. - -### Пример - -Рассмотрим две версии `Point` - -```julia-repl -julia> struct APoint - x - y - end - -julia> struct TPoint{T} - x::T - y::T - end -``` - -Создадим функцию, вычисляющую расстояние от точки до начала координат - -```julia-repl -julia> dist(p) = sqrt(p.x^2 + p.y^2) -dist (generic function with 1 method) -``` - -Заметьте, в этой функции нет никаких ограничений на тип `p`. - -Создадим два массива случайных точек - -```julia-repl -julia> AA = [APoint(rand(2)...) for _ in 1:1_000_000]; - -julia> TA = [TPoint(rand(2)...) for _ in 1:1_000_000]; - -julia> typeof(AA), typeof(TA) -(Vector{APoint}, Vector{TPoint{Float64}}) -``` - -Про массив `TA` компилятор явно знает больше, судя по `typeof`. - -Измерим время работы. Точный бенчмарк показывает разницу времени работы в два порядка. - -```julia-repl -julia> using BenchmarkTools - -julia> @btime dist.(AA); - 117.766 ms (4999502 allocations: 83.92 MiB) - -julia> @btime dist.(TA); - 1.290 ms (5 allocations: 7.63 MiB) -``` - -```{tip} -:class: dropdown - -Поисследовать, может ли компилятор предугадать типы в теле вызова можно с помощью макроса `@code_warntype` - -:::julia-repl -julia> @code_warntype dist(APoint(1, 2)) -Variables - #self#::Core.Const(dist) - p::APoint - -Body::Any -1 ─ %1 = Base.getproperty(p, :x)::Any -│ %2 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %3 = (%2)()::Core.Const(Val{2}()) -│ %4 = Base.literal_pow(Main.:^, %1, %3)::Any -│ %5 = Base.getproperty(p, :y)::Any -│ %6 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %7 = (%6)()::Core.Const(Val{2}()) -│ %8 = Base.literal_pow(Main.:^, %5, %7)::Any -│ %9 = (%4 + %8)::Any -│ %10 = Main.sqrt(%9)::Any -└── return %10 - -julia> @code_warntype dist(TPoint(1, 2)) -Variables - #self#::Core.Const(dist) - p::TPoint{Int64} - -Body::Float64 -1 ─ %1 = Base.getproperty(p, :x)::Int64 -│ %2 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %3 = (%2)()::Core.Const(Val{2}()) -│ %4 = Base.literal_pow(Main.:^, %1, %3)::Int64 -│ %5 = Base.getproperty(p, :y)::Int64 -│ %6 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) -│ %7 = (%6)()::Core.Const(Val{2}()) -│ %8 = Base.literal_pow(Main.:^, %5, %7)::Int64 -│ %9 = (%4 + %8)::Int64 -│ %10 = Main.sqrt(%9)::Float64 -└── return %10 -::: -``` diff --git a/_sources/nlroot/bisection_regula_falsi.ipynb b/_sources/nlroot/bisection_regula_falsi.ipynb deleted file mode 100644 index 6c1e553..0000000 --- a/_sources/nlroot/bisection_regula_falsi.ipynb +++ /dev/null @@ -1,428 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "770a4e57", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "f0b286f4", - "metadata": {}, - "source": [ - "# Методы бисекции и regula falsi\n", - "\n", - "## Метод бисекции\n", - "\n", - "Для непрерывной функции известно, что, имея разные знаки $f(a)f(b)<0$ на концах отрезка $[a, b]$, функция $f$ имеет также корень $f(x^*)=0$ на этом отрезке $x^* \\in [a, b]$.\n", - "\n", - "Метод бисекции пользуется этим утверждением. Разобъём исходный отрезок $[x_1, x_2]$ пополам точкой $x_3 = (x_1 + x_2) / 2$. Тогда, если $x_3$ не является корнем уравнения, то $f$ имеет разные знаки либо на концах отрезка $[x_1, x_3]$, либо на концах отрезка $[x_3, x_2]$. Выберем в качестве нового отрезка тот, на котором функция имеет разные знаки и продолжим процедуру.\n", - "\n", - "Метод бисекции гарантирует локализацию корня. Поскольку за итерацию длина отрезка уменьшается вдвое $\\Delta_{k+1} = \\Delta_k / 2$, то имеет место *линейная сходимость* метода.\n", - "\n", - "Общая формула длины отрезка имеет вид\n", - "\n", - "```{math}\n", - "\\Delta_k = \\frac{\\Delta_0}{2^k}.\n", - "```\n", - "\n", - "Тогда, если потребовать точность найденного корня в виде\n", - "\n", - "```{math}\n", - "|x_{k+1} - x_k| = \\Delta_k < \\text{xtol},\\quad k = 0, 1, 2, ...\n", - "```\n", - "\n", - "то получим необходимое число итераций\n", - "```{margin}\n", - "$\\lceil \\cdot \\rceil$ -- округление до целого вверх (\"потолок\"), $\\lceil 1.1 \\rceil = \\lceil 1.5 \\rceil = \\lceil 1.9 \\rceil = 2$.\n", - "```\n", - "\n", - "```{math}\n", - "k_\\max = \\Big\\lceil \\log_2\\Big(\\frac{\\Delta_0}{\\text{xtol}}\\Big) \\Big\\rceil.\n", - "```\n", - "\n", - "Метод бисекции один из немногих, в которых известно наперёд число итераций, необходимое для достижения заданной точности.\n", - "\n", - "```{proof:function} bisection\n", - "\n", - "**Метод бисекции**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Ищет корень уравнения `f`(x) = 0 бисекцией с точностью локализации корня `xtol`.\n", - "Итерации заканчиваются досрочно, если `f`(xₖ) < `ftol`.\n", - "\"\"\"\n", - "function bisection(f, x₁, x₂; xtol=eps(), ftol=eps())\n", - " if x₁ > x₂; x₁, x₂ = x₂, x₁; end\n", - " y₁, y₂ = f(x₁), f(x₂)\n", - "\n", - " sign(y₁) == sign(y₂) && error(\"Функция должна иметь разные знаки в концах отрезка\")\n", - " abs(y₁) < ftol && return x₁\n", - " abs(y₂) < ftol && return x₂\n", - " \n", - " maxiter = ceil(Int, log2((x₂-x₁)/xtol))\n", - " \n", - " for i in 1:maxiter\n", - " xnew = (x₂ + x₁) / 2\n", - " ynew = f(xnew)\n", - " \n", - " if sign(y₂) == sign(ynew)\n", - " x₂, y₂ = xnew, ynew\n", - " elseif sign(y₁) == sign(ynew)\n", - " x₁, y₁ = xnew, ynew\n", - " else\n", - " return xnew\n", - " end\n", - " abs(ynew) < ftol && return xnew\n", - " end\n", - " return (x₂ + x₁)/2\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод бисекции\n", - "```\n", - "```{raw} html\n", - "
\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "f8054251", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bisection(f, 0.5, 1.6; xtol = 1.0e-6) = 0.9999997854232789\n", - "bisection(f, 0.5, 1.6; xtol = 1.0e-10) = 1.0000000000145521\n" - ] - } - ], - "source": [ - "f = (x) -> -x^2 + x\n", - "@show bisection(f, 0.5, 1.6; xtol=1e-6)\n", - "@show bisection(f, 0.5, 1.6; xtol=1e-10);" - ] - }, - { - "cell_type": "markdown", - "id": "53300f01", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Regula falsi\n", - "\n", - "В методе ложной позиции (*regula falsi*, *false position*) по двум приближениям корня $x_1$ и $x_2$, на которых функция имеет разные знаки $f(x_1)f(x_2) < 0$, проводится секущая. Затем вычисляется точка пересечения секущей с осью абсцисс $x_3$. После чего, подобно методу бисекции, по $f(x_3)$ выбирается новый интервал, локализующий корень.\n", - "\n", - "Для многих функций и начальных интервалов, метод regula falsi имеет *сверхлинейную сходимость* {cite}`NumRecipes2007`.\n", - "\n", - "Метод очень напоминает метод секущих. Разница лишь в том, что метод секущих всегда строит новое приближение корня по двум предыдущим, тогда как regula falsi, поддерживая разные знаки функции на концах отрезка, заменяет один из концов новым приближением.\n", - "\n", - "```{proof:algorithm} Метод regula falsi\n", - "Пусть задан отрезок $[x_l, x_r]$, такой что, $f(x_l)f(x_r)<0$.\n", - "\n", - "1. Вычислим $x_f$\n", - "\n", - " $$\n", - " x_f = \\frac{f(x_r)x_l - f(x_l)x_r}{f(x_r) - f(x_l)}.\n", - " $$\n", - "\n", - "2. Из двух $[x_l, x_f]$, $[x_f, x_r]$ в качестве нового выберем тот, на котором функция имеет разные знаки.\n", - "```\n", - "\n", - "```{proof:function} regulafalsi\n", - "\n", - "**Метод ложной позиции (regula falsi)**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Вычисляет корень уравнения `f`(x) = 0 методом ложной позиции.\n", - "Начальный отрезок задаётся как [`x₁`, `x₂`]. Выполняет не более `maxiter`\n", - "итераций. Если при этом интервал не уменьшился до `xtol` или абсолютное значение \n", - "функции на нём до `ftol`, то выдаёт ошибку.\n", - "\"\"\"\n", - "function regulafalsi(f, x₁, x₂; maxiter=25, xtol=eps(), ftol=eps())\n", - " if x₁ > x₂; x₁, x₂ = x₂, x₁; end\n", - " y₁, y₂ = f.((x₁, x₂))\n", - " sign(y₁) == sign(y₂) && error(\"Функция должна иметь разные знаки в концах отрезка\")\n", - " abs(y₁) < ftol && return x₁\n", - " abs(y₂) < ftol && return x₂\n", - " \n", - " for i in 1:maxiter\n", - " y₂ = f(x₂)\n", - " xnew = (y₂*x₁ - y₁*x₂) / (y₂ - y₁)\n", - " ynew = f(xnew)\n", - "\n", - " if sign(y₂) == sign(ynew)\n", - " x₂, y₂ = xnew, ynew\n", - " elseif sign(y₁) == sign(ynew)\n", - " x₁, y₁ = xnew, ynew\n", - " else\n", - " return xnew\n", - " end\n", - " abs(ynew) < ftol && return xnew\n", - " abs(x₂ - x₁) < xtol && return xnew\n", - " end\n", - " error(\"Число итераций превышено.\")\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод regula falsi\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Ниже показаны несколько первых секущих, порождающихся методом regula falsi для функции $-x^2 + x + 10$ с начальным отрезком $[-4, 2]$. Заметьте, как одна из точек отрезка для данной функции остаётся фиксированной." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "3c501043", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/nlroot/bisection_regula_falsi_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "f = (x) -> -x^2 + x + 10\n", - "path = [\n", - " -4 2;\n", - " -4 -0.6666666666666666;\n", - " -4 -2.235294117647059;\n", - "]\n", - "root = regulafalsi(f, -4, 2; ftol=1e-6)\n", - "plot(f;\n", - " xlim=(-4.5, 3),\n", - " label=L\"-x^2 + x + 10\",\n", - " leg=:bottomright,\n", - " lw=2,\n", - " xlabel=L\"x\",\n", - " ylabel=L\"f(x)\",\n", - ")\n", - "for (i, p) in eachrow(path) |> enumerate\n", - " plot!(p, f.(p); label=\"секущая $i\", marker=:o)\n", - "end\n", - "scatter!([root], [f(root)]; label=\"найденный корень\", color=:red, marker=:square)" - ] - }, - { - "cell_type": "markdown", - "id": "26f186b9", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Упражнения\n", - "\n", - "1. Почему в методе regula falsi важно устанавливать гарантию малости функции $\\text{ftol}$?\n", - "2. Для каких функций в методе regula falsi одна из точек приближения корня остаётся фиксированной в течение работы всего алгоритма?" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 95, - 99, - 171, - 191 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/bisection_regula_falsi.md b/_sources/nlroot/bisection_regula_falsi.md index f6e6d79..147e6f8 100644 --- a/_sources/nlroot/bisection_regula_falsi.md +++ b/_sources/nlroot/bisection_regula_falsi.md @@ -4,10 +4,12 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- ```{code-cell} @@ -16,6 +18,12 @@ kernelspec: include("../src.jl") ``` +```{eval-rst} +.. meta:: + :description: Рассмотрим методы бисекции (деления пополам) и ложной позиции (regula falsi) для решения нелинейного уравнения. + :keywords: бисекция, деление пополам, метод ложной позиции, regula falsi, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + # Методы бисекции и regula falsi ## Метод бисекции diff --git a/_sources/nlroot/ex.ipynb b/_sources/nlroot/ex.ipynb deleted file mode 100644 index cfe75d9..0000000 --- a/_sources/nlroot/ex.ipynb +++ /dev/null @@ -1,456 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "c1649117", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "4d2f8707", - "metadata": {}, - "source": [ - "# Задания\n", - "\n", - "\n", - "\n", - "## Вычисление квадратного корня\n", - "\n", - "Напишите функцию `mysqrt(x)`, вычисляющую квадратный корень $\\sqrt{x}$ для неотрицательного $x \\ge 0$.\n", - "Сравните невязку написанной вами функции со стандартной функцией `sqrt(x)` в диапазоне `range(0, 10; step=0.1)`.\n", - "\n", - "## Уравнение фазовых концентраций\n", - "\n", - "Уравнение фазовых концентраций (Rachford-Rice equation) используется для расчётов парожидкостного равновесия смеси веществ {cite}`Brusilovsky2002`. Уравнение выводится из массового баланса веществ в каждой фазе и представляет собой\n", - "\n", - "$$\n", - "F(G) = \\sum_{i} \\frac{z_i \\times (K_i - 1)}{G \\times (K_i - 1) + 1} = 0,\n", - "$$\n", - "\n", - "где $z_i$ мольная доля $i$-го компонента в смеси, $K_i$ константа равновесия $i$-го компонента (отношение мольной доли компонента в газе к его мольной доли в жидкости) и $G$ мольная доля газа в двухфазном состоянии.\n", - "\n", - "Решение этого уравнения показывает мольную долю газа в двухфазном состоянии при соответствующем распределении компонентов по жидкой и газовой фазе.\n", - "\n", - "Можно показать {cite}`Brusilovsky2002`, что решение уравнения стоит искать в интервале\n", - "\n", - "$$\n", - "1 / (1 - \\max K_i) \\quad \\ldots \\quad 1 / (1 - \\min K_i).\n", - "$$\n", - "\n", - "Этот интервал содержит в себе физические значения \n", - "мольной доли газа $G$, а функция $F(G)$ на нём убывает.\n", - "\n", - "**Задание**\n", - "\n", - "Напишите функцию `rachford_rice_solve(z, K) -> G`, решающую уравнение фазовых концентраций.\n", - "Постройте график функции $F(G)$ и найденный корень уравнения $F(G) = 0$ для случаев\n", - "\n", - "- $z = [0.9, 0.1]$, $K = [1.5, 0.01]$;\n", - "- $z = [0.2463, 0.2208, 0.2208, 0.3121]$, $K = [40, 25, 0.6, 0.005]$.\n", - "\n", - "Для построения графиков воспользуйтесь пакетом [Plots.jl](https://docs.juliaplots.org/stable/).\n", - "\n", - "\n", - "(ex_vdw_binodal_lekner)=\n", - "## Бинодаль уравнения состояния ван дер Ваальса\n", - "\n", - "```{note}\n", - "В этом задании вам предстоит найти область двухфазного равновесия для уравнения состояния ван дер Ваальса.\n", - "```\n", - "\n", - "В приведённых величинах $P_r = P / P_c$, $V_r = V / V_c$, $T_r = T / T_c$ уравнение ван дер Ваальса имеет вид\n", - "\n", - "```{math}\n", - "P_r(V_r, T_r) = \\frac{8 T_r}{3 V_r - 1} - \\frac{3}{V_r^2}.\n", - "```\n", - "\n", - "Несложно построить набор изотерм." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "eb144cd4", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/nlroot/ex_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "pressure(Vr::Real, Tr::Real) = 8Tr / (3Vr - 1) - 3 / Vr^2\n", - "V = range(0.34, 5; length=200)\n", - "plt = plot(;\n", - " ylim=(0, 2),\n", - " xlim=(0, 5),\n", - " xlabel=L\"V/V_c\",\n", - " ylabel=L\"P/P_c\",\n", - " lw=2,\n", - ")\n", - "for Tr in (0.85, 0.9, 0.95, 1.0, 1.1)\n", - " plot!(V, pressure.(V, Tr); label=L\"T_r = %$(Tr)\")\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "ccbd4318", - "metadata": {}, - "source": [ - "Рассмотрим подробнее изотерму для докритической температуры $T^* \\in (0, T_c)$.\n", - "\n", - "```{figure} vdw_isotherm.png\n", - "---\n", - "height: 480px\n", - "---\n", - "Изотерма ван дер Ваальса при температуре ниже критической.\n", - "```\n", - "\n", - "Красный участок на изотерме соответствует запрещённым термодинамическим состояниям, поскольку $\\partial P_r / \\partial V_r > 0$. Жёлтый участок изобары $P_X$ соответствует давлению, при котором при данной температуре $T^*$ жидкая и газовая фазы сосуществуют. При объёмах $V_r < V_L$ всё вещество находится в жидком состоянии, а при объёмах $V_r > V_G$ в газовом. Синий и зелёный участки изотермы соответствуют метастабильным состояниям.\n", - "\n", - "Можно вычилисть ряд величин $V_L$ и $V_G$ для диапазона температур, тогда получим границу двухфазной области.\n", - "\n", - "\n", - "```{figure} vdw_task_answer.svg\n", - "---\n", - "height: 480px\n", - "name: nlroot_vdw_task_answer\n", - "---\n", - "Уравнение ван дер Ваальса. Сплошными линиями показаны изотермы для ряда температур. Красная линия с точками соответствует бинодали: это граница значений давлений и объёмов $V_L$, $V_G$, при которых возможно двухфазное состояние. Красная область под бинодалью -- двухфазная область.\n", - "```\n", - "\n", - "Чтобы для данной температуры $T^*$ определить равновесные объёмы $V_G$, $V_L$ и давление $P_X$, требуется находить минимум потенциала Гельмгольца. Это требует решения нелинейной системы, но можно поступить иначе.\n", - "\n", - "Лекнером {cite}`lekner1982` предложена параметризация величин для двухфазного равновесия. В качестве параметра используется $y = \\Delta s / 2$, где $\\Delta s$ представляет собой скачок энтропии на частицу между газовой и жидкой фазами в единицах $k_B$. Для параметризации используются функции $f(y)$ и $g(y)$\n", - "\n", - "```{math}\n", - "\\begin{align}\n", - "f(y) &= \\frac{y \\cosh{y} - \\sinh{y}}{\\sinh{y}\\cosh{y}-y},\\\\\n", - "g(y) &= 1 + 2 f(y) \\cosh{y} + f^2(y),\n", - "\\end{align}\n", - "```\n", - "\n", - "через которые выражаются термодинамические величины.\n", - "\n", - "Так, приведённые температура $T_X$ и давление $P_X$ задают $(P, T)$-границу двухфазного равновесия. Функции параметризованы следующим образом\n", - "\n", - "```{math}\n", - "\\begin{align}\n", - "T_X(y) &= \\frac{27 f(y)[f(y) + \\cosh{y}]}{4g^2(y)},\\\\\n", - "P_X(y) &= \\frac{27 f^2(y)[1 - f^2(y)]}{g^2(y)}.\\\\\n", - "\\end{align}\n", - "```\n", - "\n", - "**Задание**\n", - "\n", - "Ваша задача состоит в том, чтобы определить $V_L$ и $V_G$ для ряда температур $T_r \\in [0.85, 1]$ и соответствующих им давлений, получив таким образом границу фазового равновесия. Нанесите полученные точки $(P_X, V_L)$ и $(P_X, V_G)$ поверх изотерм, как на {numref}`Рисунке %s `.\n", - "\n", - "```{tip}\n", - "Подробную информацию об уравнении ван дер Ваальса можно получить из статьи {cite}`Johnston2014`.\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 86, - 100 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/ex.md b/_sources/nlroot/ex.md index 3161ae0..51aaeb4 100644 --- a/_sources/nlroot/ex.md +++ b/_sources/nlroot/ex.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему численного решения нелинейного уравнения. + :keywords: задача, упражение, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -18,18 +26,14 @@ include("../src.jl") # Задания - ## Вычисление квадратного корня diff --git a/_sources/nlroot/index.md b/_sources/nlroot/index.md index 608a2ce..b280cc9 100644 --- a/_sources/nlroot/index.md +++ b/_sources/nlroot/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу численного решения нелинейного уравнения. + :keywords: нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + # Нелинейные уравнения В этом разделе изучается задача поиска корня нелинейного уравнения diff --git a/_sources/nlroot/itp.ipynb b/_sources/nlroot/itp.ipynb deleted file mode 100644 index ba2c170..0000000 --- a/_sources/nlroot/itp.ipynb +++ /dev/null @@ -1,239 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "defb5f21", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "2134656b", - "metadata": {}, - "source": [ - "# ITP метод\n", - "\n", - "В общем виде алгоритм с локализацией корня (бисекция, regula falsi, метод Риддерса) можно описать так.\n", - "\n", - "(algo:bracketing)=\n", - "```{proof:algorithm} Алгоритм с локализацией корня\n", - "Пусть дана функция $f$, начальный интервал $(a, b)$, такой что $f(a) f(b) < 0$ и $\\text{xtol}$.\n", - "Алгоритм состоит в следующих шагах.\n", - "\n", - "1. Выбрать некоторое приближение решения $\\tilde{x} \\in (a, b)$.\n", - "2. По значению $f(\\tilde{x})$ обновить интервал $(a, b)$ так, чтобы функция имела разные знаки на концах нового интервала.\n", - "3. Если достигнута точность $|b - a| < \\text{xtol}$, завершить, иначе -- перейти на шаг 1.\n", - "```\n", - "\n", - "Метод бисекции обладает замечательным свойством -- он **заранее** предсказывает необходимое число итераций $n_{1/2}$ по заданной точности локализации корня $\\text{xtol}$. \n", - "\n", - "Авторы работы {cite}`itp2020` показали, что это свойство (называемое minmax optimality) сохраняется во всяком алгоритме с локализацией корня, если новое приближение $\\tilde{x}$ попадает в область $I = [x_{1/2}-r, x_{1/2}+r]$ вокруг середины интервала $x_{1/2}$. Ниже приведено выражение для $r$ на $i$-ой итерации алгоритма\n", - "\n", - "```{math}\n", - ":label: itp_radius\n", - "\n", - "r_i = \\text{xtol } 2^{n_{1/2} - i} - \\frac{b_i - a_i}{2}, \\quad i = 1, 2, ..., n_{1/2}.\n", - "```\n", - "\n", - "Так, можно модифицировать {numref}`Алгоритм %s `, добавив после шага 1 проверку: попадает ли приближение $\\tilde{x}$ в область $I$. Если попадает, то оставить его, как есть, а если не попадает, взять приближение как у бисекции $\\tilde{x} := x_{1/2}$. Таким образом, модифицированный алгоритм гарантированно будет работать не хуже бисекции, а в лучшем случае как алгоритм, взятый за основу (например, метод Риддерса).\n", - "\n", - "\n", - "\n", - "## Описание метода\n", - "\n", - "Авторами {cite}`itp2020` был предложен метод ITP (Interpolate, Truncate and Project).\n", - "\n", - "**Interpolate**. На этом шаге определяется $x_f$ приближение по методу regula falsi (пересечение абсциссы секущей).\n", - "\n", - "**Truncate**. В этом методе, помимо описанной выше модификации присутствует шаг truncate, смещающий найденный при интерполяции корень в сторону $x_{1/2}$. Делается это в надежде на уменьшение интервала $[a, b]$ более чем в два раза. Результат этого шага точка $x_t$.\n", - "\n", - "**Project**. На этом шаге определяется, попадает ли $x_t$ в область minmax optimality. Если $x_t$ не попадает, то он перемещается (проецируется) в эту область и получается $x_{\\text{ITP}}$. В конце итерации происходит выбор нового отрезка по точкам $a_i$, $b_i$ и $x_{\\text{ITP}}$.\n", - "\n", - "В методе присутствует три параметра. Параметр $n_0 \\ge 0$ определяет число дополнительных итераций, в результате в формуле {eq}`itp_radius` присутствует не $n_{1/2}$, а $n_\\max = n_{1/2} + n_0$. Параметры $\\kappa_1 > 0$ и $\\kappa_2 \\in [1, 1 + \\phi)$ ($\\phi \\approx 1.618$, золотое сечение) определяют, как происходит truncate шаг. Так, они задают область $[x_{1/2} - \\delta, x_{1/2}+\\delta]$, где \n", - "\n", - "```{math}\n", - "\\delta = \\kappa_1 (b_i - a_i)^{\\kappa_2} / (b_0 - a_0).\n", - "```\n", - "\n", - "Если $x_f$ находится за пределами области $\\delta \\le |x_{1/2} - x_f|$, то он смещается в сторону середины $x_{1/2}$ на $\\delta$. Иначе устанавливается в $x_t := x_{1/2}$.\n", - "\n", - "Авторами метода показано, что в случае дважды дифференциируемой функции метод сходится к простому корню со скоростью $\\sqrt{\\kappa_2}$. Например, в случае $\\kappa_2 = 2$ ожидается сверхлинейная сходимость со скоростью $\\sqrt{2}$.\n", - "\n", - "## Реализация\n", - "\n", - "```{proof:function} itproot\n", - "\n", - "**Метод ITP**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Метод ITP поиска корня `f`(x) = 0 c точностью `xtol`.\n", - "\"\"\"\n", - "function itproot(f, x₁, x₂; xtol=eps(), ftol=eps(), κ₁=0.1, κ₂=2, n₀=1)\n", - " if x₁ > x₂; x₁, x₂ = x₂, x₁; end\n", - " y₁, y₂ = f(x₁), f(x₂)\n", - " y₁ * y₂ > 0 && error(\"Функция должна иметь разные знаки в концах отрезка\")\n", - " abs(y₁) < ftol && return x₁\n", - " abs(y₂) < ftol && return x₂\n", - " \n", - " nbisect = ceil(Int, log2((x₂-x₁)/xtol))\n", - " maxiter = nbisect + n₀\n", - " brackorig = x₂ - x₁\n", - "\n", - " for i in 1:maxiter\n", - " # interpolate\n", - " xf = (y₂*x₁ - y₁*x₂)/(y₂ - y₁)\n", - "\n", - " # truncate\n", - " xmid = (x₁ + x₂)/2\n", - " σ = sign(xmid - xf)\n", - " δ = κ₁ * (x₂ - x₁)^κ₂ / brackorig\n", - " xt = δ ≤ abs(xmid - xf) ? xf + copysign(δ, σ) : xmid\n", - " \n", - " # project\n", - " r = xtol * 2.0^(maxiter - i) - (x₂ - x₁)/2\n", - " xnew = abs(xt - xmid) ≤ r ? xt : xmid - copysign(r, σ)\n", - "\n", - " ynew = f(xnew)\n", - " if sign(y₂) == sign(ynew)\n", - " x₂, y₂ = xnew, ynew\n", - " elseif sign(y₁) == sign(ynew)\n", - " x₁, y₁ = xnew, ynew\n", - " else # ynew == 0\n", - " return xnew\n", - " end\n", - "\n", - " abs(ynew) < ftol && (x₁ + x₂)/2\n", - " abs(x₂ - x₁) < xtol && (x₁ + x₂)/2\n", - " end\n", - " return (x₁ + x₂)/2\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод ITP\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим работу метода на функции $xe^x - 1$." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "09d3f26c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "itproot(f, -1, 1; xtol = 2.0e-10, n₀ = 0) = 0.5671432904087239\n", - "ridders(f, -1, 1; xtol = 2.0e-10, maxiter = 4) = 0.5671432904097838\n" - ] - } - ], - "source": [ - "f = (x) -> x*exp(x) - 1\n", - "@show itproot(f, -1, 1; xtol=2e-10, n₀=0)\n", - "@show ridders(f, -1, 1; xtol=2e-10, maxiter=4);" - ] - }, - { - "cell_type": "markdown", - "id": "c87cde73", - "metadata": {}, - "source": [ - "Если немного поменять функцию `itproot`, то можно увидеть, что метод справился с поиском корня за 8 итераций, тогда как бисекция требует 34. В то же время метод Риддерса справляется за 4 итерации, **но** он требует 8 вычислений функции (по два вычисления за итерацию).\n", - "\n", - "На функции $\\ln |x - 10/9|$ ITP выигрывает по числу вычислений функции." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "c28d2126", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "itproot(f, -1, 1; xtol = 2.0e-10, n₀ = 0) = 0.11111111111111119\n", - "ridders(f, -1, 1; xtol = 2.0e-10, maxiter = 5) = 0.1111111111111111\n" - ] - } - ], - "source": [ - "f = (x) -> (log ∘ abs)(x - 10/9)\n", - "@show itproot(f, -1, 1; xtol=2e-10, n₀=0)\n", - "@show ridders(f, -1, 1; xtol=2e-10, maxiter=5);" - ] - }, - { - "cell_type": "markdown", - "id": "4ed2bb7d", - "metadata": {}, - "source": [ - "Здесь ITP потребовалось 8 вычислений, бисекции 34, а методу Риддерса 10.\n", - "\n", - "Сравнение на большем числе функций вы можете посмотреть в оригинальной работе {cite}`itp2020`.\n", - "\n", - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 127, - 131, - 137, - 141 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/itp.md b/_sources/nlroot/itp.md index 496ad8c..d3f6db4 100644 --- a/_sources/nlroot/itp.md +++ b/_sources/nlroot/itp.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим метод Interpolate-Truncate-Project (ITP) для решения нелинейного уравнения. + :keywords: метод itp, interpolate truncate project, itp method, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/nlroot/newton_secant.ipynb b/_sources/nlroot/newton_secant.ipynb deleted file mode 100644 index c3fa895..0000000 --- a/_sources/nlroot/newton_secant.ipynb +++ /dev/null @@ -1,593 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "303f8830", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "5bf4ce3d", - "metadata": {}, - "source": [ - "# Метод Ньютона и секущих\n", - "\n", - "## Метод Ньютона-Рафсона\n", - "\n", - "В методе Ньютона (также, Ньютона-Рафсона *Newton–Raphson method*) функция приближается прямой. Т.е. через текущее приближение корня $x_k$ проводится касательная $q(x)$ и корень касательной $q(x_{k+1}) = 0$ берётся за новое приближение.\n", - "\n", - "Уравнение касательной в точке $x_k$ функции $f$ имеет вид\n", - "\n", - "```{math}\n", - "q(x) = f(x_k) + f'(k) (x - x_k).\n", - "```\n", - "\n", - "Откуда при $q(x) = 0$ получаем\n", - "\n", - "```{proof:algorithm} Метод Ньютона поиска корня нелинейного уравнения\n", - "Пусть известна дифференциируемая функция $f$, её производная $f'$ и начальное приближение корня $x_1$, метод Ньютона заключается в построении приближений вида\n", - "\n", - "$$\n", - "x_{k+1} = x_k - \\frac{f(x_k)}{f'(x_k)}, \\quad k = 1, 2, ....\n", - "$$\n", - "```\n", - "\n", - "Метод Ньютона обладает квадратичной сходимостью для \"хороших\" функций. Сходимость может *не наблюдаться*, например, для немотононных функций или когда неудачно выбрано начальное приближение для корня.\n", - "\n", - "% todo доказательство квадратичной сходимости\n", - "\n", - "```{proof:definition} Квадратичная сходимость\n", - "Пусть последовательность приближений $x_k$ сходится к $x^*$. Если при этом для ошибки $\\epsilon_k = x_k - x^*$ верно\n", - "\n", - "$$\n", - "\\lim_{k\\to \\infty}\\frac{|\\epsilon_{k+1}|}{|\\epsilon_k|^2} = L > 0,\n", - "$$\n", - "\n", - "то говорят, что последовательность обладает **сходится квадратично**.\n", - "```\n", - "\n", - "```{proof:function} newton\n", - "\n", - "**Метод Ньютона поиска корня нелинейного уравнения**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Решает уравнение вида `f`(x) = 0 методом Ньютона. Требует производную функцию `df` и\n", - "начальное приближение корня `x₁`. Выполняет не более `maxiter` итераций.\n", - "\"\"\"\n", - "function newton(f, df, x₁; maxiter=25, ftol=eps(), xtol=eps())\n", - " x = float(x₁)\n", - " for i in 1:maxiter\n", - " fx = f(x)\n", - " δx = - fx / df(x)\n", - " x += δx\n", - "\n", - " abs(fx) < ftol && return x\n", - " abs(δx) < xtol && return x\n", - " end\n", - " error(\"Число итераций превышено.\")\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод Ньютона\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Пример для параболы $f(x) = -x (x-1)$." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "a592c6db", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "r1 = 1.0\n", - "r2 = -5.396595270071815e-16\n" - ] - } - ], - "source": [ - "f = (x) -> -x * (x-1)\n", - "df = (x) -> -2x + 1\n", - "r1 = newton(x -> -x^2 + x, x -> -2x + 1, 0.6; xtol=1e-6)\n", - "r2 = newton(x -> -x^2 + x, x -> -2x + 1, -0.5; xtol=1e-6)\n", - "@show r1 r2;" - ] - }, - { - "cell_type": "markdown", - "id": "c6d95d32", - "metadata": {}, - "source": [ - "Помимо того, что метод Ньютона плохо обусловлен для корней с нулевой производной, также можно привести случай расхождения метода.\n", - "\n", - "Например, для кубического корня $f(x) = x^{1/3}$ и начального приближения $x_1 = 0.1$ получим следующую *расходящуюся* последовательность\n", - "\n", - "```{math}\n", - "x_k = 0.1, \\quad -0.2, \\quad 0.4, \\quad -0.8, \\quad 1.6\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "b923d601", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/nlroot/newton_secant_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "x = [0.1, -0.2, 0.4, -0.8, 1.6]\n", - "plt = plot(cbrt; xlim=(-1, 2), leg=:topleft, label=\"куб. корень\")\n", - "scatter!(x, cbrt.(x); label=\"итерации\")\n", - "@views for (a, b) in zip(x[1:end-1], x[2:end])\n", - " plot!([a, b], cbrt.([a, b]); label=\"\", arrow=true, linecolor=:red)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "14ec449d", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "(chapter-nlroot-secant)=\n", - "## Метод секущих\n", - "\n", - "Метод секущих основывается на интерполяции функции прямой. Пусть есть два приближения корня $x_1$ и $x_2$. Проведём секущую $q(x)$ через точки $(x_1, f(x_1))$ и $(x_2, f(x_2))$\n", - "\n", - "```{math}\n", - "q(x) = f(x_1) + \\frac{f(x_2) - f(x_1)}{x_2 - x_1} (x - x_1).\n", - "```\n", - "\n", - "Новое приближение корня $x_3$ возьмём из пересечения секущей абсциссы $q(x_3) = 0$, откуда\n", - "\n", - "```{math}\n", - "x_3 = x_1 - f(x_1)\\frac{x_2 - x_1}{f(x_2) - f(x_1)} = \\frac{f(x_2)x_1 - f(x_1)x_2}{f(x_2) - f(x_1)}.\n", - "```\n", - "\n", - "```{proof:algorithm} Метод секущих\n", - "Пусть известны два приближения корня $x_{k-1}$ и $x_k$, следующее приближение корня вычисляется по формуле\n", - "\n", - "$$\n", - "x_{k+1} = \\frac{f(x_k)x_{k-1} - f(x_{k-1})x_k}{f(x_k) - f(x_{k-1})}, \\quad k=2, 3, ....\n", - "$$\n", - "\n", - "Таким образом, в этом методе секущие проводятся всегда по двум последним приближениям корня.\n", - "```\n", - "\n", - "Метод секущих обладает сверхлинейной сходимостью со скоростью, равной золотому сечению $\\alpha = (1 + \\sqrt{5})/2 \\approx 1.618$.\n", - "\n", - "```{proof:definition} Сверхлинейная сходимость\n", - "Пусть последовательность приближений $x_k$ сходится к $x^*$. Если при этом для ошибки $\\epsilon_k = x_k - x^*$ верно\n", - "\n", - "$$\n", - "\\lim_{k\\to \\infty}\\frac{|\\epsilon_{k+1}|}{|\\epsilon_k|^\\alpha} = L > 0,\n", - "$$\n", - "\n", - "то говорят, что последовательность обладает **сверхлинейной сходимостью** со скоростью $\\alpha \\in (1, 2)$.\n", - "```\n", - "\n", - "Метод секущих требует два начальных приближений вместо одного, но не требует вычисления производной. На практике важно время работы алгоритма и зачастую именно вычисление функции самое трудоёмкое. Поэтому наряду со скоростью сходимости метода вводят скорость сходимости *на вычисление* функции. Так, для метода Ньютона получим что за один шаг ошибка из $\\epsilon_k = \\delta$ станет $\\epsilon_{k+1}=\\delta^2$, но на это уходит два вычисления (функции и её производной), тогда на одно вычисление справедлива оценка $\\delta^\\sqrt{2}$. В это же время в методе секущих одна итерация требует одно вычисление, при этом ошибка уменьшается с $\\delta$ на $\\delta^{1.618}$. Поэтому в смысле сходимости за одно вычисление функции метод секущих оказывается быстрее.\n", - "\n", - "```{proof:function} secant\n", - "\n", - "**Метод секущих**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Ищет корень уравнения `f`(x) = 0 методом секущих, начиная с приближений `x₁`, `x₂`.\n", - "Выполняет не более `maxiter` итераций, пока не будет выполнено либо\n", - "|`x₁` - `x₂`| < `xtol`, либо |`f(x₂)`| < `ftol`.\n", - "\"\"\"\n", - "function secant(f, x₁, x₂; maxiter=25, ftol=eps(), xtol=eps())\n", - " y₁ = f(x₁)\n", - " for i in 1:maxiter\n", - " y₂ = f(x₂)\n", - " xnew = (y₂ * x₁ - y₁*x₂) / (y₂ - y₁)\n", - " x₁, y₁ = x₂, y₂\n", - " x₂ = xnew\n", - "\n", - " abs(y₂) < ftol && return x₂\n", - " abs(x₂ - x₁) < xtol && return x₂\n", - " end\n", - " error(\"Число итераций превышено.\")\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод секущих\n", - "```\n", - "```{raw} html\n", - "
\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "198aa151", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 4, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/nlroot/newton_secant_6_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "f = (x) -> x*exp(x) - 2\n", - "root = secant(f, 0, 1)\n", - "plot(f; xlim=(0.6, 1), label=L\"xe^x - 2\")\n", - "scatter!([root], [f(root)]; label=\"метод секущих\")" - ] - }, - { - "cell_type": "markdown", - "id": "ba19aa99", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 88, - 94, - 104, - 112, - 189, - 194 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/newton_secant.md b/_sources/nlroot/newton_secant.md index 9bfdd7c..fdd58b7 100644 --- a/_sources/nlroot/newton_secant.md +++ b/_sources/nlroot/newton_secant.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим методы Ньютона и секущих для решения нелинейного уравнения. + :keywords: метод Ньютона, метод секущих, secant, newton, fixed point, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -196,4 +204,3 @@ scatter!([root], [f(root)]; label="метод секущих") ```{raw} html ``` - diff --git a/_sources/nlroot/ridders.ipynb b/_sources/nlroot/ridders.ipynb deleted file mode 100644 index 237ca7e..0000000 --- a/_sources/nlroot/ridders.ipynb +++ /dev/null @@ -1,507 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "2b66c161", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "2e940f8d", - "metadata": {}, - "source": [ - "# Метод Риддерса\n", - "\n", - "Метод Риддерса {cite}`ridders1979` основывается на линеаризации исходной функции с последующим применением regula falsi к новой, модифицированной функции.\n", - "\n", - "## Вывод метода\n", - "\n", - "Пусть мы ищем приближение корня уравнения $f(x) = 0$ на отрезке $[x_0, x_2]$, при этом $f(x_0)f(x_2) < 0$. Заведём новую функцию $g(x)$\n", - "\n", - "```{math}\n", - "g(x) = f(x) e^{mx},\n", - "```\n", - "\n", - "таким образом, что точки $(x_0, g(x_0))$, $(x_2, g(x_2))$ и $(x_1, g(x_1))$ (где $x_1 = (x_0 + x_2)/2$) лежат на одной прямой:\n", - "\n", - "```{math}\n", - "g(x_1) = \\frac{g(x_0) + g(x_2)}{2} \\iff g(x_0) - 2 g(x_1) + g(x_2) = 0.\n", - "```\n", - "\n", - "```{figure} ridders_notation.png\n", - "---\n", - "height: 480px\n", - "---\n", - "К методу Риддерса.\n", - "```\n", - "\n", - "Подставим сюда определение $g(x)$ и получим уравнение\n", - "\n", - "```{math}\n", - "f(x_0)e^{mx_0} - 2 f(x_1) e^{mx_1} + f(x_2)e^{mx_2} = 0.\n", - "```\n", - "\n", - "Домножим на $e^{-mx_0}$ и получим квадратное уравнение на $e^{md}$\n", - "\n", - "```{math}\n", - "f(x_0) - 2 f(x_1) e^{md} + f(x_2) e^{2md} = 0,\\quad d = x_2 - x_1 = x_1 - x_0.\n", - "```\n", - "\n", - "Решая его, получим\n", - "\n", - "```{math}\n", - "e^{md} = \\frac{f(x_1) - \\sign(f(x_0))\\sqrt{W}}{f(x_2)}, \\quad W = f(x_1)^2 - f(x_0)f(x_2).\n", - "```\n", - "\n", - "Таким образом, функция $g(x) = f(x) e^{md}$ задана. Теперь сделаем regula falsi шаг через точки $(x_1, g(x_1))$ и $(x_2, g(x_2))$, получив $x_3$\n", - "\n", - "```{math}\n", - "x_3 = \\frac{x_1 g(x_2) - x_2 g(x_1)}{g(x_2) - g(x_1)}.\n", - "```\n", - "\n", - "Или\n", - "\n", - "```{math}\n", - "x_3 = x_1 + \\sign(f(x_0))\\frac{f(x_1)d}{\\sqrt{W}}.\n", - "```\n", - "\n", - "После чего обновим интервал так, чтобы $f(x_3) f(x_i) < 0$, $i=0,1,2$.\n", - "\n", - "Метод Риддерса обладает квадратичной сходимостью, но требует 2 вычисления функции на итерации (в точках $x_1$ и $x_3$), поэтому его скорость сходимости на вычисление равняется $\\sqrt{2}$ и можно говорить о *сверхлинейной сходимости на вычисление функции*.\n", - "\n", - "## Реализация\n", - "\n", - "```{proof:function} ridders\n", - "\n", - "**Метод Риддерса**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " ridders(f, x₁, x₂[; maxiter=25, xtol=eps(), ftol=eps()])\n", - "\n", - "Решает уравнение `f`(x) = 0 методом Риддерса на отрезке [`x₁`, `x₂`].\n", - "Если отрезок не уменьшится до `xtol`, или функция не уменьшится до `ftol`\n", - "за ≤ `maxiter` итераций, выдаёт ошибку.\n", - "\"\"\"\n", - "function ridders(f, x₁, x₂; maxiter=25, xtol=eps(), ftol=eps())\n", - " if x₁ > x₂; x₁, x₂ = x₂, x₁; end\n", - " y₁, y₂ = f.((x₁, x₂))\n", - " sign(y₁) == sign(y₂) && error(\"Функция должна иметь разные знаки в концах отрезка\")\n", - " abs(y₁) < ftol && return x₁\n", - " abs(y₂) < ftol && return x₂\n", - " \n", - " for i in 1:maxiter\n", - " xmid = (x₁ + x₂) / 2\n", - " ymid = f(xmid)\n", - " xnew = xmid + (xmid - x₁) * sign(y₁) * ymid / sqrt(ymid^2 - y₁*y₂)\n", - " ynew = f(xnew)\n", - "\n", - " abs(ynew) < ftol && return xnew\n", - " \n", - " if sign(ynew) == sign(y₂)\n", - " x₂, y₂ = xnew, ynew\n", - " elseif sign(ynew) == sign(y₁)\n", - " x₁, y₁ = xnew, ynew\n", - " end\n", - " \n", - " abs(ynew) < ftol && return xnew\n", - " abs(x₁ - x₂) < xtol && return xnew\n", - " end\n", - " error(\"Число итераций превышено.\")\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Метод Риддерса\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим работу метода Риддерса на функции $f(x) = (\\tan{x})^{\\tan{x}} - 10^3$ из оригинальной работы {cite}`ridders1979`.\n", - "\n", - "\n", - "\n", - "В качестве начального интервала возьмём $[0, 1.5]$. Функция принимает в концах отрезка значения, отличающиеся на 13 порядков!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "bb805756", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "f(0) = -999.0\n", - "f(1.5) = 1.607822215747618e16\n" - ] - } - ], - "source": [ - "f = (x) -> tan(x)^tan(x) - 1e3\n", - "@show f(0) f(1.5);" - ] - }, - { - "cell_type": "markdown", - "id": "f3511e56", - "metadata": {}, - "source": [ - "Ниже на верхнем графике показано масштаб функции на отрезке. А на втором графике найденный методом Риддерса корень. Метод справился за 8 итераций с точностью локализации корня `xtol = 1e-6`." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "054d3d7c", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/nlroot/ridders_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "root = ridders(f, 0, 1.5; xtol=1e-6, maxiter=8)\n", - "plt = plot(; layout=(2,1), xlabel=L\"x\", ylabel=L\"f(x)\")\n", - "plot!(f; xlim=(0, 1.5), subplot=1, label=L\"(\\tan x)^{\\tan x} - 10^3\")\n", - "\n", - "plot!(f; xlim=(1.25, 1.38), subplot=2, label=L\"(\\tan x)^{\\tan x} - 10^3\")\n", - "scatter!([root], [f(root)]; subplot=2, label=\"Найденный корень\", leg=:topleft)" - ] - }, - { - "cell_type": "markdown", - "id": "d6e7c425", - "metadata": {}, - "source": [ - "Сравним с методом regula falsi. Для этого выставим для методов одинаковые `ftol`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "96aa0316", - "metadata": { - "tags": [ - "raises-exception" - ] - }, - "outputs": [ - { - "ename": "LoadError", - "evalue": "Число итераций превышено.", - "output_type": "error", - "traceback": [ - "Число итераций превышено.", - "", - "Stacktrace:", - " [1] error(s::String)", - " @ Base ./error.jl:33", - " [2] regulafalsi(f::var\"#35#36\", x₁::Int64, x₂::Float64; maxiter::Int64, xtol::Float64, ftol::Float64)", - " @ Main ~/JIHT/computational_thermodynamics/book/src.jl:370", - " [3] top-level scope", - " @ In[4]:1", - " [4] eval", - " @ ./boot.jl:360 [inlined]", - " [5] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)", - " @ Base ./loading.jl:1116" - ] - } - ], - "source": [ - "regulafalsi(f, 0, 1.5; ftol=1e-6, maxiter=1000);" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "43b4e17f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ridders(f, 0, 1.5; ftol = 1.0e-6, maxiter = 8) = 1.3547104419557727\n" - ] - } - ], - "source": [ - "@show ridders(f, 0, 1.5; ftol=1e-6, maxiter=8);" - ] - }, - { - "cell_type": "markdown", - "id": "c99dd01b", - "metadata": {}, - "source": [ - "Метод Риддерса обнаружил корень на отрезке за 8 итераций, тогда как regula falsi не справился за 1000.\n", - "\n", - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 133, - 136, - 140, - 147, - 151, - 159, - 161 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/ridders.md b/_sources/nlroot/ridders.md index 7706d98..bf44843 100644 --- a/_sources/nlroot/ridders.md +++ b/_sources/nlroot/ridders.md @@ -4,18 +4,27 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим метод Риддерса (Ridders) для решения нелинейного уравнения. + :keywords: метод риддерса, метод риддера, ridders method, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] include("../src.jl") ``` +(sec:nlroot:ridders)= # Метод Риддерса Метод Риддерса {cite}`ridders1979` основывается на линеаризации исходной функции с последующим применением regula falsi к новой, модифицированной функции. @@ -149,9 +158,7 @@ scatter!([root], [f(root)]; subplot=2, label="Найденный корень", Сравним с методом regula falsi. Для этого выставим для методов одинаковые `ftol`. ```{code-cell} ---- -tags: [raises-exception] ---- +:tags: [raises-exception] regulafalsi(f, 0, 1.5; ftol=1e-6, maxiter=1000); ``` diff --git a/_sources/nlroot/simpleiter.ipynb b/_sources/nlroot/simpleiter.ipynb deleted file mode 100644 index e011e79..0000000 --- a/_sources/nlroot/simpleiter.ipynb +++ /dev/null @@ -1,301 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "92588d58", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "itproot" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "11685672", - "metadata": {}, - "source": [ - "(chapter_nlroot_simpleiter)=\n", - "# Метод простой итерации\n", - "\n", - "Задачу поиска корня $f(x) = 0$ можно свести к поиску неподвижной точки.\n", - "\n", - "```{proof:definition} Задача поиска неподвижной точки\n", - "\n", - "Пусть дана функция $g(x)$, тогда требуется найти её неподвижную точку $x = p$\n", - "\n", - "$$\n", - "p: g(p) = p.\n", - "$$\n", - "```\n", - "\n", - "Например, в качестве $g$ можно взять $g(x) = f(x) + x$ или, в более общем случае, $g(x) = c f(x) + x$, где $c \\neq 0$. Тогда получим\n", - "\n", - "```{math}\n", - "p = g(p) = c f(p) + p \\implies f(p) = 0.\n", - "```\n", - "\n", - "Алгоритм метода простой итерации (*fixed point iteration*) сводится к следующему. Пусть дано начальное приближение корня $x_1$, тогда вычислим следующие приближения из рекуррентного соотношения\n", - "\n", - "```{math}\n", - "x_{k+1} = g(x_k), \\quad k = 1, 2, ...\n", - "```\n", - "\n", - "```{index} метод; простой итерации\n", - "```\n", - "```{proof:function} fixedpoint\n", - "\n", - "**Метод простой итерации**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - "Ищет неподвижную точку функции `g`, начиная с `x₁`. Выполняет итерации до тех пор,\n", - "пока подшаг к ответу ≥ `xtol`, но не более `maxiter` раз.\n", - "\"\"\"\n", - "function fixedpoint(g, x₁; xtol=eps(), maxiter=25)\n", - " x = float(x₁)\n", - " for i in 1:maxiter\n", - " xprev = x\n", - " x = g(xprev)\n", - " abs(x - xprev) < xtol && return x\n", - " end\n", - " error(\"Число итераций превышено.\")\n", - "end\n", - ":::\n", - "```\n", - "\n", - "## Сходимость\n", - "\n", - "Допустим, мы получаем серию приближений $x_k$ неподвижной точки $p$. Вместо серии $x_k$ рассмотрим серию ошибок $\\epsilon_k = x_k - p$, тогда в окрестности $p$ получим\n", - "\n", - "```{math}\n", - "\\epsilon_{k+1} + p = g(\\epsilon_k + p) = g(p) + g'(p)\\epsilon_k + O(\\epsilon_k^2).\n", - "```\n", - "\n", - "Отсюда, поскольку $g(p) = p$\n", - "\n", - "```{math}\n", - ":label: simpleiter_error\n", - "\n", - "\\epsilon_{k+1} = g'(p)\\epsilon_k + O(\\epsilon_k^2).\n", - "```\n", - "\n", - "Или $\\epsilon_{k+1} \\approx g'(p)\\epsilon_k$. Значит, ошибка может как расти (метод не сходится), так и убывать (метод сходится). Поэтому имеет место \n", - "\n", - "```{proof:proposition} Сходимость метода простой итерации\n", - "Метод простой итерации для дифференциируемой $g$ *может сойтись* к неподвижной точке $p$ при условии $|g'(p)| < 1$.\n", - "```\n", - "\n", - "Кроме того, из {eq}`simpleiter_error` видно, что отношение $\\epsilon_{k+1} / \\epsilon_k$ стремится к константе $\\sigma = g'(p)$. Такой вид сходимости распространён в задачах оптимизации и решения нелинейных уравнений. Для него введено определение.\n", - "\n", - "```{index} сходимость; линейная\n", - "```\n", - "```{index} сходимость; скорость\n", - "```\n", - "```{proof:definition} Линейная сходимость\n", - "Пусть последовательность приближений $x_k$ сходится к $x^*$. Если при этом для ошибки $\\epsilon_k = x_k - x^*$ верно\n", - "\n", - "$$\n", - "\\lim_{k\\to \\infty}\\frac{|\\epsilon_{k+1}|}{|\\epsilon_k|} = \\sigma < 1,\n", - "$$\n", - "\n", - "то говорят, что последовательность обладает **линейной сходимостью**. А число $\\sigma$ называют **скоростью сходимости**.\n", - "```\n", - "\n", - "Из-за особенностей сходимости метод простой итерации применяется не часто. Однако в задачах, для которых выполняется условие сходимости (хотя бы постфактум), метод является дешёвым способом получить грубое решение задачи. Метод активно применяется в NPT расчётах фазового равновесия и некоторых разностных схемах.\n", - "\n", - "```{proof:demo} Метод простой итерации\n", - "```\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Пусть необходимо найти корни полинома $f(x) = -x^2 + x$. Возьмём тогда $g(x) = f(x) + x$.\n", - "\n", - "Если взять начальное приближение $x_1 \\in (0, 2)$, то метод сойдётся к точке $x=1$." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "52cba206", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fixedpoint(g, 1.9) = 1.0\n", - "fixedpoint(g, 0.1) = 1.0\n" - ] - } - ], - "source": [ - "g = (x) -> -x*(x-1) + x\n", - "@show fixedpoint(g, 1.9) fixedpoint(g, 0.1);" - ] - }, - { - "cell_type": "markdown", - "id": "70ac8775", - "metadata": {}, - "source": [ - "Этот случай предсказывается ограничением на производную $g'(x) = -2x + 2$ в неподвижной точке $g'(1) = 0$.\n", - "\n", - "А вот для корня $x = 0$ тогда ожидать сходимости не стоит, поскольку $g'(0) = 2$." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "528c6842", - "metadata": { - "tags": [ - "raises-exception" - ] - }, - "outputs": [ - { - "ename": "LoadError", - "evalue": "Число итераций превышено.", - "output_type": "error", - "traceback": [ - "Число итераций превышено.", - "", - "Stacktrace:", - " [1] error(s::String)", - " @ Base ./error.jl:33", - " [2] fixedpoint(g::var\"#35#36\", x₁::Float64; xtol::Float64, maxiter::Int64)", - " @ Main ~/JIHT/computational_thermodynamics/book/src.jl:272", - " [3] top-level scope", - " @ In[3]:1", - " [4] eval", - " @ ./boot.jl:360 [inlined]", - " [5] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)", - " @ Base ./loading.jl:1116" - ] - } - ], - "source": [ - "fixedpoint(g, -0.1; maxiter=100)" - ] - }, - { - "cell_type": "markdown", - "id": "d8531d0c", - "metadata": {}, - "source": [ - "Однако, можно взять другую функцию $g_1(x) = -f(x) + x$, для неё уже $g_1'(0) = 2x|_0 = 0$" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2f656c7e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fixedpoint(g1, -0.1) = 1.232595164407831e-32\n" - ] - } - ], - "source": [ - "g1 = (x) -> -(-x*(x-1)) + x\n", - "@show fixedpoint(g1, -0.1);" - ] - }, - { - "cell_type": "markdown", - "id": "d15ec1c1", - "metadata": {}, - "source": [ - "Аналогично приходится поступать и для более \"интересной\" функции $f(x) = xe^x - 2$, здесь $g(x) = -0.25 f(x) + x$" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "e656d38c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "root = 0.8526055020137255\n", - "f(root) = 0.0\n" - ] - } - ], - "source": [ - "f = (x) -> x * exp(x) - 2\n", - "g = (x) -> -0.25 * f(x) + x\n", - "root = fixedpoint(g, 0.8)\n", - "@show root f(root);" - ] - }, - { - "cell_type": "markdown", - "id": "e3a5cb7e", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 119, - 122, - 128, - 134, - 138, - 141, - 145, - 150 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/nlroot/simpleiter.md b/_sources/nlroot/simpleiter.md index 1962c1c..1023d7a 100644 --- a/_sources/nlroot/simpleiter.md +++ b/_sources/nlroot/simpleiter.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим простейший метод решения нелинейного уравнения - метод простой итерации. + :keywords: метод простой итерации, неподвижная точка, fixed point, нелинейное уравнение, поиск корня, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -126,9 +134,7 @@ g = (x) -> -x*(x-1) + x А вот для корня $x = 0$ тогда ожидать сходимости не стоит, поскольку $g'(0) = 2$. ```{code-cell} ---- -tags: [raises-exception] ---- +:tags: [raises-exception] fixedpoint(g, -0.1; maxiter=100) ``` diff --git a/_sources/ode/adaptive_rungekutta.ipynb b/_sources/ode/adaptive_rungekutta.ipynb deleted file mode 100644 index fe67163..0000000 --- a/_sources/ode/adaptive_rungekutta.ipynb +++ /dev/null @@ -1,649 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "074ac790", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "rk23" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "303591e1", - "metadata": {}, - "source": [ - "# Адаптивные методы\n", - "\n", - "Анализ большинства методов предполагает фиксированный шаг интегрирования $\\tau$, поэтому и поведение методов предсказывается локально. Однако, мы уже сталкивались с проблемами ({numref}`%s Адаптивное интегрирование `), в которых локальное поведение сильно отличается. Для решения ОДУ также существуют методы, подстраивающие шаг интегрирования в зависимости от локального поведения решения.\n", - "\n", - "В данном разделе мы рассмотрим пример адаптивного алгоритма на основе методов Рунге-Кутта.\n", - "\n", - "## Выбор шага интегрирования\n", - "\n", - "Пусть мы решаем уравнение начиная с $y_i$. Используем два разных метода, пусть у первого метода порядок аппроксимации $p$, а у второго $p+1$. Тогда при интегрировании на $\\tau$ мы получим два приближения $y^{(p)}_{i+1}$ и $y^{(p+1)}_{i+1}$. Мы ожидаем, что второе приближение намного точнее первого, поэтому возьмём их разницу за оценку погрешности первого метода \n", - "\n", - "```{math}\n", - "E_i(\\tau) = |u_i - y^{(p)}_{i+1}| \\approx |y^{(p+1)}_{i+1} - y^{(p)}_{i+1}|.\n", - "```\n", - "\n", - "Теперь потребуем, чтобы ошибка при интегрировании была меньше заданной пользователем $\\epsilon$. При $\\tau \\to 0$ погрешность имеет вид $E_i(\\tau) \\approx C \\tau^{p+1}$. Если бы мы использовали вместо $\\tau$ шаг $q \\tau$, $q > 0$, тогда ошибка бы составила\n", - "\n", - "```{math}\n", - "E_i(q\\tau) \\approx C q^{p+1} \\tau^{p+1}.\n", - "```\n", - "\n", - "Отсюда следует оценка для подбора $q$, задающего новую сетку.\n", - "\n", - "```{math}\n", - "\\epsilon = E_i(q \\tau) \\approx C q^{p+1} \\tau^{p+1} \\approx E_i(\\tau) q^{p+1},\n", - "```\n", - "\n", - "откуда\n", - "\n", - "```{math}\n", - ":label: ode_adaptive_q_choice\n", - "\n", - "q \\approx \\bigg(\\frac{\\epsilon}{E_i(\\tau)}\\bigg)^{1/(p+1)}.\n", - "```\n", - "\n", - "Заметим также, что $q$ может быть как меньше $1$ (требуется шаг мельче), так и больше 1 (можно увеличить шаг). Во втором случае $q$ следует ограничивать сверху, иначе можно проскочить участки, где требуется мелкий шаг.\n", - "\n", - "Теперь можно составить алгоритм решения.\n", - "\n", - "(ode_adaptive_algo_outline)=\n", - "```{proof:algorithm} Адаптивное решение ОДУ\n", - "Пусть известно приближение решения $y_i$ в $t = t_i$ и шаг интегрирования $\\tau$\n", - "\n", - "1. Подсчитать два приближения решения $y^{(p)}_{i+1}$, $y^{(p+1)}_{i+1}$ и оценить ошибку.\n", - "2. Если ошибка мала (меньше заданной пользователем), то принять в качестве решения в $t=t_i + \\tau$ $y_{i+1} = y^{(p+1)}_{i+1}$.\n", - "3. Подстроить шаг $\\tau$, заменив на $q\\tau$ {eq}`ode_adaptive_q_choice`.\n", - "4. Повторять, пока $t$ не достигнет $T$.\n", - "```\n", - "\n", - "## Встроенные формулы\n", - "\n", - "Допустим, мы будем использовать методы Рунге-Кутты второго и третьего порядков. Вообще говоря, нам может понадобится до 5 вычислений функции $f(t, u)$, поскольку точки, в которых происходит вычисление могут не совпадать. Пять вычислений уже вдвое больше, чем для двухэтапного метода.\n", - "\n", - "Поскольку методы Рунге-Кутты являются параметрическими семействами, то выведены пары методов, использующие общие точки для вычисления $f(t, u)$. Их называют **встроенными методами Рунге-Кутта** (*embedded Runge-Kutta*). За счёт этого свойства, встроенные методы экономят количество вычислений.\n", - "\n", - "```{margin}\n", - "Метод Богацкого-Шампина можно встретить под именем РК23.\n", - "```\n", - "В качестве примера мы воспользуемся методом **Богацкого-Шампина** (*Bogacki–Shampine*), являющимся встроенным методом Рунге-Кутты и пользующимся приближениями второго и третьего порядков. Его таблица Бутчера имеет вид\n", - "\n", - "```{math}\n", - "\\begin{array}{r|cccc}\n", - "0 & & & & \\\\\n", - "\\frac{1}{2} & \\frac{1}{2} & & & \\\\\n", - "\\frac{3}{4} & 0 & \\frac{3}{4} & & \\\\\n", - "1 & \\frac{2}{9} & \\frac{1}{3} & \\frac{4}{9} & \\\\\n", - "\\hline\n", - " & \\frac{2}{9} & \\frac{1}{3} & \\frac{4}{9} & 0 \\\\\n", - "\\hline\n", - " & \\frac{7}{24} & \\frac{1}{4} & \\frac{1}{3} & \\frac{1}{8}\n", - "\\end{array}\n", - "```\n", - "\n", - "Верхняя часть таблицы по-прежнему задаёт коэффициенты $a_s$ и $b_{sj}$, для обоих методов они одинаковые. Отличаются же методы весами $\\sigma_s$. Первая строка нижней части таблицы задаёт $\\sigma^{(2)}_s$ веса для метода второго порядка, а вторая строка (она же последняя) задаёт веса $\\sigma^{(3)}_s$ для метода третьего порядка.\n", - "\n", - "Предоставим также явный вид метода\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "k_1 &= f(t_i, y_i),\\\\\n", - "k_2 &= f\\Big(t_i + \\frac{1}{2}\\tau, y_i + \\frac{1}{2}\\tau k_1\\Big),\\\\\n", - "k_3 &= f\\Big(t_i + \\frac{3}{4}\\tau, y_i + \\frac{3}{4}\\tau k_2\\Big),\\\\\n", - "y^{(2)}_{i+1} &= y_i + \\frac{2}{9}\\tau k_1 + \\frac{1}{3}\\tau k_2 + \\frac{4}{9}\\tau k_3,\\\\\n", - "k_4 &= f(t_i + \\tau, y^{(2)}_{i+1}),\\\\\n", - "y^{(3)}_{i+1} &= y_i + \\frac{7}{24}\\tau k_1 + \\frac{1}{4}\\tau k_2 + \\frac{1}{3}\\tau k_3 + \\frac{1}{8}\\tau k_4.\n", - "\\end{split}\n", - "```\n", - "\n", - "Заметьте, что если в качестве $y_{i+1}$ брать второе приближение $y^{(2)}_{i+1}$ на шаге 2 {numref}`Алгоритма %s `, то $k_4$ равняется $k_1$ на итерации $i+1$.\n", - "Данное свойство называют *first same as last* (FSAL). Это позволяет уменьшить количество вычислений $f(t, u)$, и в итоге получаем одно вычисление при инициализации алгоритма и по три вычисления за шаг.\n", - "\n", - "Наиболее популярным является [метод Дорманда-Принса](https://en.wikipedia.org/wiki/Dormand%E2%80%93Prince_method) (*Dormand-Prince*), использующий методы Рунге-Кутты четвёртого и пятого порядка аппроксимации и ту же идею для оценки ошибки.\n", - "\n", - "## Реализация\n", - "\n", - "```{proof:function} rk23\n", - "\n", - "**Метод Богацкого-Шампина**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " rk23(problem; tol[, maxsteps, maxadjuststeps])\n", - "\n", - "Решает задачу Коши `problem` адаптивным методом Богацкого-Шампина.\n", - "Погрешность вычислений задаётся `tol`, а максимальное количество шагов\n", - "интегрирования `maxsteps`. Число шагов, разрешённое для адаптации шага `maxadjuststeps`.\n", - "\"\"\"\n", - "function rk23(problem::CauchyODEProblem;\n", - " tol::Real,\n", - " maxsteps::Integer=10000,\n", - " maxadjuststeps::Integer=20,\n", - ")\n", - " t₀, T = problem.bound\n", - " trange = [t₀]\n", - " u = [problem.u₀]\n", - " k₁ = problem.f(t₀, problem.u₀)\n", - " τ = 0.5 * tol^(1/3)\n", - "\n", - " for i in 1:maxsteps\n", - " tᵢ, uᵢ = trange[i], u[i]\n", - " \n", - " tᵢ == T && break\n", - " \n", - " if tᵢ + τ == tᵢ\n", - " @warn \"Достигнут предел машинной точности по τ\"\n", - " break\n", - " end\n", - "\n", - " for j in 1:maxadjuststeps\n", - " k₂ = problem.f(tᵢ + τ/2, uᵢ + τ*k₁/2)\n", - " k₃ = problem.f(tᵢ + 3τ/4, uᵢ + 3τ*k₂/4)\n", - " unew2 = uᵢ + τ*(2k₁ + 3k₂ + 4k₃)/9 # РК2 приближение\n", - " k₄ = problem.f(tᵢ + τ, unew2)\n", - "\n", - " Δ = τ * (-5k₁/72 + k₂/12 + k₃/9 - k₄/8) # разница РК2 и РК3 приближений\n", - " err = norm(Δ, Inf)\n", - " maxerr = tol * (1 + norm(uᵢ, Inf))\n", - "\n", - " accepted = err < maxerr\n", - " if accepted\n", - " push!(trange, tᵢ + τ)\n", - " push!(u, unew2)\n", - " k₁ = k₄ # FSAL: k₄ = f(tᵢ + τ, uᵢ₊₁) == new k₁\n", - " end\n", - " \n", - " # подбор нового шага\n", - " q = 0.8 * (maxerr/err)^(1/3) # оценка шага из погрешности\n", - " q = min(q, 4.0) # ограничиваем максимальное увеличение\n", - " τ = min(q*τ, T - trange[end]) # не выходим за предел T\n", - "\n", - " accepted && break\n", - " \n", - " j == maxadjuststeps && error(\"Число шагов по подбору τ превышено.\")\n", - " end\n", - " \n", - " i == maxsteps && @warn \"Число шагов превышено, конечное время не достигнуто\"\n", - " end\n", - " return trange, u\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Ниже представлен пример решения задачи Коши\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "u' &= e^{t - u \\sin u}, \\quad t \\in (0, 5],\\\\\n", - "u(0) &= 0.\n", - "\\end{split}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "49b8bfda", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/ode/adaptive_rungekutta_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "problem = CauchyODEProblem(\n", - " f=(t, u) -> exp(t - u*sin(u)),\n", - " tstart=0,\n", - " tend=5,\n", - " u₀=0,\n", - ")\n", - "plt = plot(;\n", - " title=L\"u' = e^{t - u \\sin{u}},\\quad u(0) = 0,\\quad t\\in [0, 5]\",\n", - " leg=:topleft,\n", - " layout=(2,1),\n", - ")\n", - "t, u = rk23(problem; tol=1e-5, maxsteps=1000)\n", - "plot!(t, u; label=\"РК23\", marker=:o, subplot=1, ylabel=L\"u\", xlim=(-0.1, 5.1))\n", - "plot!(t[1:end-1], diff(t);\n", - " subplot=2,\n", - " title=\"\",\n", - " yaxis=(:log10, L\"\\tau\"),\n", - " label=\"\",\n", - " xlabel=L\"t\",\n", - " xlim=(-0.1, 5.1),\n", - ")\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "eb826762", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 195, - 218 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/ode/adaptive_rungekutta.md b/_sources/ode/adaptive_rungekutta.md index 092e48b..cc0bd0a 100644 --- a/_sources/ode/adaptive_rungekutta.md +++ b/_sources/ode/adaptive_rungekutta.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим адаптивный выбор шага интегрирования при решении ОДУ. + :keywords: адаптивный метод, встроенный метод рунге кутты, метод богацкого шампина, рк23, embedded runge kutta, bogacki, shampine, оду, обыкновенное дифференциальное уравнение, дифуры, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -219,4 +227,4 @@ plt ```{raw} html -``` \ No newline at end of file +``` diff --git a/_sources/ode/euler.ipynb b/_sources/ode/euler.ipynb deleted file mode 100644 index a9ceecf..0000000 --- a/_sources/ode/euler.ipynb +++ /dev/null @@ -1,429 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "1631e498", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "rk23" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "e44d611a", - "metadata": {}, - "source": [ - "# Метод Эйлера\n", - "\n", - "Простейшим методом решения {eq}`ode_cauchy_scalar`\n", - "\n", - "```{math}\n", - "u' = f(t, u)\n", - "```\n", - "\n", - "является метод Эйлера. В этом методе производная $u'$ заменяется *конечной разностью*\n", - "\n", - "```{math}\n", - ":label: ode_euler_explicit\n", - "\n", - "\\begin{split}\n", - "\\frac{y_{i+1} - y_i}{\\tau} &= f(t_i, y_i),\\quad i = 0, 1, 2, \\ldots, \\\\\n", - "y_0 &= u_0.\n", - "\\end{split}\n", - "```\n", - "\n", - "В геометрической интерпретации это означает, что метод приближает $y_{i+1}$ значением касательной через $(t_i, y_i)$ в точке $t_i + \\tau$.\n", - "\n", - "```{index} разностный метод; Эйлера явный\n", - "```\n", - "```{proof:algorithm} Явный метод Эйлера\n", - "Пусть дана задача Коши для функции $u$. Значения $u(t)$ при $t>0$ находим из рекуррентной формулы\n", - "\n", - ":::{math}\n", - "y_{i+1} = y_i + \\tau f(t_i, y_i),\\quad y_0 = u_0,\\quad i = 0, 1, 2, \\ldots.\n", - "::: \n", - "```\n", - "\n", - "На примере метода Эйлера введём несколько понятий, применяющихся к разностным схемам {cite}`SamarskiyGulin1989`.\n", - "\n", - "```{index} разностный метод; сходимость\n", - "```\n", - "```{proof:definition} Сходимость разностного метода\n", - "Фиксируем точку $t$ и построим последовательность сеток $\\omega_\\tau$ {eq}`ode_grid` таких, что $\\tau \\to 0$ и $t_i = i \\tau = t$. Говорят, что *метод сходится в точке* $t$, если\n", - "\n", - ":::{math}\n", - "|y_i - u(t_i)| \\to 0,\\quad \\tau \\to 0,\\: t_i = t.\n", - ":::\n", - "\n", - "Метод называют *сходящимся на отрезке* $(0, T]$, если он сходится в каждой точке отрезка.\n", - "\n", - "Если при этом\n", - "\n", - ":::{math}\n", - "|y_i - u(t_i)| = O(\\tau^p),\\quad p>0,\\: \\tau \\to 0,\n", - ":::\n", - "\n", - "то говорят, что метод имеет $p$-ый *порядок точности*.\n", - "```\n", - "\n", - "Альтернативное определение сходимости {cite}`Ryabenkiy2016` заключается в рассмотрении $y_\\tau$ и проекции $u_\\tau$ как сеточных функций (т.е. функций, определённых на $\\omega_\\tau$), тогда требуют $\\|y_\\tau - u_\\tau\\|_{F_\\tau} \\to 0$, где $F_\\tau$ -- пространство сеточных функций.\n", - "\n", - "При подстановке решения $u$ в численный метод получается выражение для *погрешности аппроксимации разностного уравнения на решении исходного уравнения*, или *невязки*. Например, для метода Эйлера {eq}`ode_euler_explicit` получим вид невязки $\\psi_i$\n", - "\n", - "```{math}\n", - ":label: ode_euler_residual\n", - "\n", - "\\psi_i = - \\frac{u_{i+1} - u_i}{\\tau} + f(t_i, u_i).\n", - "```\n", - "\n", - "```{index} разностный метод; аппроксимация\n", - "```\n", - "```{proof:definition} Аппроксимация\n", - "Если невязка\n", - "\n", - ":::{math}\n", - "|\\psi_i| \\to 0,\\quad \\tau \\to 0,\n", - ":::\n", - "\n", - "то говорят, что разностный метод *аппроксимирует* исходное дифференциальное уравнение.\n", - "\n", - "При этом, если невязка имеет вид\n", - "\n", - ":::{math}\n", - "\\psi_i = O(\\tau^p), \\tau \\to 0,\n", - ":::\n", - "\n", - "то говорят о $p$-ом *порядке аппроксимации*.\n", - "```\n", - "\n", - "Несложно найти порядок аппроксимации метода Эйлера. Сама невязка имеет вид {eq}`ode_euler_residual`, для её получения разложим $u_{i+1}-u_i$ по формуле Тейлора\n", - "\n", - "```{math}\n", - "u_{i+1} - u_i = u(t_i + \\tau) - u(t_i) = u(t_i) + \\tau u'(t_i) - u(t_i) + O(\\tau) = \\tau u'(t_i) + O(\\tau).\n", - "```\n", - "\n", - "Подставим полученное соотношение в невязку {eq}`ode_euler_residual`\n", - "\n", - "```{math}\n", - "\\psi_i = - u'(t_i) + f(t_i, u_i) + O(\\tau).\n", - "```\n", - "\n", - "Таким образом, метод Эйлера имеет первый порядок аппроксимации.\n", - "\n", - "```{index} разностный метод; устойчивость\n", - "```\n", - "Помимо сходимости и аппроксимации, вводят различные понятия *устойчивости*. Одной из обобщённых является **устойчивость по правой части**. Данная устойчивость {cite}`Ryabenkiy2016` означает, что при малом возмущении правой части уравнения $f + \\epsilon$ разностный метод будет иметь (а) единственное решение $z_\\tau$, (б) решение $z_\\tau$ будет не сильно отличаться от невозмущённого, т.е. $\\|z_\\tau - y_\\tau\\| \\le c \\|\\epsilon_\\tau\\|$.\n", - "\n", - "```{proof:proposition}\n", - "Показано {cite}`Ryabenkiy2016`, что из аппроксимации и устойчивости по правой части следует сходимость метода с порядком точности, совпадающем с порядком аппроксимации.\n", - "```\n", - "\n", - "## Реализация\n", - "\n", - "В этой главе для постановки задачи Коши (скалярной) мы будем пользоваться структурой данных `CauchyODEProblem`.\n", - "\n", - "```julia\n", - "struct CauchyODEProblem{T<:Real,F<:Function}\n", - " bound::Tuple{T,T} # отрезок интегрирования\n", - " u₀::T # начальное значение интегрируемой функции\n", - " f::F # правая часть ОДУ\n", - " function CauchyODEProblem(; f::Function, tstart::Real, tend::Real, u₀::Real)\n", - " new{Float64, typeof(f)}(\n", - " float.(tuple(tstart, tend)),\n", - " float(u₀),\n", - " f,\n", - " )\n", - " end\n", - "end\n", - "```\n", - "\n", - "```{proof:function} euler\n", - "\n", - "**Явный метод Эйлера**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " euler(problem; nsteps)\n", - "\n", - "Решает задачу Коши `problem` явным методом Эйлера за `nsteps` шагов.\n", - "\"\"\"\n", - "function euler(problem::CauchyODEProblem; nsteps::Integer)\n", - " u = Vector{Float64}(undef, nsteps + 1)\n", - " u[1] = problem.u₀\n", - " tstart, tend = problem.bound\n", - " trange = range(tstart, tend; length=nsteps+1)\n", - " τ = step(trange)\n", - " @inbounds for i in 1:nsteps\n", - " tᵢ, uᵢ = trange[i], u[i]\n", - " u[i+1] = uᵢ + τ * problem.f(tᵢ, uᵢ)\n", - " end\n", - " return trange, u\n", - "end\n", - ":::\n", - "```\n", - "\n", - "(ode_euler_demo_cauchy)=\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Решим задачу Коши\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "u &= -u + 2 e^t,\\quad t \\in (0, 1],\\\\\n", - "u(0) &= 2\n", - "\\end{split}\n", - "```\n", - "\n", - "явным методом Эйлера и сравним с точным решением $u = 2 \\cosh t$." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "9568cfb3", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/ode/euler_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "problem = CauchyODEProblem(\n", - " f=(t, u) -> -u + 2exp(t),\n", - " tstart=0,\n", - " tend=1,\n", - " u₀=2,\n", - ")\n", - "plt = plot(; xlabel=\"time\", leg=:topleft)\n", - "plot!((t) -> 2cosh(t); label=L\"2\\cosh t\", lw=2, xlabel=L\"t\")\n", - "for n in (1, 2, 3, 10)\n", - " t, u = euler(problem; nsteps=n)\n", - " plot!(t, u; label=\"euler, nsteps = $n\", marker=:o)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "00702942", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 186, - 200 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/ode/euler.md b/_sources/ode/euler.md index e3b65c9..8a4b0ff 100644 --- a/_sources/ode/euler.md +++ b/_sources/ode/euler.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим простейший метод численного решения ОДУ - метод Эйлера. + :keywords: метод эйлера, явный метод эйлера, оду, обыкновенное дифференциальное уравнение, дифуры, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -185,13 +193,13 @@ u(0) &= 2 ```{code-cell} problem = CauchyODEProblem( - f=(t, u) -> -u + 2exp(t), + f=(t, u) -> -u + 2 * exp(t), tstart=0, tend=1, u₀=2, ) plt = plot(; xlabel="time", leg=:topleft) -plot!((t) -> 2cosh(t); label=L"2\cosh t", lw=2, xlabel=L"t") +plot!((t) -> 2 * cosh(t); label=L"2 \times \cosh{t}", lw=2, xlabel=L"t", ylabel=L"u(t)") for n in (1, 2, 3, 10) t, u = euler(problem; nsteps=n) plot!(t, u; label="euler, nsteps = $n", marker=:o) @@ -201,4 +209,4 @@ plt ```{raw} html -``` \ No newline at end of file +``` diff --git a/_sources/ode/ex.md b/_sources/ode/ex.md index 9b6259d..6153909 100644 --- a/_sources/ode/ex.md +++ b/_sources/ode/ex.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему численного решения обыкновенных дифференциальных уравнений. + :keywords: задача, упражнение, задание, метод верле, оду, обыкновенное дифференциальное уравнение, дифуры, вычислительная математика, вычматы +``` + # Задания ## Решение системы ОДУ diff --git a/_sources/ode/index.md b/_sources/ode/index.md index 102ffeb..7ccf74d 100644 --- a/_sources/ode/index.md +++ b/_sources/ode/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим методы численного решения обыкновенных дифференциальных уравнений. + :keywords: задача коши, оду, обыкновенное дифференциальное уравнение, дифуры, вычислительная математика, вычматы +``` + # Обыкновенные дифференциальные уравнения В данном разделе рассматривается решение обыкновенных дифференциальных уравнений. В частности, мы рассмотрим **задачу Коши** для уравнения @@ -49,4 +55,4 @@ u'(t) &= f(t, u(t)),\\ u_i &= u(t_i),\\ y_i &= y(t_i). \end{split} -``` \ No newline at end of file +``` diff --git a/_sources/ode/rungekutta.ipynb b/_sources/ode/rungekutta.ipynb deleted file mode 100644 index 3948f66..0000000 --- a/_sources/ode/rungekutta.ipynb +++ /dev/null @@ -1,998 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "7362add6", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "rk23" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "e615e500", - "metadata": {}, - "source": [ - "# Методы Рунге-Кутта\n", - "\n", - "В отличие от метода Эйлера, методы Рунге-Кутты (*Runge-Kutta*) используют информацию о правой части не в одной точке на отрезке $[t_i, t_{i+1}]$, а в нескольких. Подобные методы называют **многоэтапными** (*multistage*).\n", - "\n", - "```{index} метод; Рунге-Кутта\n", - "```\n", - "\n", - "Для задачи Коши\n", - "\n", - "```{math}\n", - ":label: ode_rk_cauchy\n", - "\n", - "\\begin{split}\n", - "u' &= f(t, u),\\quad t \\in (0, T]\\\\\n", - "u(0) &= u_0\n", - "\\end{split}\n", - "```\n", - "\n", - "*явный $m$-этапный метод Рунге-Кутты* определяется следующим образом.\n", - "\n", - "В исходном уравнении производная заменяется разностным соотношением, а правая часть -- взвешенной суммой\n", - "\n", - "```{math}\n", - ":label: ode_rk_sum\n", - "\n", - "\\frac{y_{i+1} - y_i}{\\tau} = \\sum_{s=1}^m \\sigma_s k_s,\n", - "```\n", - "\n", - "где $\\sigma_s$, $s=1,\\ldots,m$ -- коэффициенты метода, а $k_s$ задаются рекуррентно последовательностью\n", - "\n", - "```{math}\n", - ":label: ode_rk_k\n", - "\n", - "\\begin{split}\n", - "k_1 &= f(t_i, y_i),\\\\\n", - "k_2 &= f(t_i + a_2 \\tau, y_i + b_{21} \\tau k_1),\\\\\n", - "k_3 &= f(t_i + a_3 \\tau, y_i + b_{31}\\tau k_1 + b_{32} \\tau k_2),\\\\\n", - "\\ldots\\\\\n", - "k_m &= f\\bigg(t_i + a_m \\tau, y_i + \\tau\\sum_{s=1}^{m-1} b_{m,s}k_s\\bigg),\n", - "\\end{split}\n", - "```\n", - "\n", - "где $a_s$ и $b_{sj}$ $s = 2, 3 \\ldots, m$, $j=1,2,\\ldots,m-1$ -- также коэффициенты метода наряду с $\\sigma_s$. Для явного метода матрица $b_{sj}$ является нижнетреугольной с нулевой диагональю.\n", - "\n", - "Коэффициенты $a_s$, $b_{sj}$ и $\\sigma_s$ выбираются из соображений точности. Так, для выполнения аппроксимации требуется условие $\\sum \\sigma_s = 1$.\n", - "\n", - "Набор коэффициентов $\\sigma_s$, $a_s$, $b_{sj}$ часто записывают в виде **таблицы Бутчера**\n", - "\n", - "```{math}\n", - "\\begin{array}{r|cccc}\n", - " 0 & & & & \\\\\n", - " a_2 & b_{21} & & & \\\\\n", - " a_3 & b_{31} & b_{32} & & \\\\\n", - "\\vdots & \\vdots & \\vdots & \\ddots & \\\\\n", - " a_m & b_{m1} & b_{m2} & \\cdots & b_{m,m-1} \\\\\n", - " \\hline\n", - " & \\sigma_1 & \\sigma_2 & \\cdots & \\sigma_m\n", - "\\end{array}\n", - "```\n", - "\n", - "Методы Рунге-Кутты обобщаются на векторный случай задачи Коши\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "\\mathbf{u}' &= \\mathbf{f}(t, \\mathbf{u}),\\quad t \\in (0, T]\\\\\n", - "\\mathbf{u}(0) &= \\mathbf{u}_0\n", - "\\end{split}\n", - "``` \n", - "\n", - "При этом метод использует те же коэффициенты, что и скалярный аналог\n", - "\n", - "```{math}\n", - ":label: ode_rk_system_k\n", - "\n", - "\\begin{split}\n", - "\\frac{\\mathbf{u}_{i+1} - \\mathbf{u}_i}{\\tau} &= \\sum_{s=1}^m \\sigma_s \\mathbf{k}_s, \\\\\n", - "\\mathbf{k}_1 &= \\mathbf{f}(t_i, \\mathbf{y}_i),\\\\\n", - "\\mathbf{k}_2 &= \\mathbf{f}(t_i + a_2 \\tau, \\mathbf{y}_i + b_{21} \\tau \\mathbf{k}_1),\\\\\n", - "\\mathbf{k}_3 &= \\mathbf{f}(t_i + a_3 \\tau, \\mathbf{y}_i + b_{31}\\tau \\mathbf{k}_1 + b_{32} \\tau \\mathbf{k}_2),\\\\\n", - "\\ldots\\\\\n", - "\\mathbf{k}_m &= \\mathbf{f}\\bigg(t_i + a_m \\tau, \\mathbf{y}_i + \\tau\\sum_{s=1}^{m-1} b_{m,s}\\mathbf{k}_s\\bigg),\n", - "\\end{split}\n", - "```\n", - "\n", - "В дальнейшем мы будем излагать скалярный случай.\n", - "\n", - "(ode_rk_rk2_derivation)=\n", - "## Пример вывода 2-этапного метода\n", - "\n", - "Рассмотрим отдельно два метода. При $m=1$ получаем явный метод Эйлера. При $m=2$ имеем семейство методов\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "k_1 &= f(t_i, y_i),\\\\\n", - "k_2 &= f(t_i + a_2\\tau, y_i + b_{21}\\tau k_1),\\\\\n", - "y_{i+1} &= y_i + \\tau (\\sigma_1 k_1 + \\sigma_2 k_2).\n", - "\\end{split}\n", - "```\n", - "\n", - "Исследуем аппроксимацию этого метода. В начале исключим $k_1$ и $k_2$\n", - "\n", - "```{math}\n", - "\\frac{y_{i+1} - y_i}{\\tau} = y_i +\\sigma_1 f(t_i, y_i) + \\sigma_2 f(t_i + a_2\\tau, y_i + b_{21}\\tau f(t_i, y_i)).\n", - "```\n", - "\n", - "Рассмотрим невязку и определим порядок аппроксимации метода. Для этого подставим в качестве $y_i$ точное решение задачи $u_i$\n", - "\n", - "```{math}\n", - "\\psi = -\\frac{u_{i+1} - u_i}{\\tau} + \\sigma_1 f(t_i, u_i) + \\sigma_2 f(t_i + a_2\\tau, u_i + b_{21}\\tau f(t_i, u_i)),\n", - "```\n", - "\n", - "и разложим все величины по формуле Тейлора в $t_i$.\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "\\frac{u_{i+1} - u_i}{\\tau} &= u'(t_i) + \\frac{\\tau}{2} u''(t_i) + O(\\tau^2),\\\\\n", - "f(t_i + a_2\\tau, u_i + b_{21}\\tau f(t_i, u_i))\n", - " &= f(t_i, u_i) + a_2\\tau \\frac{\\partial f}{\\partial t}(t_i, u_i)\n", - " + b_{21}\\tau f(t_i, u_i) \\frac{\\partial f}{\\partial u}(t_i, u_i) + O(\\tau^2).\n", - "\\end{split}\n", - "```\n", - "\n", - "Согласно исходной задачи {eq}`ode_rk_cauchy`\n", - "\n", - "```{math}\n", - "u'' = \\frac{\\diff f}{\\diff t} = \\frac{\\part f}{\\part t} + \\frac{\\part f}{\\part u} u'.\n", - "```\n", - "\n", - "Подставим всё в невязку и получим\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "\\psi &= -u'(t_i) \\\\\n", - " &+ (\\sigma_1 + \\sigma_2) f(t_i, u_i)\\\\\n", - " &+ \\tau \\bigg[\n", - " (\\sigma_2 b_{21} - 0.5) f(t_i, y_i) \\frac{\\part f}{\\part u}(t_i, y_i)\n", - " + (\\sigma_2 a_2 - 0.5) \\frac{\\part f}{\\part t}(t_i, u_i)\n", - " \\bigg] \\\\\n", - " &+ O(\\tau^2).\n", - "\\end{split}\n", - "```\n", - "\n", - "Таким образом, при $\\sigma_1 + \\sigma_2 = 1$ получаем метод первого порядка аппроксимации. А если дополнительно потребовать $\\sigma_2 a_2 = \\sigma_2 b_{21} = 0.5$, то получаем семество методов второго порядка аппроксимации.\n", - "\n", - "Одним из таких используемых методов имеет коэффициенты $a_2 = 0.5$, $b_{21} = 0.5$, $\\sigma_1 = 0$, $\\sigma_2 = 1$, т.е.\n", - "\n", - "```{math}\n", - "y_{i+1} = y_i + \\tau f(t_i + 0.5\\tau, y_i + 0.5 \\tau f(t_i, y_i)).\n", - "```\n", - "\n", - "Таблица Бутчера для этого метода имеет вид\n", - "\n", - "```{math}\n", - "\\begin{array}{r|cc}\n", - "0 & & \\\\\n", - "0.5 & 0.5 & \\\\\n", - "\\hline\n", - " & 0 & 1\n", - "\\end{array}\n", - "```\n", - "\n", - "## Сходимость\n", - "\n", - "Приведём сначала утверждение о сходимости.\n", - "\n", - "```{proof:proposition} Сходимость явных методов Рунге-Кутта\n", - "{cite}`SamarskiyGulin1989` Если явный метод Рунге-Кутта аппроксимирует исходное уравнение, то он сходится при $\\tau \\to 0$, причём порядок точности совпадает с порядком аппроксимации.\n", - "```\n", - "\n", - "Отметим, что данное утверждение не связывает этапность метода $m$ и порядок аппроксимации.\n", - "В случае методов с числом этапов $1$, $2$, $3$, $4$ порядок аппроксимации (и точности) совпадает с числом этапов, однако, при $m=5$ система на коэффициенты метода уже не является совместной в предположении о пятом порядке аппроксимации. Данное утверждение было доказано Бутчером и носит название *первого барьера*.\n", - "\n", - "```{proof:proposition} Первый барьер Бутчера\n", - "Среди явных методов Рунге-Кутты с числом этапов $m = 5$ не существует методов пятого порядка аппроксимации.\n", - "```\n", - "\n", - "Так, достижение пятого порядка аппроксимации реализуемо для явного $6$-ти этапного метода Рунге-Кутты. Более того, при поиске методов с большим порядком аппроксимации требуется всё больше этапов и возникают новые барьеры Бутчера. С другой стороны, вместе с этапностью метода растёт и количество вычислений правой части $f(t, u)$. Поэтому, на практике явные методы Рунге-Кутта с порядком $m > 5$ используются реже {cite}`SamarskiyGulin1989`.\n", - "\n", - "## РК4\n", - "\n", - "Наибольшее распространение получил метод 4-го порядка, задаваемый следующей таблицей Бутчера\n", - "\n", - "```{math}\n", - "\\begin{array}{r|cccc}\n", - "0 & & & & \\\\\n", - "\\frac{1}{2} & \\frac{1}{2} & & & \\\\\n", - "\\frac{1}{2} & 0 & \\frac{1}{2} & & \\\\\n", - "1 & 0 & 0 & 1 & \\\\\n", - "\\hline\n", - " & \\frac{1}{6} & \\frac{1}{3} & \\frac{1}{3}& \\frac{1}{6}\n", - "\\end{array}\n", - "```\n", - "\n", - "Этот метод также сокращённо называют *РК4* (*RK4*).\n", - "\n", - "На практике каждый метод реализуют отдельно, последовательно вычисляя $k_s$, вместо использования общего алгоритма, принимающего на вход таблицу Бутчера. Оказывается, что такой подход вычислительно более выгоден.\n", - "\n", - "```{proof:algorithm} РК4, явный 4-этапный метод Рунге-Кутты\n", - ":::{math}\n", - "\\begin{split}\n", - "k_1 &= f(t_i, y_i), \\\\\n", - "k_2 &= f(t_i + \\tau / 2, y_i + \\tau k_1 / 2), \\\\\n", - "k_3 &= f(t_i + \\tau / 2, y_i + \\tau k_2 / 2), \\\\\n", - "k_4 &= f(t_i + \\tau, y_i + \\tau k_3), \\\\\n", - "y_{i+1} &= y_i + \\tau \\bigg( \\frac{1}{6} k_1 + \\frac{1}{3} k_2 + \\frac{1}{3} k_3 + \\frac{1}{6} k_4 \\bigg).\n", - "\\end{split}\n", - ":::\n", - "```\n", - "\n", - "```{proof:function} rk4\n", - "\n", - "**Явный метод Рунге-Кутта 4-го порядка**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " rk4(problem; nsteps)\n", - "\n", - "Решает задачу Коши `problem` явным 4-этапным методом Рунге-Кутта за `nsteps` шагов.\n", - "\"\"\"\n", - "function rk4(problem::CauchyODEProblem; nsteps::Integer)\n", - " u = Vector{Float64}(undef, nsteps + 1)\n", - " u[1] = problem.u₀\n", - " tstart, tend = problem.bound\n", - " trange = range(tstart, tend; length=nsteps+1)\n", - " τ = step(trange)\n", - " for i in 1:nsteps\n", - " tᵢ, uᵢ = trange[i], u[i]\n", - " \n", - " k₁ = problem.f(tᵢ, uᵢ)\n", - " k₂ = problem.f(tᵢ + τ/2, uᵢ + τ*k₁/2)\n", - " k₃ = problem.f(tᵢ + τ/2, uᵢ + τ*k₂/2)\n", - " k₄ = problem.f(tᵢ + τ, uᵢ + τ * k₃)\n", - "\n", - " u[i+1] = uᵢ + τ * (k₁ + 2*(k₂ + k₃) + k₄)/6\n", - " end\n", - " return trange, u\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Аппроксимация РК4 и явного метода Эйлера\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим решение задачи Коши из {numref}`Демонстрации %s ` 4-этапным методом Рунге-Кутты." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "fade272d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 2, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/ode/rungekutta_2_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "problem = CauchyODEProblem(;\n", - " f=(t, u) -> -u + 2exp(t),\n", - " tstart=0,\n", - " tend=1,\n", - " u₀=2,\n", - ")\n", - "plt = plot(; xlabel=L\"t\", leg=:topleft, layout=(2,2))\n", - "for (i, n) in enumerate((1, 2, 3, 4))\n", - " t, u = rk4(problem; nsteps=n)\n", - " plot!((t) -> 2cosh(t); label=\"\", line=2, subplot=i)\n", - " plot!(t, u; label=\"nsteps = $n\", marker=:o, subplot=i)\n", - "end\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "id": "93f04e6d", - "metadata": {}, - "source": [ - "Невооруженным глазом видно, насколько лучше РК4 справляется с этой задачей, чем метод Эйлера (см. {numref}`Демонстрация %s `).\n", - "\n", - "Проверим также порядок аппроксимации РК4 и явного метода Эйлера на той же задаче." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0efa4d61", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - "execution_count": 3, - "metadata": { - "filenames": { - "image/svg+xml": "/Users/stepanzh/JIHT/Практикум по вычислительной термодинамике/Сайт/computational_thermodynamics/book/_build/jupyter_execute/ode/rungekutta_4_0.svg" - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "function residual(problem, method::Function, nsteps, exact::Function)\n", - " err = Float64[]\n", - " for n in nsteps\n", - " t, u = method(problem; nsteps=n)\n", - " push!(err, norm(u .- exact.(t), Inf))\n", - " end\n", - " return err\n", - "end\n", - "\n", - "problem = CauchyODEProblem(\n", - " f=(t, u) -> -u + 2exp(t),\n", - " tstart=0,\n", - " tend=1,\n", - " u₀=2,\n", - ")\n", - "uexact(t) = 2cosh(t)\n", - "\n", - "nsteps = [2, 5, 10, 25, 50, 100, 500, 1000]\n", - "residual_euler = residual(problem, euler, nsteps, uexact)\n", - "residual_rk4 = residual(problem, rk4, nsteps, uexact)\n", - "\n", - "plot(; xaxis=(:log10, L\"n\"), yaxis=(:log10, \"норма невязки\"), leg=:bottomleft)\n", - "yticks!([10.0^(-n) for n in 0:2:14])\n", - "plot!(nsteps, residual_euler; marker=(:o, :red), line=:red, label=\"явный м. Эйлера\")\n", - "plot!(nsteps, 5e-2*(nsteps).^(-1); line=(:dash, 2, :red), label=L\"O(n^{-1})\")\n", - "plot!(nsteps, residual_rk4; marker=(:o, :blue), label=\"явный м. РК4\", line=(:blue))\n", - "plot!(nsteps, 5e-3*(nsteps).^(-4); line=(:dash, 2, :blue), label=L\"O(n^{-4})\")" - ] - }, - { - "cell_type": "markdown", - "id": "369f45e6", - "metadata": {}, - "source": [ - "Построение нормы невязки подтверждает, что метод Эйлера обладает первым порядком сходимости, а метод РК4 -- четвёртым.\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Неявные методы Рунге-Кутта\n", - "\n", - "**Комментарий**. Причиной разработки неявных методов послужило плохое решение (потеря устойчивости) явными методами жёстких систем уравнений. В жёстких системах компоненты решения $\\mathbf{u}$ изменяются со значительно разными скоростями. В случае явных систем шаг интегрирования $\\tau$ лимитируется самой быстро меняющейся компонентой, что приводит к выбору мелкого шага, а в перспективе к накоплению ошибок на больших масштабах $T$. Для неявных методов, как правило ограничения на шаг более мягкие или почти отсутствуют. В теории решения жёстких систем вводятся специальные определения устойчивости, которые требуют отдельного рассмотрения. Жёсткие системы появляются, например, в задачах прикладной химии по расчёту динамики многостадийных реакций.\n", - "\n", - "Неявными методами Рунге-Кутта называют методы, для которых $k_j$ зависит не только от предыдущих $k$, но и от следующих. То есть,\n", - "\n", - "```{math}\n", - ":label: ode_rk_impl_k\n", - "\n", - "k_j = f\\bigg(t_i + a_j \\tau, y_i + \\tau\\sum_{s=1}^m b_{j,s}k_s\\bigg),\\quad j = 1,\\ldots,m,\n", - "```\n", - "\n", - "но матрица коэффициентов $b_{j,s}$, в отличие от явных методов, уже не имеет нижнетреугольный вид.\n", - "\n", - "Простейшим среди таких методов является **неявный метод Эйлера** (*implicit/backward Euler method*)\n", - "\n", - "```{math}\n", - "\\frac{y_{i+1} - y_i}{\\tau} = f(t_i+\\tau, y_{i+1}).\n", - "```\n", - "\n", - "Неявные методы требуют в общем случае решения нелинейной системы на $k_j$ {eq}`ode_rk_impl_k`. Однако, в некоторых случаях показано, что достаточно использовать {ref}`метод простой итерации ` для решения такой системы, т.е. явным образом итеративно вычислять \n", - "\n", - "```{math}\n", - "k^{(n+1)}_j = f\\bigg(t_i + a_j \\tau, y_i + \\tau\\sum_{s=1}^m b_{j,s}k^{(n)}_s\\bigg),\\quad j = 1,\\ldots,m,\n", - "```\n", - "\n", - "пока два приближения системы $k^{(n+1)}_j$ и $k^{(n)}_j$ не станут сильно отличаться.\n", - "\n", - "Существуют $m$-этапные неявные методы Рунге-Кутты с порядком аппроксимации $2m$. Хотя, неявный метод Эйлера к таким не относится." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 267, - 281, - 287, - 315 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/ode/rungekutta.md b/_sources/ode/rungekutta.md index 35f1937..940bfff 100644 --- a/_sources/ode/rungekutta.md +++ b/_sources/ode/rungekutta.md @@ -4,19 +4,27 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Рассмотрим семейство методов для численного решения ОДУ - методы Рунге-Кутты. + :keywords: метод рунге кутты, явный метод рунге кутта, рунге кутта, таблица бутчера, рк 4, runge kutta, неявный метод эйлера, оду, обыкновенное дифференциальное уравнение, дифуры, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] include("../src.jl") ``` -# Методы Рунге-Кутта +# Методы Рунге-Кутты В отличие от метода Эйлера, методы Рунге-Кутты (*Runge-Kutta*) используют информацию о правой части не в одной точке на отрезке $[t_i, t_{i+1}]$, а в нескольких. Подобные методы называют **многоэтапными** (*multistage*). @@ -262,7 +270,7 @@ end
``` -Рассмотрим решение задачи Коши из {numref}`Демонстрации %s ` 4-этапным методом Рунге-Кутты. +Рассмотрим решение задачи Коши из {numref}`Демонстрации %s ` 4-этапным методом Рунге-Кутты. ```{code-cell} problem = CauchyODEProblem(; @@ -322,7 +330,20 @@ plot!(nsteps, 5e-3*(nsteps).^(-4); line=(:dash, 2, :blue), label=L"O(n^{-4})") ## Неявные методы Рунге-Кутта -**Комментарий**. Причиной разработки неявных методов послужило плохое решение (потеря устойчивости) явными методами жёстких систем уравнений. В жёстких системах компоненты решения $\mathbf{u}$ изменяются со значительно разными скоростями. В случае явных систем шаг интегрирования $\tau$ лимитируется самой быстро меняющейся компонентой, что приводит к выбору мелкого шага, а в перспективе к накоплению ошибок на больших масштабах $T$. Для неявных методов, как правило ограничения на шаг более мягкие или почти отсутствуют. В теории решения жёстких систем вводятся специальные определения устойчивости, которые требуют отдельного рассмотрения. Жёсткие системы появляются, например, в задачах прикладной химии по расчёту динамики многостадийных реакций. +```{note} +Иногда в системах дифференциальных уравнений компоненты решения $\mathbf{u}$ изменяются со значительно разными скоростями. +Такие системы называются _жёсткими_. +Они появляются, например, в задачах прикладной химии при расчётах динамики многостадийных реакций. + +Явные методы плохо применимы для решения жёстких систем. +Для них шаг интегрирования $\tau$ лимитируется наиболее быстро меняющимся уравнением системы $\mathbf{u}' = \mathbf{f}(t, \mathbf{u})$. +Это требует выбора мелкого шага $\tau$ и приводит к накоплению ошибок на больших масштабах времени решения $T$. +Иначе говоря, явные методы быстро теряют численную устойчивость при решении жёстких систем. + +Для жёстких систем используются неявные методы, для которых (как правило) ограничения на шаг интегрирования $\tau$ более мягкие или почти отсутствуют. + +В теории решения жёстких систем вводятся специальные определения устойчивости, которые требуют отдельного рассмотрения. +``` Неявными методами Рунге-Кутта называют методы, для которых $k_j$ зависит не только от предыдущих $k$, но и от следующих. То есть, diff --git a/_sources/optim/bfgs.md b/_sources/optim/bfgs.md index 6ea2fa3..2fa402d 100644 --- a/_sources/optim/bfgs.md +++ b/_sources/optim/bfgs.md @@ -1,8 +1,20 @@ -# Квазиньютоновские методы +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим метод BFGS для решения задачи оптимизации. + :keywords: bfgs, бфгс, квазиньютоновский, метод ньютона, разложение холецкого, поиск вдоль направления, line search, оптимизация, минимизация, вычислительная математика, вычматы +``` + +# Метод BFGS + +{ref}`Метод Ньютона ` требует (дорогой) поддержки положительной определённости матрицы Гессе и, вообще, вычисления матрицы. +Одной из альтернатив методу Ньютона являются _квазиньютоновские_ методы. + +Квазиньютоновские методы оптимизации также используют ньютоновское направление убывания. +Однако, в отличие от метода Ньютона, эти методы не вычисляют гессиан на итерации, а обновляют его по некоторому правилу (например, используя матрицу Гессе с предыдущей итерации). +Методы отличаются между собой формулой обновления, ниже мы рассмотрим широко-используемый *метод Бройдена -- Флетчера -- Гольдфарба -- Шанно* (*Broyden -- Fletcher -- Goldfarb -- Shanno*) или, более кратко, метод *BFGS*. -Квазиньютоновские методы оптимизации также используют Ньютоновское направление убывания. Однако, в отличие от метода Ньютона, эти методы не вычисляют гессиан на итерации, а добавляют к нему поправку. Методы отличаются между собой формулой обновления поправки, ниже мы приводим *метод Бройдена -- Флетчера -- Гольдфарба -- Шанно* (*Broyden -- Fletcher -- Goldfarb -- Shanno*) или, более кратко *БФГС*. -## Метод БФГС +## Метод Обозначим приближение гессиана на $k$-ой итерации через $\mathbf{B}_k$. После того, как направление вычислено как направление Ньютона @@ -29,9 +41,9 @@ используя их для нового приближения гессиана $\mathbf{B}_{k+1}$. -В методе БФГС используется следующее правило обновления +В методе BFGS используется следующее правило обновления -```{proof:definition} Правило БФГС +```{proof:definition} Правило BFGS :::{math} :label: optim_bfgs_rule @@ -48,7 +60,7 @@ Однако, $\mathbf{B}_k$ требует решение линейной системы {eq}`optim_bfgs_dir`. Чтобы этого не делать, можно аналитически обратить {eq}`optim_bfgs_rule` и работать с обратным приближением гессиана $\mathbf{B}^{-1}_k$, тогда {eq}`optim_bfgs_dir` уже будет представлен не систему уравнений, а матрично-векторное умножение. -```{proof:definition} Правило БФГС для обратного гессиана +```{proof:definition} Правило BFGS для обратного гессиана :::{math} \mathbf{B}^{-1}_{k+1} = \mathbf{B}^{-1}_k + \frac{ @@ -74,7 +86,7 @@ Модифицированное разложение Холецкого приведено в {ref}`Приложении `. -Ниже дан шаблон метода БФГС с обратным гессианом, который нужно будет завершить в домашнем задании. +Ниже дан шаблон метода BFGS с обратным гессианом, который нужно будет завершить в домашнем задании. Структура данных для результата алгоритма @@ -88,13 +100,13 @@ end ```{proof:function} bfgs -**Метод БФГС (шаблон)** +**Метод BFGS (шаблон)** :::julia """ bfgs(f, ∇f, x0[, invH0; maxiter=200, gtol=1e-5]) -Поиск минимума методом БФГС функции `f` с градиентом `∇f`, начиная с `x0`. +Поиск минимума методом BFGS функции `f` с градиентом `∇f`, начиная с `x0`. Оптимизация длится не более `maxiter` итераций, при этом, если норма градиента не превышает `gtol`, завершается досрочно. - `f::Function`: по вектору x возвращает значение функции, `f(x)`: `Vector` → `Real`; diff --git a/_sources/optim/ex.md b/_sources/optim/ex.md index a231f98..104f852 100644 --- a/_sources/optim/ex.md +++ b/_sources/optim/ex.md @@ -1,6 +1,12 @@ +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему численного решения задачи оптимизации. + :keywords: задача, задание, упражение, оптимизация, минимизация, вычислительная математика, вычматы +``` + # Задания -В этом задание вам нужно завершить написание алгоритмов Ньютона и БФГС для оптимизации. +В этом задание вам нужно завершить написание алгоритмов Ньютона и BFGS для оптимизации. Затем проверьте работу обоих алгоритмов на тестовых функциях. diff --git a/_sources/optim/index.md b/_sources/optim/index.md index 91760b5..225ce47 100644 --- a/_sources/optim/index.md +++ b/_sources/optim/index.md @@ -1,4 +1,10 @@ -# Методы оптимизации +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим методы решения задачи оптимизации (минимизации, максимизации) функции. + :keywords: оптимизация, минимизация, вычислительная математика, вычматы +``` + +# Задача оптимизации В этом разделе изложены некоторые методы решения задачи **безусловной оптимизации** (*unconstrained optimization*), т.е. нахождение $\mathbf{x}^*$, в котором достигается минимум функции $f: \real^n \to \real$. Математически мы будем формулировать это так diff --git a/_sources/optim/intro.md b/_sources/optim/intro.md index 2fac164..0cada4c 100644 --- a/_sources/optim/intro.md +++ b/_sources/optim/intro.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Предварительно рассмотрим определения и утверждения из матанализа, которые понадобятся для решения задачи оптимизации. + :keywords: градиент, матрица гессе, гессиан, условия минимума, оптимизация, минимизация, вычислительная математика, вычматы +``` + # Предварительные сведения ```{proof:definition} Градиент diff --git a/_sources/optim/linesearch.md b/_sources/optim/linesearch.md index d93af3b..37b85b7 100644 --- a/_sources/optim/linesearch.md +++ b/_sources/optim/linesearch.md @@ -1,7 +1,12 @@ -# Линейный поиск +```{eval-rst} +.. meta:: + :description: Рассмотрим решение скалярной задачи минимзации методом поиска вдоль направления. + :keywords: поиск вдоль направления, line search, оптимизация, минимизация, вычислительная математика, вычматы +``` -Пусть на шаге алгоритма оптимизации текущее приближение минимума равняется $\mathbf{x}_k$ и выбрано направление убывания $\mathbf{d}_k$. +# Поиск вдоль направления +Пусть на шаге алгоритма оптимизации текущее приближение минимума равняется $\mathbf{x}_k$ и выбрано направление убывания функции $\mathbf{d}_k$. Построим скалярную функцию $\phi(\alpha): \real \to \real$ ```{math} @@ -10,13 +15,23 @@ \phi(\alpha) = f(\mathbf{x}_k + \alpha \mathbf{d}_k). ``` -Задача идеального линейного поиска состоит в минимизации +Логично подбирать амплитуду шага $\alpha$ такой, которая в точности минимизирует $\phi(\alpha)$ + +```{math} +\alpha^{*} = \argmin_{\alpha > 0} \phi(\alpha), +``` + +однако данный подход вычислительно трудоёмок. +Поэтому на практике шаг $\alpha$ находят приближённо, т.е. решают задачу ```{math} -\min_{\alpha > 0} \phi(\alpha), +\alpha^{*} \approx \argmin_{\alpha > 0} \phi(\alpha). ``` -однако данный подход вычислительно трудоёмок. Вместо этого используют *приближённый линейный поиск*, задача которого приближённо минимизировать $\phi(\alpha)$ за небольшое количество вычислений. Для этого могут быть использованы разные критерии, о двух из них пойдёт речь дальше. Далее под линейным поиском будет пониматься приближённый вариант. +Для решения этой задачи применяют _поиск вдоль направления_ (line search). +Поиск должен с неплохой точностью находить шаг $\alpha^{*}$ за _приемлемое_ время. +Чтобы построить оптимальный по точности и быстродействию алгоритм, используются условия Вольфе. + ## Условия Вольфе @@ -80,11 +95,13 @@ f(\mathbf{x}_k + \alpha\mathbf{d}_k) \le f(\mathbf{x}_k) + \beta \alpha \nabla f Итак набор условий {eq}`optim_wolfe1` и {eq}`optim_wolfe2_weak` называют *слабыми условиями Вольфе*, а набор {eq}`optim_wolfe1` и {eq}`optim_wolfe2_strong` называют *сильными условиями Вольфе*. -## Линейный поиск назад -Линейный поиск назад строится лишь на первом условии Вольфе {eq}`optim_wolfe1`. -```{proof:algorithm} Линейный поиск назад +## Поиск вдоль направления назад + +Поиск вдоль направления назад строится лишь на первом условии Вольфе {eq}`optim_wolfe1`. + +```{proof:algorithm} Поиск вдоль направления назад Входные данные - функция $f$, @@ -104,9 +121,9 @@ f(\mathbf{x}_k + \alpha\mathbf{d}_k) \le f(\mathbf{x}_k) + \beta \alpha \nabla f Поиск называется "поиском назад" (*backtracking*), поскольку начинает с крупного $\alpha$, которое в последствии итеративно уменьшается. -## Сильный линейный поиск назад +## Сильный поиск вдоль направления -Сильный линейный поиск назад (*strong backtracking*) учитывает сильные условия Вольфе и требует более сложного алгоритма. +Сильный поиск вдоль направления (*strong backtracking*) учитывает сильные условия Вольфе и требует более сложного алгоритма. Поиск делится на фазы *локализации* (*bracketing*) и *уточнения* (*zoom*). @@ -128,13 +145,13 @@ f(\mathbf{x} + \alpha\mathbf{d}) &> f(\mathbf{x}) + \beta \alpha \nabla f(\mathb ```{proof:function} strong_backtracking -**Строгий линейный поиск назад** +**Сильный поиск вдоль направления** :::julia """ strong_backtracking(f, ∇f, x0, d[; α0=1.0, αmax=Inf, β=1e-4, σ=0.9]) -Линейный поиск значения α вдоль направления `d`, при котором для функции `f` +Сильный поиск вдоль направления значения α вдоль направления `d`, при котором для функции `f` выполнятся сильные условия Вольфе в точке `x0 + α*d`. `∇f` - функция градиента. Опционально задаётся начальное значение α `α0`, и параметры условий Вольфе: diff --git a/_sources/optim/newton.md b/_sources/optim/newton.md index 1eeaa55..4eea113 100644 --- a/_sources/optim/newton.md +++ b/_sources/optim/newton.md @@ -1,3 +1,10 @@ +```{eval-rst} +.. meta:: + :description: Метод Ньютона с поиском вдоль направления для решение задачи оптимизации. + :keywords: метод ньютона, разложение холецкого, поиск вдоль направления, line search, оптимизация, минимизация, вычислительная математика, вычматы +``` + +(sec:optim:newton)= # Метод Ньютона Приблизим локально значение функции $f$ в точке $\mathbf{x}_k + \mathbf{d}$ квадратичной функцией $m_k(\mathbf{d})$, используя разложение Тейлора diff --git a/_sources/ptsplit/index.md b/_sources/ptsplit/index.md index a2ab6a2..0513d6a 100644 --- a/_sources/ptsplit/index.md +++ b/_sources/ptsplit/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу фазового равновесия типа пар-жидкость в изобарно-изотермической постановке. + :keywords: pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # PT расслоение В этом разделе мы рассмотрим задачу нахождения фазового равновесия в флюиде при заданных давлении $P$ и температуре $T$. diff --git a/_sources/ptsplit/problem.md b/_sources/ptsplit/problem.md index ed0977e..89f90af 100644 --- a/_sources/ptsplit/problem.md +++ b/_sources/ptsplit/problem.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Постановка задачи фазового равновесия типа пар-жидкость в изобарно-изотермической постановке. + :keywords: pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # Постановка задачи Сначала рассмотрим общую постановку задачи двухфазного равновесия пар-жидкость. @@ -57,7 +63,7 @@ G^{II}(\mathbf{N}_{\vapor}, P, T) по составу паровой фазы $\mathbf{N}_{\vapor}$. При этом составы должны удовлетворять некоторым условиям, например, положительности количеств вещества каждого компонента, балансу распределения вещества по фазам и, возможно, условиями, накладываемыми уравнением состояния (моделью флюида). -Мы не будем решать задачу равновесия в виде минимизации, а воспользуемся _необходимым условием_ минимума --- равенство нулю градиента $\partial G^{II} / \partial N_{\text{пар},i} = \mathbf{0}$. +Мы не будем решать задачу равновесия в виде минимизации, а воспользуемся _необходимым условием_ минимума --- равенство нулю градиента $\partial G^{II} / \partial N_{\text{пар},i} = 0$. Это условие приводит к равенству химпотенциалов компонентов в паре и жидкости ```{math} \begin{split} diff --git a/_sources/ptsplit/problem_as_min.md b/_sources/ptsplit/problem_as_min.md deleted file mode 100644 index aa32860..0000000 --- a/_sources/ptsplit/problem_as_min.md +++ /dev/null @@ -1,127 +0,0 @@ -# Постановка задачи - -Сначала рассмотрим общую постановку задачи двухфазного равновесия пар-жидкость. -Пусть известны количество вещества компонентов в смеси $\mathbf{N} = [N_1, \dots, N_n]^\top$, приложенное к смеси давление $P$ и температура $T$. -Такие условия можно интерпретировать как закрытую систему (нет обмена веществом с окружающей средой), вещество которой помещено в термостат под поршень. - -Чтобы решить задачу двухфазного равновесия, проверим сначала _устойчивость однофазного состояния_. -Если проверка показывает устойчивость состояния, то задача решена: в равновесии существует одна фаза, а её состав равен $\mathbf{N}$. -В противном случае мы предполагаем (в рамках нашей задачи), что в равновесии сосуществуют две фазы: пар и жидкость. -Равновесное состояние определяется _минимумом свободной энергии Гиббса_, в нашем случае энергия состояния состоит из вкладов энергий паровой и жидкой фаз -```{math} -G^{II} = G_{\vapor} + G_{\liquid} -= G(\mathbf{N}_{\vapor}, P, T) + G(\mathbf{N}_{\liquid}, P, T), -``` -где энергия каждой фазы задаётся соотношением -```{math} -:label: eq:gibbs_energy_for_phase -G_{\alpha} = \sum_{i} N_{\alpha,i} \times \mu_{i}(\mathbf{N}_{\alpha}, P, T). -``` -Здесь $i \in \{1, \dots, n\}$ это индекс компонента, $\alpha \in \{\vapor, \liquid\}$ это индекс фазы, а $N_{\alpha,i}$ это количество вещества компонента $i$ в фазе $\alpha$. - -Поскольку мы предполагаем отсутствие химических превращений, то количество вещества каждого компонента $N_i$ сохраняется, т.е. $\mathbf{N}_{\vapor} + \mathbf{N}_{\liquid} = \mathbf{N}$. -Воспользуемся этим и получим, что энергия $G^{II}$ является функцией $n$ переменных (давление и температура постоянны) -```{math} -G^{II}(\mathbf{N}_{\vapor}, P, T) -= G(\mathbf{N}_{\vapor}, P, T) + G(\mathbf{N} - \mathbf{N}_{\vapor}, P, T). -``` - -Сама задача фазового равновесия сводится к задаче условной минимизации -```{math} -:label: eq:problem_as_min -\mathbf{N}^*_{\vapor} = \argmin\limits_{\mathbf{N}_{\vapor}} G^{II}(\mathbf{N}_{\vapor}, P, T), \quad P = \const, T = \const, -``` -по составу паровой фазы $\mathbf{N}_{\vapor}$. -При этом составы должны удовлетворять некоторым условиям, например, положительности количеств вещества каждого компонента, балансу распределения вещества по фазам и, возможно, условиями, накладываемыми уравнением состояния (моделью флюида). - -Мы не будем решать задачу равновесия в виде минимизации, а воспользуемся _необходимым условием_ минимума --- равенство нулю градиента $\partial G^{II} / \partial N_{\text{пар},i} = \mathbf{0}$. -Это условие приводит к равенству химпотенциалов компонентов в паре и жидкости -```{math} -\begin{split} - \frac{\partial G^{II}}{\partial N_{\vapor,i}} - &= \frac{\partial G_{\vapor}}{\partial N_{\vapor,i}} + \frac{\partial G_{\liquid}}{\partial N_{\vapor,i}} - = \mu_{i}(\mathbf{N}_{\vapor}, P, T) + \frac{\partial G_{\liquid}}{\partial N_{\liquid,i}} \frac{\partial N_{\liquid,i}}{\partial N_{\vapor,i}} - \\ &= \mu_{i}(\mathbf{N}_{\vapor}, P, T) - \mu_{i}(\mathbf{N}_{\liquid}, P, T) = 0. -\end{split} -``` - -Так, задача минимизации {eq}`eq:problem_as_min` свелась к решению нелинейной системы -```{math} -:label: eq:problem_as_nlsystem - \mu_{\vapor,i} = \mu_{\liquid,i},\quad i = 1, \dots, n. -``` -Однако, стоит помнить, что в общем случае решения задач {eq}`eq:problem_as_min` и {eq}`eq:problem_as_nlsystem` разные. -Например, решение задачи в виде нелинейной системы может содержать седловые точки. - -## Составы и мольные доли - -В системе {eq}`eq:problem_as_nlsystem` присутствуют только химпотенциалы компонентов в фазах. -Химпотенциал в переменных $\mathbf{N}$, $P$ и $T$ является однородной функцией нулевого порядка по $\mathbf{N}$, т.е. -```{math} -\mu_i(\mathbf{N}, P, T) = \mu_i(\boldsymbol{\chi}, P, T), -``` -где $\boldsymbol{\chi}$ это вектор из мольных долей компонентов (в фазе) -```{math} -\chi_i -= \frac{\text{кол-во вещества компонента $i$ в фазе}}{\text{общее кол-во вещества в фазе}} -= \frac{N_i}{\sum N_i}. -``` - -В задаче парожидкостного равновесия устоялись следующие обозначения составов в мольных долях -```{math} -\mathbf{z} = (\text{состав в мол. долях смеси в целом}) = \frac{\mathbf{N}}{\sum_i N_i}, -``` -```{math} -\mathbf{x} = (\text{состав в мол. долях жидкой фазы}), -``` -```{math} -\mathbf{y} = (\text{состав в мол. долях паровой (газовой) фазы}). -``` -А для обозначения долей жидкой и паровой фаз используются -```{math} - L = (\text{мол. доля жидкой фазы}) - = \frac{N_{\liquid}}{\sum_{\alpha} N_{\alpha}} - = \frac{N_{\liquid}}{\sum_{i} N_{i}}, -``` -```{math} - V = (\text{мол. доля паровой фазы}) - = \frac{N_{\vapor}}{\sum_{\alpha} N_{\alpha}} - = \frac{N_{\vapor}}{\sum_{i} N_{i}}, -``` -где $N_{\alpha} = \sum_i N_{\alpha,i}$ это количество вещества, содержащегося в фазе. - - -## Постановка задачи в виде нелинейной системы - -С учётом введённых обозначений, задача парожидкостного равновесия ставится следующим образом. - -```{proof:definition} Задача расчёта двухфазного равновесия пар-жидкость -Пусть дана смесь из $n$ компонентов с мольным составом $\mathbf{z} = [z_1, \ldots, z_n]^\top$ при температуре $T$ и давлении $P$. -Необходимо определить, одна или две фазы сосуществуют в термодинамическом равновесии. -Если фазы две, то для каждой из них нужно определить долю ($L$, $V$) и состав ($\mathbf{x}$, $\mathbf{y}$). -``` - -Как было сказано ранее, число фаз определяется из проверки термодинамической устойчивости. -В случае двухфазного состояния имеет место система -```{math} -:label: eq:nlsystem:chempot -\mu_{\vapor,i} = \mu_{\liquid,i},\quad i = 1,\dots,n, \quad \text{($n$ уравнений)} -``` -```{math} -:label: eq:nlsystem:sum_x -\sum_{i} x_i = 1, \quad \text{(1 уравнение)} -``` -```{math} -:label: eq:nlsystem:sum_y -\sum_{i} y_{i} = 1, \quad \text{(1 уравнение)} -``` -```{math} -:label: eq:nlsystem:LV -L + V = 1, \quad \text{(1 уравнение)} -``` -```{math} -:label: eq:nlsystem:comp_balance -x_{i} L + y_{i} V = z_{i}, \quad \text{($n$ уравнений)} -``` -Эта система содержит $2n + 2$ неизвестных ($x_{i}$, $y_{i}$, $V$ и $L$), а уравнений $2 n + 3$. -Однако, уравнения баланса вещества {eq}`eq:nlsystem:sum_x`-{eq}`eq:nlsystem:comp_balance` связаны между собой, поэтому можно одно отбросить, например, {eq}`eq:nlsystem:sum_x`. diff --git a/_sources/ptsplit/solution.md b/_sources/ptsplit/solution.md index 625aa6c..90f2861 100644 --- a/_sources/ptsplit/solution.md +++ b/_sources/ptsplit/solution.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Решение задачи фазового равновесия типа пар-жидкость в изобарно-изотермической постановке. + :keywords: pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # Решение задачи Чтобы решить задачу {eq}`eq:nlsystem:chempot`-{eq}`eq:nlsystem:comp_balance` можно воспользоваться {ref}`методом Ньютона-Рафсона `. @@ -33,7 +39,7 @@ K_{i} :label: eq:fixedpoint K_{i} = \frac{\varphi_{i}(\mathbf{x}(\mathbf{K}))}{ \varphi_{i}(\mathbf{y}(\mathbf{K})) }. ``` -Полученная система является системой на неподвижную точку вида $K_{i} = g(\mathbf{K})$. +Полученная система является системой на неподвижную точку вида $\mathbf{K} = g(\mathbf{K})$. Осталось определить зависимости $x_{i}(\mathbf{K})$ и $y_{i}(\mathbf{K})$. Воспользуемся уравнением {eq}`eq:nlsystem:comp_balance`, учтём в нём $L = 1 - V$ {eq}`eq:nlsystem:LV`, $y_{i} = K_{i} x_{i}$, и получим diff --git a/_sources/ptstability/algorithm.md b/_sources/ptstability/algorithm.md index b471e77..a8cac7e 100644 --- a/_sources/ptstability/algorithm.md +++ b/_sources/ptstability/algorithm.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Алгоритм решения задачи проверки устойчивости фазы в изобарно-изотермической постановке. + :keywords: pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # Алгоритм решения Подытожим, что, по существу, задача свелась к решению нелинейной системы {eq}`ptstab_chempot_stationary_system_final` для вектора неизвестных $\boldsymbol{X}$. diff --git a/_sources/ptstability/criterion.md b/_sources/ptstability/criterion.md deleted file mode 100644 index 3b42061..0000000 --- a/_sources/ptstability/criterion.md +++ /dev/null @@ -1,60 +0,0 @@ -# Постановка задачи - -Пусть дана смесь из $n$ компонентов с мольным составом $\boldsymbol{N} = [N_1, \ldots, N_n]^\top$ при температуре $T$ и давлении $P$. Необходимо определить, является ли однофазное состояние смеси термодинамически стабильным. - -## Критерий стабильности - -Идея решения задачи заключается в сравнении энергий двух систем - -- однофазная (исходная) система; -- двухфазная система, где вторая фаза представлена в малом количестве. - -Также можно сказать, что мы попытаемся найти флуктуацию (состава и плотности), приводящую систему к двухфазному состоянию, имеющему энергию меньше, чем у однофазной системы. В этом случае однофазное состояние нестабильно. Если же такой флуктуации не существует, то однофазное состояние термодинамически стабильно. - -Рассмотрим собственный потенциал NPT системы -- свободную энергию Гиббса[^gibbs_derivation] - -```{math} -G = G(\boldsymbol{N}, P, T) = \sum_i N_i \mu_i(\boldsymbol{N}, P, T). -``` - -В дальнейшем зависимость от давления $P$ и температуры $T$ писать не будем -- это параметры задачи. - -[^gibbs_derivation]: Выражение свободной энергии Гиббса для смеси следует из аддитивности внутренней энергии и энтропии. Подробнее об этом в {cite}`Brusilovsky2002` (Раздел 2.9, Химический потенциал). - -Теперь предположим, что часть вещества $\boldsymbol{\varepsilon}$ исходной системы образует вторую фазу. Тогда разница энергий двухфазного и однофазного состояний будет -```{math} -:label: ptstab_gibbs_delta - -\Delta G = G(\boldsymbol{N} - \boldsymbol{\varepsilon}) + G(\boldsymbol{\varepsilon}) - G(\boldsymbol{N}) -``` - -Если получится найти такое количество вещества $\boldsymbol{\varepsilon}$, что $\Delta G < 0$, то двухфазное состояние имеет меньшую энергию, а однофазное состояние -- нестабильно. Для этого, можно, например, найти глобальный минимум $\Delta G$ и посмотреть его знак. Однако, распространён следующий метод. - -Будем считать, что общее количество вещества во второй фазе $\|\boldsymbol{\varepsilon}\|$ мало (вторая фаза в зародышевом состоянии, например). Разложим тогда в ряд Тейлора первое слагаемое из уравнения {eq}`ptstab_gibbs_delta` -```{math} -G(\boldsymbol{N} - \boldsymbol{\varepsilon}) \approx G(\boldsymbol{N}) - \sum_i \varepsilon_i \frac{\partial G}{\partial N_i} (\boldsymbol{N}) -= G(\boldsymbol{N}) - \sum_i \varepsilon_i \mu_i(\boldsymbol{N}). -``` - -С учётом разложения, получаем[^gibbs_delta_approx] -```{math} -\Delta G = \sum_i \varepsilon_i \mu_i(\boldsymbol{\varepsilon}) - \sum_i \varepsilon_i \mu_i(\boldsymbol{N}) -= \sum_i \varepsilon_i (\mu_i(\boldsymbol{\varepsilon}) - \mu_i(\boldsymbol{N})). -``` - -[^gibbs_delta_approx]: Строго говоря, это равенство выполняется приближённо. Знак точного равенства поставлен с целью упрощения изложения и математической записи. - -Избавимся от абсолютных величин, введя общее количество вещества в фазе-зародыше $\varepsilon = \sum_i \varepsilon_i$ -```{math} -:label: ptstab_gibbs_delta_relative - -\Delta G = \varepsilon \sum_i x_i (\mu_i(\boldsymbol{x}) - \mu^0_i), -``` -здесь $\boldsymbol{x} \equiv \boldsymbol{\varepsilon} / \varepsilon$ -- мольный состав фазы-зародыша, а $\mu^0_i$ -- химпотенциал компонентна в однофазном состоянии. - -Поскольку в {eq}`ptstab_gibbs_delta_relative` $\varepsilon > 0$, получаем критерий стабильности фазы -```{math} -:label: ptstab_tpd - -F(\boldsymbol{x}) = \sum_i x_i (\mu_i(\boldsymbol{x}) - \mu^0_i) \ge 0. -``` diff --git a/_sources/ptstability/exercise.md b/_sources/ptstability/exercise.md index a579f6d..fb587bc 100644 --- a/_sources/ptstability/exercise.md +++ b/_sources/ptstability/exercise.md @@ -1,5 +1,10 @@ -# Задания +```{eval-rst} +.. meta:: + :description: Задания и упражнения на тему проверки устойчивости фазы в изобарно-изотермической постановке. + :keywords: задание, упражнение, задача, pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` +# Задания ## Проверка стабильности diff --git a/_sources/ptstability/index.md b/_sources/ptstability/index.md index 4ae1bee..392cd3a 100644 --- a/_sources/ptstability/index.md +++ b/_sources/ptstability/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу проверки термодинамической устойчивости фазы в изобарно-изотермической постановке. + :keywords: устойчивость, pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # PT стабильность Стандартный расчёт двухфазного фазового равновесия в флюидах проводится в два этапа. diff --git a/_sources/ptstability/problem.md b/_sources/ptstability/problem.md index 55ba17f..c3fdfd3 100644 --- a/_sources/ptstability/problem.md +++ b/_sources/ptstability/problem.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Постановка задачи проверки термодинамической устойчивости фазы в изобарно-изотермической постановке. + :keywords: устойчивость, pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # Постановка задачи Пусть дана смесь из $n$ компонентов с мольным составом $\boldsymbol{N} = [N_1, \ldots, N_n]^\top$ при температуре $T$ и давлении $P$. Необходимо определить, является ли однофазное состояние смеси термодинамически стабильным. diff --git a/_sources/ptstability/vanderwaals.md b/_sources/ptstability/vanderwaals.md index f76f731..71debca 100644 --- a/_sources/ptstability/vanderwaals.md +++ b/_sources/ptstability/vanderwaals.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим уравнение состояния ван дер Ваальса для смеси. + :keywords: уравнение состояния, ван дер ваальс, летучесть, сжимаемость, pt, изобарный, фазовое равновесие, пар, жидкость, смесь, термодинамика, термодинамика смесей +``` + # Уравнение состояния ван дер Ваальса Для решения системы {eq}`ptstab_chempot_stationary_system_final` необходимо знать коэффициент летучести $\varphi_i$ (или вид свободной энергии Гиббса, или вид химпотенциала). Фактически, мы можем решать эту задачу для разных физических моделей флюида. В термодинамике, моделью вещества является уравнение состояния. diff --git a/_sources/syslinear/conditioning.md b/_sources/syslinear/conditioning.md index 861534d..240f474 100644 --- a/_sources/syslinear/conditioning.md +++ b/_sources/syslinear/conditioning.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Мы рассмотрим обусловленность численного решения линейных систем уравнений. + :keywords: вычислительная математика, вычматы, обусловленность, линейная система уравнений +``` + # Обусловленность линейных систем По аналогии с обусловленностью вычисления скалярной функции, вводится понятие обусловленности линейной системы diff --git a/_sources/syslinear/decompose_overview.ipynb b/_sources/syslinear/decompose_overview.ipynb deleted file mode 100644 index f65a3cf..0000000 --- a/_sources/syslinear/decompose_overview.ipynb +++ /dev/null @@ -1,173 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "67455732", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "plufact" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "a68026a3", - "metadata": {}, - "source": [ - "# Обзор других разложений и задач\n", - "\n", - "В данном разделе приведены некоторые разложения матриц и их применение.\n", - "\n", - "## LU-разложение\n", - "\n", - "LU-разложение можно применять не только для решения линейных систем. Зная разложение, несложно вычислить детерминант матрицы.\n", - "\n", - "```{math}\n", - "\\det{\\mathbf{AB}} = \\det{\\mathbf{A}}\\det{\\mathbf{B}},\\quad \\det{\\mathbf{L}} = \\prod_{i} L_{ii}.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "4fed27cd", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "prod(diag(L)) * prod(diag(U)) = -3510.0\n", - "p = [2, 3, 4, 1]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "det(A) = 3510.0\n" - ] - } - ], - "source": [ - "A = [\n", - " 2 0 4 3;\n", - " -4 5 -7 10;\n", - " 1 15 2 -4;\n", - " -2 0 2 -13\n", - "]\n", - "L, U, p = plufact(A)\n", - "\n", - "@show prod(diag(L)) * prod(diag(U)) p det(A);" - ] - }, - { - "cell_type": "markdown", - "id": "f17b74f2", - "metadata": {}, - "source": [ - "Знак детерминанта определяется чётностью перестановки. В данном случае для \"сортировки\" вектора перестановок `p` требуется три операции, поэтому необходимо домножение на $(-1)^3$.\n", - "\n", - "Вычисление детерминанта из определения через миноры стоит $O(n!)$ флопс, тогда как вычисление через LU-разложение $O(n^3)$ флопс.\n", - "\n", - "Алгоритм также используется для проверки матрицы на обратимость.\n", - "\n", - "(chapter_syslinear_qr)=\n", - "## QR-разложение\n", - "\n", - "QR-разложение выводится из ортогонализации по Граму-Шмидту и применяется для прямоугольной матрицы\n", - "\n", - "```{math}\n", - "\\mathbf{A}_{m\\times n} = \\mathbf{Q R},\n", - "```\n", - "\n", - "где $\\mathbf{Q}$ -- ортогональная матрица, а $\\mathbf{R}$ -- верхнетреугольная.\n", - "\n", - "Данное разложение применятся для переопределённых систем (число уравнений превышает число неизвестных), например, в методе наименьших квадратов. Кроме того, разложение позволяет найти ядро преобразования и пространство столбцов. А в случае квадратной матрицы $\\mathbf{A}_{n\\times n}$ разложение применимо для решения линейной системы, как и LU-разложение.\n", - "\n", - "В одном из вариантов метода Бройдена решения нелинейной системы уравнений эффективней (по времени работы) использовать QR-разложение. Подобная ситуация встречается и в других алгоритмах, где-то одно разложение несёт больше необходимой алгоритму информации, а где-то подходящее разложение экономит время вычислений.\n", - "\n", - "Вычислительная сложность $\\propto 2mn^2 - \\frac{2}{3} n^3$.\n", - "\n", - "(syslinear_ch_cholesky)=\n", - "## Разложение Холецкого\n", - "\n", - "Данное разложение применяется для квадратной симметричной положительно-определённой матрицы $\\mathbf{x}^\\top \\mathbf{A} \\mathbf{x} > 0$\n", - "\n", - "```{math}\n", - "\\mathbf{A}_{n\\times n} = \\mathbf{L}\\mathbf{L}^\\top,\n", - "```\n", - "\n", - "где $\\mathbf{L}$ -- нижнетреугольная матрица.\n", - "\n", - "Подобные матрицы возникают, например, в задаче оптимизации (нахождение минимума функции $f(\\mathbf{x})$), где ноль градиента и положительная определённость гессиана определяют локальный минимум.\n", - "\n", - "Разложение используется для решения линейных систем, проверки матрицы на положительную определённость, нахождение детерминанта и обращении матриц.\n", - "\n", - "Также часто используется модифицированное разложение Холецкого, которое находит близкую положительно-определённую матрицу к исходной, не обязательно положительно-определённой. Эта матрица может использоваться как приближение гессиана.\n", - "\n", - "Вычислительная стоимость $\\propto \\frac{1}{3} n^3$ флопс.\n", - "\n", - "## Спектральное разложение\n", - "\n", - "Существует целое семейство разложений, где в качестве множителей присутствуют матрицы из собственных векторов и значений. Одно из них -- спектральное.\n", - "\n", - "Спектральное разложение представляет квадратную матрицу $\\mathbf{A}$ в виде\n", - "\n", - "```{math}\n", - "\\mathbf{A}_{n\\times n} = \\mathbf{VDV}^{-1},\n", - "```\n", - "\n", - "где $\\mathbf{V}$ -- матрица, составленная из собственных векторов матрицы $\\mathbf{A}$, а $\\mathbf{D}$ -- диагональная матрица из собственных значений $\\mathbf{A}$.\n", - "\n", - "Как следует из определения, разложение применяется для нахождения собственных значений и векторов матрицы. Такая задача может возникнуть, например, при решении системы обыкновенных дифференциальных уравнений.\n", - "\n", - "Обобщением является сингулярное разложения (*SVD*-разложение)." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 31, - 41 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/syslinear/decompose_overview.md b/_sources/syslinear/decompose_overview.md index 10c9bee..a9a4d0b 100644 --- a/_sources/syslinear/decompose_overview.md +++ b/_sources/syslinear/decompose_overview.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Мы сделаем обзор разложений систем, используемых в вычислительной линейной алгебре. А также задачи, в которых они используются. + :keywords: вычислительная математика, вычматы, lu разложение, qr разложение, разложение холецкого, спектральное разложение +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/syslinear/ex.md b/_sources/syslinear/ex.md index c3ef3c9..b1815e1 100644 --- a/_sources/syslinear/ex.md +++ b/_sources/syslinear/ex.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему вычислительной линейной алгебры. + :keywords: вычислительная математика, вычматы, линейная алгебра, упражнения +``` + (syslinear-ex)= # Задания diff --git a/_sources/syslinear/index.md b/_sources/syslinear/index.md index 0e3bc54..2ac3dc1 100644 --- a/_sources/syslinear/index.md +++ b/_sources/syslinear/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Алгоритмы решения линейных систем уравнений. + :keywords: вычислительная математика, вычматы, система линейных уравнений +``` + # Линейные системы уравнений В этом разделе рассматривается решение линейной системы уравнений diff --git a/_sources/syslinear/lu.ipynb b/_sources/syslinear/lu.ipynb deleted file mode 100644 index b9f7b27..0000000 --- a/_sources/syslinear/lu.ipynb +++ /dev/null @@ -1,670 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "7a6e1da7", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "lufact" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "96312c5d", - "metadata": {}, - "source": [ - "# LU-разложение\n", - "\n", - "На практике оказывается, что проще работать не с самой матрицей, а с представлением её в виде произведения нескольких матриц, которое называется разложением. \n", - "В данном разделе выводится алгоритм решения системы уравнений, представляющий исходную матрицу в виде произведения $\\mathbf{A}=\\mathbf{L}\\mathbf{U}$, после чего пользующийся прямой и обратной подстановкой.\n", - "\n", - "## Внешнее произведение\n", - "\n", - "Вывод алгоритма разложения основывается на внешнем произведении векторов (*outer product*).\n", - "Для двух векторов $\\mathbf{u} \\in \\real^m$, $\\mathbf{v} \\in \\real^n$ внешнее произведение является матрицей размера $m \\times n$\n", - "\n", - "```{math}\n", - "\\mathbf{u}\\mathbf{v}^\\top\n", - "= \\begin{bmatrix}\n", - "u_1 v_1 & u_1 v_2 & \\cdots & u_1 v_n \\\\\n", - "u_2 v_1 & u_2 v_2 & \\cdots & u_2 v_n \\\\\n", - "\\vdots & \\vdots & & \\vdots \\\\\n", - "u_m v_n & u_m v_n & \\cdots & u_m v_n\n", - "\\end{bmatrix}.\n", - "```\n", - "\n", - "Другими словами, столбец $\\mathbf{u}$ умножается на строку $\\mathbf{v}$.\n", - "\n", - "Произведение матриц $\\mathbf{A}\\mathbf{B}$ является суммой внешних произведений столбцов $\\mathbf{a}_{k}$ матрицы $\\mathbf{A}$ на строки $\\mathbf{b}^{\\top}_{k}$ матрицы $\\mathbf{B}$, т.е.\n", - "\n", - "```{math}\n", - ":label: matrouterprod\n", - "\n", - "\\mathbf{A}\\mathbf{B} = \\sum_{k=1}^n \\mathbf{a}_k \\mathbf{b}_k^\\top.\n", - "```\n", - "\n", - "Рассмотрим теперь произведение нижнетреугольной матрицы на верхнетреугольную $\\mathbf{L}\\mathbf{U}$.\n", - "Обозначим $\\mathbf{l}_k$ столбцы матрицы $\\mathbf{L}$, а $\\mathbf{u}_k^\\top$ -- строки матрицы $\\mathbf{U}$. Тогда произведение запишется в виде {eq}`matrouterprod`\n", - "\n", - "```{math}\n", - "\\mathbf{L}\\mathbf{U} = \\sum_{k=1}^n \\mathbf{l}_k \\mathbf{u}_k^\\top.\n", - "```\n", - "\n", - "Первая строка этого произведения имеет вид (здесь $\\mathbf{e}_1^\\top$ -- первая строка единичной матрицы, домножение на неё слева выделяет первую строку)\n", - "\n", - "```{math}\n", - ":label: lu_row\n", - "\n", - "\\mathbf{e}_1^\\top \\sum_{k=1}^n \\mathbf{l}_k \\mathbf{u}_k^\\top\n", - "= \\sum_{k=1}^n (\\mathbf{e}_1^\\top \\mathbf{l}_k) \\mathbf{u}_k^\\top\n", - "= L_{11} \\mathbf{u}_1^\\top,\n", - "```\n", - "\n", - "поскольку только первый элемент столбца $\\mathbf{l}_k$ ненулевой только у $\\mathbf{l}_1$.\n", - "Посмотрите на схему ниже\n", - "\n", - "```\n", - " L U\n", - "\n", - "| □ ⋅ ⋅ ⋅ | | □ □ □ □ |\n", - "| □ □ ⋅ ⋅ | | ⋅ □ □ □ |\n", - "| □ □ □ ⋅ | | ⋅ ⋅ □ □ |\n", - "| □ □ □ □ | | ⋅ ⋅ ⋅ □ |\n", - "```\n", - "\n", - "Первый же столбец $\\mathbf{L}\\mathbf{U}$ имеет вид\n", - "\n", - "```{math}\n", - ":label: lu_col\n", - "\n", - "\\Bigg( \\sum_{k=1}^n \\mathbf{l}_k \\mathbf{u}_k^\\top \\Bigg) \\mathbf{e}_1\n", - "= \\sum_{k=1}^n \\mathbf{l}_k (\\mathbf{u}_k^\\top \\mathbf{e}_1)\n", - "= U_{11} \\mathbf{l}_1.\n", - "```\n", - "\n", - "Воспользуемся свойствами {eq}`lu_row` и {eq}`lu_col` для вывода LU-разложения.\n", - "\n", - "## Разложение\n", - "\n", - "```{proof:definition} LU-разложение\n", - "Для квадратной матрицы $\\mathbf{A}$ размера $n \\times n$ необходимо найти\n", - "\n", - "$$\n", - "\\mathbf{A} = \\mathbf{LU},\n", - "$$\n", - "\n", - "где $\\mathbf{L}$ -- нижнетреугольная матрица, а $\\mathbf{U}$ -- верхнетреугольная матрица.\n", - "```\n", - "\n", - "LU-разложение сводится к нахождению $n^2 + n$ неизвестных.\n", - "\n", - "Пусть диагональные элементы $\\mathbf{L}$ единичны $L_{11} = L_{22} = \\cdots = L_{nn} = 1$. Теперь, зная $L_{11} = 1$, применим {eq}`lu_row`, и получим\n", - "\n", - "```{math}\n", - "\\mathbf{a}_1^\\top = \\mathbf{e}_1^\\top \\mathbf{A} = \\mathbf{e}_1^\\top (\\mathbf{LU}) = \\mathbf{u}_1^\\top,\n", - "```\n", - "\n", - "т.е. первая строка матрицы $\\mathbf{U}$ равняется первой строке матрицы $\\mathbf{A}$, $\\mathbf{u}_1^\\top = \\mathbf{a}_1^\\top$.\n", - "\n", - "На этом шаге нам стало известно значение $U_{11}$. Воспользуемся теперь {eq}`lu_col`\n", - "\n", - "```{math}\n", - "\\mathbf{a}_1 = \\mathbf{A} \\mathbf{e}_1 = (\\mathbf{LU}) \\mathbf{e}_1 = U_{11} \\mathbf{l}_1,\n", - "```\n", - "\n", - "откуда следует выражение для первого столбца матрицы $\\mathbf{L}$\n", - "\n", - "```{math}\n", - "\\mathbf{l}_1 = \\frac{\\mathbf{a}_1}{U_{11}}.\n", - "```\n", - "\n", - "Теперь вычтем из исходной матрицы внешнее произведение\n", - "\n", - "```{math}\n", - "\\mathbf{A}_2 = \\mathbf{A} - \\mathbf{l}_1 \\mathbf{u}_1^\\top\n", - "= \\sum_{k=2}^n \\mathbf{l}_k \\mathbf{u}_k^\\top.\n", - "```\n", - "\n", - "Полученная матрица $\\mathbf{A}_2$ имеет нулевую первую строку и нулевой первый столбец.\n", - "\n", - "Таким образом, задача свелась к предыдущей, но, фактически, на квадратной матрице меньшего размера.\n", - "Повторяя эту процедуру дальше, получим остальные строки и столбцы разложения.\n", - "Ниже приведена схема вычислений и демонстрация на небольшой матрице.\n", - "\n", - "```\n", - " A₁ = A A₂ A₃ A₄\n", - "\n", - "| □ □ □ □ | | ⋅ ⋅ ⋅ ⋅ | | ⋅ ⋅ ⋅ ⋅ | | ⋅ ⋅ ⋅ ⋅ |\n", - "| □ □ □ □ | | ⋅ □ □ □ | | ⋅ ⋅ ⋅ ⋅ | | ⋅ ⋅ ⋅ ⋅ |\n", - "| □ □ □ □ | | ⋅ □ □ □ | | ⋅ ⋅ □ □ | | ⋅ ⋅ ⋅ ⋅ |\n", - "| □ □ □ □ | | ⋅ □ □ □ | | ⋅ ⋅ □ □ | | ⋅ ⋅ ⋅ □ |\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим пример работы алгоритма на матрице размера $4 \\times 4$. Исходную матрицу обозначим `A₁`, нижнетреугольную `L` проинициализируем единичной матрицей, а верхнетреугольную `U` нулями." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c4e3d49d", - "metadata": {}, - "outputs": [], - "source": [ - "A₁ = Float64[\n", - " 5 1 0 9;\n", - " 4 2 -1 4;\n", - " 8 -1 4 1;\n", - " 5 7 4 6;\n", - "]\n", - "L = diagm(0 => ones(4))\n", - "U = zeros(4, 4);" - ] - }, - { - "cell_type": "markdown", - "id": "d4800bf6", - "metadata": {}, - "source": [ - "Первый шаг алгоритма основывается на {eq}`lu_row`: вычисляем первую строку `U`" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "c76b6236", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 5.0 1.0 0.0 9.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U[1, :] .= A₁[1, :]\n", - "U" - ] - }, - { - "cell_type": "markdown", - "id": "f2623a5f", - "metadata": {}, - "source": [ - "Теперь вычислим первый столбец `L` {eq}`lu_col`" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7c149075", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 1.0 0.0 0.0 0.0\n", - " 0.8 1.0 0.0 0.0\n", - " 1.6 0.0 1.0 0.0\n", - " 1.0 0.0 0.0 1.0" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L[:, 1] .= A₁[:, 1] ./ U[1, 1]\n", - "L" - ] - }, - { - "cell_type": "markdown", - "id": "aa210510", - "metadata": {}, - "source": [ - "Вычтем из `A₁` внешнее произведение первого столбца `L` и первой строки `U`" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "d2fe0f72", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 1.2 -1.0 -3.2\n", - " 0.0 -2.6 4.0 -13.4\n", - " 0.0 6.0 4.0 -3.0" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₂ = A₁ - L[:, 1] * U[1, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "a1c26155", - "metadata": {}, - "source": [ - "$\\mathbf{A}_2 = \\mathbf{l}_2 \\mathbf{u}_2^\\top + \\mathbf{l}_3 \\mathbf{u}_3^\\top + \\mathbf{l}_4 \\mathbf{u}_4^\\top$. Так, задача свелась к предыдущей, на матрице размера $3 \\times 3$." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "218094e6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 1.83333 -20.3333\n", - " 0.0 0.0 9.0 13.0" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U[2, :] .= A₂[2, :]\n", - "L[:, 2] .= A₂[:, 2] ./ U[2, 2]\n", - "A₃ = A₂ - L[:, 2] * U[2, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "2a4c16ec", - "metadata": {}, - "source": [ - "Предпоследний шаг" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "98573298", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 112.818" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U[3, :] .= A₃[3, :]\n", - "L[:, 3] .= A₃[:, 3] ./ U[3, 3]\n", - "A₄ = A₃ - L[:, 3] * U[3, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "478b129d", - "metadata": {}, - "source": [ - "И последний" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "6bad9492", - "metadata": {}, - "outputs": [], - "source": [ - "U[4, 4] = A₄[4, 4];" - ] - }, - { - "cell_type": "markdown", - "id": "db30cd2d", - "metadata": {}, - "source": [ - "Теперь известно разложение матрицы" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "baed221b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 5.0 1.0 0.0 9.0\n", - " 0.0 1.2 -1.0 -3.2\n", - " 0.0 0.0 1.83333 -20.3333\n", - " 0.0 0.0 0.0 112.818" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "384c8281", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 1.0 0.0 0.0 0.0\n", - " 0.8 1.0 0.0 0.0\n", - " 1.6 -2.16667 1.0 0.0\n", - " 1.0 5.0 4.90909 1.0" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L" - ] - }, - { - "cell_type": "markdown", - "id": "73643fdf", - "metadata": {}, - "source": [ - "Проверим, что $\\mathbf{A} = \\mathbf{LU}$. Из-за погрешность вычислений с плавающей точкой, возможны неточности." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "592142d2", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 2.22045e-16 0.0 0.0\n", - " 0.0 0.0 0.0 0.0" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₁ - L * U" - ] - }, - { - "cell_type": "markdown", - "id": "3f98072f", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Следуя примеру выше несложно написать реализацию.\n", - "\n", - "(function-lufact)=\n", - "```{proof:function} lufact\n", - "\n", - "**LU-разложение (нестабильное)**\n", - "\n", - ":::julia\n", - "\"Нестабильное LU-разложение квадратной матрицы `A`. Возвращает `L`, `U`.\"\n", - "function lufact(A::AbstractMatrix)\n", - " n = size(A, 1)\n", - " L = diagm(0 => ones(n))\n", - " U = zeros(n, n)\n", - " Aₖ = float(copy(A))\n", - " \n", - " for k in 1:n-1\n", - " U[k, :] .= Aₖ[k, :]\n", - " L[:, k] .= Aₖ[:, k] ./ U[k, k]\n", - " Aₖ .-= L[:, k] * U[k, :]'\n", - " end\n", - " U[n, n] = Aₖ[n, n]\n", - " return LowerTriangular(L), UpperTriangular(U)\n", - "end\n", - ":::\n", - "\n", - ":::{note}\n", - "В строке `Aₖ = float(copy(A))` используется копирование входной матрицы, поскольку в Julia массивы передаются в функцию по ссылке.\n", - "\n", - "В теле цикла использован броадкаст операций для избежания выделений памяти. Например, операция `Aₖ[:, k] / U[k, k]` выделяет вектор `Aₖ[:, k]`, а затем выделяет новый вектор в результате деления. В случае с броадкастом операций такие выделения памяти не происходят.\n", - ":::\n", - "```\n", - "\n", - "## Решение системы уравнений\n", - "\n", - "```{proof:algorithm} Решение системы уравнений через LU-разложение\n", - "Пусть дана система уравнений $\\mathbf{A x} = \\mathbf{b}$. Алгоритм решения следующий\n", - "\n", - "1. Разложить матрицу $\\mathbf{A} = \\mathbf{LU}$;\n", - "2. Решить $\\mathbf{L z} = \\mathbf{b}$, используя прямую подставновку;\n", - "3. Решить $\\mathbf{U x} = \\mathbf{z}$, используя обратную подстановку.\n", - "```\n", - "\n", - "Решение системы уравнений через LU-разложение имеет преимущество над методом Гаусса.\n", - "Так, в методе Гаусса составляется матрица $[\\mathbf{A}\\:\\mathbf{b}]$, где левая часть приводится к треугольному виду. В результате, для нескольких систем с разными правыми частями приходится проводить процедуру заново. В LU-разложении достаточно один раз разложить исходную матрицу, а затем воспользоваться шагами 2 и 3 алгоритма выше для разных правых частей $\\mathbf{b}$.\n", - "\n", - "```{proof:demo} Пример решения\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим решение системы" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "da3e84f9", - "metadata": {}, - "outputs": [], - "source": [ - "A = [5 1 0 9; 4 2 -1 4; 8 -1 4 1; 5 7 4 6]\n", - "b = [1, 2, 7, 3];" - ] - }, - { - "cell_type": "markdown", - "id": "81ea760d", - "metadata": {}, - "source": [ - "Сначала выполним разложение, а затем последовательно воспользуемся прямой и обратной подстановками" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "ff9624a1", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Float64}:\n", - " 0.876712328767123\n", - " 0.06849315068493178\n", - " 0.10958904109589054\n", - " -0.38356164383561636" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L, U = lufact(A)\n", - "z = forwardsub(L, b)\n", - "x = backwardsub(U, z)" - ] - }, - { - "cell_type": "markdown", - "id": "e262a7f0", - "metadata": {}, - "source": [ - "Невязка при этом составила" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "d9d0ccaa", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Float64}:\n", - " -4.440892098500626e-16\n", - " 2.220446049250313e-16\n", - " 8.881784197001252e-16\n", - " -1.7763568394002505e-15" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "b - A*x" - ] - }, - { - "cell_type": "markdown", - "id": "1bb568fb", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 154, - 163, - 167, - 170, - 174, - 177, - 181, - 183, - 187, - 191, - 195, - 199, - 203, - 205, - 209, - 212, - 214, - 218, - 220, - 279, - 282, - 286, - 290, - 294, - 296 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/syslinear/lu.md b/_sources/syslinear/lu.md index 4f621aa..a14a43e 100644 --- a/_sources/syslinear/lu.md +++ b/_sources/syslinear/lu.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Мы рассмотрим центральный алгоритм вычислительной линейной алгебры - LU-разложение. + :keywords: вычислительная математика, вычматы, lu разложение, алгоритм, код, пример +``` + ```{code-cell} :tags: [remove-cell] @@ -209,6 +217,7 @@ U[4, 4] = A₄[4, 4]; ```{code-cell} U ``` + ```{code-cell} L ``` diff --git a/_sources/syslinear/plu.ipynb b/_sources/syslinear/plu.ipynb deleted file mode 100644 index dad442e..0000000 --- a/_sources/syslinear/plu.ipynb +++ /dev/null @@ -1,903 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "00388b75", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "plufact" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "e06babb1", - "metadata": {}, - "source": [ - "# PLU-разложение\n", - "\n", - "Разложение, представленное в предыдущем разделе, существует не всегда.\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Применим разложение к следующей матрице." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "1ba42ad0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 LowerTriangular{Float64, Matrix{Float64}}:\n", - " 1.0 ⋅ ⋅ ⋅ \n", - " 1.0 NaN ⋅ ⋅ \n", - " 5.0 -Inf NaN ⋅ \n", - " -8.0 Inf NaN 1.0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A = [\n", - " 1 2 -1 9;\n", - " 1 2 1 3;\n", - " 5 1 8 7;\n", - " -8 6 5 1;\n", - "]\n", - "L, U = lufact(A)\n", - "L" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "64421c28", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 UpperTriangular{Float64, Matrix{Float64}}:\n", - " 1.0 2.0 -1.0 9.0\n", - " ⋅ 0.0 2.0 -6.0\n", - " ⋅ ⋅ Inf -Inf\n", - " ⋅ ⋅ ⋅ NaN" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U" - ] - }, - { - "cell_type": "markdown", - "id": "41c6499c", - "metadata": {}, - "source": [ - "Матрицы разложения имеют `NaN` и `Inf` значения, возникшие в результате деления на ноль. При этом сама матрица обратимая." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2c688a0e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "det(A) = 1196.0\n" - ] - } - ], - "source": [ - "@show det(A);" - ] - }, - { - "cell_type": "markdown", - "id": "9e1b6152", - "metadata": {}, - "source": [ - "На первом шаге разложения всё в порядке" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "0ee63b7f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 1.0 0.0 0.0 0.0\n", - " 1.0 1.0 0.0 0.0\n", - " 5.0 0.0 1.0 0.0\n", - " -8.0 0.0 0.0 1.0" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L = diagm(0 => ones(4))\n", - "U = zeros(4, 4)\n", - "A₁ = float(copy(A))\n", - "U[1, :] .= A₁[1, :]\n", - "L[:, 1] .= A₁[:, 1] ./ U[1, 1]\n", - "L" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "67ecf750", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 2.0 -6.0\n", - " 0.0 -9.0 13.0 -38.0\n", - " 0.0 22.0 -3.0 73.0" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₂ = A₁ - L[:, 1] * U[1, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "c1b9fabd", - "metadata": {}, - "source": [ - "Из вида матрицы `A₂` понятно, что на втором шаге возникнет деление на ноль. А именно, при присваивании матрице `U` новой строки всё нормально, первое деление на ноль возникает при подсчёте столбца матрицы `L`, поскольку `U[2, 2] == A₂[2, 2]`" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "f6421b0b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 1.0 NaN 0.0 0.0\n", - " 1.0 NaN 0.0 0.0\n", - " 5.0 -Inf 1.0 0.0\n", - " -8.0 Inf 0.0 1.0" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U[2, :] .= A₂[2, :]\n", - "L[:, 2] .= A₂[:, 2] ./ U[2, 2];\n", - "L" - ] - }, - { - "cell_type": "markdown", - "id": "02730748", - "metadata": {}, - "source": [ - "Полученные `NaN` и `Inf` значения распроcтранятся в результате операции" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "a057b956", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " NaN NaN NaN NaN\n", - " NaN NaN NaN NaN\n", - " NaN NaN Inf -Inf\n", - " NaN NaN -Inf Inf" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₃ = A₂ - L[:, 2] * U[2, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "456ac219", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Чтобы подобной ситуации для обратимых матриц не возникало, достаточно на итерации выбирать главный элемент.\n", - "\n", - "## Выбор главного элемента\n", - "\n", - "Гланым элементом (англ., *pivot*) называют диагональный элемент матрицы `U[k, k]`, который возникает в строке функции {numref}`Функция {number} `\n", - "\n", - "```julia\n", - "for k in 1:n-1\n", - " U[k, :] .= Aₖ[k, :]\n", - " L[:, k] .= Aₖ[:, k] ./ U[k, k]\n", - " Aₖ .-= L[:, k] * U[k, :]'\n", - "end\n", - "``` \n", - "\n", - "Чтобы избежать делений на ноль, необходимо выбрать в качестве *главного элемента* ненулевой $p$-ый элемент $k$-ого столбца матрицы `Aₖ`. И затем уже работать со строкой `Aₖ[p, :]` в теле цикла, которую называют *главной строкой*.\n", - "\n", - "Выбрать главный элемент можно разными способами, однако, численная стабильность разложения достигается при выборе элемента с максимальным абсолютным значением.\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим ту же матрицу, что и в начале раздела." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "d0464e90", - "metadata": {}, - "outputs": [], - "source": [ - "A = [\n", - " 1 2 -1 9;\n", - " 1 2 1 3;\n", - " 5 1 8 7;\n", - " -8 6 5 1;\n", - "]\n", - "L = diagm(0 => ones(4))\n", - "U = zeros(4, 4)\n", - "A₁ = float(copy(A));" - ] - }, - { - "cell_type": "markdown", - "id": "d69089b3", - "metadata": {}, - "source": [ - "Но на этот раз будем производить выбор главного элемента." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "4579b8d9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "p = 4\n", - "A₁[p, 1] = -8.0\n" - ] - } - ], - "source": [ - "p = argmax(abs.(A₁[:, 1]))\n", - "@show p\n", - "@show A₁[p, 1];" - ] - }, - { - "cell_type": "markdown", - "id": "136df119", - "metadata": {}, - "source": [ - "Функция `argmax` возвращает индекс наибольшего элемента массива. В качестве массива используется столбец из абсолютных значений столбца матрицы `A₁[:, 1]`.\n", - "\n", - "Проведём обновление матриц разложения и убедимся, что на этот раз `L` не содержит неопределённых float-значений." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "69192bcb", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " -0.125 0.0 0.0 0.0\n", - " -0.125 1.0 0.0 0.0\n", - " -0.625 0.0 1.0 0.0\n", - " 1.0 0.0 0.0 1.0" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U[1, :] .= A₁[p, :]\n", - "L[:, 1] .= A₁[:, 1] ./ U[1, 1];\n", - "L" - ] - }, - { - "cell_type": "markdown", - "id": "9081e28c", - "metadata": {}, - "source": [ - "Завершим шаг" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "1c55170e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 2.75 -0.375 9.125\n", - " 0.0 2.75 1.625 3.125\n", - " 0.0 4.75 11.125 7.625\n", - " 0.0 0.0 0.0 0.0" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₂ = A₁ - L[:, 1] * U[1, :]'" - ] - }, - { - "cell_type": "markdown", - "id": "2e67cb7a", - "metadata": {}, - "source": [ - "Поскольку главным элементом был четвёртый, то и `A₂` имеет нулевую четвёртую строку.\n", - "\n", - "Продолжим шаги дальше" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "ef3e5d91", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "p = argmax(abs.(A₂[:, 2])) = 3\n", - "p = argmax(abs.(A₃[:, 3])) = 1\n", - "p = argmax(abs.(A₄[:, 4])) = 2\n" - ] - } - ], - "source": [ - "@show p = argmax(abs.(A₂[:, 2]))\n", - "U[2, :] .= A₂[p, :]\n", - "L[:, 2] .= A₂[:, 2] ./ U[2, 2]\n", - "A₃ = A₂ - L[:, 2] * U[2, :]'\n", - "\n", - "@show p = argmax(abs.(A₃[:, 3]))\n", - "U[3, :] .= A₃[p, :]\n", - "L[:, 3] .= A₃[:, 3] ./ U[3, 3]\n", - "A₄ = A₃ - L[:, 3] * U[3, :]'\n", - "\n", - "@show p = argmax(abs.(A₄[:, 4]))\n", - "U[4, :] .= A₄[p, :]\n", - "L[:, 4] .= A₄[:, 4] ./ U[4, 4];" - ] - }, - { - "cell_type": "markdown", - "id": "6cb97986", - "metadata": {}, - "source": [ - "Мы действительно получили разложение $\\mathbf{A}=\\mathbf{LU}$" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "73cd83b0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 2.22045e-16 0.0\n", - " 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A₁ - L*U" - ] - }, - { - "cell_type": "markdown", - "id": "6565f4ab", - "metadata": {}, - "source": [ - "При этом матрица $\\mathbf{U}$ имеет верхнетреугольную структуру" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "e3f71625", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " -8.0 6.0 5.0 1.0\n", - " 0.0 4.75 11.125 7.625\n", - " 0.0 0.0 -6.81579 4.71053\n", - " 0.0 0.0 0.0 -4.61776" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U" - ] - }, - { - "cell_type": "markdown", - "id": "3a03710e", - "metadata": {}, - "source": [ - "А матрица $\\mathbf{L}$ теперь не нижнетреугольная." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "ff378754", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " -0.125 0.578947 1.0 -0.0\n", - " -0.125 0.578947 0.706564 1.0\n", - " -0.625 1.0 -0.0 -0.0\n", - " 1.0 0.0 -0.0 -0.0" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L" - ] - }, - { - "cell_type": "markdown", - "id": "17fcad70", - "metadata": {}, - "source": [ - "Чтобы восстановить структуру матрицы $\\mathbf{L}$, достаточно переставить в ней строки согласно последовательности выбора главных элементов. В нашем случае это были $4$, $3$, $1$ и $2$. В Julia это осуществляется с помощью следующего синтаксиса" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "2172007e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4×4 Matrix{Float64}:\n", - " 1.0 0.0 -0.0 -0.0\n", - " -0.625 1.0 -0.0 -0.0\n", - " -0.125 0.578947 1.0 -0.0\n", - " -0.125 0.578947 0.706564 1.0" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L = L[[4, 3, 1, 2], :]" - ] - }, - { - "cell_type": "markdown", - "id": "707b3d28", - "metadata": {}, - "source": [ - "*Voilà!*\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "```{proof:proposition}\n", - "LU-разложение с выбором главной строки выполнимо, если производится над обратимой матрицей {cite}`fnc2017`.\n", - "```\n", - "\n", - "Несмотря на это утверждение, существуют примеры обратимых матриц, для которых *численный алгоритм* разложения всё-таки не работает, однако на практике такие матрицы встречаются редко.\n", - "\n", - "## PLU-разложение\n", - "\n", - "Теперь есть всё, чтобы построить LU-разложение с выбором главной строки. Такое разложение называют PLU-разложением (англ., row-pivoting LU factorization).\n", - "\n", - "```{index} разложение; PLU\n", - "```\n", - "```{proof:definition} PLU-разложение\n", - "Пусть дана матрица $\\mathbf{A}$ размера $n\\times n$. PLU-разложением называется тройка из\n", - "\n", - "- нижнетреугольной матрицы $\\mathbf{L}$;\n", - "- верхнетреугольной матрицы $\\mathbf{U}$;\n", - "- и перестановки $i_1, i_2, \\ldots, i_n$ индексов $1, \\ldots, n$.\n", - "\n", - "Эта тройка такова, что\n", - "\n", - "$$\n", - "\\hat{\\mathbf{A}} = \\mathbf{LU},\n", - "$$\n", - "\n", - "где строки $1, \\ldots, n$ матрицы $\\hat{\\mathbf{A}}$ это строки $i_1, i_2, \\ldots, i_n$ исходной матрицы $\\mathbf{A}$.\n", - "```\n", - "\n", - "Итак, для реализации теперь необходимо возвращать не только матрицы разложения, но и вектор-перестановку.\n", - "\n", - "```{proof:function} plufact\n", - "\n", - "**LU-разложение с выбором главной строки**\n", - "\n", - ":::julia\n", - "\"PLU-разложение матрицы `A`. Возвращает `L`, `U` и вектор-перестановку.\"\n", - "function plufact(A::AbstractMatrix)\n", - " n = size(A, 1)\n", - " p = zeros(Int, n)\n", - " \n", - " U = float(similar(A))\n", - " L = similar(U)\n", - " Aₖ = float(copy(A))\n", - " \n", - " for k in 1:n-1\n", - " p[k] = argmax(abs.(Aₖ[:, k]))\n", - " U[k, :] .= Aₖ[p[k], :]\n", - " L[:, k] .= Aₖ[:, k] ./ U[k, k]\n", - " Aₖ .-= L[:, k] * U[k, :]'\n", - " end\n", - " \n", - " p[n] = argmax(abs.(Aₖ[:, n]))\n", - " U[n, n] = Aₖ[p[n], n]\n", - " L[:, n] = Aₖ[:, n] / U[n, n]\n", - " \n", - " return LowerTriangular(L[p, :]), UpperTriangular(U), p\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo} Пример решения системы\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим решение системы" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "233e2718", - "metadata": {}, - "outputs": [], - "source": [ - "A = [5 1 0 9; 4 2 -1 4; 8 -1 4 1; 5 7 4 6]\n", - "b = [1, 2, 7, 3];" - ] - }, - { - "cell_type": "markdown", - "id": "fa06fd3a", - "metadata": {}, - "source": [ - "Как и в случае LU, cначала выполним разложение" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "0ffdeef7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Int64}:\n", - " 3\n", - " 4\n", - " 2\n", - " 1" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "L, U, p = plufact(A);\n", - "p" - ] - }, - { - "cell_type": "markdown", - "id": "4624a2f5", - "metadata": {}, - "source": [ - "Однако, для решения системы нужно сначала сделать перестановку в векторе правой части $\\mathbf{b}$" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "e1fc52e0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Float64}:\n", - " 0.8767123287671232\n", - " 0.06849315068493142\n", - " 0.10958904109589052\n", - " -0.38356164383561636" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "z = forwardsub(L, b[p])\n", - "x = backwardsub(U, z)" - ] - }, - { - "cell_type": "markdown", - "id": "075c73d1", - "metadata": {}, - "source": [ - "Невязка при этом составила" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "fdca8892", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4-element Vector{Float64}:\n", - " -4.440892098500626e-16\n", - " 2.220446049250313e-16\n", - " 0.0\n", - " -8.881784197001252e-16" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "b - A*x" - ] - }, - { - "cell_type": "markdown", - "id": "f85eb182", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "PLU-разложение является центральным алгоритмом для решения систем линейных уравнений общего вида. Его вычислительная сложность (число операций с плавающей точкой: флопс, flops) составляет $\\propto \\frac{2}{3} n^3$, где $n$ -- размер матрицы системы.\n", - "\n", - "В дальнейшем, упоминая LU-разложение, мы для краткости будем подразумевать PLU-разложение.\n", - "\n", - "## PLU в Julia\n", - "\n", - "В Julia PLU разложение называется просто LU разложением и доступно в модуле `LinearAlgebra`.\n", - "\n", - "- Функция `lu(A)` возвращает объект разложения `F`, содержащий\n", - " + множители `F.L` и `F.U`\n", - " + матрицу перестановок `F.P`\n", - " + вектор перестановок `F.p`\n", - "- Для решения системы уравнений можно пользоваться самим объектом разложения\n", - "- Решение системы можно выполнять\n", - " + оператором `F \\ b`, тогда решение будет аллоцироваться\n", - " + функцией `ldiv!(x, F, b)`, тогда решение не будет аллоцироваться и запишется в `x`\n", - "\n", - "```julia-repl\n", - "julia> A = [5 1 0 9; 4 2 -1 4; 8 -1 4 1; 5 7 4 6];\n", - "julia> b = [1, 2, 7, 3];\n", - "julia> F = lu(A);\n", - "\n", - "julia> F \\ b - A \\ b\n", - "4-element Vector{Float64}:\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - "\n", - "julia> norm(F.L * F.U - A[F.p, :])\n", - "5.570606194861277e-16\n", - "\n", - "julia> F.p\n", - "4-element Vector{Int64}:\n", - " 3\n", - " 4\n", - " 2\n", - " 1\n", - "\n", - "julia> ldiv!(x, F, b);\n", - "julia> norm(x - F \\ b)\n", - "0.0\n", - "```\n", - "\n", - "```{margin}\n", - "Технические детали здесь опускаются, диспатч оператора `\\` [немного сложнее](https://github.com/JuliaLang/julia/blob/eea2ca79ea00060080de64c1449454bb86bc10cf/stdlib/LinearAlgebra/src/generic.jl#L1065-L1113).\n", - "```\n", - "В чём разница между `A \\ b` и `F \\ b`? У оператора `\\` есть несколько методов. Наиболее общий из них принимает на вход `AbstractMatrix` и вектор `AsbtractVector`. Этот метод проверяет, квадратная ли система, и является ли она треугольной. Если условия не выполнены, то применяется LU разложение, и вызывается второй метод -- `F \\ b`. Таким образом, в первом случае производятся проверки и LU разложение, а во втором нет -- разложение уже хранится в `F` и достаточно применить прямую/обратную подстановки." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 31, - 42, - 44, - 48, - 50, - 54, - 63, - 65, - 69, - 73, - 77, - 79, - 111, - 121, - 125, - 129, - 135, - 139, - 143, - 145, - 151, - 165, - 169, - 171, - 175, - 177, - 181, - 183, - 187, - 189, - 265, - 268, - 272, - 275, - 279, - 282, - 286, - 288 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/syslinear/plu.md b/_sources/syslinear/plu.md index 9edf5c6..f19e01e 100644 --- a/_sources/syslinear/plu.md +++ b/_sources/syslinear/plu.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: Мы рассмотрим центральный алгоритм вычислительной линейной алгебры - LU-разложение с выбором главного элемента. + :keywords: вычислительная математика, вычматы, plu разложение, lu разложение, алгоритм, код, пример +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/syslinear/triangular.ipynb b/_sources/syslinear/triangular.ipynb deleted file mode 100644 index b9d4908..0000000 --- a/_sources/syslinear/triangular.ipynb +++ /dev/null @@ -1,123 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "420be452", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "ca441bd2", - "metadata": {}, - "source": [ - "# Треугольные системы\n", - "\n", - "Прежде всего рассмотрим решение треугольной системы.\n", - "\n", - "Рассмотрим частный случай для системы $\\mathbf{L}\\mathbf{x}=\\mathbf{b}$, где $\\mathbf{L}$ -- **нижнетреугольная** матрица размера 4\n", - "\n", - "```{math}\n", - "\\begin{bmatrix}\n", - "L_{11} & 0 & 0 & 0 \\\\\n", - "L_{21} & L_{22} & 0 & 0 \\\\\n", - "L_{31} & L_{32} & L_{33} & 0 \\\\\n", - "L_{41} & L_{42} & L_{43} & L_{44}\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "x_1 \\\\ x_2 \\\\ x_3 \\\\ x_4\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "b_1 \\\\ b_2 \\\\ b_3 \\\\ b_4\n", - "\\end{bmatrix}\n", - "```\n", - "\n", - "```{index} подстановка; прямая\n", - "```\n", - "Эта система может быть решена итерационно, начиная с $x_1$\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "x_1 &= \\frac{b_1}{L_{11}}\\\\\n", - "x_2 &= \\frac{b_2 - L_{21}x_1}{L_{22}}\\\\\n", - "x_3 &= \\frac{b_3 - (L_{31}x_1 + L_{32}x_2)}{L_{33}}\\\\\n", - "x_4 &= \\frac{b_4 - (L_{41}x_1 + L_{42}x_2 + L_{43}x_3)}{L_{44}}\n", - "\\end{split}\n", - "```\n", - "\n", - "Алгоритм, который здесь применён называют **прямой подстановкой** (*forward substitution*).\n", - "\n", - "```{index} подстановка; обратная\n", - "```\n", - "\n", - "Аналогично, система $\\mathbf{U}\\mathbf{x}=\\mathbf{b}$, где $\\mathbf{U}$ -- **верхнетреугольная** матрица, может быть решена алгоритмом **обратной подстановки** (*backward substitution*). Например, для случая $\\mathbf{U}$ размера 4\n", - "\n", - "```{math}\n", - "\\begin{bmatrix}\n", - "U_{11} & U_{12} & U_{13} & U_{14} \\\\\n", - "0 & U_{22} & U_{23} & U_{24} \\\\\n", - "0 & 0 & U_{33} & U_{34} \\\\\n", - "0 & 0 & 0 & U_{44}\n", - "\\end{bmatrix}\n", - "\\begin{bmatrix}\n", - "x_1 \\\\ x_2 \\\\ x_3 \\\\ x_4\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "b_1 \\\\ b_2 \\\\ b_3 \\\\ b_4\n", - "\\end{bmatrix}\n", - "```\n", - "\n", - "алгоритм обратной подстановки начинается с $x_4$ и включает следующие шаги\n", - "\n", - "```{math}\n", - "\\begin{split}\n", - "x_4 &= \\frac{b_4}{U_{44}}\\\\\n", - "x_3 &= \\frac{b_3 - U_{34}x_4}{U_{33}}\\\\\n", - "x_2 &= \\frac{b_2 - (U_{23}x_3 + U_{24}x_4)}{U_{22}}\\\\\n", - "x_1 &= \\frac{b_1 - (U_{12} x_2 + U_{13}x_3 + U_{14}x_4)}{U_{11}}.\n", - "\\end{split}\n", - "```\n", - "\n", - "Алгоритм постановки показывает следующее утверждение.\n", - "\n", - "```{proof:proposition}\n", - "Треугольная матрица вырождена тогда и только тогда, когда хотя бы один ёё диагональнй элемент нулевой.\n", - "```\n", - "\n", - "## Реализация\n", - "\n", - "Реализация алгоритмов подстановки входит в {ref}`домашнее задание `." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "source_map": [ - 13, - 17 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/syslinear/triangular.md b/_sources/syslinear/triangular.md index ed7e593..6c7b588 100644 --- a/_sources/syslinear/triangular.md +++ b/_sources/syslinear/triangular.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Треугольные системы уравнений и алгоритмы их решения: прямая и обратная подстановка. + :keywords: вычислительная математика, вычматы, треугольная система, подстановка, прямая подстановка, обратная подстановка +``` + # Треугольные системы Прежде всего рассмотрим решение треугольной системы. diff --git a/_sources/sysnonlinear/ex.md b/_sources/sysnonlinear/ex.md index b7a53d6..a02e041 100644 --- a/_sources/sysnonlinear/ex.md +++ b/_sources/sysnonlinear/ex.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: Задачи и упражения на тему для решения нелинейной системы уравнений. + :keywords: задание, задача, упражение, нелинейное уравнение, система нелинейных уравнений, снау, вычислительная математика, вычматы +``` + # Задания ## Фазовое равновесие уравнения ван дер Ваальса diff --git a/_sources/sysnonlinear/index.md b/_sources/sysnonlinear/index.md index 9fa48ad..20cdde2 100644 --- a/_sources/sysnonlinear/index.md +++ b/_sources/sysnonlinear/index.md @@ -1,3 +1,9 @@ +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим задачу решения нелинейной системы уравнений и некоторые методы её решения. + :keywords: нелинейное уравнение, система нелинейных уравнений, снау, вычислительная математика, вычматы +``` + # Нелинейные системы уравнений В данном разделе рассматривается решение нелинейных систем уравнений diff --git a/_sources/sysnonlinear/newton.ipynb b/_sources/sysnonlinear/newton.ipynb deleted file mode 100644 index 7a842b0..0000000 --- a/_sources/sysnonlinear/newton.ipynb +++ /dev/null @@ -1,346 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "95f30481", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "broydensys" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "4b7ff066", - "metadata": {}, - "source": [ - "(sec-nlsystem-newton)=\n", - "# Метод Ньютона\n", - "\n", - "Одним из простых методов решения является обобщение метода Ньютона (Ньютона-Рафсона, *Newton-Raphson method*) на случай многомерной функции $\\mathbf{f}$.\n", - "\n", - "Как и для скалярного метода, представим $\\mathbf{f}$ линейной моделью\n", - "\n", - "```{math}\n", - ":label: sysnonlinear_taylor\n", - "\n", - "f_i(\\mathbf{x} + \\mathbf{\\delta x})\n", - "= f_i(\\mathbf{x}) + \\sum_{j=1}^n \\frac{\\partial f_i}{\\partial x_j}(\\mathbf{x}) \\delta x_j + O(\\mathbf{\\delta x}^2)\n", - "```\n", - "\n", - "```{margin}\n", - "В русскоязычной литературе якобианом называют, как правило, детерминант матрицы Якоби.\n", - "```\n", - "```{index} якобиан\n", - "```\n", - "```{index} pair: Якоби; матрица\n", - "```\n", - "Матрицу $\\mathbf{J}(\\mathbf{x})$ с элементами $J_{ij}(\\mathbf{x}) = \\frac{\\partial f_i}{\\partial x_j}(\\mathbf{x})$ называют **матрицей Якоби**, мы же, для краткости, будем называть её просто **якобианом**.\n", - "\n", - "С помощью якобиана система {eq}`sysnonlinear_taylor` записывается в виде\n", - "\n", - "```{math}\n", - "\\mathbf{f}(\\mathbf{x} + \\mathbf{\\delta x})\n", - "= \\mathbf{f}(\\mathbf{x}) + \\mathbf{J}(\\mathbf{x}) \\delta \\mathbf{x} + O(\\mathbf{\\delta x^2}).\n", - "```\n", - "\n", - "Положим теперь $\\mathbf{f}(\\mathbf{x} + \\mathbf{\\delta x}) = \\mathbf{0}$ и отбросим квадратичную поправку. Тогда получим условие\n", - "\n", - "```{math}\n", - ":label: sysnonlinear_newton_step\n", - "\n", - "\\mathbf{J}(\\mathbf{x}) \\delta \\mathbf{x} = - \\mathbf{f}(\\mathbf{x}),\n", - "```\n", - "\n", - "которое для *фиксированного* $\\mathbf{x}$ является линейной системой на $\\delta\\mathbf{x}$.\n", - "\n", - "Так, метод Ньютона строит серию приближений\n", - "\n", - "```{math}\n", - "\\mathbf{x}_\\text{new} = \\mathbf{x}_\\text{old} + \\delta\\mathbf{x} = \\mathbf{x}_\\text{old} - \\mathbf{J}^{-1}(\\mathbf{x}_\\text{old})\\mathbf{f}(\\mathbf{x}_\\text{old}).\n", - "```\n", - "\n", - "```{index} шаг; ньтоновский (нелинейные системы)\n", - "```\n", - "В свою очередь, шаг $\\delta\\mathbf{x}$, найденный из условия {eq}`sysnonlinear_newton_step` называют **ньютоновским** шагом. \n", - "\n", - "\n", - "```{index} метод; Ньютона многомерный\n", - "```\n", - "```{proof:algorithm} Многомерный метод Ньютона\n", - "Пусть дана функция $\\mathbf{f}(\\mathbf{x})$, её якобиан $\\mathbf{J}(\\mathbf{x})$ и начальное приближение корня $\\mathbf{x}_1$. Последующие $\\mathbf{x}_k$, $k=2, 3, 4, \\ldots$ приближения корня строятся следующим образом.\n", - "\n", - "1. Вычислить значение функции $\\mathbf{f}_k = \\mathbf{f}(\\mathbf{x}_k)$ и якобиан $\\mathbf{J}_k = \\mathbf{J}(\\mathbf{x}_k)$;\n", - "\n", - "2. Решить линейную систему $\\mathbf{J}_k \\delta \\mathbf{x} = - \\mathbf{f}_k$ на шаг $\\delta \\mathbf{x}$;\n", - "\n", - "3. Построить новое приближение корня $\\mathbf{x}_{k+1} = \\mathbf{x}_k + \\delta \\mathbf{x}$.\n", - "```\n", - "\n", - "## Реализация\n", - "\n", - "```{proof:function} newtonsys\n", - "\n", - "**Метод Ньютона-Рафсона решения системы нелинейных уравнений**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " newtonsys(f, x, J[; maxiter=50, xtol=1e-6, ftol=1e-6])\n", - "\n", - "Решает нелинейную систему `f`(x) = 0 методом Ньютона-Рафсона, начиная с приближения `x`.\n", - "Функция `J`(x) должна возвращать матрицу Якоби системы. Работа метода ограничена\n", - "числом итераций `maxiter`, досрочное завершение происходит при достижении\n", - "`norm(x) < xtol` или `norm(f(x)) < ftol`. При превышении числа итераций вызывает\n", - "ошибку. Возвращает найденный корень.\n", - "\"\"\"\n", - "function newtonsys(f, x, J; maxiter=50, xtol=1e-6, ftol=1e-6)\n", - " x = float(copy(x))\n", - " δx, y = similar.((x, x))\n", - " for i in 1:maxiter\n", - " y .= f(x)\n", - " δx .= .- (J(x) \\ y)\n", - " x .+= δx\n", - "\n", - " norm(δx) < xtol && return x\n", - " norm(y) < ftol && return x\n", - " end\n", - " error(\"Превышено число итераций.\")\n", - "end\n", - ":::\n", - "\n", - ":::{note}\n", - "В данной реализации необходимая память выделяется до цикла, а затем переиспользуется с помощью механизма броадкаста. Единственное место, всё ещё выделяющее память алгоритмом, является операция `\\` решения линейной системы. Поскольку `J(x)` возвращает квадратную матрицу, `\\`-операция сначала совершает LU-разложение, требующее аллоцирования. Чтобы избежать этой аллокации, смотрите `LinearAlgebra.ldiv!`.\n", - ":::\n", - "```\n", - "\n", - "(demo_sysnonlinear_newton)=\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим в качестве примера решение системы\n", - "\n", - "```{math}\n", - "\\mathbf{f}(\\mathbf{x})\n", - "= \\begin{bmatrix}\n", - "x_1^2 - 2 x_2^2 - x_1 x_2 + 2x_1 - x_2 + 1\\\\\n", - "2x_1^2 - x_2^2 + x_1 x_2 + 3 x_2 - 5\n", - "\\end{bmatrix}\n", - "= \\mathbf{0}\n", - "```\n", - "\n", - "Якобиан данной функции имеет вид\n", - "\n", - "```{math}\n", - "\\mathbf{J}(\\mathbf{x})\n", - "= \\begin{bmatrix}\n", - "2x_1 - x_2 + 2 & -4x_2 - x_1 - 1 \\\\\n", - "4x_1 + x_2 & -2x_2 + x_1 + 3 \n", - "\\end{bmatrix}\n", - "```\n", - "\n", - "Для решения заведём две функции `f` и `J` для функции $\\mathbf{f}$ и якобиана $\\mathbf{J}$ соответственно" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "78d22781", - "metadata": { - "tags": [ - "remove-output" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "J (generic function with 1 method)" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function f(x)\n", - " x₁, x₂ = x\n", - " return [\n", - " x₁^2 - 2x₂^2 - x₁*x₂ + 2x₁ - x₂ + 1,\n", - " 2x₁^2 - x₂^2 + x₁*x₂ + 3x₂ - 5,\n", - " ]\n", - "end\n", - "\n", - "function J(x)\n", - " x₁, x₂ = x\n", - " return [\n", - " 2x₁-x₂+2 -4x₂-x₁-1;\n", - " 4x₁+x₂ -2x₂+x₁+3\n", - " ]\n", - "end" - ] - }, - { - "cell_type": "markdown", - "id": "5c277727", - "metadata": {}, - "source": [ - "При наборе якобиана будьте внимательны. В Julia знак пробела или табуляция в литерале массивов означает горизонтальную конкатенацию. И в некоторых версиях языка `[x+y 0;]` (матрица `1 × 2`) может не быть эквивалентом `[x + y 0;]`.\n", - "\n", - "Попробуем запустить метод из разных начальных приближений." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "c0a0a354", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([1.0000000000000258, 1.0], [7.72715225139109e-14, 1.2878587085651816e-13])" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "root = newtonsys(f, [10.0, 10.0], J)\n", - "root, f(root)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "60905b08", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.5, 0.5000000000000001], [0.0, 0.0])" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "root = newtonsys(f, [-10.0, 10.0], J)\n", - "root, f(root)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "e2eb28fa", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.5, 0.5000000000000002], [-2.220446049250313e-16, 0.0])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "root = newtonsys(f, [10.0, -10.0], J)\n", - "root, f(root)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "88dc3406", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.6666666666666665, -0.33333333333333315], [1.1102230246251565e-16, 0.0])" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "root = newtonsys(f, [-10.0, -10.0], J)\n", - "root, f(root)" - ] - }, - { - "cell_type": "markdown", - "id": "2de8bf94", - "metadata": {}, - "source": [ - "Так, найдено три корня системы.\n", - "\n", - "```{raw} html\n", - "
\n", - "```" - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 148, - 166, - 172, - 177, - 182, - 187, - 190 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/sysnonlinear/newton.md b/_sources/sysnonlinear/newton.md index d82ed13..f147fe5 100644 --- a/_sources/sysnonlinear/newton.md +++ b/_sources/sysnonlinear/newton.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим метод Ньютона для решения нелинейной системы уравнений. + :keywords: метод ньютона, нелинейное уравнение, система нелинейных уравнений, снау, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] diff --git a/_sources/sysnonlinear/quasinewton.ipynb b/_sources/sysnonlinear/quasinewton.ipynb deleted file mode 100644 index 308a9c0..0000000 --- a/_sources/sysnonlinear/quasinewton.ipynb +++ /dev/null @@ -1,577 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "cbb60297", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "broydensys" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "include(\"../src.jl\")" - ] - }, - { - "cell_type": "markdown", - "id": "9bcfab84", - "metadata": {}, - "source": [ - "# Метод Бройдена\n", - "\n", - "Метод Ньютона послужил основой для многих других методов. Недостатком метода является требовательное по времени вычисление якобиана на каждой итерации. Для некоторых приложений это неприемлимо. Вместо прямого вычисления якобиана, **квазиньютоновские** методы заменяют якобиан некоторым приближением.\n", - "\n", - "## Приближение якобиана конечной разностью\n", - "\n", - "В {numref}`%s Методе секущих ` мы фактически сталкивались с приближением производной функции в точке $f'(x_{k+1})$\n", - "\n", - "```{math}\n", - "\\frac{f(x_{k+1}) - f(x_k)}{x_{k+1} - x_k}.\n", - "```\n", - "\n", - "Численный метод, приближающий производную \"из определения\" ($\\lim_{\\Delta x \\to 0} \\Delta f / \\Delta x$) называется методом конечной разности. Формулу замены производной её численным аналогом называют *разностной схемой*. Эти методы распространнены в решении дифференциальных уравнений.\n", - "\n", - "Подобным образом можно поступить для приближения якобиана. В общем случае для $\\mathbf{f}: \\real^n \\to \\real^m$ якобиан преобразования имеет размер $m \\times n$. Выпишем его $j$-ый столбец\n", - "\n", - "```{math}\n", - "\\mathbf{J}(\\mathbf{x}) \\mathbf{e}_j\n", - "= \\begin{bmatrix}\n", - "\\frac{\\partial f_1}{\\partial x_j}\\\\\n", - "\\frac{\\partial f_2}{\\partial x_j}\\\\\n", - "\\vdots\\\\\n", - "\\frac{\\partial f_m}{\\partial x_j}\n", - "\\end{bmatrix},\n", - "```\n", - "\n", - "где $\\mathbf{e}_j$ -- $j$-ый столбец единичной матрицы.\n", - "\n", - "Якобиан состоит из частных производных, таким образом, можно выписать его приближение через конечные разности\n", - "\n", - "```{math}\n", - "\\mathbf{J}(\\mathbf{x}) \\mathbf{e}_j\n", - "\\approx \\frac{\\mathbf{f}(\\mathbf{x} + \\delta \\mathbf{e}_j) - \\mathbf{f}(\\mathbf{x})}{\\delta},\\quad \\delta \\in \\real.\n", - "```\n", - "\n", - "Значение $\\delta$ выбирают, по умолчанию, близким к $\\sqrt{\\macheps}$ как предел численной стабильности метода конечных разностей. Этот предел берётся из сопоставления ошибки, даваемой самим методом и ошибкой округления при вычислениях.\n", - "\n", - "```{proof:function} jacobianfd\n", - "\n", - "**Приближение якобиана конечной разностью**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " jacobianfd(f, x[; y, δ])\n", - "\n", - "Вычисляет якобиан функции `f` в точке `x` через конечную разность в точках `x` и `x + δ\n", - "I[:, j]`, где `δ::Number` - скаляр. Опционально можно подать `y == f(x)`. \n", - "\"\"\"\n", - "function jacobianfd(f, x; y=f(x), δ=sqrt(eps())*max(norm(x), 1))\n", - " m, n = size(y, 1), size(x, 1)\n", - " J = zeros(m, n)\n", - " x = float(copy(x))\n", - " for j in 1:n\n", - " x[j] += δ\n", - " J[:, j] .= (f(x) .- y) ./ δ\n", - " x[j] -= δ\n", - " end\n", - " return J\n", - "end\n", - ":::\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Сравним на небольшом примере точность приближения якобиана. В качестве функции и точки приближения возьмём\n", - "\n", - "```{math}\n", - "\\mathbf{f}(\\mathbf{x})\n", - "= \\begin{bmatrix}\n", - "x_2 \\exp{x_1} + \\sin{x_1}\\\\\n", - "\\cos{x_2} + x_1 x_3\\\\\n", - "\\log{x_3} + x_2^2\n", - "\\end{bmatrix}\n", - ",\\quad\n", - "\\mathbf{x}\n", - "= \\begin{bmatrix}\n", - "\\frac{2}{3}\\\\\n", - "-1\\\\\n", - "\\sqrt{2}\n", - "\\end{bmatrix}.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "da24b9b8", - "metadata": { - "tags": [ - "remove-output" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "J (generic function with 1 method)" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function f(x)\n", - " x₁, x₂, x₃ = x\n", - " return [\n", - " x₂*exp(x₁) + sin(x₁),\n", - " cos(x₂) + x₁*x₃,\n", - " log(x₃) + x₂^2,\n", - " ]\n", - "end\n", - "\n", - "function J(x)\n", - " x₁, x₂, x₃ = x\n", - " return [\n", - " x₂*exp(x₁)+cos(x₁) exp(x₁) 0 ;\n", - " x₃ -sin(x₂) x₁ ;\n", - " 0 2x₂ 1/x₃ ;\n", - " ]\n", - "end" - ] - }, - { - "cell_type": "markdown", - "id": "c236a5d6", - "metadata": {}, - "source": [ - "Вычислим якобиан напрямую `Jexact`, и через конченые раности `Jfd`" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "f7f03c89", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3×3 Matrix{Float64}:\n", - " -1.16185 1.94773 0.0\n", - " 1.41421 0.841471 0.666667\n", - " 0.0 -2.0 0.707107" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "3×3 Matrix{Float64}:\n", - " -1.16185 1.94773 0.0\n", - " 1.41421 0.841471 0.666667\n", - " 0.0 -2.0 0.707107" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "norm(Jexact - Jfd) = 4.4920040357185245e-8\n" - ] - } - ], - "source": [ - "x = [2/3, -1.0, sqrt(2)]\n", - "Jexact, Jfd = J(x), jacobianfd(f, x)\n", - "Jexact |> display\n", - "Jfd |> display\n", - "@show norm(Jexact - Jfd);" - ] - }, - { - "cell_type": "markdown", - "id": "345c03e9", - "metadata": {}, - "source": [ - "Отличие в данной точке получилось небольшим. В качестве меры невязки здесь приведена норма Фробениуса для матриц $\\sqrt{\\sum A_{ij}^2}$.\n", - "\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Метод Бройдена\n", - "\n", - "Обозначим приближение якобиана в точке $\\mathbf{x}_k$ через $\\mathbf{B}_k$, т.е.\n", - "\n", - "```{math}\n", - "\\mathbf{J}(\\mathbf{x}_k) \\approx \\mathbf{B}_k.\n", - "```\n", - "\n", - "На $k$-ой итерации шаг квазиньютоновского метода будем находить из системы\n", - "\n", - "```{math}\n", - ":label: sysnonlinear_quasi_step\n", - "\n", - "\\mathbf{B}_k \\delta \\mathbf{x}_k = - \\mathbf{f}_k,\n", - "```\n", - "\n", - "здесь обозначены $\\delta \\mathbf{x}_k = \\mathbf{x}_{k+1} - \\mathbf{x}_k$, а $\\mathbf{f}_k = \\mathbf{f}(\\mathbf{x}_k)$.\n", - "\n", - "Квазиньютоновское условие на новое приближение якобиана $\\mathbf{B}_{k+1}$ состоит в\n", - "\n", - "```{math}\n", - ":label: sysnonlinear_quasi_cond\n", - "\\mathbf{B}_{k+1} \\delta \\mathbf{x}_k = \\mathbf{f}_{k+1} - \\mathbf{f}_k.\n", - "```\n", - "\n", - "Выбор $\\mathbf{B}_{k+1}$ не однозначен. На практике хорошие результаты показывает правило Бройдена, выведенное из минимальной в смысле нормы Фробениуса поправки к $\\mathbf{B}_k$\n", - "\n", - "```{math}\n", - ":label: sysnonlinear_broyden_cond\n", - "\n", - "\\min \\|\\mathbf{B}_{k+1} - \\mathbf{B}_k \\|_\\text{F},\\quad \\| \\mathbf{A} \\|_\\text{F}\n", - "= \\big( \\sum_{i, j} |A_{ij}|^2 \\big)^{1/2},\n", - "```\n", - "\n", - "такой, что условие {eq}`sysnonlinear_quasi_cond` удовлетворится.\n", - "\n", - "```{proof:definition} Правило Бройдена\n", - "\n", - ":::{math}\n", - ":label: sysnonlinear_broyden_update\n", - "\n", - "\\mathbf{B}_{k+1} = \\mathbf{B}_k + \\frac{1}{\\delta \\mathbf{x}^\\top_k \\delta \\mathbf{x}_k}\n", - "(\\mathbf{f}_{k+1} - \\mathbf{f}_k - \\mathbf{B}_k \\delta \\mathbf{x}_k)\n", - "\\delta \\mathbf{x}^\\top_k.\n", - ":::\n", - "```\n", - "\n", - "Самыми ресурсоемкими операциями в правиле Бройдена является матричное умножение ($\\mathbf{B}_k \\delta \\mathbf{x}_k$) и внешнее произведение ($\\square \\cdot \\delta \\mathbf{x}^\\top_k$). При этом при использовании {ref}`QR-разложения ` получается сэкономить часть операций (для этого разложения $\\text{QR}(\\mathbf{A} + \\mathbf{a}\\mathbf{b}^\\top)$ выражается через $\\text{QR}(\\mathbf{A})$).\n", - "\n", - "\n", - "```{index} метод; Бройдена, Бройдена метод\n", - "```\n", - "```{proof:algorithm} Метод Бройдена\n", - "Пусть дана функция $\\mathbf{f}$, начальная точка $\\mathbf{x}_1$ и приближение якобиана в этой точке $\\mathbf{B}_1$. Последующие приближения $k = 2, 3, \\ldots$ получаются примением действий\n", - "\n", - "1. Решить систему {eq}`sysnonlinear_quasi_step`, найдя таким образом шаг $\\delta \\mathbf{x}_k$;\n", - "\n", - "2. Построить новое приближение корня $\\mathbf{x}_{k+1} = \\mathbf{x}_k + \\delta \\mathbf{x}_k$ и вычислить значение функции в нём $\\mathbf{f}_{k+1} = \\mathbf{f}(\\mathbf{x}_{k+1})$;\n", - "\n", - "3. Получить новое приближение для якобиана $\\mathbf{B}_{k+1}$ из формулы {eq}`sysnonlinear_broyden_update`.\n", - "```\n", - "\n", - "В качестве начального приближения якобиана можно использовать как его конечную разность, так и настоящий якобиан.\n", - "\n", - "## Реализация\n", - "\n", - "```{proof:function} broydensys\n", - "\n", - "**Метод Бройдена**\n", - "\n", - ":::julia\n", - "\"\"\"\n", - " broydensys(f, x, J[; maxiter, xtol, ftol])\n", - "\n", - "Решает нелинейную систему уравнений `f`(x) = 0 методом Бройдена.\n", - "Требует начального приближения корня `x` уравнения и якобиана `J` в этой точке.\n", - "Выполняет итерации, пока норма решения `> xtol` или норма функции `> ftol`.\n", - "В случае превышения числа итераций `maxiter` вызывает ошибку.\n", - "\"\"\"\n", - "function broydensys(f, x, J; maxiter=50, xtol=1e-6, ftol=1e-6)\n", - " δx = float(similar(x))\n", - " yp, yn = similar.((δx, δx))\n", - " x = float(copy(x))\n", - " B = float(copy(J))\n", - " yn .= f(x)\n", - " for i in 1:maxiter\n", - " yp .= yn\n", - " δx .= .- (B \\ yp)\n", - " x .+= δx\n", - " yn .= f(x)\n", - "\n", - " norm(δx) < xtol && return x\n", - " norm(yn) < ftol && return x\n", - " \n", - " g = B * δx\n", - " B .+= (1 / dot(δx, δx)) .* (yn .- yp .- g) .* δx'\n", - " end\n", - " error(\"Превышено число итераций.\")\n", - "end\n", - ":::\n", - "\n", - "В данной реализации для простоты изложения явно не использовано QR-разложение, имеющее преимещуство перед LU-разложением при обновлении `B`.\n", - "```\n", - "\n", - "```{proof:demo}\n", - "```\n", - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "Рассмотрим пример использования метода Бройдена. Возьмём функцию и якобиан из {numref}`Демонстрации %s `, где использовался метод Ньютона" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "b4371632", - "metadata": { - "tags": [ - "remove-output" - ] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "J (generic function with 1 method)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "function f(x)\n", - " x₁, x₂ = x\n", - " return [\n", - " x₁^2 - 2x₂^2 - x₁*x₂ + 2x₁ - x₂ + 1,\n", - " 2x₁^2 - x₂^2 + x₁*x₂ + 3x₂ - 5,\n", - " ]\n", - "end\n", - "\n", - "function J(x)\n", - " x₁, x₂ = x\n", - " return [\n", - " 2x₁-x₂+2 -4x₂-x₁-1;\n", - " 4x₁+x₂ -2x₂+x₁+3\n", - " ]\n", - "end" - ] - }, - { - "cell_type": "markdown", - "id": "ab2f422c", - "metadata": {}, - "source": [ - "Сравним решения методом Бройдена, где в качестве $\\mathbf{B}_1$ сначала используется истинный якобиан, а затем его конечная разность" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "d26546ad", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "rjac = [0.9999999480032709, 1.0000000136175218]\n", - "rfdjac = [0.9999999480032629, 1.0000000136175238]\n", - "f(rjac) = [-2.3769531543038624e-7, -2.327485972841714e-7]\n" - ] - } - ], - "source": [ - "x = [10.0, 10.0]\n", - "rjac = broydensys(f, x, J(x))\n", - "rfdjac = broydensys(f, x, jacobianfd(f, x))\n", - "@show rjac\n", - "@show rfdjac\n", - "@show f(rjac);" - ] - }, - { - "cell_type": "markdown", - "id": "60cfe7e6", - "metadata": {}, - "source": [ - "Поищем также другие корни, не используя подлинный якобиан" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "51eb16ac", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.4999998826044423, 0.5000004907722759], [-9.122522761639829e-7, -4.002895854782196e-7])" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = [-10.0, 10.0]\n", - "root = broydensys(f, x, jacobianfd(f, x))\n", - "root, f(root)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1e5663e4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.4999999895175518, 0.5000000339688467], [-6.667694529838286e-8, -4.066904324417919e-8])" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = [10.0, -10.0]\n", - "root = broydensys(f, x, jacobianfd(f, x))\n", - "root, f(root)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "d23e7008", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([-1.6666666787349111, -0.3333330286952693], [6.213441907654271e-7, 6.937537433415741e-7])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = [-10.0, -10.0]\n", - "root = broydensys(f, x, jacobianfd(f, x))\n", - "root, f(root)" - ] - }, - { - "cell_type": "markdown", - "id": "c33190fb", - "metadata": {}, - "source": [ - "```{raw} html\n", - "
\n", - "```\n", - "\n", - "## Другие версии метода\n", - "\n", - "Изложенная выше версия метода {eq}`sysnonlinear_broyden_update` требует решения линейной системы {eq}`sysnonlinear_quasi_step`. Однако, она сочетается с линейным поиском, обеспечивающим глобальную сходимость метода, т.е. сходимостью к корню из произвольного начального приближения $\\mathbf{x}_1$, если корень существует. Правда, для этого необходимо переформулировать постановку задачи $\\mathbf{f}(\\mathbf{x}) = \\mathbf{0}$ под задачу минимизации {cite}`NumRecipes2007`.\n", - "\n", - "Если же линейный поиск не используется, распространены две версии алгоритма, использующие вместо матрицы $\\mathbf{B}$ обратную к ней $\\mathbf{B}^{-1}$, полученную аналитически. Использование $\\mathbf{B}^{-1}$ позволяет не решать систему {eq}`sysnonlinear_quasi_step`, а сразу вычислять шаг\n", - "\n", - "```{math}\n", - "\\delta \\mathbf{x}_k = - \\mathbf{B}^{-1}_k \\mathbf{f}_k.\n", - "```\n", - "\n", - "Самим Бройденом была предложена формула для $\\mathbf{B}^{-1}$ на основе применения [формулы Шермана-Моррисона](https://en.wikipedia.org/wiki/Sherman%E2%80%93Morrison_formula) к {eq}`sysnonlinear_broyden_update`\n", - "\n", - "```{math}\n", - "\\mathbf{B}^{-1}_{k+1}\n", - "= \\mathbf{B}^{-1}_k\n", - "+ \\frac{\\delta \\mathbf{x}_k - \\mathbf{B}^{-1}_k \\delta \\mathbf{f}_k}{\n", - " \\delta \\mathbf{x}_k^\\top \\mathbf{B}^{-1}_k \\delta \\mathbf{f}_k\n", - " }\n", - "\\delta \\mathbf{x}_k^\\top \\mathbf{B}^{-1}_k,\n", - "```\n", - "\n", - "здесь $\\delta \\mathbf{f}_k = \\mathbf{f}_{k+1} - \\mathbf{f}_k$. Как и формула {eq}`sysnonlinear_broyden_update`, данная формула минимизирует поправку {eq}`sysnonlinear_broyden_cond` для \"прямой\" матрицы $\\mathbf{B}_{k+1}$. Метод, основанный на данной формуле ещё называют \"хорошим методом Бройдена\" (*good Broyden's method*).\n", - "\n", - "Вторая версия метода на основе обратной матрицы $\\mathbf{B}^{-1}$ использует формулу\n", - "\n", - "```{math}\n", - "\\mathbf{B}^{-1}_{k+1}\n", - "= \\mathbf{B}^{-1}_k\n", - "+ \\frac{\\delta \\mathbf{x}_k - \\mathbf{B}^{-1}_k \\delta \\mathbf{f}_k}{\\delta \\mathbf{f}_k^\\top \\delta \\mathbf{f}_k}\n", - "\\delta \\mathbf{f}_k^\\top,\n", - "```\n", - "\n", - "которая минимизирует норму Фробениуса уже между обратными приближениями якобиана\n", - "\n", - "```{math}\n", - "\\min \\|\\mathbf{B}^{-1}_{k+1} - \\mathbf{B}^{-1}_k \\|_\\text{F}.\n", - "```\n", - "\n", - "Эта версия распространилась под названием \"плохого метода Бройдена\" (*bad Broyden's method*). Хотя, слова \"плохой\" и \"хороший\" в названии методов имеют нейтральную коннотацию." - ] - } - ], - "metadata": { - "jupytext": { - "formats": "md:myst", - "text_representation": { - "extension": ".md", - "format_name": "myst" - } - }, - "kernelspec": { - "display_name": "Julia", - "language": "julia", - "name": "julia-1.6" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.6.2" - }, - "source_map": [ - 13, - 17, - 105, - 125, - 129, - 135, - 255, - 273, - 277, - 284, - 288, - 293, - 298, - 302 - ] - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/_sources/sysnonlinear/quasinewton.md b/_sources/sysnonlinear/quasinewton.md index aa4942b..4d6e775 100644 --- a/_sources/sysnonlinear/quasinewton.md +++ b/_sources/sysnonlinear/quasinewton.md @@ -4,12 +4,20 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 kernelspec: - display_name: Julia + display_name: Julia 1.9.4 language: julia - name: julia-1.6 + name: julia-1.9 --- +```{eval-rst} +.. meta:: + :description: В этом разделе мы рассмотрим метод Бройдена (Broyden) для решения нелинейной системы уравнений. + :keywords: метод бройдена, broyden, нелинейное уравнение, система нелинейных уравнений, снау, вычислительная математика, вычматы +``` + ```{code-cell} :tags: [remove-cell] @@ -100,7 +108,7 @@ x_2 \exp{x_1} + \sin{x_1}\\ -1\\ \sqrt{2} \end{bmatrix}. -``` +``` ```{code-cell} :tags: [remove-output] @@ -290,11 +298,13 @@ x = [-10.0, 10.0] root = broydensys(f, x, jacobianfd(f, x)) root, f(root) ``` + ```{code-cell} x = [10.0, -10.0] root = broydensys(f, x, jacobianfd(f, x)) root, f(root) ``` + ```{code-cell} x = [-10.0, -10.0] root = broydensys(f, x, jacobianfd(f, x)) diff --git a/_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css b/_sphinx_design_static/design-style.4045f2051d55cab465a707391d5b2007.min.css similarity index 56% rename from _static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css rename to _sphinx_design_static/design-style.4045f2051d55cab465a707391d5b2007.min.css index 704c42e..3225661 100644 --- a/_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css +++ b/_sphinx_design_static/design-style.4045f2051d55cab465a707391d5b2007.min.css @@ -1 +1 @@ -.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #007bff;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0069d9;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #007bff;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0069d9;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/_static/__init__.py b/_static/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/_static/__pycache__/__init__.cpython-38.pyc b/_static/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 30620ffdc59c9edf37a4b11242fbc18089923b76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmWIL<>g`k0_6q5Ng(<$h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o10TKeRZts93+a zB()$huPQ@7EH$r8KdZE$vLv-ADL+43KPNLuAIQtd&okDu&@av`N!2Y#OwLYBPX+2K z$jHpAhzF^QFUd&FO$C~hSdy8nA0MBYmst`YuUAlci^C>2KczG$)edC!XCP((0GF^a A*#H0l diff --git a/_static/_sphinx_javascript_frameworks_compat.js b/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 0000000..8549469 --- /dev/null +++ b/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/_static/basic.css b/_static/basic.css index d54be80..9e364ed 100644 --- a/_static/basic.css +++ b/_static/basic.css @@ -222,7 +222,7 @@ table.modindextable td { /* -- general body styles --------------------------------------------------- */ div.body { - min-width: 450px; + min-width: 360px; max-width: 800px; } @@ -237,16 +237,6 @@ a.headerlink { visibility: hidden; } -a.brackets:before, -span.brackets > a:before{ - content: "["; -} - -a.brackets:after, -span.brackets > a:after { - content: "]"; -} - h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, @@ -334,12 +324,16 @@ aside.sidebar { p.sidebar-title { font-weight: bold; } +nav.contents, +aside.topic, div.admonition, div.topic, blockquote { clear: left; } /* -- topics ---------------------------------------------------------------- */ +nav.contents, +aside.topic, div.topic { border: 1px solid #ccc; @@ -379,6 +373,9 @@ div.body p.centered { div.sidebar > :last-child, aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, + div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; @@ -386,6 +383,9 @@ div.admonition > :last-child { div.sidebar::after, aside.sidebar::after, +nav.contents::after, +aside.topic::after, + div.topic::after, div.admonition::after, blockquote::after { @@ -428,10 +428,6 @@ table.docutils td, table.docutils th { border-bottom: 1px solid #aaa; } -table.footnote td, table.footnote th { - border: 0 !important; -} - th { text-align: left; padding-right: 5px; @@ -615,6 +611,7 @@ ul.simple p { margin-bottom: 0; } +/* Docutils 0.17 and older (footnotes & citations) */ dl.footnote > dt, dl.citation > dt { float: left; @@ -632,6 +629,33 @@ dl.citation > dd:after { clear: both; } +/* Docutils 0.18+ (footnotes & citations) */ +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +/* Footnotes & citations ends */ + dl.field-list { display: grid; grid-template-columns: fit-content(30%) auto; diff --git a/_static/copybutton.css b/_static/copybutton.css index 40eafe5..f1916ec 100644 --- a/_static/copybutton.css +++ b/_static/copybutton.css @@ -35,7 +35,8 @@ div.highlight { position: relative; } -.highlight:hover button.copybtn { +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { opacity: 1; } diff --git a/_static/copybutton.js b/_static/copybutton.js index 40ac331..2ea7ff3 100644 --- a/_static/copybutton.js +++ b/_static/copybutton.js @@ -20,7 +20,7 @@ const messages = { }, 'fr' : { 'copy': 'Copier', - 'copy_to_clipboard': 'Copié dans le presse-papier', + 'copy_to_clipboard': 'Copier dans le presse-papier', 'copy_success': 'Copié !', 'copy_failure': 'Échec de la copie', }, @@ -102,18 +102,25 @@ const clearSelection = () => { } } -// Changes tooltip text for two seconds, then changes it back +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + const temporarilyChangeTooltip = (el, oldText, newText) => { el.setAttribute('data-tooltip', newText) el.classList.add('success') - setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000) - setTimeout(() => el.classList.remove('success'), 2000) + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) } // Changes the copy button icon for two seconds, then changes it back const temporarilyChangeIcon = (el) => { el.innerHTML = iconCheck; - setTimeout(() => {el.innerHTML = iconCopy}, 2000) + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) } const addCopyButtonToCodeCells = () => { @@ -125,7 +132,8 @@ const addCopyButtonToCodeCells = () => { } // Add copybuttons to all of our code cells - const codeCells = document.querySelectorAll('div.highlight pre') + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) codeCells.forEach((codeCell, index) => { const id = codeCellId(index) codeCell.setAttribute('id', id) @@ -141,10 +149,25 @@ function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + // Callback when a copy button is clicked. Will be passed the node that was clicked // should then grab the text and replace pieces of text that shouldn't be used in output function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { - var regexp; var match; @@ -199,7 +222,12 @@ function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onl var copyTargetText = (trigger) => { var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); - return formatCopyText(target.innerText, '', false, true, true, true, '', '') + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') } // Initialize with a callback so we can modify the text before copy diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js index b9168c5..dbe1aaa 100644 --- a/_static/copybutton_funcs.js +++ b/_static/copybutton_funcs.js @@ -2,10 +2,25 @@ function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + // Callback when a copy button is clicked. Will be passed the node that was clicked // should then grab the text and replace pieces of text that shouldn't be used in output export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { - var regexp; var match; diff --git a/_static/css/blank.css b/_static/css/blank.css deleted file mode 100644 index 8a686ec..0000000 --- a/_static/css/blank.css +++ /dev/null @@ -1,2 +0,0 @@ -/* This file is intentionally left blank to override the stylesheet of the -parent theme via theme.conf. The parent style we import directly in theme.css */ \ No newline at end of file diff --git a/_static/css/index.ff1ffe594081f20da1ef19478df9384b.css b/_static/css/index.ff1ffe594081f20da1ef19478df9384b.css deleted file mode 100644 index 9b1c5d7..0000000 --- a/_static/css/index.ff1ffe594081f20da1ef19478df9384b.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v4.5.0 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors - * Copyright 2011-2020 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:540px;--breakpoint-md:720px;--breakpoint-lg:960px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;line-height:1.5;color:#212529;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;background-color:transparent}a:hover{color:#0056b3}a:not([href]),a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{margin-top:1rem;margin-bottom:1rem;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer:before{content:"\2014\00A0"}.img-fluid,.img-thumbnail{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:540px){.container{max-width:540px}}@media (min-width:720px){.container{max-width:720px}}@media (min-width:960px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1400px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:540px){.container,.container-sm{max-width:540px}}@media (min-width:720px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:960px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1400px}}.row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-auto,.col-lg,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-auto,.col-md,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md-auto,.col-sm,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.33333%;max-width:8.33333%}.col-2{flex:0 0 16.66667%;max-width:16.66667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333%;max-width:33.33333%}.col-5{flex:0 0 41.66667%;max-width:41.66667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333%;max-width:58.33333%}.col-8{flex:0 0 66.66667%;max-width:66.66667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333%;max-width:83.33333%}.col-11{flex:0 0 91.66667%;max-width:91.66667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}@media (min-width:540px){.col-sm{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}}@media (min-width:720px){.col-md{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}}@media (min-width:960px){.col-lg{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}}@media (min-width:1200px){.col-xl{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:hsla(0,0%,100%,.075)}@media (max-width:539.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:719.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:959.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:flex;flex-flow:row wrap;align-items:center}.form-inline .form-check{width:100%}@media (min-width:540px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{display:flex;align-items:center;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:flex;align-items:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success.focus,.btn-success:focus,.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info.focus,.btn-info:focus,.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light.focus,.btn-light:focus,.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:540px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:720px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:960px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle:before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label:before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label:before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label:before{pointer-events:none;background-color:#fff;border:1px solid #adb5bd}.custom-control-label:after,.custom-control-label:before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:""}.custom-control-label:after{background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label:after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{position:relative;width:100%;height:calc(1.5em + .75rem + 2px)}.custom-file-input{z-index:2;margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{left:0;z-index:1;height:calc(1.5em + .75rem + 2px);font-weight:400;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label,.custom-file-label:after{position:absolute;top:0;right:0;padding:.375rem .75rem;line-height:1.5;color:#495057}.custom-file-label:after{bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;padding:.5rem 1rem}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;background-size:100% 100%}@media (max-width:539.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:540px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:719.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:720px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:959.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:960px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0,0,0,0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:hsla(0,0%,100%,.5);border-color:hsla(0,0%,100%,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255,255,255,0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:540px){.card-deck{display:flex;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:540px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:540px){.card-columns{column-count:3;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb,.breadcrumb-item{display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:540px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{height:1rem;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{flex-direction:column;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{display:flex;align-items:flex-start}.media-body{flex:1}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:540px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:720px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:960px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translateY(-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{display:block;height:calc(100vh - 1rem);height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:540px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:min-content}.modal-sm{max-width:300px}}@media (min-width:960px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover,.popover .arrow{position:absolute;display:block}.popover .arrow{width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow:after,.popover .arrow:before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{top:0;border-width:0 .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{top:1px;border-width:0 .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid;border-right:.25em solid transparent;border-radius:50%;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:540px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:720px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:960px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive:before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9:before{padding-top:42.85714%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:540px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:720px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:960px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:540px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:720px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:960px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{user-select:all!important}.user-select-auto{user-select:auto!important}.user-select-none{user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:540px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:720px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:960px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:transparent}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:540px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:720px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:960px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:960px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}html{font-size:var(--pst-font-size-base);scroll-padding-top:calc(var(--pst-header-height) + 12px)}body{padding-top:calc(var(--pst-header-height) + 20px);background-color:#fff;font-family:var(--pst-font-family-base);font-weight:400;line-height:1.65;color:rgba(var(--pst-color-text-base),1)}p{margin-bottom:1.15rem;font-size:1em;color:rgba(var(--pst-color-paragraph),1)}p.rubric{border-bottom:1px solid #c9c9c9}a{color:rgba(var(--pst-color-link),1);text-decoration:none}a:hover{color:rgba(var(--pst-color-link-hover),1);text-decoration:underline}a.headerlink{color:rgba(var(--pst-color-headerlink),1);font-size:.8em;padding:0 4px;text-decoration:none}a.headerlink:hover{background-color:rgba(var(--pst-color-headerlink),1);color:rgba(var(--pst-color-headerlink-hover),1)}.heading-style,h1,h2,h3,h4,h5,h6{margin:2.75rem 0 1.05rem;font-family:var(--pst-font-family-heading);font-weight:400;line-height:1.15}h1{margin-top:0;font-size:var(--pst-font-size-h1);color:rgba(var(--pst-color-h1),1)}h2{font-size:var(--pst-font-size-h2);color:rgba(var(--pst-color-h2),1)}h3{font-size:var(--pst-font-size-h3);color:rgba(var(--pst-color-h3),1)}h4{font-size:var(--pst-font-size-h4);color:rgba(var(--pst-color-h4),1)}h5{font-size:var(--pst-font-size-h5);color:rgba(var(--pst-color-h5),1)}h6{font-size:var(--pst-font-size-h6);color:rgba(var(--pst-color-h6),1)}.text_small,small{font-size:var(--pst-font-size-milli)}hr{border:0;border-top:1px solid #e5e5e5}code,kbd,pre,samp{font-family:var(--pst-font-family-monospace)}code{color:rgba(var(--pst-color-inline-code),1)}pre{margin:1.5em 0;padding:10px;background-color:rgba(var(--pst-color-preformatted-background),1);color:rgba(var(--pst-color-preformatted-text),1);line-height:1.2em;border:1px solid #c9c9c9;border-radius:.2rem;box-shadow:1px 1px 1px #d8d8d8}dd{margin-top:3px;margin-bottom:10px;margin-left:30px}.navbar{position:fixed;min-height:var(--pst-header-height);width:100%;padding:0}.navbar .container-xl{height:100%}@media (min-width:960px){.navbar #navbar-end>.navbar-end-item{display:inline-block}}.navbar-brand{position:relative;height:var(--pst-header-height);width:auto;padding:.5rem 0}.navbar-brand img{max-width:100%;height:100%;width:auto}.navbar-light{background:#fff!important;box-shadow:0 .125rem .25rem 0 rgba(0,0,0,.11)}.navbar-light .navbar-nav li a.nav-link{padding:0 .5rem;color:rgba(var(--pst-color-navbar-link),1)}.navbar-light .navbar-nav li a.nav-link:hover{color:rgba(var(--pst-color-navbar-link-hover),1)}.navbar-light .navbar-nav>.active>.nav-link{font-weight:600;color:rgba(var(--pst-color-navbar-link-active),1)}.navbar-header a{padding:0 15px}.admonition,div.admonition{margin:1.5625em auto;padding:0 .6rem .8rem;overflow:hidden;page-break-inside:avoid;border-left:.2rem solid;border-left-color:rgba(var(--pst-color-admonition-default),1);border-bottom-color:rgba(var(--pst-color-admonition-default),1);border-right-color:rgba(var(--pst-color-admonition-default),1);border-top-color:rgba(var(--pst-color-admonition-default),1);border-radius:.2rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1);transition:color .25s,background-color .25s,border-color .25s}.admonition :last-child,div.admonition :last-child{margin-bottom:0}.admonition p.admonition-title~*,div.admonition p.admonition-title~*{padding:0 1.4rem}.admonition>ol,.admonition>ul,div.admonition>ol,div.admonition>ul{margin-left:1em}.admonition>.admonition-title,div.admonition>.admonition-title{position:relative;margin:0 -.6rem;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(var(--pst-color-admonition-default),.1)}.admonition>.admonition-title:before,div.admonition>.admonition-title:before{position:absolute;left:.6rem;width:1rem;height:1rem;color:rgba(var(--pst-color-admonition-default),1);font-family:Font Awesome\ 5 Free;font-weight:900;content:var(--pst-icon-admonition-default)}.admonition>.admonition-title+*,div.admonition>.admonition-title+*{margin-top:.4em}.admonition.attention,div.admonition.attention{border-color:rgba(var(--pst-color-admonition-attention),1)}.admonition.attention>.admonition-title,div.admonition.attention>.admonition-title{background-color:rgba(var(--pst-color-admonition-attention),.1)}.admonition.attention>.admonition-title:before,div.admonition.attention>.admonition-title:before{color:rgba(var(--pst-color-admonition-attention),1);content:var(--pst-icon-admonition-attention)}.admonition.caution,div.admonition.caution{border-color:rgba(var(--pst-color-admonition-caution),1)}.admonition.caution>.admonition-title,div.admonition.caution>.admonition-title{background-color:rgba(var(--pst-color-admonition-caution),.1)}.admonition.caution>.admonition-title:before,div.admonition.caution>.admonition-title:before{color:rgba(var(--pst-color-admonition-caution),1);content:var(--pst-icon-admonition-caution)}.admonition.warning,div.admonition.warning{border-color:rgba(var(--pst-color-admonition-warning),1)}.admonition.warning>.admonition-title,div.admonition.warning>.admonition-title{background-color:rgba(var(--pst-color-admonition-warning),.1)}.admonition.warning>.admonition-title:before,div.admonition.warning>.admonition-title:before{color:rgba(var(--pst-color-admonition-warning),1);content:var(--pst-icon-admonition-warning)}.admonition.danger,div.admonition.danger{border-color:rgba(var(--pst-color-admonition-danger),1)}.admonition.danger>.admonition-title,div.admonition.danger>.admonition-title{background-color:rgba(var(--pst-color-admonition-danger),.1)}.admonition.danger>.admonition-title:before,div.admonition.danger>.admonition-title:before{color:rgba(var(--pst-color-admonition-danger),1);content:var(--pst-icon-admonition-danger)}.admonition.error,div.admonition.error{border-color:rgba(var(--pst-color-admonition-error),1)}.admonition.error>.admonition-title,div.admonition.error>.admonition-title{background-color:rgba(var(--pst-color-admonition-error),.1)}.admonition.error>.admonition-title:before,div.admonition.error>.admonition-title:before{color:rgba(var(--pst-color-admonition-error),1);content:var(--pst-icon-admonition-error)}.admonition.hint,div.admonition.hint{border-color:rgba(var(--pst-color-admonition-hint),1)}.admonition.hint>.admonition-title,div.admonition.hint>.admonition-title{background-color:rgba(var(--pst-color-admonition-hint),.1)}.admonition.hint>.admonition-title:before,div.admonition.hint>.admonition-title:before{color:rgba(var(--pst-color-admonition-hint),1);content:var(--pst-icon-admonition-hint)}.admonition.tip,div.admonition.tip{border-color:rgba(var(--pst-color-admonition-tip),1)}.admonition.tip>.admonition-title,div.admonition.tip>.admonition-title{background-color:rgba(var(--pst-color-admonition-tip),.1)}.admonition.tip>.admonition-title:before,div.admonition.tip>.admonition-title:before{color:rgba(var(--pst-color-admonition-tip),1);content:var(--pst-icon-admonition-tip)}.admonition.important,div.admonition.important{border-color:rgba(var(--pst-color-admonition-important),1)}.admonition.important>.admonition-title,div.admonition.important>.admonition-title{background-color:rgba(var(--pst-color-admonition-important),.1)}.admonition.important>.admonition-title:before,div.admonition.important>.admonition-title:before{color:rgba(var(--pst-color-admonition-important),1);content:var(--pst-icon-admonition-important)}.admonition.note,div.admonition.note{border-color:rgba(var(--pst-color-admonition-note),1)}.admonition.note>.admonition-title,div.admonition.note>.admonition-title{background-color:rgba(var(--pst-color-admonition-note),.1)}.admonition.note>.admonition-title:before,div.admonition.note>.admonition-title:before{color:rgba(var(--pst-color-admonition-note),1);content:var(--pst-icon-admonition-note)}table.field-list{border-collapse:separate;border-spacing:10px;margin-left:1px}table.field-list th.field-name{padding:1px 8px 1px 5px;white-space:nowrap;background-color:#eee}table.field-list td.field-body p{font-style:italic}table.field-list td.field-body p>strong{font-style:normal}table.field-list td.field-body blockquote{border-left:none;margin:0 0 .3em;padding-left:30px}.table.autosummary td:first-child{white-space:nowrap}.sig{font-family:var(--pst-font-family-monospace)}.sig-inline.c-texpr,.sig-inline.cpp-texpr{font-family:unset}.sig.c .k,.sig.c .kt,.sig.c .m,.sig.c .s,.sig.c .sc,.sig.cpp .k,.sig.cpp .kt,.sig.cpp .m,.sig.cpp .s,.sig.cpp .sc{color:rgba(var(--pst-color-text-base),1)}.sig-name{color:rgba(var(--pst-color-inline-code),1)}blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}dt.label>span.brackets:not(:only-child):before{content:"["}dt.label>span.brackets:not(:only-child):after{content:"]"}a.footnote-reference{vertical-align:super;font-size:small}div.deprecated{margin-bottom:10px;margin-top:10px;padding:7px;background-color:#f3e5e5;border:1px solid #eed3d7;border-radius:.5rem}div.deprecated p{color:#b94a48;display:inline}.topic{background-color:#eee}.seealso dd{margin-top:0;margin-bottom:0}.viewcode-back{font-family:var(--pst-font-family-base)}.viewcode-block:target{background-color:#f4debf;border-top:1px solid #ac9;border-bottom:1px solid #ac9}span.guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}footer{width:100%;border-top:1px solid #ccc;padding:10px}footer .footer-item p{margin-bottom:0}.bd-search{position:relative;padding:1rem 15px;margin-right:-15px;margin-left:-15px}.bd-search .icon{position:absolute;color:#a4a6a7;left:25px;top:25px}.bd-search input{border-radius:0;border:0;border-bottom:1px solid #e5e5e5;padding-left:35px}.bd-toc{-ms-flex-order:2;order:2;height:calc(100vh - 2rem);overflow-y:auto}@supports (position:-webkit-sticky) or (position:sticky){.bd-toc{position:-webkit-sticky;position:sticky;top:calc(var(--pst-header-height) + 20px);height:calc(100vh - 5rem);overflow-y:auto}}.bd-toc .onthispage{color:#a4a6a7}.section-nav{padding-left:0;border-left:1px solid #eee;border-bottom:none}.section-nav ul{padding-left:1rem}.toc-entry,.toc-entry a{display:block}.toc-entry a{padding:.125rem 1.5rem;color:rgba(var(--pst-color-toc-link),1)}@media (min-width:1200px){.toc-entry a{padding-right:0}}.toc-entry a:hover{color:rgba(var(--pst-color-toc-link-hover),1);text-decoration:none}.bd-sidebar{padding-top:1em}@media (min-width:720px){.bd-sidebar{border-right:1px solid rgba(0,0,0,.1)}@supports (position:-webkit-sticky) or (position:sticky){.bd-sidebar{position:-webkit-sticky;position:sticky;top:calc(var(--pst-header-height) + 20px);z-index:1000;height:calc(100vh - var(--pst-header-height) - 20px)}}}.bd-sidebar.no-sidebar{border-right:0}.bd-links{padding-top:1rem;padding-bottom:1rem;margin-right:-15px;margin-left:-15px}@media (min-width:720px){.bd-links{display:block}@supports (position:-webkit-sticky) or (position:sticky){.bd-links{max-height:calc(100vh - 11rem);overflow-y:auto}}}.bd-sidenav{display:none}.bd-content{padding-top:20px}.bd-content .section{max-width:100%}.bd-content .section table{display:block;overflow:auto}.bd-toc-link{display:block;padding:.25rem 1.5rem;font-weight:600;color:rgba(0,0,0,.65)}.bd-toc-link:hover{color:rgba(0,0,0,.85);text-decoration:none}.bd-toc-item.active{margin-bottom:1rem}.bd-toc-item.active:not(:first-child){margin-top:1rem}.bd-toc-item.active>.bd-toc-link{color:rgba(0,0,0,.85)}.bd-toc-item.active>.bd-toc-link:hover{background-color:transparent}.bd-toc-item.active>.bd-sidenav{display:block}nav.bd-links p.caption{font-size:var(--pst-sidebar-caption-font-size);text-transform:uppercase;font-weight:700;position:relative;margin-top:1.25em;margin-bottom:.5em;padding:0 1.5rem;color:rgba(var(--pst-color-sidebar-caption),1)}nav.bd-links p.caption:first-child{margin-top:0}.bd-sidebar .nav{font-size:var(--pst-sidebar-font-size)}.bd-sidebar .nav ul{list-style:none;padding:0 0 0 1.5rem}.bd-sidebar .nav li>a{display:block;padding:.25rem 1.5rem;color:rgba(var(--pst-color-sidebar-link),1)}.bd-sidebar .nav li>a:hover{color:rgba(var(--pst-color-sidebar-link-hover),1);text-decoration:none;background-color:transparent}.bd-sidebar .nav li>a.reference.external:after{font-family:Font Awesome\ 5 Free;font-weight:900;content:"\f35d";font-size:.75em;margin-left:.3em}.bd-sidebar .nav .active:hover>a,.bd-sidebar .nav .active>a{font-weight:600;color:rgba(var(--pst-color-sidebar-link-active),1)}.toc-h2{font-size:.85rem}.toc-h3{font-size:.75rem}.toc-h4{font-size:.65rem}.toc-entry>.nav-link.active{font-weight:600;color:#130654;color:rgba(var(--pst-color-toc-link-active),1);background-color:transparent;border-left:2px solid rgba(var(--pst-color-toc-link-active),1)}.nav-link:hover{border-style:none}#navbar-main-elements li.nav-item i{font-size:.7rem;padding-left:2px;vertical-align:middle}.bd-toc .nav .nav{display:none}.bd-toc .nav .nav.visible,.bd-toc .nav>.active>ul{display:block}.prev-next-area{margin:20px 0}.prev-next-area p{margin:0 .3em;line-height:1.3em}.prev-next-area i{font-size:1.2em}.prev-next-area a{display:flex;align-items:center;border:none;padding:10px;max-width:45%;overflow-x:hidden;color:rgba(0,0,0,.65);text-decoration:none}.prev-next-area a p.prev-next-title{color:rgba(var(--pst-color-link),1);font-weight:600;font-size:1.1em}.prev-next-area a:hover p.prev-next-title{text-decoration:underline}.prev-next-area a .prev-next-info{flex-direction:column;margin:0 .5em}.prev-next-area a .prev-next-info .prev-next-subtitle{text-transform:capitalize}.prev-next-area a.left-prev{float:left}.prev-next-area a.right-next{float:right}.prev-next-area a.right-next div.prev-next-info{text-align:right}.alert{padding-bottom:0}.alert-info a{color:#e83e8c}#navbar-icon-links i.fa,#navbar-icon-links i.fab,#navbar-icon-links i.far,#navbar-icon-links i.fas{vertical-align:middle;font-style:normal;font-size:1.5rem;line-height:1.25}#navbar-icon-links i.fa-github-square:before{color:#333}#navbar-icon-links i.fa-twitter-square:before{color:#55acee}#navbar-icon-links i.fa-gitlab:before{color:#548}#navbar-icon-links i.fa-bitbucket:before{color:#0052cc}.tocsection{border-left:1px solid #eee;padding:.3rem 1.5rem}.tocsection i{padding-right:.5rem}.editthispage{padding-top:2rem}.editthispage a{color:var(--pst-color-sidebar-link-active)}.xr-wrap[hidden]{display:block!important}.toctree-checkbox{position:absolute;display:none}.toctree-checkbox~ul{display:none}.toctree-checkbox~label i{transform:rotate(0deg)}.toctree-checkbox:checked~ul{display:block}.toctree-checkbox:checked~label i{transform:rotate(180deg)}.bd-sidebar li{position:relative}.bd-sidebar label{position:absolute;top:0;right:0;height:30px;width:30px;cursor:pointer;display:flex;justify-content:center;align-items:center}.bd-sidebar label:hover{background:rgba(var(--pst-color-sidebar-expander-background-hover),1)}.bd-sidebar label i{display:inline-block;font-size:.75rem;text-align:center}.bd-sidebar label i:hover{color:rgba(var(--pst-color-sidebar-link-hover),1)}.bd-sidebar li.has-children>.reference{padding-right:30px}div.doctest>div.highlight span.gp,span.linenos,table.highlighttable td.linenos{user-select:none;-webkit-user-select:text;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.docutils.container{padding-left:unset;padding-right:unset} \ No newline at end of file diff --git a/_static/css/theme.css b/_static/css/theme.css deleted file mode 100644 index 2e03fe3..0000000 --- a/_static/css/theme.css +++ /dev/null @@ -1,120 +0,0 @@ -/* Provided by the Sphinx base theme template at build time */ -@import "../basic.css"; - -:root { - /***************************************************************************** - * Theme config - **/ - --pst-header-height: 60px; - - /***************************************************************************** - * Font size - **/ - --pst-font-size-base: 15px; /* base font size - applied at body / html level */ - - /* heading font sizes */ - --pst-font-size-h1: 36px; - --pst-font-size-h2: 32px; - --pst-font-size-h3: 26px; - --pst-font-size-h4: 21px; - --pst-font-size-h5: 18px; - --pst-font-size-h6: 16px; - - /* smaller then heading font sizes*/ - --pst-font-size-milli: 12px; - - --pst-sidebar-font-size: .9em; - --pst-sidebar-caption-font-size: .9em; - - /***************************************************************************** - * Font family - **/ - /* These are adapted from https://systemfontstack.com/ */ - --pst-font-family-base-system: -apple-system, BlinkMacSystemFont, Segoe UI, "Helvetica Neue", - Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; - --pst-font-family-monospace-system: "SFMono-Regular", Menlo, Consolas, Monaco, - Liberation Mono, Lucida Console, monospace; - - --pst-font-family-base: var(--pst-font-family-base-system); - --pst-font-family-heading: var(--pst-font-family-base); - --pst-font-family-monospace: var(--pst-font-family-monospace-system); - - /***************************************************************************** - * Color - * - * Colors are defined in rgb string way, "red, green, blue" - **/ - --pst-color-primary: 19, 6, 84; - --pst-color-success: 40, 167, 69; - --pst-color-info: 0, 123, 255; /*23, 162, 184;*/ - --pst-color-warning: 255, 193, 7; - --pst-color-danger: 220, 53, 69; - --pst-color-text-base: 51, 51, 51; - - --pst-color-h1: var(--pst-color-primary); - --pst-color-h2: var(--pst-color-primary); - --pst-color-h3: var(--pst-color-text-base); - --pst-color-h4: var(--pst-color-text-base); - --pst-color-h5: var(--pst-color-text-base); - --pst-color-h6: var(--pst-color-text-base); - --pst-color-paragraph: var(--pst-color-text-base); - --pst-color-link: 0, 91, 129; - --pst-color-link-hover: 227, 46, 0; - --pst-color-headerlink: 198, 15, 15; - --pst-color-headerlink-hover: 255, 255, 255; - --pst-color-preformatted-text: 34, 34, 34; - --pst-color-preformatted-background: 250, 250, 250; - --pst-color-inline-code: 232, 62, 140; - - --pst-color-active-navigation: 19, 6, 84; - --pst-color-navbar-link: 77, 77, 77; - --pst-color-navbar-link-hover: var(--pst-color-active-navigation); - --pst-color-navbar-link-active: var(--pst-color-active-navigation); - --pst-color-sidebar-link: 77, 77, 77; - --pst-color-sidebar-link-hover: var(--pst-color-active-navigation); - --pst-color-sidebar-link-active: var(--pst-color-active-navigation); - --pst-color-sidebar-expander-background-hover: 244, 244, 244; - --pst-color-sidebar-caption: 77, 77, 77; - --pst-color-toc-link: 119, 117, 122; - --pst-color-toc-link-hover: var(--pst-color-active-navigation); - --pst-color-toc-link-active: var(--pst-color-active-navigation); - - /***************************************************************************** - * Icon - **/ - - /* font awesome icons*/ - --pst-icon-check-circle: '\f058'; - --pst-icon-info-circle: '\f05a'; - --pst-icon-exclamation-triangle: '\f071'; - --pst-icon-exclamation-circle: '\f06a'; - --pst-icon-times-circle: '\f057'; - --pst-icon-lightbulb: '\f0eb'; - - /***************************************************************************** - * Admonitions - **/ - - --pst-color-admonition-default: var(--pst-color-info); - --pst-color-admonition-note: var(--pst-color-info); - --pst-color-admonition-attention: var(--pst-color-warning); - --pst-color-admonition-caution: var(--pst-color-warning); - --pst-color-admonition-warning: var(--pst-color-warning); - --pst-color-admonition-danger: var(--pst-color-danger); - --pst-color-admonition-error: var(--pst-color-danger); - --pst-color-admonition-hint: var(--pst-color-success); - --pst-color-admonition-tip: var(--pst-color-success); - --pst-color-admonition-important: var(--pst-color-success); - - --pst-icon-admonition-default: var(--pst-icon-info-circle); - --pst-icon-admonition-note: var(--pst-icon-info-circle); - --pst-icon-admonition-attention: var(--pst-icon-exclamation-circle); - --pst-icon-admonition-caution: var(--pst-icon-exclamation-triangle); - --pst-icon-admonition-warning: var(--pst-icon-exclamation-triangle); - --pst-icon-admonition-danger: var(--pst-icon-exclamation-triangle); - --pst-icon-admonition-error: var(--pst-icon-times-circle); - --pst-icon-admonition-hint: var(--pst-icon-lightbulb); - --pst-icon-admonition-tip: var(--pst-icon-lightbulb); - --pst-icon-admonition-important: var(--pst-icon-exclamation-circle); - -} diff --git a/_sphinx_design_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css b/_static/design-style.4045f2051d55cab465a707391d5b2007.min.css similarity index 56% rename from _sphinx_design_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css rename to _static/design-style.4045f2051d55cab465a707391d5b2007.min.css index 704c42e..3225661 100644 --- a/_sphinx_design_static/design-style.b7bb847fb20b106c3d81b95245e65545.min.css +++ b/_static/design-style.4045f2051d55cab465a707391d5b2007.min.css @@ -1 +1 @@ -.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #007bff;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0069d9;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #007bff;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0069d9;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/_static/doctools.js b/_static/doctools.js index e1bfd70..c3db08d 100644 --- a/_static/doctools.js +++ b/_static/doctools.js @@ -2,357 +2,263 @@ * doctools.js * ~~~~~~~~~~~ * - * Sphinx JavaScript utilities for all documentation. + * Base JavaScript utilities for all Sphinx HTML documentation. * * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ +"use strict"; -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); } - return decodeURIComponent(x.replace(/\+/g, ' ')); }; /** - * small helper function to urlencode strings + * highlight a given string on a node by wrapping it in + * span elements with the given class name. */ -jQuery.urlencode = encodeURIComponent; +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); } } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; }; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; /** * Small JavaScript module for the documentation. */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - this.initOnKeyListeners(); +const Documentation = { + init: () => { + Documentation.highlightSearchWords(); + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); }, /** * i18n support */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, - LOCALE : 'unknown', + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated === 'undefined') - return string; - return (typeof translated === 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated === 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } }, - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; }, - /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; }, /** * highlight the search words provided in the url in the text */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); - } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); - } - }, + highlightSearchWords: () => { + const highlight = + new URLSearchParams(window.location.search).get("highlight") || ""; + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) === 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); }, /** * helper function to hide the search marks again */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - var url = new URL(window.location); - url.searchParams.delete('highlight'); - window.history.replaceState({}, '', url); + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + const url = new URL(window.location); + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); }, - /** + /** * helper function to focus on search bar */ - focusSearchBar : function() { - $('input[name=q]').first().focus(); + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); }, /** - * make the url absolute + * Initialise the domain index toggle buttons */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this === '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); }, - initOnKeyListeners: function() { + initOnKeyListeners: () => { // only install a listener if it is really needed - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - return; + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; - $(document).keydown(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box, textarea, dropdown or button - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && activeElementType !== 'BUTTON') { - if (event.altKey || event.ctrlKey || event.metaKey) - return; + const blacklistedElements = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", + ]); + document.addEventListener("keydown", (event) => { + if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements + if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys - if (!event.shiftKey) { - switch (event.key) { - case 'ArrowLeft': - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) - break; - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - break; - case 'ArrowRight': - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) - break; - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - break; - case 'Escape': - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - break; - Documentation.hideSearchWords(); - return false; - } - } - - // some keyboard layouts may need Shift to get / + if (!event.shiftKey) { switch (event.key) { - case '/': - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - break; - Documentation.focusSearchBar(); - return false; + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + case "Escape": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.hideSearchWords(); + event.preventDefault(); } } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } }); - } + }, }; // quick alias for translations -_ = Documentation.gettext; +const _ = Documentation.gettext; -$(document).ready(function() { - Documentation.init(); -}); +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js index 877e3c3..162a6ba 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,14 +1,14 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), VERSION: '', - LANGUAGE: 'None', + LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', FILE_SUFFIX: '.html', LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '', - NAVIGATION_WITH_KEYS: true, + NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: true, + ENABLE_SEARCH_SHORTCUTS: false, }; \ No newline at end of file diff --git a/_static/jquery-3.5.1.js b/_static/jquery-3.6.0.js similarity index 98% rename from _static/jquery-3.5.1.js rename to _static/jquery-3.6.0.js index 5093733..fc6c299 100644 --- a/_static/jquery-3.5.1.js +++ b/_static/jquery-3.6.0.js @@ -1,15 +1,15 @@ /*! - * jQuery JavaScript Library v3.5.1 + * jQuery JavaScript Library v3.6.0 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * - * Copyright JS Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * - * Date: 2020-05-04T22:49Z + * Date: 2021-03-02T17:08Z */ ( function( global, factory ) { @@ -76,12 +76,16 @@ var support = {}; var isFunction = function isFunction( obj ) { - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; var isWindow = function isWindow( obj ) { @@ -147,7 +151,7 @@ function toType( obj ) { var - version = "3.5.1", + version = "3.6.0", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -401,7 +405,7 @@ jQuery.extend( { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? - [ arr ] : arr + [ arr ] : arr ); } else { push.call( ret, arr ); @@ -496,9 +500,9 @@ if ( typeof Symbol === "function" ) { // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( _i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); function isArrayLike( obj ) { @@ -518,14 +522,14 @@ function isArrayLike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v2.3.5 + * Sizzle CSS Selector Engine v2.3.6 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * - * Date: 2020-03-14 + * Date: 2021-02-16 */ ( function( window ) { var i, @@ -1108,8 +1112,8 @@ support = Sizzle.support = {}; * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { - var namespace = elem.namespaceURI, - docElem = ( elem.ownerDocument || elem ).documentElement; + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; // Support: IE <=8 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes @@ -3024,9 +3028,9 @@ var rneedsContext = jQuery.expr.match.needsContext; function nodeName( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); -}; +} var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); @@ -3997,8 +4001,8 @@ jQuery.extend( { resolveContexts = Array( i ), resolveValues = slice.call( arguments ), - // the master Deferred - master = jQuery.Deferred(), + // the primary Deferred + primary = jQuery.Deferred(), // subordinate callback factory updateFunc = function( i ) { @@ -4006,30 +4010,30 @@ jQuery.extend( { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); + primary.resolveWith( resolveContexts, resolveValues ); } }; }; // Single- and empty arguments are adopted like Promise.resolve if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, !remaining ); // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || + if ( primary.state() === "pending" || isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - return master.then(); + return primary.then(); } } // Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); } - return master.promise(); + return primary.promise(); } } ); @@ -4180,8 +4184,8 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { for ( ; i < len; i++ ) { fn( elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); } } @@ -5089,10 +5093,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) { } -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { return true; @@ -5387,8 +5388,8 @@ jQuery.event = { event = jQuery.event.fix( nativeEvent ), handlers = ( - dataPriv.get( this, "events" ) || Object.create( null ) - )[ event.type ] || [], + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event @@ -5512,12 +5513,12 @@ jQuery.event = { get: isFunction( hook ) ? function() { if ( this.originalEvent ) { - return hook( this.originalEvent ); + return hook( this.originalEvent ); } } : function() { if ( this.originalEvent ) { - return this.originalEvent[ name ]; + return this.originalEvent[ name ]; } }, @@ -5656,7 +5657,13 @@ function leverageNative( el, type, expectSync ) { // Cancel the outer synthetic event event.stopImmediatePropagation(); event.preventDefault(); - return result.value; + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; } // If this is an inner synthetic event for an event with a bubbling surrogate @@ -5821,34 +5828,7 @@ jQuery.each( { targetTouches: true, toElement: true, touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } + which: true }, jQuery.event.addProp ); jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { @@ -5874,6 +5854,12 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp return true; }, + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + delegateType: delegateType }; } ); @@ -6541,6 +6527,10 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); // set in CSS while `offset*` properties report correct values. // Behavior in IE 9 is more subtle than in newer versions & it passes // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) reliableTrDimensions: function() { var table, tr, trChild, trStyle; if ( reliableTrDimensionsVal == null ) { @@ -6548,17 +6538,32 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); tr = document.createElement( "tr" ); trChild = document.createElement( "div" ); - table.style.cssText = "position:absolute;left:-11111px"; + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. tr.style.height = "1px"; trChild.style.height = "9px"; + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + documentElement .appendChild( table ) .appendChild( tr ) .appendChild( trChild ); trStyle = window.getComputedStyle( tr ); - reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; documentElement.removeChild( table ); } @@ -7022,10 +7027,10 @@ jQuery.each( [ "height", "width" ], function( _i, dimension ) { // Running getBoundingClientRect on a disconnected node // in IE throws an error. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); } }, @@ -7084,7 +7089,7 @@ jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, swap( elem, { marginLeft: 0 }, function() { return elem.getBoundingClientRect().left; } ) - ) + "px"; + ) + "px"; } } ); @@ -7223,7 +7228,7 @@ Tween.propHooks = { if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.nodeType === 1 && ( - jQuery.cssHooks[ tween.prop ] || + jQuery.cssHooks[ tween.prop ] || tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { @@ -7468,7 +7473,7 @@ function defaultPrefilter( elem, props, opts ) { anim.done( function() { - /* eslint-enable no-loop-func */ + /* eslint-enable no-loop-func */ // The final step of a "hide" animation is actually hiding the element if ( !hidden ) { @@ -7588,7 +7593,7 @@ function Animation( elem, properties, options ) { tweens: [], createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); return tween; }, @@ -7761,7 +7766,8 @@ jQuery.fn.extend( { anim.stop( true ); } }; - doAnimation.finish = doAnimation; + + doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : @@ -8401,8 +8407,8 @@ jQuery.fn.extend( { if ( this.setAttribute ) { this.setAttribute( "class", className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" + "" : + dataPriv.get( this, "__className__" ) || "" ); } } @@ -8417,7 +8423,7 @@ jQuery.fn.extend( { while ( ( elem = this[ i++ ] ) ) { if ( elem.nodeType === 1 && ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; + return true; } } @@ -8707,9 +8713,7 @@ jQuery.extend( jQuery.event, { special.bindType || type; // jQuery handler - handle = ( - dataPriv.get( cur, "events" ) || Object.create( null ) - )[ event.type ] && + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); @@ -8856,7 +8860,7 @@ var rquery = ( /\?/ ); // Cross-browser xml parsing jQuery.parseXML = function( data ) { - var xml; + var xml, parserErrorElem; if ( !data || typeof data !== "string" ) { return null; } @@ -8865,12 +8869,17 @@ jQuery.parseXML = function( data ) { // IE throws on parseFromString with invalid input. try { xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } + } catch ( e ) {} - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); } return xml; }; @@ -8971,16 +8980,14 @@ jQuery.fn.extend( { // Can add propHook for "elements" to filter or add form elements var elements = jQuery.prop( this, "elements" ); return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { + } ).filter( function() { var type = this.type; // Use .is( ":disabled" ) so that fieldset[disabled] works return this.name && !jQuery( this ).is( ":disabled" ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( _i, elem ) { + } ).map( function( _i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { @@ -9033,7 +9040,8 @@ var // Anchor tag for parsing the document origin originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; + +originAnchor.href = location.href; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { @@ -9414,8 +9422,8 @@ jQuery.extend( { // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, + jQuery( callbackContext ) : + jQuery.event, // Deferreds deferred = jQuery.Deferred(), @@ -9727,8 +9735,10 @@ jQuery.extend( { response = ajaxHandleResponses( s, jqXHR, responses ); } - // Use a noop converter for missing script - if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { s.converters[ "text script" ] = function() {}; } @@ -10466,12 +10476,6 @@ jQuery.offset = { options.using.call( elem, props ); } else { - if ( typeof props.top === "number" ) { - props.top += "px"; - } - if ( typeof props.left === "number" ) { - props.left += "px"; - } curElem.css( props ); } } @@ -10640,8 +10644,11 @@ jQuery.each( [ "top", "left" ], function( _i, prop ) { // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, - function( defaultExtra, funcName ) { + jQuery.each( { + padding: "inner" + name, + content: type, + "": "outer" + name + }, function( defaultExtra, funcName ) { // Margin is only for outerHeight, outerWidth jQuery.fn[ funcName ] = function( margin, value ) { @@ -10726,7 +10733,8 @@ jQuery.fn.extend( { } } ); -jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + +jQuery.each( + ( "blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu" ).split( " " ), function( _i, name ) { @@ -10737,7 +10745,8 @@ jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + this.on( name, null, data, fn ) : this.trigger( name ); }; - } ); + } +); diff --git a/_static/jquery.js b/_static/jquery.js index b061403..c4c6022 100644 --- a/_static/jquery.js +++ b/_static/jquery.js @@ -1,2 +1,2 @@ -/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0=0)return 1;return 0}();var o=n&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),i))}};function r(t){return t&&"[object Function]"==={}.toString.call(t)}function s(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function a(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function l(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=s(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/(auto|scroll|overlay)/.test(n+o+i)?t:l(a(t))}function c(t){return t&&t.referenceNode?t.referenceNode:t}var u=n&&!(!window.MSInputMethodContext||!document.documentMode),h=n&&/MSIE 10/.test(navigator.userAgent);function f(t){return 11===t?u:10===t?h:u||h}function d(t){if(!t)return document.documentElement;for(var e=f(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===s(n,"position")?d(n):n:t?t.ownerDocument.documentElement:document.documentElement}function p(t){return null!==t.parentNode?p(t.parentNode):t}function m(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?t:e,o=n?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var s,a,l=r.commonAncestorContainer;if(t!==l&&e!==l||i.contains(o))return"BODY"===(a=(s=l).nodeName)||"HTML"!==a&&d(s.firstElementChild)!==s?d(l):l;var c=p(t);return c.host?m(c.host,e):m(t,p(e).host)}function g(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",i=t.nodeName;if("BODY"===i||"HTML"===i){var o=t.ownerDocument.documentElement,r=t.ownerDocument.scrollingElement||o;return r[n]}return t[n]}function v(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=g(e,"top"),o=g(e,"left"),r=n?-1:1;return t.top+=i*r,t.bottom+=i*r,t.left+=o*r,t.right+=o*r,t}function _(t,e){var n="x"===e?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+i+"Width"])}function b(t,e,n,i){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],f(10)?parseInt(n["offset"+t])+parseInt(i["margin"+("Height"===t?"Top":"Left")])+parseInt(i["margin"+("Height"===t?"Bottom":"Right")]):0)}function y(t){var e=t.body,n=t.documentElement,i=f(10)&&getComputedStyle(n);return{height:b("Height",e,n,i),width:b("Width",e,n,i)}}var w=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},E=function(){function t(t,e){for(var n=0;n2&&void 0!==arguments[2]&&arguments[2],i=f(10),o="HTML"===e.nodeName,r=D(t),a=D(e),c=l(t),u=s(e),h=parseFloat(u.borderTopWidth),d=parseFloat(u.borderLeftWidth);n&&o&&(a.top=Math.max(a.top,0),a.left=Math.max(a.left,0));var p=S({top:r.top-a.top-h,left:r.left-a.left-d,width:r.width,height:r.height});if(p.marginTop=0,p.marginLeft=0,!i&&o){var m=parseFloat(u.marginTop),g=parseFloat(u.marginLeft);p.top-=h-m,p.bottom-=h-m,p.left-=d-g,p.right-=d-g,p.marginTop=m,p.marginLeft=g}return(i&&!n?e.contains(c):e===c&&"BODY"!==c.nodeName)&&(p=v(p,e)),p}function k(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,i=N(t,n),o=Math.max(n.clientWidth,window.innerWidth||0),r=Math.max(n.clientHeight,window.innerHeight||0),s=e?0:g(n),a=e?0:g(n,"left"),l={top:s-i.top+i.marginTop,left:a-i.left+i.marginLeft,width:o,height:r};return S(l)}function O(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===s(t,"position"))return!0;var n=a(t);return!!n&&O(n)}function A(t){if(!t||!t.parentElement||f())return document.documentElement;for(var e=t.parentElement;e&&"none"===s(e,"transform");)e=e.parentElement;return e||document.documentElement}function I(t,e,n,i){var o=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r={top:0,left:0},s=o?A(t):m(t,c(e));if("viewport"===i)r=k(s,o);else{var u=void 0;"scrollParent"===i?"BODY"===(u=l(a(e))).nodeName&&(u=t.ownerDocument.documentElement):u="window"===i?t.ownerDocument.documentElement:i;var h=N(u,s,o);if("HTML"!==u.nodeName||O(s))r=h;else{var f=y(t.ownerDocument),d=f.height,p=f.width;r.top+=h.top-h.marginTop,r.bottom=d+h.top,r.left+=h.left-h.marginLeft,r.right=p+h.left}}var g="number"==typeof(n=n||0);return r.left+=g?n:n.left||0,r.top+=g?n:n.top||0,r.right-=g?n:n.right||0,r.bottom-=g?n:n.bottom||0,r}function x(t){return t.width*t.height}function j(t,e,n,i,o){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var s=I(n,i,r,o),a={top:{width:s.width,height:e.top-s.top},right:{width:s.right-e.right,height:s.height},bottom:{width:s.width,height:s.bottom-e.bottom},left:{width:e.left-s.left,height:s.height}},l=Object.keys(a).map((function(t){return C({key:t},a[t],{area:x(a[t])})})).sort((function(t,e){return e.area-t.area})),c=l.filter((function(t){var e=t.width,i=t.height;return e>=n.clientWidth&&i>=n.clientHeight})),u=c.length>0?c[0].key:l[0].key,h=t.split("-")[1];return u+(h?"-"+h:"")}function L(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=i?A(e):m(e,c(n));return N(n,o,i)}function P(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),i=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+i,height:t.offsetHeight+n}}function F(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function R(t,e,n){n=n.split("-")[0];var i=P(t),o={width:i.width,height:i.height},r=-1!==["right","left"].indexOf(n),s=r?"top":"left",a=r?"left":"top",l=r?"height":"width",c=r?"width":"height";return o[s]=e[s]+e[l]/2-i[l]/2,o[a]=n===a?e[a]-i[c]:e[F(a)],o}function M(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function B(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t[e]===n}));var i=M(t,(function(t){return t[e]===n}));return t.indexOf(i)}(t,"name",n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&r(n)&&(e.offsets.popper=S(e.offsets.popper),e.offsets.reference=S(e.offsets.reference),e=n(e,t))})),e}function H(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=L(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=j(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=R(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=B(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function q(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function Q(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),i=0;i1&&void 0!==arguments[1]&&arguments[1],n=Z.indexOf(t),i=Z.slice(n+1).concat(Z.slice(0,n));return e?i.reverse():i}var et="flip",nt="clockwise",it="counterclockwise";function ot(t,e,n,i){var o=[0,0],r=-1!==["right","left"].indexOf(i),s=t.split(/(\+|\-)/).map((function(t){return t.trim()})),a=s.indexOf(M(s,(function(t){return-1!==t.search(/,|\s/)})));s[a]&&-1===s[a].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,c=-1!==a?[s.slice(0,a).concat([s[a].split(l)[0]]),[s[a].split(l)[1]].concat(s.slice(a+1))]:[s];return(c=c.map((function(t,i){var o=(1===i?!r:r)?"height":"width",s=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,s=!0,t):s?(t[t.length-1]+=e,s=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,i){var o=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+o[1],s=o[2];if(!r)return t;if(0===s.indexOf("%")){var a=void 0;switch(s){case"%p":a=n;break;case"%":case"%r":default:a=i}return S(a)[e]/100*r}if("vh"===s||"vw"===s){return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r}return r}(t,o,e,n)}))}))).forEach((function(t,e){t.forEach((function(n,i){X(n)&&(o[e]+=n*("-"===t[i-1]?-1:1))}))})),o}var rt={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],i=e.split("-")[1];if(i){var o=t.offsets,r=o.reference,s=o.popper,a=-1!==["bottom","top"].indexOf(n),l=a?"left":"top",c=a?"width":"height",u={start:T({},l,r[l]),end:T({},l,r[l]+r[c]-s[c])};t.offsets.popper=C({},s,u[i])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n=e.offset,i=t.placement,o=t.offsets,r=o.popper,s=o.reference,a=i.split("-")[0],l=void 0;return l=X(+n)?[+n,0]:ot(n,r,s,a),"left"===a?(r.top+=l[0],r.left-=l[1]):"right"===a?(r.top+=l[0],r.left+=l[1]):"top"===a?(r.left+=l[0],r.top-=l[1]):"bottom"===a&&(r.left+=l[0],r.top+=l[1]),t.popper=r,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||d(t.instance.popper);t.instance.reference===n&&(n=d(n));var i=Q("transform"),o=t.instance.popper.style,r=o.top,s=o.left,a=o[i];o.top="",o.left="",o[i]="";var l=I(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);o.top=r,o.left=s,o[i]=a,e.boundaries=l;var c=e.priority,u=t.offsets.popper,h={primary:function(t){var n=u[t];return u[t]l[t]&&!e.escapeWithReference&&(i=Math.min(u[n],l[t]-("right"===t?u.width:u.height))),T({},n,i)}};return c.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";u=C({},u,h[e](t))})),t.offsets.popper=u,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,i=e.reference,o=t.placement.split("-")[0],r=Math.floor,s=-1!==["top","bottom"].indexOf(o),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]r(i[a])&&(t.offsets.popper[l]=r(i[a])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!G(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var o=t.placement.split("-")[0],r=t.offsets,a=r.popper,l=r.reference,c=-1!==["left","right"].indexOf(o),u=c?"height":"width",h=c?"Top":"Left",f=h.toLowerCase(),d=c?"left":"top",p=c?"bottom":"right",m=P(i)[u];l[p]-ma[p]&&(t.offsets.popper[f]+=l[f]+m-a[p]),t.offsets.popper=S(t.offsets.popper);var g=l[f]+l[u]/2-m/2,v=s(t.instance.popper),_=parseFloat(v["margin"+h]),b=parseFloat(v["border"+h+"Width"]),y=g-t.offsets.popper[f]-_-b;return y=Math.max(Math.min(a[u]-m,y),0),t.arrowElement=i,t.offsets.arrow=(T(n={},f,Math.round(y)),T(n,d,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(q(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=I(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split("-")[0],o=F(i),r=t.placement.split("-")[1]||"",s=[];switch(e.behavior){case et:s=[i,o];break;case nt:s=tt(i);break;case it:s=tt(i,!0);break;default:s=e.behavior}return s.forEach((function(a,l){if(i!==a||s.length===l+1)return t;i=t.placement.split("-")[0],o=F(i);var c=t.offsets.popper,u=t.offsets.reference,h=Math.floor,f="left"===i&&h(c.right)>h(u.left)||"right"===i&&h(c.left)h(u.top)||"bottom"===i&&h(c.top)h(n.right),m=h(c.top)h(n.bottom),v="left"===i&&d||"right"===i&&p||"top"===i&&m||"bottom"===i&&g,_=-1!==["top","bottom"].indexOf(i),b=!!e.flipVariations&&(_&&"start"===r&&d||_&&"end"===r&&p||!_&&"start"===r&&m||!_&&"end"===r&&g),y=!!e.flipVariationsByContent&&(_&&"start"===r&&p||_&&"end"===r&&d||!_&&"start"===r&&g||!_&&"end"===r&&m),w=b||y;(f||v||w)&&(t.flipped=!0,(f||v)&&(i=s[l+1]),w&&(r=function(t){return"end"===t?"start":"start"===t?"end":t}(r)),t.placement=i+(r?"-"+r:""),t.offsets.popper=C({},t.offsets.popper,R(t.instance.popper,t.offsets.reference,t.placement)),t=B(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],i=t.offsets,o=i.popper,r=i.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return o[s?"left":"top"]=r[n]-(a?o[s?"width":"height"]:0),t.placement=F(e),t.offsets.popper=S(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!G(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=M(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottomn.right||e.top>n.bottom||e.right2&&void 0!==arguments[2]?arguments[2]:{};w(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=o(this.update.bind(this)),this.options=C({},t.Defaults,s),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(C({},t.Defaults.modifiers,s.modifiers)).forEach((function(e){i.options.modifiers[e]=C({},t.Defaults.modifiers[e]||{},s.modifiers?s.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return C({name:t},i.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&r(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)})),this.update();var a=this.options.eventsEnabled;a&&this.enableEventListeners(),this.state.eventsEnabled=a}return E(t,[{key:"update",value:function(){return H.call(this)}},{key:"destroy",value:function(){return W.call(this)}},{key:"enableEventListeners",value:function(){return Y.call(this)}},{key:"disableEventListeners",value:function(){return z.call(this)}}]),t}();st.Utils=("undefined"!=typeof window?window:t).PopperUtils,st.placements=J,st.Defaults=rt,e.default=st}.call(this,n(4))},function(t,e,n){t.exports=n(5)},function(t,e,n){ -/*! - * Bootstrap v4.5.0 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -!function(t,e,n){"use strict";function i(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};c.jQueryDetection(),e.fn.emulateTransitionEnd=l,e.event.special[c.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var u="alert",h=e.fn[u],f=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=c.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=c.getTransitionDurationFromElement(t);e(t).one(c.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',f._handleDismiss(new f)),e.fn[u]=f._jQueryInterface,e.fn[u].Constructor=f,e.fn[u].noConflict=function(){return e.fn[u]=h,f._jQueryInterface};var d=e.fn.button,p=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var r=i.querySelector(".active");r&&e(r).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"LABEL"===i.tagName&&o&&"checkbox"===o.type&&t.preventDefault(),p._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(c.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(g),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=a(a({},_),t),c.typeCheckConfig(m,t,b),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),r=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(r),r},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,r,s=this,a=this._element.querySelector(".active.carousel-item"),l=this._getItemIndex(a),u=n||a&&this._getItemByDirection(t,a),h=this._getItemIndex(u),f=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",r="left"):(i="carousel-item-right",o="carousel-item-prev",r="right"),u&&e(u).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(u,r).isDefaultPrevented()&&a&&u){this._isSliding=!0,f&&this.pause(),this._setActiveIndicatorElement(u);var d=e.Event("slid.bs.carousel",{relatedTarget:u,direction:r,from:l,to:h});if(e(this._element).hasClass("slide")){e(u).addClass(o),c.reflow(u),e(a).addClass(i),e(u).addClass(i);var p=parseInt(u.getAttribute("data-interval"),10);p?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=p):this._config.interval=this._config.defaultInterval||this._config.interval;var m=c.getTransitionDurationFromElement(a);e(a).one(c.TRANSITION_END,(function(){e(u).removeClass(i+" "+o).addClass("active"),e(a).removeClass("active "+o+" "+i),s._isSliding=!1,setTimeout((function(){return e(s._element).trigger(d)}),0)})).emulateTransitionEnd(m)}else e(a).removeClass("active"),e(u).addClass("active"),this._isSliding=!1,e(this._element).trigger(d);f&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),o=a(a({},_),e(this).data());"object"==typeof n&&(o=a(a({},o),n));var r="string"==typeof n?n:o.slide;if(i||(i=new t(this,o),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof r){if(void 0===i[r])throw new TypeError('No method named "'+r+'"');i[r]()}else o.interval&&o.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=c.getSelectorFromElement(this);if(i){var o=e(i)[0];if(o&&e(o).hasClass("carousel")){var r=a(a({},e(o).data()),e(this).data()),s=this.getAttribute("data-slide-to");s&&(r.interval=!1),t._jQueryInterface.call(e(o),r),s&&e(o).data("bs.carousel").to(s),n.preventDefault()}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return _}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",w._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n0&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!(this._isTransitioning||e(this._element).hasClass("show")||(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var r=e.Event("show.bs.collapse");if(e(this._element).trigger(r),!r.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var s=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[s]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var a="scroll"+(s[0].toUpperCase()+s.slice(1)),l=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[s]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(l),this._element.style[s]=this._element[a]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",c.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var r=0;r0},i._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},i._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),a(a({},t),this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if(void 0===i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,r=i.length;o0&&s--,40===n.which&&sdocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:M,popperConfig:null},K={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},$=function(){function t(t,e){if(void 0===n)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var i=t.prototype;return i.enable=function(){this._isEnabled=!0},i.disable=function(){this._isEnabled=!1},i.toggleEnabled=function(){this._isEnabled=!this._isEnabled},i.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},i.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},i.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var i=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(i);var o=c.findShadowRoot(this.element),r=e.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!r)return;var s=this.getTipElement(),a=c.getUID(this.constructor.NAME);s.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&e(s).addClass("fade");var l="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(l);this.addAttachmentClass(u);var h=this._getContainer();e(s).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(s).appendTo(h),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new n(this.element,s,this._getPopperConfig(u)),e(s).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var f=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var d=c.getTransitionDurationFromElement(this.tip);e(this.tip).one(c.TRANSITION_END,f).emulateTransitionEnd(d)}else f()}},i.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),r=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var s=c.getTransitionDurationFromElement(i);e(i).one(c.TRANSITION_END,r).emulateTransitionEnd(s)}else r();this._hoverState=""}},i.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},i.isWithContent=function(){return Boolean(this.getTitle())},i.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},i.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},i.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},i.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=q(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},i.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},i._getPopperConfig=function(t){var e=this;return a(a({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),this.config.popperConfig)},i._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},i._getContainer=function(){return!1===this.config.container?document.body:c.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},i._getAttachment=function(t){return z[t.toUpperCase()]},i._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=a(a({},this.config),{},{trigger:"manual",selector:""}):this._fixTitle()},i._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},i._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},i._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},i._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},i._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==V.indexOf(t)&&delete n[t]})),"number"==typeof(t=a(a(a({},this.constructor.Default),n),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),c.typeCheckConfig(Q,t,this.constructor.DefaultType),t.sanitize&&(t.template=q(t.template,t.whiteList,t.sanitizeFn)),t},i._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},i._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(U);null!==n&&n.length&&t.removeClass(n.join(""))},i._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},i._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if(void 0===i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return X}},{key:"NAME",get:function(){return Q}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return K}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Y}}]),t}();e.fn[Q]=$._jQueryInterface,e.fn[Q].Constructor=$,e.fn[Q].noConflict=function(){return e.fn[Q]=W,$._jQueryInterface};var G="popover",J=e.fn[G],Z=new RegExp("(^|\\s)bs-popover\\S+","g"),tt=a(a({},$.Default),{},{placement:"right",trigger:"click",content:"",template:''}),et=a(a({},$.DefaultType),{},{content:"(string|element|function)"}),nt={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},it=function(t){var n,i;function r(){return t.apply(this,arguments)||this}i=t,(n=r).prototype=Object.create(i.prototype),n.prototype.constructor=n,n.__proto__=i;var s=r.prototype;return s.isWithContent=function(){return this.getTitle()||this._getContent()},s.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},s.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},s.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},s._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},s._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(Z);null!==n&&n.length>0&&t.removeClass(n.join(""))},r._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new r(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if(void 0===n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},o(r,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return tt}},{key:"NAME",get:function(){return G}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return nt}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return et}}]),r}($);e.fn[G]=it._jQueryInterface,e.fn[G].Constructor=it,e.fn[G].noConflict=function(){return e.fn[G]=J,it._jQueryInterface};var ot="scrollspy",rt=e.fn[ot],st={offset:10,method:"auto",target:""},at={offset:"number",method:"string",target:"(string|element)"},lt=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,r=c.getSelectorFromElement(t);if(r&&(n=document.querySelector(r)),n){var s=n.getBoundingClientRect();if(s.width||s.height)return[e(n)[i]().top+o,r]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=a(a({},st),"object"==typeof t&&t?t:{})).target&&c.isElement(t.target)){var n=e(t.target).attr("id");n||(n=c.getUID(ot),e(t.target).attr("id",n)),t.target="#"+n}return c.typeCheckConfig(ot,t,at),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&(void 0===this._offsets[o+1]||t li > .active":".active";i=(i=e.makeArray(e(o).find(s)))[i.length-1]}var a=e.Event("hide.bs.tab",{relatedTarget:this._element}),l=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(a),e(this._element).trigger(l),!l.isDefaultPrevented()&&!a.isDefaultPrevented()){r&&(n=document.querySelector(r)),this._activate(this._element,o);var u=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,u):u()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,r=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],s=i&&r&&e(r).hasClass("fade"),a=function(){return o._transitionComplete(t,r,i)};if(r&&s){var l=c.getTransitionDurationFromElement(r);e(r).removeClass("show").one(c.TRANSITION_END,a).emulateTransitionEnd(l)}else a()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),c.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var r=e(t).closest(".dropdown")[0];if(r){var s=[].slice.call(r.querySelectorAll(".dropdown-toggle"));e(s).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if(void 0===o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ut._jQueryInterface.call(e(this),"show")})),e.fn.tab=ut._jQueryInterface,e.fn.tab.Constructor=ut,e.fn.tab.noConflict=function(){return e.fn.tab=ct,ut._jQueryInterface};var ht=e.fn.toast,ft={animation:"boolean",autohide:"boolean",delay:"number"},dt={animation:!0,autohide:!0,delay:500},pt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),c.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=a(a(a({},dt),e(this._element).data()),"object"==typeof t&&t?t:{}),c.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if(void 0===o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"DefaultType",get:function(){return ft}},{key:"Default",get:function(){return dt}}]),t}();e.fn.toast=pt._jQueryInterface,e.fn.toast.Constructor=pt,e.fn.toast.noConflict=function(){return e.fn.toast=ht,pt._jQueryInterface},t.Alert=f,t.Button=p,t.Carousel=w,t.Collapse=D,t.Dropdown=x,t.Modal=F,t.Popover=it,t.Scrollspy=lt,t.Tab=ut,t.Toast=pt,t.Tooltip=$,t.Util=c,Object.defineProperty(t,"__esModule",{value:!0})}(e,n(0),n(1))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){"use strict";n.r(e);n(0),n(3),n.p;$(document).ready(()=>{!function(){var t=document.getElementById("bd-docs-nav");let e=parseInt(sessionStorage.getItem("sidebar-scroll-top"),10);if(isNaN(e)){var n,i=t.querySelectorAll(".active"),o=0;for(n=i.length-1;n>0;n--){var r=i[n];void 0!==r&&(o+=r.offsetTop)}o-=t.offsetTop,void 0!==r&&o>.5*t.clientHeight&&(t.scrollTop=o-.2*t.clientHeight)}else t.scrollTop=e;window.addEventListener("beforeunload",()=>{sessionStorage.setItem("sidebar-scroll-top",t.scrollTop)})}(),$(window).on("activate.bs.scrollspy",(function(){document.querySelectorAll("#bd-toc-nav a").forEach(t=>{t.parentElement.classList.remove("active")}),document.querySelectorAll("#bd-toc-nav a.active").forEach(t=>{t.parentElement.classList.add("active")})}))})}]); \ No newline at end of file diff --git a/_static/language_data.js b/_static/language_data.js index ebe2f03..2e22b06 100644 --- a/_static/language_data.js +++ b/_static/language_data.js @@ -10,7 +10,7 @@ * */ -var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; /* Non-minified version is copied as a separate JS file, is available */ @@ -197,101 +197,3 @@ var Stemmer = function() { } } - - - -var splitChars = (function() { - var result = {}; - var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, - 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, - 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, - 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, - 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, - 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, - 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, - 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, - 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, - 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; - var i, j, start, end; - for (i = 0; i < singles.length; i++) { - result[singles[i]] = true; - } - var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], - [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], - [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], - [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], - [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], - [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], - [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], - [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], - [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], - [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], - [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], - [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], - [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], - [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], - [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], - [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], - [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], - [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], - [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], - [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], - [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], - [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], - [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], - [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], - [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], - [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], - [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], - [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], - [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], - [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], - [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], - [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], - [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], - [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], - [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], - [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], - [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], - [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], - [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], - [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], - [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], - [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], - [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], - [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], - [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], - [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], - [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], - [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], - [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; - for (i = 0; i < ranges.length; i++) { - start = ranges[i][0]; - end = ranges[i][1]; - for (j = start; j <= end; j++) { - result[j] = true; - } - } - return result; -})(); - -function splitQuery(query) { - var result = []; - var start = -1; - for (var i = 0; i < query.length; i++) { - if (splitChars[query.charCodeAt(i)]) { - if (start !== -1) { - result.push(query.slice(start, i)); - start = -1; - } - } else if (start === -1) { - start = i; - } - } - if (start !== -1) { - result.push(query.slice(start)); - } - return result; -} - - diff --git a/_static/locales/ar/LC_MESSAGES/booktheme.mo b/_static/locales/ar/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..15541a6a375f93efed3f410c2f892174ba91aaa0 GIT binary patch literal 1541 zcmZvaJ!}+56vrn40$lhsA5n;v39lh z&UUPnK|(?lfROD&7suGxxK0yMQ@o*|gesy+5vu&(?mBh?qn-WTn|=G<|NZw~b#1&Y zus*}?#(shQ752{`;fA&4V5qyTPS`e-!60i}(%5{r(0^;D!zP`#V66yFspV7<>kvF5*86z5`j$ z=8ez}?gu^a8}Li;DtHLIQScsk0P*i2&-V)CK7WC%Q*07qAJ7GU4juvd{a%p0tQWim zeu4N7$oY#!{2XK-Ul-?ZLAIP{VE@?5Oee^5uV0WLc46~8yjT}6*2P}4uiOhI#i!V; zXZ>RTx%Xyl*phu;(K~`m+PV^FjkZeL1V5sYI1K7moHI9c!}v9+ja5U&{2;G|4YhWh zm^7}c{~g+Tn8?Tvl<2F47Nu9i{l>4L9=6uy?FAD0FiY3w(=eiIKTWvQbqOe&{(Wd5^qM9YH}dGcsaNzja& zq-k29Wt#nO;9At7wwrWQc-|J&abpO^Bu%@f8>dB@7kE5QPu!GiO4q{asH8bJN^P3Y zvv7uYJM=8C@P0OzYSB}gLot+ZNt#(-bAo@Zj6?Yfp?anYnoPQR?;I# z{we#%LHPn31obOfkF`-+I9KUX>gUj zW@~ literal 0 HcmV?d00001 diff --git a/_static/locales/ar/LC_MESSAGES/booktheme.po b/_static/locales/ar/LC_MESSAGES/booktheme.po index b5c145f..2e8d682 100644 --- a/_static/locales/ar/LC_MESSAGES/booktheme.po +++ b/_static/locales/ar/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: ar\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "مخزن" - -msgid "open issue" -msgstr "قضية مفتوحة" - -msgid "Contents" -msgstr "محتويات" - -msgid "Fullscreen mode" -msgstr "وضع ملء الشاشة" +msgid "suggest edit" +msgstr "أقترح تحرير" -msgid "Download this page" -msgstr "قم بتنزيل هذه الصفحة" +msgid "Last updated on" +msgstr "آخر تحديث في" -msgid "Download source file" -msgstr "تنزيل ملف المصدر" +msgid "Edit this page" +msgstr "قم بتحرير هذه الصفحة" msgid "Launch" msgstr "إطلاق" -msgid "Edit this page" -msgstr "قم بتحرير هذه الصفحة" +msgid "Print to PDF" +msgstr "طباعة إلى PDF" + +msgid "open issue" +msgstr "قضية مفتوحة" + +msgid "Download notebook file" +msgstr "تنزيل ملف دفتر الملاحظات" msgid "Toggle navigation" msgstr "تبديل التنقل" -msgid "Theme by the" -msgstr "موضوع بواسطة" - msgid "Source repository" msgstr "مستودع المصدر" -msgid "Last updated on" -msgstr "آخر تحديث في" - msgid "By the" msgstr "بواسطة" +msgid "next page" +msgstr "الصفحة التالية" + +msgid "repository" +msgstr "مخزن" + msgid "Sphinx Book Theme" msgstr "موضوع كتاب أبو الهول" -msgid "Open an issue" -msgstr "افتح قضية" +msgid "Download source file" +msgstr "تنزيل ملف المصدر" -msgid "next page" -msgstr "الصفحة التالية" +msgid "Contents" +msgstr "محتويات" + +msgid "By" +msgstr "بواسطة" msgid "Copyright" msgstr "حقوق النشر" -msgid "Search this book..." -msgstr "بحث في هذا الكتاب ..." - -msgid "Print to PDF" -msgstr "طباعة إلى PDF" +msgid "Fullscreen mode" +msgstr "وضع ملء الشاشة" -msgid "By" -msgstr "بواسطة" +msgid "Open an issue" +msgstr "افتح قضية" msgid "previous page" msgstr "الصفحة السابقة" -msgid "Search the docs ..." -msgstr "ابحث في المستندات ..." - -msgid "Download notebook file" -msgstr "تنزيل ملف دفتر الملاحظات" +msgid "Download this page" +msgstr "قم بتنزيل هذه الصفحة" -msgid "suggest edit" -msgstr "أقترح تحرير" +msgid "Theme by the" +msgstr "موضوع بواسطة" diff --git a/_static/locales/bg/LC_MESSAGES/booktheme.mo b/_static/locales/bg/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..da95120037f8d7c52ad1f166a7682ea55ca47a01 GIT binary patch literal 1708 zcmaKqOKcQJ5QaOv0vkhkhC?jT2nh&cNkBwFYxY90B_t3AOpcMpyUpy7b@wpSL+}lZ zc_s=RKte*|C2`<_7URcy7jLdPR->G9h;qvTamgjhjlX8bj}R-P?fIs=y6dm{dw*ZQ z?5@DG8KWEHSBxzfKYoB0o|Q|4z)!5gYX#T^t^_xLtH5sX6L34Y5iEo2!IR(`P=OzV zHs>hFdG3I#!TVqr_zYYJPUie2U;izi{|U0*KVSh|x->h#2IP4+$a!{vO>jTB41AmO zFOci|8~haPLhws)C%7B@Hs=rEKFpioR`3nD2VA{8JAV*le@=j0?>TT6cp2OVJ_ot4 z*WiBe50LY0LeuQ=S0K-igY45ea0fUFvgOv1JgO3NWrRpO`@TbYDa&#J04 z8uLU~YT|f^4W5=k94AWjM}bBXBl{2ciBp+gq(T!1)p!vCDOMX z%z7FyzF${Td*=h+vjIf3x?r>F4C`bfVWiFnCdtcQkUma)U!h8cPEd+Dt17m5q+0w& zMKQ9KWTsza{bH(IICkV%?|gjko-YcyvBiPmP?e-b0iTC;FVH=*QuCr%+4AXuzT$!T zeUYc*Gb$?f>WZlb+AqligMlp^^|YVB*ODCc3;p#Z^6JGt6Ai^Bsl#*{m-qF^?6bU6 z%dKU(_p_dYpa*V5&_n77dhBk}xVz~t(j+x#hMF`X=r)bH5$d>$?h>`ABk5bs2r;-dTfq#Q2#?t@q|9teP3*uNPWy^ACfqd~8<8}Y{+a1%CJzCK zxEruG6KALRIVJ-U$3Yy!~NpG7AK|w8QyPuG1485SvTmo%i zrHNb3JL61fEcXDLQBPwL`;mLLOPayeL#0F0B5ju4Yr5-c6aTq5cjf(V=MS}!0~aLI KlK*|VZ0$SA#iddJ literal 0 HcmV?d00001 diff --git a/_static/locales/bg/LC_MESSAGES/booktheme.po b/_static/locales/bg/LC_MESSAGES/booktheme.po index 4e1bc06..56ef0eb 100644 --- a/_static/locales/bg/LC_MESSAGES/booktheme.po +++ b/_static/locales/bg/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: bg\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "хранилище" - -msgid "open issue" -msgstr "отворен брой" - -msgid "Contents" -msgstr "Съдържание" - -msgid "Fullscreen mode" -msgstr "Режим на цял екран" +msgid "suggest edit" +msgstr "предложи редактиране" -msgid "Download this page" -msgstr "Изтеглете тази страница" +msgid "Last updated on" +msgstr "Последна актуализация на" -msgid "Download source file" -msgstr "Изтеглете изходния файл" +msgid "Edit this page" +msgstr "Редактирайте тази страница" msgid "Launch" msgstr "Стартиране" -msgid "Edit this page" -msgstr "Редактирайте тази страница" +msgid "Print to PDF" +msgstr "Печат в PDF" + +msgid "open issue" +msgstr "отворен брой" + +msgid "Download notebook file" +msgstr "Изтеглете файла на бележника" msgid "Toggle navigation" msgstr "Превключване на навигацията" -msgid "Theme by the" -msgstr "Тема от" - msgid "Source repository" msgstr "Хранилище на източника" -msgid "Last updated on" -msgstr "Последна актуализация на" - msgid "By the" msgstr "По" +msgid "next page" +msgstr "Следваща страница" + +msgid "repository" +msgstr "хранилище" + msgid "Sphinx Book Theme" msgstr "Тема на книгата Sphinx" -msgid "Open an issue" -msgstr "Отворете проблем" +msgid "Download source file" +msgstr "Изтеглете изходния файл" -msgid "next page" -msgstr "Следваща страница" +msgid "Contents" +msgstr "Съдържание" + +msgid "By" +msgstr "От" msgid "Copyright" msgstr "Авторско право" -msgid "Search this book..." -msgstr "Търсене в тази книга ..." - -msgid "Print to PDF" -msgstr "Печат в PDF" +msgid "Fullscreen mode" +msgstr "Режим на цял екран" -msgid "By" -msgstr "От" +msgid "Open an issue" +msgstr "Отворете проблем" msgid "previous page" msgstr "предишна страница" -msgid "Search the docs ..." -msgstr "Търсене в документите ..." - -msgid "Download notebook file" -msgstr "Изтеглете файла на бележника" +msgid "Download this page" +msgstr "Изтеглете тази страница" -msgid "suggest edit" -msgstr "предложи редактиране" +msgid "Theme by the" +msgstr "Тема от" diff --git a/_static/locales/bn/LC_MESSAGES/booktheme.mo b/_static/locales/bn/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6b96639b726a2fa959a6419b6f8b7e0dfcce33ae GIT binary patch literal 1646 zcmbV~&5IOA7>8S2xE{WN>)mqrjbP_+ zD|`%n|9`+8@Gtlc{Cs5;eF=|2zkdOGUHYZ{3U0$*$xxrd?Ipj1NbvXay{#>+)sQwK zLc@BGr=Q8s@3s2pVyti%e$UVEm)Gmv@K$Kxb@iIkGQ)QH3Dc6%KAm>6q}ejje*L3r z>$oA5HgZzyAH?ybE$6p$-O1{5(WYr7xk%%tj7A!XA>+Uti*qA7X(KkWA+(Cd;*P4f zqC=@vB32^F^Nx(hvqTZ3#rXcw=x~uglc~-VqqA;wIBg~Bl-TQgnP|xqG73*IS+qW( zo6WWqDn6MsW0O!s$y282M*BKNku;Mh6WuA>9MAOkvTmve8r7pR%ZaLqqE6Ml~R{3$6RYz1^ zHxkvXiQSWlsf@*{*+H+Gm{gVVb|;J5)lr?D$ZJBS!OVxh8WP3p@HQnr8y3617^+0h zTGzYm>~GFKb#|8L(pyu`-gfp`;o|IhXQy$z<$9NR^WnYI&Q1wu?}S90&tc32?JEMg4wtZV(;LB0u<-^*y2)npB|JLL@f}SDrcO%Hi&xc%8I{oPgE$%7j?Kgl1>Fz ze@F9IjWZ|r@GsvuUE*t^AN05zoTs2{kFZmI~m25V-8`&>S^dPTx z$^cEyl^jJ+?oOKAsWhagj`qI>dC8~bzq_0hZSgC)LsF@U6+9F=tR`Ky;!WHMs_vF; z;&hv=3*2(}kGreju(wh1_KV>qMpKtu5HHORr>y#KY7MM6T^uJ&R^K(T z4hABYyJ6tQiOxVI^L*F1qO_S8am=vBunT>6i=$ATZdb3f&v8VJ2BK9Ft@hoIsQAhin!}wxzs(N*6pVu~DVqb08$hD1)Yjm|` zLS;tVxWMJrDAJYrr0_baPC1|EHL_WMn2%o?qrvC+h@~^*GMofV4`)o0LtLbidwpll9h6X)!5Y za@FKiW0X*mn3iX1k|l^w_?&_QX>NDCJM7-fGBbN{ zu90Yv ze2zJT`3vTkm``?L!Pxha5O~CXEFXgh!F}K{a6dQ$o&?W;$H6Xm6ub={0u}ff7#cnT z+0QfZQ*aGD2(E)iz#kj_+}M9>_J4vL?;Y3zckiz69|Czl1G1m9;7jl_xEK7Z;olA4 zfrnxL7yKGLyhn&Hz$@Tsa2Y%S-Uqp^$KWaO2ax0Z1af_E!2{s0AfNlAvHt_IJ_it- z&m9L@hqKN83dlMwfSm7Lkn7GsmYi+Vd*Crl_RV$g90)P3f&KE}ym+u5)|z$Y8sKu8 zBlmXaVEsAAPcR|Fw7=ro7!QS1iR;z`WrD|#V(fI1264kaFu9d685`8V+Kg6ouC~qI zmM&5s7(=Q(6*5s`F4h6A|KHA+dF~^pl%b)GmAEN=pt6W%P%&A9eQBapEEYH*4QcO7 zC3;R9II+~bF)xtNkjEETCX59u1`)=$+?iRns%x~9HOl3bCIBb~^g5yYs6 zq0Y{7oH|J1)JWU1NqdKTUnYq{mI{?16?;!bp}i2dzgNz~TZiiSZI0ibMsD3&xHY%^ z{^Gd{twz{(e_W^z1tf63$fY*36s6L66}rp)`S#WAb50t+qFj5Cn}I4y~Kg zBqen1P~=;^ymT^e&s#V29Wupq>${g`ss7ph#?V(?y7=vEOZ04vuGQ<}z{^y~66*P^ zno!}Y$w-Q&P)$-}%RuPqz&a}Is;MT!%#Nz{)Y2fgS=pT0Tnmc4rqvjN;Qj07&Ihjp zVvrB;Z*XvQD zxu;CEAr^xgZM{%PrEqqD`$N&!KBKt)RPHp%tyA?Xw}`Se37c!8k8_eTqth`htw3AZ zm~1S1a92z`@RU9C@Xu~NJj63$#L LZS{&p7>oY^Ev$2? literal 0 HcmV?d00001 diff --git a/_static/locales/cs/LC_MESSAGES/booktheme.po b/_static/locales/cs/LC_MESSAGES/booktheme.po index 4889556..3818df9 100644 --- a/_static/locales/cs/LC_MESSAGES/booktheme.po +++ b/_static/locales/cs/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: cs\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "úložiště" - -msgid "open issue" -msgstr "otevřené číslo" - -msgid "Contents" -msgstr "Obsah" - -msgid "Fullscreen mode" -msgstr "Režim celé obrazovky" +msgid "suggest edit" +msgstr "navrhnout úpravy" -msgid "Download this page" -msgstr "Stáhněte si tuto stránku" +msgid "Last updated on" +msgstr "Naposledy aktualizováno" -msgid "Download source file" -msgstr "Stáhněte si zdrojový soubor" +msgid "Edit this page" +msgstr "Upravit tuto stránku" msgid "Launch" msgstr "Zahájení" -msgid "Edit this page" -msgstr "Upravit tuto stránku" +msgid "Print to PDF" +msgstr "Tisk do PDF" + +msgid "open issue" +msgstr "otevřené číslo" + +msgid "Download notebook file" +msgstr "Stáhnout soubor poznámkového bloku" msgid "Toggle navigation" msgstr "Přepnout navigaci" -msgid "Theme by the" -msgstr "Téma od" - msgid "Source repository" msgstr "Zdrojové úložiště" -msgid "Last updated on" -msgstr "Naposledy aktualizováno" - msgid "By the" msgstr "Podle" +msgid "next page" +msgstr "další strana" + +msgid "repository" +msgstr "úložiště" + msgid "Sphinx Book Theme" msgstr "Téma knihy Sfinga" -msgid "Open an issue" -msgstr "Otevřete problém" +msgid "Download source file" +msgstr "Stáhněte si zdrojový soubor" -msgid "next page" -msgstr "další strana" +msgid "Contents" +msgstr "Obsah" + +msgid "By" +msgstr "Podle" msgid "Copyright" msgstr "autorská práva" -msgid "Search this book..." -msgstr "Hledat v této knize ..." - -msgid "Print to PDF" -msgstr "Tisk do PDF" +msgid "Fullscreen mode" +msgstr "Režim celé obrazovky" -msgid "By" -msgstr "Podle" +msgid "Open an issue" +msgstr "Otevřete problém" msgid "previous page" msgstr "předchozí stránka" -msgid "Search the docs ..." -msgstr "Hledat v dokumentech ..." - -msgid "Download notebook file" -msgstr "Stáhnout soubor poznámkového bloku" +msgid "Download this page" +msgstr "Stáhněte si tuto stránku" -msgid "suggest edit" -msgstr "navrhnout úpravy" +msgid "Theme by the" +msgstr "Téma od" diff --git a/_static/locales/da/LC_MESSAGES/booktheme.mo b/_static/locales/da/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f43157d70c63ff21b4385dc36cb73f5b14eb6b01 GIT binary patch literal 1304 zcmZ9KyKmG$5XKi02pkaJ&;+qGJPH$nD9}aMKoTh;K$JVu@15uDO?nzn&U>A+XM4Phfw-zKH#7 zA8uHO_6vba9LDV+coaMYo(2zt6W}@UGI$1TfTzGEa2zD?I2bB!f*j{Lcno|A9tB^6 zC&9NBKUV%PmHi!Ly?>3CQ(qR(uY!{wt8{eFL)2d+-GK0XzbJ2D#pEAm_OQa=bqv z>yEt{#_?I3XFI&O|2#v^6KxpGSKQga zB|}Q$t~G&7@Oa2KoKDgpX6$2=SrtoT1GTMPm0g|DuG`zfb!d+>q}t0|B_w8J9T57T zIag$v?>HhOdp0JqpnQ-;9;-mHv<7xzI;nV=;{#=+_P!vo=(Ir)D;H<{wy4q`3h#>~ zA!JFY1gY2+>V#-Mj+V)JM61hEKVto8pj^8@e}8uO{nYgvwW_gEYa^$+3`k%y&y+UP zvXd(3DKs9n=AzrX-#KM`ms~V!IyTlOsmt4K9cl~8BnA3fm$9lXW`$E(G-qAU*QLn^ zrf=MwmgQsPs*#r(a_ZW2O)OJ9*z+b%Z59igr)teR+B0C^wn>Bm@6LBsXEFWfiOCp} zUSoVqXi7p(4!JPl*su1tkyFr_56Z-%sbe(I4#o^g{#-PJazXT;wvB`*ceb5TPdvg| zr`IHo4yJvN)iV_A{*4(42I?u%!cD5KXs+sR7@qEf{)q=$-v3Mo~pNRgs6dB45A_~g;fK07nJ@Atd!PtN@)FuuTCzw-;3=>No&-0+;~;^bfwAQikaeDcpMpPw z$G{ih3Gh|R-`o9n?fMUp?fnCGz(a>7-ya8gy#TV#x8N_}HSiTa&9^9*#YUsChPKG9Ug3-wb>5ahNSoell`9^ zoCmHU$Afe<^%ebHTryT9ZaN#u#(;-<*Xy#1V#z(Q#;HPD7is9+wj60gd)vV!pVPk0 zSm_{ZRgzdPbcFPDxsr?txhJx6>8J8fdK zt=*csGQxpNwNctG%DhrOQ0(2=TFGwgz2}t;Bl6j@&0V2w*_AhjI(F8SEfezEl?8P+ zO!CTPE6$HYSK7K+hThdhIeF}TXXUw`ymDc&BbHF5O7u~OM`4rK)5Mn;Zwdn zburuA-y2y!aDY4^_ YHT)aX(-~_xf`&nTEYd88)4;9x4>RdeS^xk5 literal 0 HcmV?d00001 diff --git a/_static/locales/de/LC_MESSAGES/booktheme.po b/_static/locales/de/LC_MESSAGES/booktheme.po index 70eaab5..c0027d3 100644 --- a/_static/locales/de/LC_MESSAGES/booktheme.po +++ b/_static/locales/de/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "Repository" - -msgid "open issue" -msgstr "offenes Thema" - -msgid "Contents" -msgstr "Inhalt" - -msgid "Fullscreen mode" -msgstr "Vollbildmodus" +msgid "suggest edit" +msgstr "vorschlagen zu bearbeiten" -msgid "Download this page" -msgstr "Laden Sie diese Seite herunter" +msgid "Last updated on" +msgstr "Zuletzt aktualisiert am" -msgid "Download source file" -msgstr "Quelldatei herunterladen" +msgid "Edit this page" +msgstr "Bearbeite diese Seite" msgid "Launch" msgstr "Starten" -msgid "Edit this page" -msgstr "Bearbeite diese Seite" +msgid "Print to PDF" +msgstr "In PDF drucken" + +msgid "open issue" +msgstr "offenes Thema" + +msgid "Download notebook file" +msgstr "Notebook-Datei herunterladen" msgid "Toggle navigation" msgstr "Navigation umschalten" -msgid "Theme by the" -msgstr "Thema von der" - msgid "Source repository" msgstr "Quell-Repository" -msgid "Last updated on" -msgstr "Zuletzt aktualisiert am" - msgid "By the" msgstr "Bis zum" +msgid "next page" +msgstr "Nächste Seite" + +msgid "repository" +msgstr "Repository" + msgid "Sphinx Book Theme" msgstr "Sphinx-Buch-Thema" -msgid "Open an issue" -msgstr "Öffnen Sie ein Problem" +msgid "Download source file" +msgstr "Quelldatei herunterladen" -msgid "next page" -msgstr "Nächste Seite" +msgid "Contents" +msgstr "Inhalt" + +msgid "By" +msgstr "Durch" msgid "Copyright" msgstr "Urheberrechte ©" -msgid "Search this book..." -msgstr "Dieses Buch durchsuchen ..." - -msgid "Print to PDF" -msgstr "In PDF drucken" +msgid "Fullscreen mode" +msgstr "Vollbildmodus" -msgid "By" -msgstr "Durch" +msgid "Open an issue" +msgstr "Öffnen Sie ein Problem" msgid "previous page" msgstr "vorherige Seite" -msgid "Search the docs ..." -msgstr "Durchsuchen Sie die Dokumente ..." - -msgid "Download notebook file" -msgstr "Notebook-Datei herunterladen" +msgid "Download this page" +msgstr "Laden Sie diese Seite herunter" -msgid "suggest edit" -msgstr "vorschlagen zu bearbeiten" +msgid "Theme by the" +msgstr "Thema von der" diff --git a/_static/locales/el/LC_MESSAGES/booktheme.mo b/_static/locales/el/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..fca6e9355f314677f2890f5679fd79dd67a7a5a2 GIT binary patch literal 1722 zcmZ{iPiS047{Euewt4U5n=fkKPHMz8X+JKcS{dGGPw+nU_c zCZPt>L)D-XMN9P{m<`*yO}BBoS3#I}@#Mj)Cp~!cBL2SFE!h-0?96ZHoA3Yk{@Ax; zMX{b{53_$`KhIu%fP=N`L8bVq-5d|WJ#ZJ?4|l_1_!N8@J_(C(AAASyg$6zb(>@oV z`1uSz3RmGC_yc?b-t6<2zWn$8{ZAG}N=-3*|lx#m@-51&_iV@GtlX{0B;& z|G|Us0FOuETkutwLXlsEZ^B>UVYqXrQitFhQ0g-9MK}YWfvbJC;B(wFD1G=Fz66IT z_E|X6=LsnC_o4J>9*)3IptM|SkT~LFKU;E^x(64jsmIx3FH7o|CH<3LOJ5JLNx{`F zvmIQ7ax;7w(hfIYb$phePOCsWALdpYv;G zOPqxDxMc1Trd2=DkykNltn8<_zIz?7*J?>AHYU*1VcDqDUXtp1RQ6I+)?vWC9+ax; z?Fa=g(0-ECjhcx404JfII61D)_Tt4R3KKsK<5_h!s`|lJua|GifioP~!B0M6o&VhxLBi1MZW0rDDj^PzkAoADB{_KUL1ZXW|5J z1>K9Em-u-XId|sNnX#?+BZm&>`i;#`&PJx7QxbSBs(F4es!LTbPE1;ScXB*`Y)dcp zg5;cu^J76NEc-#FppQ-YY3{TaRO_9ar-jjaZW8iNR~zWhPCd z!IGORj47br#qth1q_-xG*Y+m$QJl1ldYsi|#&y>pn)3O}2r<588%%~cb6DJv&M0zR z6Ju?!Gpp;aJ2H>n=Q;4)9QX)UBsQv>oVXExo49XqkvY35v_#)clq&D(UelG*<`bgE k?KNN}BbD^J+2#A$4_2dkCejtU)5(_TEbrUqDh*fv19*CpTMYflop9djWEuuR*>)1Ua4$Am958?gqbuT!-Hv=RLl? ztm83|e|Hk(lCvi7xt0eoxwahd<^hR9n|*n(9}lh{d$2y|1j)ji^V&Q(5ANYkOq8Lh zleoHqM}{7WYt{rZ!Q&-caXRS*F>UXd)T&q-8)(7WzFgEPZ5(@>yDt567<$^vOeG|m zu?~=4-?s8J^<76~z&terQmeydOn{H3s$Z$a!slCrhw4F8(v9dkg67!{> zqs)38tXmQDSx=k0@+!yH>Cu2hvC4%qr;bgMl%!G1I#EHx#L(SPMrYZlG|3z-YnxYL zZ<6X6Bk3-!Gg!U#kimbyhN}%YXpR zWvS9;N_Kn7c?ykNomO;Zym7(o#sxZQOml4 zuS=5^Ti>`iCCk^wX(LZG)Bqh@I0@tnvqcu0^K+ literal 0 HcmV?d00001 diff --git a/_static/locales/eo/LC_MESSAGES/booktheme.po b/_static/locales/eo/LC_MESSAGES/booktheme.po index bdf994b..6749f3a 100644 --- a/_static/locales/eo/LC_MESSAGES/booktheme.po +++ b/_static/locales/eo/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "deponejo" - -msgid "open issue" -msgstr "malferma numero" - -msgid "Contents" -msgstr "Enhavo" - -msgid "Fullscreen mode" -msgstr "Plenekrana reĝimo" +msgid "suggest edit" +msgstr "sugesti redaktadon" -msgid "Download this page" -msgstr "Elŝutu ĉi tiun paĝon" +msgid "Last updated on" +msgstr "Laste ĝisdatigita la" -msgid "Download source file" -msgstr "Elŝutu fontodosieron" +msgid "Edit this page" +msgstr "Redaktu ĉi tiun paĝon" msgid "Launch" msgstr "Lanĉo" -msgid "Edit this page" -msgstr "Redaktu ĉi tiun paĝon" +msgid "Print to PDF" +msgstr "Presi al PDF" + +msgid "open issue" +msgstr "malferma numero" + +msgid "Download notebook file" +msgstr "Elŝutu kajeran dosieron" msgid "Toggle navigation" msgstr "Ŝalti navigadon" -msgid "Theme by the" -msgstr "Temo de la" - msgid "Source repository" msgstr "Fonto-deponejo" -msgid "Last updated on" -msgstr "Laste ĝisdatigita la" - msgid "By the" msgstr "Per la" +msgid "next page" +msgstr "sekva paĝo" + +msgid "repository" +msgstr "deponejo" + msgid "Sphinx Book Theme" msgstr "Sfinksa Libro-Temo" -msgid "Open an issue" -msgstr "Malfermu numeron" +msgid "Download source file" +msgstr "Elŝutu fontodosieron" -msgid "next page" -msgstr "sekva paĝo" +msgid "Contents" +msgstr "Enhavo" + +msgid "By" +msgstr "De" msgid "Copyright" msgstr "Kopirajto" -msgid "Search this book..." -msgstr "Serĉu ĉi tiun libron ..." - -msgid "Print to PDF" -msgstr "Presi al PDF" +msgid "Fullscreen mode" +msgstr "Plenekrana reĝimo" -msgid "By" -msgstr "De" +msgid "Open an issue" +msgstr "Malfermu numeron" msgid "previous page" msgstr "antaŭa paĝo" -msgid "Search the docs ..." -msgstr "Serĉu la dokumentojn ..." - -msgid "Download notebook file" -msgstr "Elŝutu kajeran dosieron" +msgid "Download this page" +msgstr "Elŝutu ĉi tiun paĝon" -msgid "suggest edit" -msgstr "sugesti redaktadon" +msgid "Theme by the" +msgstr "Temo de la" diff --git a/_static/locales/es/LC_MESSAGES/booktheme.mo b/_static/locales/es/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..ba2ee4dc22148ed53f2aeba32c5965654d4a5a2f GIT binary patch literal 1396 zcmZ9Kzi$;s5XU#z;m3pU!zKwxjKJWQQZ~wEO{|$=X8*l*5%yj3EgEC(L#m|@E3-CIKPyLHQ^!@|o{A*Bj z4$La`8F(5z16~6q{%=5u|2}vYjQ#o}@F?a_K{@|BDEE2^ehj_>C4c{bvhUD`U0&uv z*?$p~_`U+=+!`qRz6aYpfs%6BBl;4{Ji6po;@;mNp-!U9Icai#X`&;(C9e__T(%nW zw)>mpL*DQZy5tBcRcdJ)pH3yKo8BdMDdMNz4yGuRTJ{f|^^|Mp6HmSWQEwW{d*1tzb%mTC1mCsq-qL_43=ae|t-eKOjtW>vaY#^sij18-e zU>uxyy|KKi?sj^CYadPWVO!m;OXD8uC5dfPa>c40^|ZUw#21BS?P$vslng{1KTKV8 zUUWKW55MCO;ccWl{h{a&Tjjy}+WN}g`qfKU z27O|OlkJ*EIw63|wI$;gbyiY{oW}PitHT?6`vSSR$zizSGM^h)jP#AENrPMDiUxTd zX^w*p+XS-1RUfK2(ynf&aeQr2cfaHFPM;g=s}~jrYQqQVnr;8cCiiNY181d=I%iD{ zk_k)9C=?Vlg{(ANUY4?kat==RzrVWKpj=Q5{Q{y&B&juy+NY=9viqbpt^2(7Sd&X+ zE$PfxwdF+Wo=v7AO<8KlnjOl_?lY%ZD#GnhWgz3#*VABvZk(=zpIWX+tyOg}6^wXC zsg65u%fhre9yJUf6KusrthQzv+672++(cecEV5X4sri<+xahTU@tQ2Tj8rs5BN4#T iU!*-mQ^Nsab@xTRCJqKkd{;ciD^w4Rh!536LH!R)!cyS? literal 0 HcmV?d00001 diff --git a/_static/locales/es/LC_MESSAGES/booktheme.po b/_static/locales/es/LC_MESSAGES/booktheme.po index b23d3ec..71dde37 100644 --- a/_static/locales/es/LC_MESSAGES/booktheme.po +++ b/_static/locales/es/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "repositorio" - -msgid "open issue" -msgstr "Tema abierto" - -msgid "Contents" -msgstr "Contenido" - -msgid "Fullscreen mode" -msgstr "Modo de pantalla completa" +msgid "suggest edit" +msgstr "sugerir editar" -msgid "Download this page" -msgstr "Descarga esta pagina" +msgid "Last updated on" +msgstr "Ultima actualización en" -msgid "Download source file" -msgstr "Descargar archivo fuente" +msgid "Edit this page" +msgstr "Edita esta página" msgid "Launch" msgstr "Lanzamiento" -msgid "Edit this page" -msgstr "Edita esta página" +msgid "Print to PDF" +msgstr "Imprimir en PDF" + +msgid "open issue" +msgstr "Tema abierto" + +msgid "Download notebook file" +msgstr "Descargar archivo de cuaderno" msgid "Toggle navigation" msgstr "Navegación de palanca" -msgid "Theme by the" -msgstr "Tema por el" - msgid "Source repository" msgstr "Repositorio de origen" -msgid "Last updated on" -msgstr "Ultima actualización en" - msgid "By the" msgstr "Por el" +msgid "next page" +msgstr "siguiente página" + +msgid "repository" +msgstr "repositorio" + msgid "Sphinx Book Theme" msgstr "Tema del libro de la esfinge" -msgid "Open an issue" -msgstr "Abrir un problema" +msgid "Download source file" +msgstr "Descargar archivo fuente" -msgid "next page" -msgstr "siguiente página" +msgid "Contents" +msgstr "Contenido" + +msgid "By" +msgstr "Por" msgid "Copyright" msgstr "Derechos de autor" -msgid "Search this book..." -msgstr "Buscar este libro ..." - -msgid "Print to PDF" -msgstr "Imprimir en PDF" +msgid "Fullscreen mode" +msgstr "Modo de pantalla completa" -msgid "By" -msgstr "Por" +msgid "Open an issue" +msgstr "Abrir un problema" msgid "previous page" msgstr "pagina anterior" -msgid "Search the docs ..." -msgstr "Buscar los documentos ..." - -msgid "Download notebook file" -msgstr "Descargar archivo de cuaderno" +msgid "Download this page" +msgstr "Descarga esta pagina" -msgid "suggest edit" -msgstr "sugerir editar" +msgid "Theme by the" +msgstr "Tema por el" diff --git a/_static/locales/et/LC_MESSAGES/booktheme.mo b/_static/locales/et/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..983b82391f499b67a9046c15d0dd8744650ad925 GIT binary patch literal 1341 zcmZ9Kzi%8x6vqb=^5gOYNC*@$VrY^ev%C-5~0q6cNoSQvQHcDIz*5N(ux8-*>yj7Nec{?37 zm@hCt!hG}w7K~$WDuqWK$8rQb2_6H_g2%xn@O|(C_#QX{&wyWnr$GYW22;<6py+%D zo&tXWPl7*z?}ESdeBSTB?Csw{@%I-v01qANzCR6$y#$KRMeqsu1$Y$v1AGho6Fdz5 z4az++J_JsIlKZFNIq(K3aoh#Zg45o90E(Y)LCNb!P;`Fo`2>{wpMm1IA0b zcW{Vb>7mpIdO`vjME%rCbb#Z zLB#9Ln`>&T^B1V~k&_R*YOAf;-PhM8wsB1jsl}?dyPU?psw`<|W?Y%XaN_8G>Z0@F zr*qN&8_XbscI- zgH4-*vBjDXO&n_1F3dRkd|7v|qf1VIJknP`Sstj{^T%OktXj#ancCu*yH}n+<|;=N z-jrOCj`OFMOqk`wddINU##;0GR19tBdvzi?e7zruw52+Aw>NT5Q%F&X%h*Lj=6f7z z8jNuq=-IE#jk<#c{m?m+L;rJ$825O_Nq(D^8CKl}zio+{#UD_z^uJ)WVl7Wi?YTr` zTRZHgk)aH+jLK4D)OfM3BNeE1ohJ(1utQX6H>rE`y-+P|2~e4t1fZw$r;!^}gUIe5 P_MW2m5}a<3ol*Y+f5$~k literal 0 HcmV?d00001 diff --git a/_static/locales/et/LC_MESSAGES/booktheme.po b/_static/locales/et/LC_MESSAGES/booktheme.po index 664c246..cdcd07c 100644 --- a/_static/locales/et/LC_MESSAGES/booktheme.po +++ b/_static/locales/et/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: et\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "hoidla" - -msgid "open issue" -msgstr "avatud küsimus" - -msgid "Contents" -msgstr "Sisu" - -msgid "Fullscreen mode" -msgstr "Täisekraanirežiim" +msgid "suggest edit" +msgstr "soovita muuta" -msgid "Download this page" -msgstr "Laadige see leht alla" +msgid "Last updated on" +msgstr "Viimati uuendatud" -msgid "Download source file" -msgstr "Laadige alla lähtefail" +msgid "Edit this page" +msgstr "Muutke seda lehte" msgid "Launch" msgstr "Käivitage" -msgid "Edit this page" -msgstr "Muutke seda lehte" +msgid "Print to PDF" +msgstr "Prindi PDF-i" + +msgid "open issue" +msgstr "avatud küsimus" + +msgid "Download notebook file" +msgstr "Laadige sülearvuti fail alla" msgid "Toggle navigation" msgstr "Lülita navigeerimine sisse" -msgid "Theme by the" -msgstr "Teema" - msgid "Source repository" msgstr "Allikahoidla" -msgid "Last updated on" -msgstr "Viimati uuendatud" - msgid "By the" msgstr "Autor" +msgid "next page" +msgstr "järgmine leht" + +msgid "repository" +msgstr "hoidla" + msgid "Sphinx Book Theme" msgstr "Sfinksiraamatu teema" -msgid "Open an issue" -msgstr "Avage probleem" +msgid "Download source file" +msgstr "Laadige alla lähtefail" -msgid "next page" -msgstr "järgmine leht" +msgid "Contents" +msgstr "Sisu" + +msgid "By" +msgstr "Kõrval" msgid "Copyright" msgstr "Autoriõigus" -msgid "Search this book..." -msgstr "Otsige sellest raamatust ..." - -msgid "Print to PDF" -msgstr "Prindi PDF-i" +msgid "Fullscreen mode" +msgstr "Täisekraanirežiim" -msgid "By" -msgstr "Kõrval" +msgid "Open an issue" +msgstr "Avage probleem" msgid "previous page" msgstr "eelmine leht" -msgid "Search the docs ..." -msgstr "Dokumentidest otsimine ..." - -msgid "Download notebook file" -msgstr "Laadige sülearvuti fail alla" +msgid "Download this page" +msgstr "Laadige see leht alla" -msgid "suggest edit" -msgstr "soovita muuta" +msgid "Theme by the" +msgstr "Teema" diff --git a/_static/locales/fi/LC_MESSAGES/booktheme.mo b/_static/locales/fi/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..d8ac054597c924e3010f629caeac1c748b7211cd GIT binary patch literal 1368 zcmZ9KJ#5r46vquMU&lA4Af!r|g^wXX5kqz52B58kprWEjclYv|xbfLh>>S*}#K;Cr ztS2O9B*cCTVrBw~l?gF1AR)y6B`K}2;{5K}=lB1=7k@o5`BGq<#+lRCrOA1CaQ!^kKlhsTrZJIH9K_^ryK`_q_#3i5+EIO9achW2 zhLpr@X9L;b@gpA=I!S|AaF48UDwfs-T6Zp!8`{wJvUg?CqyH8|s=drrLSix20jamb zrP3JRD~PP@yO_j1<%2BqSOtouvxrOEOU3;he^6Fx?@JOZg|3?XUWo3*(Ha#V+1j$!k61sdlv~SpmKV48XD?rEHI0qB!<^bOz`&KTmRqe+kV}^cf!#bT&>G1)AQnFuaA9SXR zO>~T6=Ywl@%y^W>^xt9_kNV@0^m3c4B9BMrgfh( zuVp?S>46Ru!ccTe7eieYS*GF0;G*3eAeplXnZCllffvOWA=>i5w+5yH-zgk~ao1dl zs44(@M0}Rt9Mp|iQ#yrKbuAq3msY|P`l$x0E<_Em{7-o?CS$aPMpfmO5T&sTb;r2u H66VBTf3Z^G literal 0 HcmV?d00001 diff --git a/_static/locales/fi/LC_MESSAGES/booktheme.po b/_static/locales/fi/LC_MESSAGES/booktheme.po index c4b0d30..3c3dd08 100644 --- a/_static/locales/fi/LC_MESSAGES/booktheme.po +++ b/_static/locales/fi/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "arkisto" - -msgid "open issue" -msgstr "avoin ongelma" - -msgid "Contents" -msgstr "Sisällys" - -msgid "Fullscreen mode" -msgstr "Koko näytön tila" +msgid "suggest edit" +msgstr "ehdottaa muokkausta" -msgid "Download this page" -msgstr "Lataa tämä sivu" +msgid "Last updated on" +msgstr "Viimeksi päivitetty" -msgid "Download source file" -msgstr "Lataa lähdetiedosto" +msgid "Edit this page" +msgstr "Muokkaa tätä sivua" msgid "Launch" msgstr "Tuoda markkinoille" -msgid "Edit this page" -msgstr "Muokkaa tätä sivua" +msgid "Print to PDF" +msgstr "Tulosta PDF-tiedostoon" + +msgid "open issue" +msgstr "avoin ongelma" + +msgid "Download notebook file" +msgstr "Lataa muistikirjatiedosto" msgid "Toggle navigation" msgstr "Vaihda navigointia" -msgid "Theme by the" -msgstr "Teeman tekijä" - msgid "Source repository" msgstr "Lähteen arkisto" -msgid "Last updated on" -msgstr "Viimeksi päivitetty" - msgid "By the" msgstr "Mukaan" +msgid "next page" +msgstr "seuraava sivu" + +msgid "repository" +msgstr "arkisto" + msgid "Sphinx Book Theme" msgstr "Sphinx-kirjan teema" -msgid "Open an issue" -msgstr "Avaa ongelma" +msgid "Download source file" +msgstr "Lataa lähdetiedosto" -msgid "next page" -msgstr "seuraava sivu" +msgid "Contents" +msgstr "Sisällys" + +msgid "By" +msgstr "Tekijä" msgid "Copyright" msgstr "Tekijänoikeus" -msgid "Search this book..." -msgstr "Hae tästä kirjasta ..." - -msgid "Print to PDF" -msgstr "Tulosta PDF-tiedostoon" +msgid "Fullscreen mode" +msgstr "Koko näytön tila" -msgid "By" -msgstr "Tekijä" +msgid "Open an issue" +msgstr "Avaa ongelma" msgid "previous page" msgstr "Edellinen sivu" -msgid "Search the docs ..." -msgstr "Hae dokumenteista ..." - -msgid "Download notebook file" -msgstr "Lataa muistikirjatiedosto" +msgid "Download this page" +msgstr "Lataa tämä sivu" -msgid "suggest edit" -msgstr "ehdottaa muokkausta" +msgid "Theme by the" +msgstr "Teeman tekijä" diff --git a/_static/locales/fr/LC_MESSAGES/booktheme.mo b/_static/locales/fr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f663d39f0faa76c5b9bd504c51252eef74cca5de GIT binary patch literal 1412 zcmZ{jJ!}+56vv0pm9t{vhm&8^IIO`h6wqyy*798~B-FLeKdo!!~aIl*+ zlr)i&DosjGX-Sm+nxs!ffzqWyh>mpmzuUEJBQe_9-_FOq|NFX^vnPL27*{aoG5^N= z4D;zRyf9{tD}_g$!Rs`57MuYuf@i>a@G^KEoCEvdEO-|@2Qqjbj4hvlV&_NjBk*VN zEI0-~27hn)XS@HRUH=P;-hW^RJaMA={W(z9^Pt$d0saAg1L9Gy@DjZ@;0NGaQ2bFR zmAVF8043f<@DuPZcoBRAia+0jpMpPtqW^1q{u?N9{{>2%|FrAZpu~0hRC7KD%K8iN z5_lUFyPKf+qrt170VU-UgXB+gDSn8C=pG)BP!}*oSBAtdL+nayq9N(OOB9IrIvT`P%K$}>uh8j13v0qZ;CRi75AO3oX*L*$lK06qM@nyU^}?vGk#|? zmL^cG3s$SSi7>stTuW6IGS6&j2uDVy3#y+NH@oiA@h}HB>+f7UZR}>YK)jOup(LluVV6L*Ln| zlGjyt&G}L2k*%l8&|h4l=Cgm((zQMpFVk1~#tn>=qIhM|}`x`)$>jU}ieUbVvBn#nWIG%|r{ z@(VpgvBl*|+YE)ZQEjFj&wG?C)!uDalV>RR`l$A11nWA{5XsPS+9@lOaXon+Y2Ue0 zE>oVUGO*E>4ZSkmuAAH}>yV{N!q_?5zAzp!&O#! TA2+cw{Vw>h7Yg+MtLz81? literal 0 HcmV?d00001 diff --git a/_static/locales/fr/LC_MESSAGES/booktheme.po b/_static/locales/fr/LC_MESSAGES/booktheme.po index 93762ce..b57d2fe 100644 --- a/_static/locales/fr/LC_MESSAGES/booktheme.po +++ b/_static/locales/fr/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "dépôt" - -msgid "open issue" -msgstr "signaler un problème" - -msgid "Contents" -msgstr "Contenu" - -msgid "Fullscreen mode" -msgstr "Mode plein écran" +msgid "suggest edit" +msgstr "suggestion de modification" -msgid "Download this page" -msgstr "Téléchargez cette page" +msgid "Last updated on" +msgstr "Dernière mise à jour le" -msgid "Download source file" -msgstr "Télécharger le fichier source" +msgid "Edit this page" +msgstr "Modifier cette page" msgid "Launch" msgstr "lancement" -msgid "Edit this page" -msgstr "Modifier cette page" +msgid "Print to PDF" +msgstr "Imprimer au format PDF" + +msgid "open issue" +msgstr "signaler un problème" + +msgid "Download notebook file" +msgstr "Télécharger le fichier notebook" msgid "Toggle navigation" msgstr "Basculer la navigation" -msgid "Theme by the" -msgstr "Thème par le" - msgid "Source repository" msgstr "Dépôt source" -msgid "Last updated on" -msgstr "Dernière mise à jour le" - msgid "By the" msgstr "Par le" +msgid "next page" +msgstr "page suivante" + +msgid "repository" +msgstr "dépôt" + msgid "Sphinx Book Theme" msgstr "Thème du livre Sphinx" -msgid "Open an issue" -msgstr "Ouvrez un problème" +msgid "Download source file" +msgstr "Télécharger le fichier source" -msgid "next page" -msgstr "page suivante" +msgid "Contents" +msgstr "Contenu" + +msgid "By" +msgstr "Par" msgid "Copyright" msgstr "droits d'auteur" -msgid "Search this book..." -msgstr "Rechercher dans ce livre ..." - -msgid "Print to PDF" -msgstr "Imprimer au format PDF" +msgid "Fullscreen mode" +msgstr "Mode plein écran" -msgid "By" -msgstr "Par" +msgid "Open an issue" +msgstr "Ouvrez un problème" msgid "previous page" msgstr "page précédente" -msgid "Search the docs ..." -msgstr "Rechercher dans les documents ..." - -msgid "Download notebook file" -msgstr "Télécharger le fichier notebook" +msgid "Download this page" +msgstr "Téléchargez cette page" -msgid "suggest edit" -msgstr "suggestion de modification" +msgid "Theme by the" +msgstr "Thème par le" diff --git a/_static/locales/hr/LC_MESSAGES/booktheme.mo b/_static/locales/hr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..eca4a1a2842830f06bd5f6235bf01d07bdd313d2 GIT binary patch literal 1402 zcmZ9KJ!~9B6vu}+kmLvh)-Bbu!YZ&sL*)#Wq0oOW>)iY z#I7UJKoJQlD$3MIh{}~uqNJdrprN2bqC$d-|Jz;1r;K*?xAU?8_kVBZ_tmrCDzsP8 z*U*1Oe;xg+XYfKhe?}=h>H=QRffvE^;1%!!xCXugz6HJv4#8FMQ}7bV;EQ1F_z)DG zZ@?G8@4$=TWAG*L$BsXD^S^cDKS7E2FW3WDR@(nBfihkLMdxksC-6Fmt?DmO{`(sg z-~WN)YvpX4?<)8j#_OQu@i8cQeBP}`P-^oC6rIQ5W$*{^dGHvNe1GZqM>qcuD0MvZ zY`gv@DF5B)#v@RCe+FI!b5KeyIf$NkxPmU8B<^y9bfYDCNE01tQa`D+)KxSg*?1KH z%T4MpwK#{4ax`^Pw+`@7ELnZzY-Ae)KI#K+iZZI(?h9Kvos)Hu_nn*4eN*x2ba2UM z{M2MDO`uvAtTuBKA$>9&rK$>r--+ODxdTQVUeRy*EU zh&bB0JyN@EJkPZYCOUthcI(pE2XsrkjZ2=fYTmTp<}`LiQ88IPH-(M{K`cLrtve@i z+90*(xpAqpy(Aw}Q7~LGGJzF0;VkyI^8P*c0crzk0e zJ5}W`eCg#p>R8HV8p8`ORd-?8+@kgmPE(NjB4ZRZpsbXo1{+%JywM17c0!7$ZS zdp+04j?>}H5RL>u+?)6`B(!QC;nQ(E%YYHwOi5)9EgF2Tundr{ymsm2Z;f2mKh k(#nYgw(f}olqHrfw@Z7L48TfWxy6y8Q4`jSBkXa^hFIaGO(a}_Drr&ngPIpyPhwkKtCW1zS zxtWoenhB;xBBn-yn24D8zwTalu&Ao9Uv<5s{`Yli#|wdR9BT&a6V_?0r`xb$Ol}tf zQ|!UE3)}}zg45t0a0WaEo&}G9U2qD#3myOoJP3w{Pe6|I9NZ7S1owfj!NcI&h98>q z&yD>JoIl_+xD%H+@5zQ2!9%dS z4R3=dU_S)+f*T;`dD8G1$o{WD_Im?z{P&Ih5#&5yK-S?0$ohz#wGPuD`<((=a*oaa zSxfd~Z8_ffK#0nR_2t3u=fQPw4%YQ37D84vb8p87>(4#hjm4TkQX%F>m@;G}=B){2 zg2zWWayrd|Sg?;xZdD?U4b-=GDA#mOTgTo;H=zFxL#DkfRZ3zp(E*`1&83*aj(wjsI*=O>qg>UnQ5~j z=eV|BMg@s#m;L%pJ)5RENuwU=R0WMBhBiW7o#i}rlG4#5ZDUjRSa=`Plu#w%B`C$N z(;&2$llB909??3o&fn(z?J9F?WqD;KhDS6Yp*?cS)QjtnT^a+xb_X5}DL&Qs{# z?=7`&Y~6Fp_%(9vMKiF8HfcxR=o0auv z_q>s3y7KCU*_ODI6J+IW*=v!hp&aNkC~@B;F{`@wufgMIJ{Em)%}J(mRd82~uKPNE zu!45VT#b~I5H)6^M@|hh?PQ`$a((5ZmR_kKRwzf4qZ=wC=HgJvLU}~a#5@JmHKeM~ zcQ+dhueyjH6-vS(Hi{zy4lKXvX09`YYnog=urAe8uFQH2W~4-u2I{*$(n5sIJAG7C T@Rc+s5Lgrh10CRyRonjp5+F85 literal 0 HcmV?d00001 diff --git a/_static/locales/id/LC_MESSAGES/booktheme.po b/_static/locales/id/LC_MESSAGES/booktheme.po index fbeca80..5db2ae1 100644 --- a/_static/locales/id/LC_MESSAGES/booktheme.po +++ b/_static/locales/id/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: id\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "gudang" - -msgid "open issue" -msgstr "masalah terbuka" - -msgid "Contents" -msgstr "Isi" - -msgid "Fullscreen mode" -msgstr "Mode layar penuh" +msgid "suggest edit" +msgstr "menyarankan edit" -msgid "Download this page" -msgstr "Unduh halaman ini" +msgid "Last updated on" +msgstr "Terakhir diperbarui saat" -msgid "Download source file" -msgstr "Unduh file sumber" +msgid "Edit this page" +msgstr "Edit halaman ini" msgid "Launch" msgstr "Meluncurkan" -msgid "Edit this page" -msgstr "Edit halaman ini" +msgid "Print to PDF" +msgstr "Cetak ke PDF" + +msgid "open issue" +msgstr "masalah terbuka" + +msgid "Download notebook file" +msgstr "Unduh file notebook" msgid "Toggle navigation" msgstr "Alihkan navigasi" -msgid "Theme by the" -msgstr "Tema oleh" - msgid "Source repository" msgstr "Repositori sumber" -msgid "Last updated on" -msgstr "Terakhir diperbarui saat" - msgid "By the" msgstr "Oleh" +msgid "next page" +msgstr "halaman selanjutnya" + +msgid "repository" +msgstr "gudang" + msgid "Sphinx Book Theme" msgstr "Tema Buku Sphinx" -msgid "Open an issue" -msgstr "Buka masalah" +msgid "Download source file" +msgstr "Unduh file sumber" -msgid "next page" -msgstr "halaman selanjutnya" +msgid "Contents" +msgstr "Isi" + +msgid "By" +msgstr "Oleh" msgid "Copyright" msgstr "hak cipta" -msgid "Search this book..." -msgstr "Telusuri buku ini ..." - -msgid "Print to PDF" -msgstr "Cetak ke PDF" +msgid "Fullscreen mode" +msgstr "Mode layar penuh" -msgid "By" -msgstr "Oleh" +msgid "Open an issue" +msgstr "Buka masalah" msgid "previous page" msgstr "halaman sebelumnya" -msgid "Search the docs ..." -msgstr "Telusuri dokumen ..." - -msgid "Download notebook file" -msgstr "Unduh file notebook" +msgid "Download this page" +msgstr "Unduh halaman ini" -msgid "suggest edit" -msgstr "menyarankan edit" +msgid "Theme by the" +msgstr "Tema oleh" diff --git a/_static/locales/it/LC_MESSAGES/booktheme.mo b/_static/locales/it/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..53ba476edd2df2a802917e9df402257ceca1a130 GIT binary patch literal 1403 zcmZXSJ&aXF6vsyafhY1QYQiQS8W$5EU!j1vc?Gb$351Os-eM!oynD~ycVOPkWoGWm zTH9#}m5qrNiM6q@vN55xvLLatGO@6+(D*<1-gP%Hxii0e=Htvc|2Z#C?tf~~-bG(P z{{{Vh^sipSfOhD0WAK^77~TMnfQP_S;9+n9db5tC&9bmQINr7VD9+^sD7S+ zZ-HNfN5E&`3Gn-#Klk&$_V(|f-uE{+0Qc?d&L0KUUI5k4BKQM%1;keK2Z+!7i9yf* z1s(_g1vTGe`;B=I{0KY^u7H})r~P~cRhutC&HGzW&wmGM{6B(v?m2h{{0%$^{sW!` z4;<+7S_JjnwcfrBYTWn1Q(y(ER@tjRN(zMHIBUF`R@^(uqn+2D6ew@4L zg5J|zQb*pB(DY&Nai5y1VnoTv1fhfnT;$=ca`*|y1aBki?jP#?!}jLE+O4&f-Stc7 zFAjQPha1~9k0>L63$?T2m#CQ8m^hE`ZLAKj?(U1$r%jH-6<>r>d^Mu0Q^|un)>jR5 z9TALm*F@`vt0B(QhBFUgSr)TwUH`yMh9yxlG%Xix0~y&& z3LB-cB(8l-D%nxCMbU^4uPmkzD-_D^sYeYovZ|_hYt|6+raF6N+B(TUeM703ahwOj z!*UGfp34HuR+WV4?HsPL=1>m45R2fh*HNhPRL3xNJhx_&?Yu^?zAcKo|5pQ*LIIU4 z9%X=yZ5mFd5t*`cmL{7}b7xJ=^_*qP(gmDLw)@AXu2??D^RnquqSO=xr-aR>O-k3u a)*Q3l*@6-(xNK#4xqhOgLbT*tS;gN$Zm<*V0gr*F!6RT6JPeM4`#}XB0Byp@Am^!p`@mOV z7q|)@0zW4Fn)rVt_HU5uZGb6o$Bx$f{UF;tAm=#)eg-dtd%-^-*V_PDx7aDf37`|? zeoukD;5CqS=MqLB_wxkgxVgmt1?-0X4dj{qO1J@X+@W2qe$Rs(cQvs`6FUcTpOYZ# zd6M|6Adj4TU>#hW-}7v_@AidK;vhE9mlyZXi}UiVd9FvXkushE>ug^<53aoj8)J$8 zzT$crKWU3f+%VcIZ9^RVa^Sf|D{h)8T{2EVYGYN-m<~=w|xXST6$p^DKQdw8cB>C zxj87tTJ-|uo6xf+D2p+_=;?>@I%^v*stG0HugtZ28aJ+6Qc^pUp6gf-MYMWoTj~tg zX%+DUHR+isk=>R)j9gbir9vl=V(zQFO%D~)cU2G~TSm6(r@4MQuACYk8XnlX?>m1n zl?*mLUiMW+S_rt{mmE*`%Y4xZLS?ge#s||^w&DUuhxb&F9?*GH@U)weS8|?B-Ey=W zVXhhJO{GRkQQ(x)gC>{=GgAAp8D=l_%hoY_R?FV3>^s+=67+^$;pPAU literal 0 HcmV?d00001 diff --git a/_static/locales/iw/LC_MESSAGES/booktheme.po b/_static/locales/iw/LC_MESSAGES/booktheme.po index a2a09f0..32b017c 100644 --- a/_static/locales/iw/LC_MESSAGES/booktheme.po +++ b/_static/locales/iw/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: iw\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "מאגר" - -msgid "open issue" -msgstr "בעיה פתוחה" - -msgid "Contents" -msgstr "תוכן" - -msgid "Fullscreen mode" -msgstr "מצב מסך מלא" +msgid "suggest edit" +msgstr "מציע לערוך" -msgid "Download this page" -msgstr "הורד דף זה" +msgid "Last updated on" +msgstr "עודכן לאחרונה ב" -msgid "Download source file" -msgstr "הורד את קובץ המקור" +msgid "Edit this page" +msgstr "ערוך דף זה" msgid "Launch" msgstr "לְהַשִׁיק" -msgid "Edit this page" -msgstr "ערוך דף זה" +msgid "Print to PDF" +msgstr "הדפס לקובץ PDF" + +msgid "open issue" +msgstr "בעיה פתוחה" + +msgid "Download notebook file" +msgstr "הורד קובץ מחברת" msgid "Toggle navigation" msgstr "החלף ניווט" -msgid "Theme by the" -msgstr "נושא מאת" - msgid "Source repository" msgstr "מאגר המקורות" -msgid "Last updated on" -msgstr "עודכן לאחרונה ב" - msgid "By the" msgstr "דרך" +msgid "next page" +msgstr "עמוד הבא" + +msgid "repository" +msgstr "מאגר" + msgid "Sphinx Book Theme" msgstr "נושא ספר ספינקס" -msgid "Open an issue" -msgstr "פתח גיליון" +msgid "Download source file" +msgstr "הורד את קובץ המקור" -msgid "next page" -msgstr "עמוד הבא" +msgid "Contents" +msgstr "תוכן" + +msgid "By" +msgstr "על ידי" msgid "Copyright" msgstr "זכויות יוצרים" -msgid "Search this book..." -msgstr "חפש בספר זה ..." - -msgid "Print to PDF" -msgstr "הדפס לקובץ PDF" +msgid "Fullscreen mode" +msgstr "מצב מסך מלא" -msgid "By" -msgstr "על ידי" +msgid "Open an issue" +msgstr "פתח גיליון" msgid "previous page" msgstr "עמוד קודם" -msgid "Search the docs ..." -msgstr "חפש במסמכים ..." - -msgid "Download notebook file" -msgstr "הורד קובץ מחברת" +msgid "Download this page" +msgstr "הורד דף זה" -msgid "suggest edit" -msgstr "מציע לערוך" +msgid "Theme by the" +msgstr "נושא מאת" diff --git a/_static/locales/ja/LC_MESSAGES/booktheme.mo b/_static/locales/ja/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..1cefd29ce3cc08792667a82dc7ff47e9843107be GIT binary patch literal 1471 zcma))U2GIp6vr=uT2=%temyktnh+I|RZ$+uHv1sbO-LX%QhlH9-p&qe?;Yo((zoth z!EFJNkCxzqu~zx0SU`c+ubA-Uv++eAe7Tv~_Q5w};+y|7GulOC;?11-%{lkn^L6K! z-gVOq>v2dQu6IDn_Xk)2*RIXZZv;v211Zik;1ak4q&&ao z_TO@S&AKd35BL)Hd%6F@2|fYNfYiq|km|n!QoJ8>{U?y}t$^hJJGcehbZ=(g z0h0bQNasgDiZ_<)lR3|UkHUThq>)oh@}pU9hR|%O@9u?E>>&uvmlpL;i{?kUXs#3! zA=v{Ey4&tWeb61=55ZW{`(?Yv@$jH7*egl~LIyrQ+;Pvb>jB%X-jWSv)wooF7*^^a zA8{ID)$FU#tBQXZgSz8$*Rlm0s5t>b|D{&KM#HaqLP$QUYJ%;x{D6mU%?d<~D+xW6 z)jE6Cg@Yxz75=BO|)yDPjO+O|NI0-c}~bwE^u;+|UZ4dMBS zR^nOyBIPfpnG5^&>>F6!-~QYSg?zBZp>bD~cz^<)cN>-?`+2o)dAX*25Q`IlO*w3@i^0SgZ zRp#5b_7~Xl$+OE7hnZ=9YND2D&Y9*#)@d&!S7*EK+UR$U{>JE*(KAMC6J0ZU+C;M^ z`q*e3JZ1ERi7p!bh0&j-o|DW(-_lp~<^OPPo;J+|qu);tEd58ke>rs)FR!$Zu=w!h z&Y7=QE_`G(9#lEWlJgUtTT#-!nao^I&VIs{Z!N}0r&&CGVrBLi!p9%ph)+&2{5I%2 zK7KuJEq2#CZ}bHdEv5a=V6`%k-R^d(Xw}Jf>8QN5e!h zBbA`3bkQ)WS=dVKSy@;~B<{I88!P_b+$$|{a=-hV^ZNe(@4NG5)%+^MSdZvHd_rtS zROaA?v3M?Hcvu@=3&Ew}VsJIs26lk!z^&jKFbl2%PlD~B0GES0VHu=655Q&M6L2Xw z0j>n66Mjh6KPU5VAnE-CQ{cRL@%?s?<{cpA*#_Ef2kG3A zWc>t4Ehi1?A9+}fAZZd{dqh6EFS_D$EB?$Vqvj_EszTqMS+R^&H z>|hBG*9E~2DXE3jK7P0*&#?=d9aa}*QCWE|l@|R-n>7qsZZHEJ ziA7vbTyRv7*q)W%4{Te&r9dUHqRxq&PWR-~XN2b?TZYH_Y0^)(lvBrgj&;rK@7cLK zl{7ZpS8_#$YZ%z&7A;41@?634e4(?a`?}KyX3lw*^v?<}-6eA>??^kt5A-`ab<~n} zfWBto^Y9)w_0g!> zVBythE}X>$!Q{z_su`ZeFjL;phL~syBFa zXVlaiX8iI$xBl9S?ljH#2qeqqHLg5*5Kc5=W8s^|_vRD}$A^$29KXrU!@=^_j5Dv6%;4cA#sHtggl>eA))${_687xQDk?6`Kc@OWFO}WOS!3uO( zjPOmFMc3|`Ymgi(M~_AsRb8*l6oj5N!k1G#oNSsg^a1i?<=NZRz?N8C9`e*ob%^~2 D6Q!<* literal 0 HcmV?d00001 diff --git a/_static/locales/ko/LC_MESSAGES/booktheme.po b/_static/locales/ko/LC_MESSAGES/booktheme.po index 8c19ab6..69dd18f 100644 --- a/_static/locales/ko/LC_MESSAGES/booktheme.po +++ b/_static/locales/ko/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: ko\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "저장소" - -msgid "open issue" -msgstr "열린 문제" - -msgid "Contents" -msgstr "내용" - -msgid "Fullscreen mode" -msgstr "전체 화면으로보기" +msgid "suggest edit" +msgstr "편집 제안" -msgid "Download this page" -msgstr "이 페이지 다운로드" +msgid "Last updated on" +msgstr "마지막 업데이트" -msgid "Download source file" -msgstr "소스 파일 다운로드" +msgid "Edit this page" +msgstr "이 페이지 편집" msgid "Launch" msgstr "시작하다" -msgid "Edit this page" -msgstr "이 페이지 편집" +msgid "Print to PDF" +msgstr "PDF로 인쇄" + +msgid "open issue" +msgstr "열린 문제" + +msgid "Download notebook file" +msgstr "노트북 파일 다운로드" msgid "Toggle navigation" msgstr "탐색 전환" -msgid "Theme by the" -msgstr "테마별" - msgid "Source repository" msgstr "소스 저장소" -msgid "Last updated on" -msgstr "마지막 업데이트" - msgid "By the" msgstr "에 의해" +msgid "next page" +msgstr "다음 페이지" + +msgid "repository" +msgstr "저장소" + msgid "Sphinx Book Theme" msgstr "스핑크스 도서 테마" -msgid "Open an issue" -msgstr "이슈 열기" +msgid "Download source file" +msgstr "소스 파일 다운로드" -msgid "next page" -msgstr "다음 페이지" +msgid "Contents" +msgstr "내용" + +msgid "By" +msgstr "으로" msgid "Copyright" msgstr "저작권" -msgid "Search this book..." -msgstr "이 책 검색 ..." - -msgid "Print to PDF" -msgstr "PDF로 인쇄" +msgid "Fullscreen mode" +msgstr "전체 화면으로보기" -msgid "By" -msgstr "으로" +msgid "Open an issue" +msgstr "이슈 열기" msgid "previous page" msgstr "이전 페이지" -msgid "Search the docs ..." -msgstr "문서 검색 ..." - -msgid "Download notebook file" -msgstr "노트북 파일 다운로드" +msgid "Download this page" +msgstr "이 페이지 다운로드" -msgid "suggest edit" -msgstr "편집 제안" +msgid "Theme by the" +msgstr "테마별" diff --git a/_static/locales/lt/LC_MESSAGES/booktheme.mo b/_static/locales/lt/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..4468ba04bc134a84fea5e3c973461cf02c9c2da3 GIT binary patch literal 1413 zcmZvaJ*-qk6vsyag_RElKVp1=p+SgQ1!6(=Ws8Trm%IpJ!!Cq&-rn=>&feLX$$UJx zy>yfs3mYDtv7j(9R@&?)#@fol&{Y(AbXL(_rUwj`9qL(er@8vgIw=pko$cKo&XOVSm=ES z^8O^qK3oL({z?6$1#4Nz2(054oJ;=;JiGzE*_kpy=GszcBB+< zVRAov2m8<3><4U^|G(mLjYp;ti7%W@WK+ZsUk6=|lDOjTSmRV7txL4wTqQTPq1|wF zISlEQU>fNty(&qp7CIsI&UP&u6NiDw%84sTTvaj2>KHSL zUeFdvoa|j$6a9r=An&41F4Us$N7~+%m$|mVh$bZFtK3-hG;n2UNLsa}OO-T4EZt3u z>KyAVM0}tv?Q&E0p7b%7C80_}Cn&{@X_(sUMf(ENwtj7O_x!@A z=Ua`j?LqCSBNGbv%p0ZcvK)?7h?KfF2W#z1yZ3^!ag#!O)ec>uZP}5RHgsxTRkqCV zwIfYx^-K=RwAWmi#E!InzKz|B%X0Cvd)CU+U3uZ$a!agNntg;f8E)25tYny{XFsAC z9jD(SkfM$V#H6LA*|v6LHF0AnD>v~vCkoohO{LBB-b;69+sY(u|L3sMiR5g1`bhd5 zjq=k+;szC}%nlMS$9vjXC#gc)P6nF&q9-bfo{CjQZe*xbNYi^#C9ConpM%1oLFKH0 za&)0WJ=gQWZ5W!M$i7!O!aIl|0e?HQ2Ro%kmCL#^O7u6its3{(8W!QLNCjg(=>2Jsvw ClWZvf literal 0 HcmV?d00001 diff --git a/_static/locales/lt/LC_MESSAGES/booktheme.po b/_static/locales/lt/LC_MESSAGES/booktheme.po index 368967f..9f03775 100644 --- a/_static/locales/lt/LC_MESSAGES/booktheme.po +++ b/_static/locales/lt/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: lt\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "saugykla" - -msgid "open issue" -msgstr "atviras klausimas" - -msgid "Contents" -msgstr "Turinys" - -msgid "Fullscreen mode" -msgstr "Pilno ekrano režimas" +msgid "suggest edit" +msgstr "pasiūlyti redaguoti" -msgid "Download this page" -msgstr "Atsisiųskite šį puslapį" +msgid "Last updated on" +msgstr "Paskutinį kartą atnaujinta" -msgid "Download source file" -msgstr "Atsisiųsti šaltinio failą" +msgid "Edit this page" +msgstr "Redaguoti šį puslapį" msgid "Launch" msgstr "Paleiskite" -msgid "Edit this page" -msgstr "Redaguoti šį puslapį" +msgid "Print to PDF" +msgstr "Spausdinti į PDF" + +msgid "open issue" +msgstr "atviras klausimas" + +msgid "Download notebook file" +msgstr "Atsisiųsti nešiojamojo kompiuterio failą" msgid "Toggle navigation" msgstr "Perjungti naršymą" -msgid "Theme by the" -msgstr "Tema" - msgid "Source repository" msgstr "Šaltinio saugykla" -msgid "Last updated on" -msgstr "Paskutinį kartą atnaujinta" - msgid "By the" msgstr "Prie" +msgid "next page" +msgstr "Kitas puslapis" + +msgid "repository" +msgstr "saugykla" + msgid "Sphinx Book Theme" msgstr "Sfinkso knygos tema" -msgid "Open an issue" -msgstr "Atidarykite problemą" +msgid "Download source file" +msgstr "Atsisiųsti šaltinio failą" -msgid "next page" -msgstr "Kitas puslapis" +msgid "Contents" +msgstr "Turinys" + +msgid "By" +msgstr "Iki" msgid "Copyright" msgstr "Autorių teisės" -msgid "Search this book..." -msgstr "Ieškoti šioje knygoje ..." - -msgid "Print to PDF" -msgstr "Spausdinti į PDF" +msgid "Fullscreen mode" +msgstr "Pilno ekrano režimas" -msgid "By" -msgstr "Iki" +msgid "Open an issue" +msgstr "Atidarykite problemą" msgid "previous page" msgstr "Ankstesnis puslapis" -msgid "Search the docs ..." -msgstr "Ieškoti dokumentuose ..." - -msgid "Download notebook file" -msgstr "Atsisiųsti nešiojamojo kompiuterio failą" +msgid "Download this page" +msgstr "Atsisiųskite šį puslapį" -msgid "suggest edit" -msgstr "pasiūlyti redaguoti" +msgid "Theme by the" +msgstr "Tema" diff --git a/_static/locales/lv/LC_MESSAGES/booktheme.mo b/_static/locales/lv/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..74aa4d8985d96a07c4c9be96f006f3b58d884342 GIT binary patch literal 1404 zcmZ9K&5ImG7{*_dsL7ZQP5eMvump*E7&XB|oMjFhcNYS?IAk~8Yi8c*sqUVtras2( zdKwT<9)#7Cr{GC*^B|r)^?-kXCk3y9;7t%O;`2^-vdb1-{p+f(exK)k=-;oN`-(7L z!d%1r1@l$R&!4~zPs;uHG2 zUH=1$um8Z;!As|eUIA~m+y%w|6qJ5G0bd5c0G|fGYu|qlzJT=-lzP8`lHs4A_&D=q zlgkxQ>Rkt~f$z861tmufO5Zssk;}JoUbN-BWGj829FU-AF-2E~^e;o|NY;|8ctc5g z22*^U9FmJ@OFxKVl@HxMz@_4p=>umY+Zgar9e9&XBW=2mZRzw_Sr>WeT%jhWmHkCxl1EW^k%TQzfIrX3xkO4V3L9xG?DPIfe<4=WtdR+$hI z)4&^xB2Eo9w`s4@^IW-LqVor|S51w*uWpOC{VC6wR(CaQdfIncRMGG) zBv*eURUdB+Oli45Wvi9v9Ia6vne84ZIht?0o$f< A2mk;8 literal 0 HcmV?d00001 diff --git a/_static/locales/lv/LC_MESSAGES/booktheme.po b/_static/locales/lv/LC_MESSAGES/booktheme.po index 066fa4e..c9633b5 100644 --- a/_static/locales/lv/LC_MESSAGES/booktheme.po +++ b/_static/locales/lv/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: lv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "krātuve" - -msgid "open issue" -msgstr "atklāts jautājums" - -msgid "Contents" -msgstr "Saturs" - -msgid "Fullscreen mode" -msgstr "Pilnekrāna režīms" +msgid "suggest edit" +msgstr "ieteikt rediģēt" -msgid "Download this page" -msgstr "Lejupielādējiet šo lapu" +msgid "Last updated on" +msgstr "Pēdējoreiz atjaunināts" -msgid "Download source file" -msgstr "Lejupielādēt avota failu" +msgid "Edit this page" +msgstr "Rediģēt šo lapu" msgid "Launch" msgstr "Uzsākt" -msgid "Edit this page" -msgstr "Rediģēt šo lapu" +msgid "Print to PDF" +msgstr "Drukāt PDF formātā" + +msgid "open issue" +msgstr "atklāts jautājums" + +msgid "Download notebook file" +msgstr "Lejupielādēt piezīmju grāmatiņu" msgid "Toggle navigation" msgstr "Pārslēgt navigāciju" -msgid "Theme by the" -msgstr "Autora tēma" - msgid "Source repository" msgstr "Avota krātuve" -msgid "Last updated on" -msgstr "Pēdējoreiz atjaunināts" - msgid "By the" msgstr "Ar" +msgid "next page" +msgstr "nākamā lapaspuse" + +msgid "repository" +msgstr "krātuve" + msgid "Sphinx Book Theme" msgstr "Sfinksa grāmatas tēma" -msgid "Open an issue" -msgstr "Atveriet problēmu" +msgid "Download source file" +msgstr "Lejupielādēt avota failu" -msgid "next page" -msgstr "nākamā lapaspuse" +msgid "Contents" +msgstr "Saturs" + +msgid "By" +msgstr "Autors" msgid "Copyright" msgstr "Autortiesības" -msgid "Search this book..." -msgstr "Meklēt šajā grāmatā ..." - -msgid "Print to PDF" -msgstr "Drukāt PDF formātā" +msgid "Fullscreen mode" +msgstr "Pilnekrāna režīms" -msgid "By" -msgstr "Autors" +msgid "Open an issue" +msgstr "Atveriet problēmu" msgid "previous page" msgstr "iepriekšējā lapa" -msgid "Search the docs ..." -msgstr "Meklēt dokumentos ..." - -msgid "Download notebook file" -msgstr "Lejupielādēt piezīmju grāmatiņu" +msgid "Download this page" +msgstr "Lejupielādējiet šo lapu" -msgid "suggest edit" -msgstr "ieteikt rediģēt" +msgid "Theme by the" +msgstr "Autora tēma" diff --git a/_static/locales/ml/LC_MESSAGES/booktheme.mo b/_static/locales/ml/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..2736e8fcf6f9e923c2403307f0b366086d37b335 GIT binary patch literal 1883 zcmbW0%ZnUE9LGydG>*^22ObnFl0!U=*`!Gj=35eWDu@Vn6%SYIC#v~L=<+PV8oUUd{}t%`e}*gYclZSS_^!ZZxSjb`_!_(p zTd=uFh;ewl;wqeG{x{qKTbqR#gE5?hpTno&U(oq&;Si6(7JLc50p0#-xD$R4pMlrl zez^G_At=eHx!OEj&F+K95`^|`3%xs|tB0$dYp$lQaXj&eABB3jp*ug}eRDN&btbLg zC_?O6*AzH~{-A|&9)JdV{ljJRVAnvQRl4{_?&D7b7KD1k z&HJ`jzT)e&M4gbqlB?mhqaXMpAZg<;-hlh5ZiX1=e36nUswzgb&SN${bnp4Gv=IQ6$P05hgaiFop^2w W+5FkQ^s?wV7=JSkIl3Km4aE({iDO&< literal 0 HcmV?d00001 diff --git a/_static/locales/ml/LC_MESSAGES/booktheme.po b/_static/locales/ml/LC_MESSAGES/booktheme.po index 2b0fd76..9a6a41e 100644 --- a/_static/locales/ml/LC_MESSAGES/booktheme.po +++ b/_static/locales/ml/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: ml\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "തുറന്ന പ്രശ്നം" +msgid "suggest edit" +msgstr "എഡിറ്റുചെയ്യാൻ നിർദ്ദേശിക്കുക" -msgid "Download this page" -msgstr "ഈ പേജ് ഡൗൺലോഡുചെയ്യുക" +msgid "Last updated on" +msgstr "അവസാനം അപ്‌ഡേറ്റുചെയ്‌തത്" -msgid "Download source file" -msgstr "ഉറവിട ഫയൽ ഡൗൺലോഡുചെയ്യുക" +msgid "Edit this page" +msgstr "ഈ പേജ് എഡിറ്റുചെയ്യുക" msgid "Launch" msgstr "സമാരംഭിക്കുക" -msgid "Edit this page" -msgstr "ഈ പേജ് എഡിറ്റുചെയ്യുക" +msgid "Print to PDF" +msgstr "PDF- ലേക്ക് പ്രിന്റുചെയ്യുക" + +msgid "open issue" +msgstr "തുറന്ന പ്രശ്നം" + +msgid "Download notebook file" +msgstr "നോട്ട്ബുക്ക് ഫയൽ ഡൺലോഡ് ചെയ്യുക" msgid "Toggle navigation" msgstr "നാവിഗേഷൻ ടോഗിൾ ചെയ്യുക" -msgid "Theme by the" -msgstr "പ്രമേയം" - msgid "Source repository" msgstr "ഉറവിട ശേഖരം" -msgid "Last updated on" -msgstr "അവസാനം അപ്‌ഡേറ്റുചെയ്‌തത്" - msgid "By the" msgstr "എഴുതിയത്" +msgid "next page" +msgstr "അടുത്ത പേജ്" + msgid "Sphinx Book Theme" msgstr "സ്ഫിങ്ക്സ് പുസ്തക തീം" -msgid "Open an issue" -msgstr "ഒരു പ്രശ്നം തുറക്കുക" +msgid "Download source file" +msgstr "ഉറവിട ഫയൽ ഡൗൺലോഡുചെയ്യുക" -msgid "next page" -msgstr "അടുത്ത പേജ്" +msgid "By" +msgstr "എഴുതിയത്" msgid "Copyright" msgstr "പകർപ്പവകാശം" -msgid "Search this book..." -msgstr "ഈ പുസ്തകം തിരയുക ..." - -msgid "Print to PDF" -msgstr "PDF- ലേക്ക് പ്രിന്റുചെയ്യുക" - -msgid "By" -msgstr "എഴുതിയത്" +msgid "Open an issue" +msgstr "ഒരു പ്രശ്നം തുറക്കുക" msgid "previous page" msgstr "മുൻപത്തെ താൾ" -msgid "Download notebook file" -msgstr "നോട്ട്ബുക്ക് ഫയൽ ഡൺലോഡ് ചെയ്യുക" +msgid "Download this page" +msgstr "ഈ പേജ് ഡൗൺലോഡുചെയ്യുക" -msgid "suggest edit" -msgstr "എഡിറ്റുചെയ്യാൻ നിർദ്ദേശിക്കുക" +msgid "Theme by the" +msgstr "പ്രമേയം" diff --git a/_static/locales/mr/LC_MESSAGES/booktheme.mo b/_static/locales/mr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..fe530100d7715cdc19a6f9db33a971665835f3c4 GIT binary patch literal 1674 zcma))-D_M$7>7rVU#qnriYO?KB2uYGt)hetL1>ylCBZ;a@uD{;yVJ8rH#3KG&bG~6 zRisua;ze5NO^wW!;71IF+EldSwKo+61wrPsjrLTQ<5nO9X$iPPmDi?R5_3f- z*T>{OU(0+)Eh-V7av_#JZ?debq)w0ISz70aXmzZP)flf6MT$}#$xUxiX4T6wMQMt1 z(Km0ZR-GJZC$ForB1Kb1(Zq`;L9Q`#U}kc-zxUba8xuy?O4rH!QlXl%M)kR(o922< zwmNB9se1h2{8TbJJXfZ=I;_fMQnySy*I84JF64D%I@MVZ^O|z8Y|M6hW!g=qOu1M! zr7ps>8h>F-#@F%PT0TB5_dY$=5YC=={Zr0fboPp~>pX9~wCwsPo&DVPkH=Hao^bXY zXIEYSL*AVI()HhVc3C?6MacEOvlp1GgbA^$%){9gR+l%mHiEnj&-JixH&Y;SGbt{+ z{t03z?p+g;%KlU0jXnJ;6hm+E zO4d<`2T4o{Hn?Oyg$)#jm)Q^UYaHJCp>S-t$!CBi7ej)}A>Wy>@(p%y@Lc$O&cyp1 zdP#?v^I4GaH+|g|B8k!Ldl%Wfwrg(}`)i>kl#a*D@zz$^*>a1%2AcIZ5x;fu4@Sqm A6951J literal 0 HcmV?d00001 diff --git a/_static/locales/mr/LC_MESSAGES/booktheme.po b/_static/locales/mr/LC_MESSAGES/booktheme.po index 51d011f..ef72d8c 100644 --- a/_static/locales/mr/LC_MESSAGES/booktheme.po +++ b/_static/locales/mr/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: mr\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "खुला मुद्दा" +msgid "suggest edit" +msgstr "संपादन सुचवा" -msgid "Download this page" -msgstr "हे पृष्ठ डाउनलोड करा" +msgid "Last updated on" +msgstr "अखेरचे अद्यतनित" -msgid "Download source file" -msgstr "स्त्रोत फाइल डाउनलोड करा" +msgid "Edit this page" +msgstr "हे पृष्ठ संपादित करा" msgid "Launch" msgstr "लाँच करा" -msgid "Edit this page" -msgstr "हे पृष्ठ संपादित करा" +msgid "Print to PDF" +msgstr "पीडीएफवर मुद्रित करा" + +msgid "open issue" +msgstr "खुला मुद्दा" + +msgid "Download notebook file" +msgstr "नोटबुक फाईल डाउनलोड करा" msgid "Toggle navigation" msgstr "नेव्हिगेशन टॉगल करा" -msgid "Theme by the" -msgstr "द्वारा थीम" - msgid "Source repository" msgstr "स्त्रोत भांडार" -msgid "Last updated on" -msgstr "अखेरचे अद्यतनित" - msgid "By the" msgstr "द्वारा" +msgid "next page" +msgstr "पुढील पृष्ठ" + msgid "Sphinx Book Theme" msgstr "स्फिंक्स बुक थीम" -msgid "Open an issue" -msgstr "एक मुद्दा उघडा" +msgid "Download source file" +msgstr "स्त्रोत फाइल डाउनलोड करा" -msgid "next page" -msgstr "पुढील पृष्ठ" +msgid "By" +msgstr "द्वारा" msgid "Copyright" msgstr "कॉपीराइट" -msgid "Search this book..." -msgstr "हे पुस्तक शोधा ..." - -msgid "Print to PDF" -msgstr "पीडीएफवर मुद्रित करा" - -msgid "By" -msgstr "द्वारा" +msgid "Open an issue" +msgstr "एक मुद्दा उघडा" msgid "previous page" msgstr "मागील पान" -msgid "Download notebook file" -msgstr "नोटबुक फाईल डाउनलोड करा" +msgid "Download this page" +msgstr "हे पृष्ठ डाउनलोड करा" -msgid "suggest edit" -msgstr "संपादन सुचवा" +msgid "Theme by the" +msgstr "द्वारा थीम" diff --git a/_static/locales/ms/LC_MESSAGES/booktheme.mo b/_static/locales/ms/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f02603fa2522a40060bd3f1b5d65052c77530de6 GIT binary patch literal 1213 zcmZXRJ8Km|6vs!6uj@1M0TG1}Eworov@58TBL2_ajS)TU%x`DrywA6>k!K8Y7V9F`8>~xM5BFh% zd;s@@AHhT5C-5lv6+91q2g&v)I0lYF`6PH1JO$nc$*v2Y0Pldu!3W?dC>w4z_m7+N zHb`+^fGzM9NcL|*vVRZ02ETwK;L`&&w?VSo0ms4TAm#b4;b-tP&Og8l;4hH$$Kizh zUTHW1Qhptf^p`=>djwK_>)<(X03HLMfK>lZ^ZpV{}g%EROCaZxzWLzM_G6K*tH6hX%sTdt($LUZL@kZi>& z4I{%>X6M;z?cd7EIOUBUu+=J4dW+9cF1<{ak_~s>uT$@tG%Y08Vne0ED+JMU%h%Z$ zic<%vtlUs0G-K1wUB*6INTU1FI=E=_I%q^eqhYw#(!$c*-uvW@iB{KW zFSU<)gG#o!N7S2DA(WoxaVD&jzH_fPA5HD)S)tvUw9%Z7O`>$#=2Ly;TZ=-c0nKak z(zRBKU_}wl8(X?I*VXXoI=7~I{oA>w`Q;9uyguDx%Y{TQY0E^;V^w*;2yki7=)(TYV{?8_pQ^c*8Iog%4v$iD&q$RjNP literal 0 HcmV?d00001 diff --git a/_static/locales/ms/LC_MESSAGES/booktheme.po b/_static/locales/ms/LC_MESSAGES/booktheme.po index 6f8a250..e29cbe2 100644 --- a/_static/locales/ms/LC_MESSAGES/booktheme.po +++ b/_static/locales/ms/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: ms\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "isu terbuka" +msgid "suggest edit" +msgstr "cadangkan edit" -msgid "Download this page" -msgstr "Muat turun halaman ini" +msgid "Last updated on" +msgstr "Terakhir dikemas kini pada" -msgid "Download source file" -msgstr "Muat turun fail sumber" +msgid "Edit this page" +msgstr "Edit halaman ini" msgid "Launch" msgstr "Lancarkan" -msgid "Edit this page" -msgstr "Edit halaman ini" +msgid "Print to PDF" +msgstr "Cetak ke PDF" + +msgid "open issue" +msgstr "isu terbuka" + +msgid "Download notebook file" +msgstr "Muat turun fail buku nota" msgid "Toggle navigation" msgstr "Togol navigasi" -msgid "Theme by the" -msgstr "Tema oleh" - msgid "Source repository" msgstr "Repositori sumber" -msgid "Last updated on" -msgstr "Terakhir dikemas kini pada" - msgid "By the" msgstr "Oleh" +msgid "next page" +msgstr "muka surat seterusnya" + msgid "Sphinx Book Theme" msgstr "Tema Buku Sphinx" -msgid "Open an issue" -msgstr "Buka masalah" +msgid "Download source file" +msgstr "Muat turun fail sumber" -msgid "next page" -msgstr "muka surat seterusnya" +msgid "By" +msgstr "Oleh" msgid "Copyright" msgstr "hak cipta" -msgid "Search this book..." -msgstr "Cari buku ini ..." - -msgid "Print to PDF" -msgstr "Cetak ke PDF" - -msgid "By" -msgstr "Oleh" +msgid "Open an issue" +msgstr "Buka masalah" msgid "previous page" msgstr "halaman sebelumnya" -msgid "Download notebook file" -msgstr "Muat turun fail buku nota" +msgid "Download this page" +msgstr "Muat turun halaman ini" -msgid "suggest edit" -msgstr "cadangkan edit" +msgid "Theme by the" +msgstr "Tema oleh" diff --git a/_static/locales/nl/LC_MESSAGES/booktheme.mo b/_static/locales/nl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..e59e7ecb308a7648cd23aa6342a9ad98a61d0009 GIT binary patch literal 1356 zcmZXTJ5Los6vqcag)1TtUj+$cqf)Gju^^CJh(JODkqBZvyL;~La`(<`W@dTSmfC47 z`~-XfW8nv|v9q$Ewb8~-3*-OXUAP1%JNw%?Gxz+@WA4%Tz*~WF19KAdE9MmDt3JFi z2G0qBM-1V00UQPg!3l5(oCL3fx52Am6C4Mhfg>P+S3qC$CCGl>fS1Ad;4pXyj)5O) zey;7`>h*V!^?rj5u)n|h{RqhGNs#^A0Y8F|zya_lcoF;svhE*{ng4G|2HU zfE@n|kmKI2*9Rc$zXmzZceVWx9L4%m%`YJ5bp-OcA0YetTieIZSNl^S#~pwZ;4H`` z=N$Mv$HI25E$f~haMji1Jb17l9<0YPv;H+qxD=N#xwoeW*MWP;bwN40{S^!Qc%)BB zJTcmn_6{G#zRi--xzS!`5#mI~uCZ|uI< zDAG*t$pwyWGo=oR?puacPMao4a*|r@WQp<_L^SRBDmueDl}KS}Co^Ro_9^$SOcFwr zgiH{M*`~+`D{-(z*1_AHtn>rc54y^YwUxD{-u}$J2aUS0!RCHJbJ8P#`$euYJujnF zSx3J4d~-RN?VYnqyB67CNk=BmbTTJr!^}5Ul}<|3bx!KMv7VP!<-xMC9S1|vUApGO zd0Bln?`nCgDQBkV8|as@-IqkwS9EI1Sg6udX`Q7gMb~>RJ??afw3Uu~8!34iTBHBl zi0Od1qM24Aq+POY$n;EGCeKm6M7k&?+d-F=M@18=IxkHDla2^|PO9GX1u3ivbE1xT z+=^}4Zo{ONva*On--8-OUjI=r94V1Y}`N=IHv19Ut jbWAeLReX?b<52fDoT%;?`~gm~I(s23S;SN2irW1H>^?=m literal 0 HcmV?d00001 diff --git a/_static/locales/nl/LC_MESSAGES/booktheme.po b/_static/locales/nl/LC_MESSAGES/booktheme.po index 4065b58..e4844d7 100644 --- a/_static/locales/nl/LC_MESSAGES/booktheme.po +++ b/_static/locales/nl/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "repository" - -msgid "open issue" -msgstr "open probleem" - -msgid "Contents" -msgstr "Inhoud" - -msgid "Fullscreen mode" -msgstr "Volledig scherm" +msgid "suggest edit" +msgstr "suggereren bewerken" -msgid "Download this page" -msgstr "Download deze pagina" +msgid "Last updated on" +msgstr "Laatst geupdate op" -msgid "Download source file" -msgstr "Download het bronbestand" +msgid "Edit this page" +msgstr "bewerk deze pagina" msgid "Launch" msgstr "Lancering" -msgid "Edit this page" -msgstr "bewerk deze pagina" +msgid "Print to PDF" +msgstr "Afdrukken naar pdf" + +msgid "open issue" +msgstr "open probleem" + +msgid "Download notebook file" +msgstr "Download notebookbestand" msgid "Toggle navigation" msgstr "Schakel navigatie" -msgid "Theme by the" -msgstr "Thema door de" - msgid "Source repository" msgstr "Bronopslagplaats" -msgid "Last updated on" -msgstr "Laatst geupdate op" - msgid "By the" msgstr "Door de" +msgid "next page" +msgstr "volgende bladzijde" + +msgid "repository" +msgstr "repository" + msgid "Sphinx Book Theme" msgstr "Sphinx-boekthema" -msgid "Open an issue" -msgstr "Open een probleem" +msgid "Download source file" +msgstr "Download het bronbestand" -msgid "next page" -msgstr "volgende bladzijde" +msgid "Contents" +msgstr "Inhoud" + +msgid "By" +msgstr "Door" msgid "Copyright" msgstr "auteursrechten" -msgid "Search this book..." -msgstr "Zoek in dit boek ..." - -msgid "Print to PDF" -msgstr "Afdrukken naar pdf" +msgid "Fullscreen mode" +msgstr "Volledig scherm" -msgid "By" -msgstr "Door" +msgid "Open an issue" +msgstr "Open een probleem" msgid "previous page" msgstr "vorige pagina" -msgid "Search the docs ..." -msgstr "Doorzoek de documenten ..." - -msgid "Download notebook file" -msgstr "Download notebookbestand" +msgid "Download this page" +msgstr "Download deze pagina" -msgid "suggest edit" -msgstr "suggereren bewerken" +msgid "Theme by the" +msgstr "Thema door de" diff --git a/_static/locales/no/LC_MESSAGES/booktheme.mo b/_static/locales/no/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6cd15c88de675226c00ca4d0430171075e5559ff GIT binary patch literal 1317 zcmZ9KJ#5r46vxeXdz6pzxm3a|d<+2!3{|TeDD*@{E2`eX#NxZWChjG6WIIQ@F#r=I zh=CaiW+cQ+7sSlefekSsA;E&g!2exRwZe-1i=UnMe;@gJZ0`$!aT;?1^9$w~%xAl> zV2tb*0*@HQvL74+N5JFYC^!M00?&abz$SPMTm}z=1ReoH&Bq}7c@7=|Ux8!bTW}nF zU-MIK->moFLDu^NHo!f5s_zejyq^Hs&w20zcpb!5@dLyoequQQ{ss?%e?g9WWG`|7 z&ww2NwR(RWJc|7Tkn_pGec+?o{vnrOx2I^Ydmn%A>ZL_zf>(PJ4kZLarm5`W=b%5)w zZL7>O-*ZGp<~Am=pnQ;J5vxG4v+R9LTr zb?c&Cq}r^>S&prfQchyH%5IfY$0kWe(x`z>RL~GHv=*x9EbCMvg`Y>jh2AfB-HRnbKxP z_EP0Mh336ZE1KHA=alg)i!%*zV<7HREar_#Z59h#6sa0`M0_gBf~5&B$u(bn(=RqnJ4d{?xCazSi7Dd36F5NEp? z<)YnpdLTAmS7{(1PP{Mcl94asi9}+1PF;uA{A!sWqQCgLP1e#J@rEvuCjIeG)u_ z_zHL&oC3+mBarlB@FchjQl1we?OzAU{{~3=--1+!&*l7gkoNrokAjC_hW4EWNq-dF z2i^p!UUxt$Ipw67YDs=blg_=fL9(w&^`%C>sF5z^AYYUllKnH&-R^8uf4W1;k81~m7!h)9ylfZ~^CgwY?O|s!8_53#eN#D}ib%4l zPdl`G0* zrR^Q^E{h@wml7v|6|*b@U!4i752bZbtMMX#mGW2nnJcq1vs2siW24t9Wnrs}c`9q% z!@$)v5lT<+ped}AzW!iwx;nnS&I;|8q^(Zrz=TRiH9p=@zH(RSC_`OqJWVR|NoGY- zoi?`RYFwxN(ABR`V3KC)moz_L=VO;ADlp!Wow9!{+QNF%d)$vmWXUlwR2&%HTrgJW19E;7l zzACcDJ`;)Rh+tW;2Q~|urlsI%&bL2qk_T%ViEOb+o5j!ziwCfPoA2cCtFji~wj$ZA z@p+raPIaI5KE$fLmvXo`p>N|Ts6=nA`!wj_O|+>xW d^Crc{P^+yKEfI-Mu31OGXlgVp$}sP%{Q=l!SrY&N literal 0 HcmV?d00001 diff --git a/_static/locales/pl/LC_MESSAGES/booktheme.po b/_static/locales/pl/LC_MESSAGES/booktheme.po index bd03ba4..fcac51d 100644 --- a/_static/locales/pl/LC_MESSAGES/booktheme.po +++ b/_static/locales/pl/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: pl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "magazyn" - -msgid "open issue" -msgstr "otwarty problem" - -msgid "Contents" -msgstr "Zawartość" - -msgid "Fullscreen mode" -msgstr "Pełny ekran" +msgid "suggest edit" +msgstr "zaproponuj edycję" -msgid "Download this page" -msgstr "Pobierz tę stronę" +msgid "Last updated on" +msgstr "Ostatnia aktualizacja" -msgid "Download source file" -msgstr "Pobierz plik źródłowy" +msgid "Edit this page" +msgstr "Edytuj tę strone" msgid "Launch" msgstr "Uruchomić" -msgid "Edit this page" -msgstr "Edytuj tę strone" +msgid "Print to PDF" +msgstr "Drukuj do PDF" + +msgid "open issue" +msgstr "otwarty problem" + +msgid "Download notebook file" +msgstr "Pobierz plik notatnika" msgid "Toggle navigation" msgstr "Przełącz nawigację" -msgid "Theme by the" -msgstr "Motyw autorstwa" - msgid "Source repository" msgstr "Repozytorium źródłowe" -msgid "Last updated on" -msgstr "Ostatnia aktualizacja" - msgid "By the" msgstr "Przez" +msgid "next page" +msgstr "Następna strona" + +msgid "repository" +msgstr "magazyn" + msgid "Sphinx Book Theme" msgstr "Motyw książki Sphinx" -msgid "Open an issue" -msgstr "Otwórz problem" +msgid "Download source file" +msgstr "Pobierz plik źródłowy" -msgid "next page" -msgstr "Następna strona" +msgid "Contents" +msgstr "Zawartość" + +msgid "By" +msgstr "Przez" msgid "Copyright" msgstr "prawa autorskie" -msgid "Search this book..." -msgstr "Przeszukaj tę książkę ..." - -msgid "Print to PDF" -msgstr "Drukuj do PDF" +msgid "Fullscreen mode" +msgstr "Pełny ekran" -msgid "By" -msgstr "Przez" +msgid "Open an issue" +msgstr "Otwórz problem" msgid "previous page" msgstr "Poprzednia strona" -msgid "Search the docs ..." -msgstr "Przeszukaj dokumenty ..." - -msgid "Download notebook file" -msgstr "Pobierz plik notatnika" +msgid "Download this page" +msgstr "Pobierz tę stronę" -msgid "suggest edit" -msgstr "zaproponuj edycję" +msgid "Theme by the" +msgstr "Motyw autorstwa" diff --git a/_static/locales/pt/LC_MESSAGES/booktheme.mo b/_static/locales/pt/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..d0ddb8728e1d5ef72dddc1537f66aa32251a83c8 GIT binary patch literal 1364 zcmZ9KJ!lj`6vsyszs~RYi3A)AKVkhsL@peXm>dKW4Dqy|yM5Uk-JMxyXV09qrC4bb zE3pu<6hyS##>&dd!p6cz!N$T$|8I9gLWZ0D-MpQB@BjWY-^NCt35+9{h16S(zZ$SR;BglC^gY3_DkUjkg^8V2+RlY+YuTO%k z_iDYq0kY*B<9wX!0496Oy4Me+EOW5GJh*=z>>q1pUk_m-WvQ8UtRL(@Yuttj8%m$V z)DS=E`y_5yrAF9A~6$c zkJPKnb{@xB&k-4!*pS4W%Dl|ePxSZ1+Sg`TPO-L5pAr(~Q+BJKIyQ=8l12@5q`XEEL(9HWXSq&QBy}{>iJ+c4DOK2kgX}J`T^Gu%F2!T+4-5Z_m|FJY}CdEoncB%=^@}k z8Y^ukWUsGWM!t2s(+;k!?Q_axOXPwX)3c#AQBz*)YTuYsCd%P!Q>MPL5a&+CLEE|{ zYf6)r%dB;ILRNoUXN)}2l9$d-G{iJ)q}Wy`Tzm+v2(=>^C{+#@RV=2IURF*jcR$wy zD??aTpZLaCOMFYpAW1l*WLmt4v{B_@b0}L2&D+qT-&mnh(n=I7vDb-`%I7N94^{E1 zcxfdiIC)dNQVDLK6_Z`3WS+>>*=|gU60=F_bfO(LmX~0$I{o6U(^gh;I@l*sE7k*N z>oXB$Fttuh#-5x(d)$^9P*fEbsVm+tv!2x!?&s);C8;hsuS6ZkWkdpvO!dtuOAFi$ LL?J8GWh3H0!r)O_ literal 0 HcmV?d00001 diff --git a/_static/locales/pt/LC_MESSAGES/booktheme.po b/_static/locales/pt/LC_MESSAGES/booktheme.po index 8ac25a1..1761db0 100644 --- a/_static/locales/pt/LC_MESSAGES/booktheme.po +++ b/_static/locales/pt/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: pt\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "repositório" - -msgid "open issue" -msgstr "questão aberta" - -msgid "Contents" -msgstr "Conteúdo" - -msgid "Fullscreen mode" -msgstr "Modo tela cheia" +msgid "suggest edit" +msgstr "sugerir edição" -msgid "Download this page" -msgstr "Baixe esta página" +msgid "Last updated on" +msgstr "Última atualização em" -msgid "Download source file" -msgstr "Baixar arquivo fonte" +msgid "Edit this page" +msgstr "Edite essa página" msgid "Launch" msgstr "Lançamento" -msgid "Edit this page" -msgstr "Edite essa página" +msgid "Print to PDF" +msgstr "Imprimir em PDF" + +msgid "open issue" +msgstr "questão aberta" + +msgid "Download notebook file" +msgstr "Baixar arquivo de notebook" msgid "Toggle navigation" msgstr "Alternar de navegação" -msgid "Theme by the" -msgstr "Tema por" - msgid "Source repository" msgstr "Repositório fonte" -msgid "Last updated on" -msgstr "Última atualização em" - msgid "By the" msgstr "Pelo" +msgid "next page" +msgstr "próxima página" + +msgid "repository" +msgstr "repositório" + msgid "Sphinx Book Theme" msgstr "Tema do livro Sphinx" -msgid "Open an issue" -msgstr "Abra um problema" +msgid "Download source file" +msgstr "Baixar arquivo fonte" -msgid "next page" -msgstr "próxima página" +msgid "Contents" +msgstr "Conteúdo" + +msgid "By" +msgstr "De" msgid "Copyright" msgstr "direito autoral" -msgid "Search this book..." -msgstr "Pesquise este livro ..." - -msgid "Print to PDF" -msgstr "Imprimir em PDF" +msgid "Fullscreen mode" +msgstr "Modo tela cheia" -msgid "By" -msgstr "De" +msgid "Open an issue" +msgstr "Abra um problema" msgid "previous page" msgstr "página anterior" -msgid "Search the docs ..." -msgstr "Pesquise os documentos ..." - -msgid "Download notebook file" -msgstr "Baixar arquivo de notebook" +msgid "Download this page" +msgstr "Baixe esta página" -msgid "suggest edit" -msgstr "sugerir edição" +msgid "Theme by the" +msgstr "Tema por" diff --git a/_static/locales/ro/LC_MESSAGES/booktheme.mo b/_static/locales/ro/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..3c36ab1df7c589ad82614599b8c91f072a25d4a6 GIT binary patch literal 1390 zcmZ{jxo;Ce6vhX_5zG}5ZUr$kT#~s&fgHI>97~Z1L||yB#=9@;f%VL44!~(cNeM!T zzkmW7Bt%b&NVHTGv{Xn`NHmD=truc}813$F=kWX9`}X8CsJNO-Bou44rIk82E zW8ekwD0mG#0%~vyTm=t+&p?jz3S_U|fL!MXkn8*mPJmxQ*7*st&Nlprc^KsLXDc>A z&U>kv-vQZju7S_7m#oj;a^0f?p-U~+<-u`yunv38zH-h8DR$!Kd`AcS&)<;qgbk%n zVs?N_h8~GIYXX_z@lp(&&U!(#>;scql}cj+b*;T8mvv4X%iczp&|iz8r@bsxMq)nI z0il0S+cD35;)smw+mysr<%5hxssg3b8qA|fdg6M41IkG4eI&8uv_TLnms)LcbExO2 zuwDo22I6MX)8?U^<=i?w>XRs+vOBD)W3wzLY1Dn4sh}ZZ=wTRUXIW<`QaHM=ZLHEB z3GZW;5wavyf>i8XN#8^5U79nrN}tCR1WA7O>Nc7D^1!X_=B#5k}&OPu5mlqSjw% ze9!ggnq18PeE0wD`{?}IYPqW%0!Wn*zA9eO0NP-Sd!P*Z&(5Mvp+E_$mG57h;3yNf z@}T<)Q9@L?UQv!@t~hzGN|ByUi8HjaaJHLM9|{Y76xA;^5T@*t78+y)y;r5zA;cW% z6j3gq1Ltf%1{N7Mh$B&^tz>kF94xj(C8Xe$PteOytPUysU!2AvEWuE6Fj7Z>o*_qS K1txIYaExD}s9q8P literal 0 HcmV?d00001 diff --git a/_static/locales/ro/LC_MESSAGES/booktheme.po b/_static/locales/ro/LC_MESSAGES/booktheme.po index d0f7d2f..db865c8 100644 --- a/_static/locales/ro/LC_MESSAGES/booktheme.po +++ b/_static/locales/ro/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: ro\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "repertoriu" - -msgid "open issue" -msgstr "problema deschisă" - -msgid "Contents" -msgstr "Cuprins" - -msgid "Fullscreen mode" -msgstr "Modul ecran întreg" +msgid "suggest edit" +msgstr "sugerează editare" -msgid "Download this page" -msgstr "Descarcă această pagină" +msgid "Last updated on" +msgstr "Ultima actualizare la" -msgid "Download source file" -msgstr "Descărcați fișierul sursă" +msgid "Edit this page" +msgstr "Editați această pagină" msgid "Launch" msgstr "Lansa" -msgid "Edit this page" -msgstr "Editați această pagină" +msgid "Print to PDF" +msgstr "Imprimați în PDF" + +msgid "open issue" +msgstr "problema deschisă" + +msgid "Download notebook file" +msgstr "Descărcați fișierul notebook" msgid "Toggle navigation" msgstr "Comutare navigare" -msgid "Theme by the" -msgstr "Tema de" - msgid "Source repository" msgstr "Depozit sursă" -msgid "Last updated on" -msgstr "Ultima actualizare la" - msgid "By the" msgstr "Langa" +msgid "next page" +msgstr "pagina următoare" + +msgid "repository" +msgstr "repertoriu" + msgid "Sphinx Book Theme" msgstr "Tema Sphinx Book" -msgid "Open an issue" -msgstr "Deschideți o problemă" +msgid "Download source file" +msgstr "Descărcați fișierul sursă" -msgid "next page" -msgstr "pagina următoare" +msgid "Contents" +msgstr "Cuprins" + +msgid "By" +msgstr "De" msgid "Copyright" msgstr "Drepturi de autor" -msgid "Search this book..." -msgstr "Căutați în această carte ..." - -msgid "Print to PDF" -msgstr "Imprimați în PDF" +msgid "Fullscreen mode" +msgstr "Modul ecran întreg" -msgid "By" -msgstr "De" +msgid "Open an issue" +msgstr "Deschideți o problemă" msgid "previous page" msgstr "pagina anterioară" -msgid "Search the docs ..." -msgstr "Căutați documente ..." - -msgid "Download notebook file" -msgstr "Descărcați fișierul notebook" +msgid "Download this page" +msgstr "Descarcă această pagină" -msgid "suggest edit" -msgstr "sugerează editare" +msgid "Theme by the" +msgstr "Tema de" diff --git a/_static/locales/ru/LC_MESSAGES/booktheme.mo b/_static/locales/ru/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6b8ca41f36ebf869818399a9584cdb15619bea78 GIT binary patch literal 1722 zcmZ{iPiz!b9LJx6N>>C0{~WCHj6uL;MNkv6buUP3NFY{Oy-#-^yQABg$;>R!8?=By zpk6eZkcjo>ZEd^jw#)9`jK?>LiHQeq#*-Is-2D7zrnWZnvTr^!zxmDY_x*j}{=RSL zmx}cqdz}3X`vCjaLtI$99#)E<8sqXP+zofZ{csG9!)M_u@M&0v```y~4>WKujB{Rv zQs)c!1iS-x!|&l!u$%MeJpNn${3n!t_hA9<*pYp|2g>s}lsboC555U^!oQ&C`x}bB zF@i6^7vWp*ZFm@l@KtyR9)~}{gYZ5)1P?rt)qfX0&vOMzodC-FMW|sH%3Qy~Bk&LS zGTh71lK%!g2;Ya|(?xg`eg?&InL*;Bbw69Q%iLQRlGKxI@mH42FH8IruciMpY+9?w z*>bj97p>AWd<Owguyc8|lEQ8#P&TV@hv4PPLlNs2UpM=~=&K)EOs=bt|Yjv8id_3$EYFWp61Twd!?)O2Z^b@jo`zxOlo&{K$k6 z)k-?+UzGmEv~%I?>9doY?~lFqdLcKqSeXk!s4V?^=qzIFXM1NyDcB~ z^h;%Z?8rnx*}Ha_UXm-xW!tfr6}wJC zN81q@gr(9Fv3Bw)dp^0PldHtnY+u_Sxf$6W-wgO>O_L_|y0EwXD@jYPrM(BqO_Ddt zDEk#lk9`p%b*uDr%Zu6PU zG_bh>@urJlTp^1w`f2$AR}2{1AJVy&({OH-XdNXBVw1Appn{Ug&D59FU~!E~qO?uY z2%}Tqa+P*D{a@R!x0@kSMzqWv;2@B-rtEiw@7eZ-vn#fz?Gn!QP_`~@{!JJr^D>2; zYX|@P$s&z$lLI4H4zg!gP;s5$q8v^-E0ZiHHwb^e&1~CN%&|G1oY;Q{yqk7fcCfJk literal 0 HcmV?d00001 diff --git a/_static/locales/ru/LC_MESSAGES/booktheme.po b/_static/locales/ru/LC_MESSAGES/booktheme.po index 9b55bfe..84ab6eb 100644 --- a/_static/locales/ru/LC_MESSAGES/booktheme.po +++ b/_static/locales/ru/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: ru\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "хранилище" - -msgid "open issue" -msgstr "открытый вопрос" - -msgid "Contents" -msgstr "Содержание" - -msgid "Fullscreen mode" -msgstr "Полноэкранный режим" +msgid "suggest edit" +msgstr "предложить редактировать" -msgid "Download this page" -msgstr "Загрузите эту страницу" +msgid "Last updated on" +msgstr "Последнее обновление" -msgid "Download source file" -msgstr "Скачать исходный файл" +msgid "Edit this page" +msgstr "Редактировать эту страницу" msgid "Launch" msgstr "Запуск" -msgid "Edit this page" -msgstr "Редактировать эту страницу" +msgid "Print to PDF" +msgstr "Распечатать в PDF" + +msgid "open issue" +msgstr "открытый вопрос" + +msgid "Download notebook file" +msgstr "Скачать файл записной книжки" msgid "Toggle navigation" msgstr "Переключить навигацию" -msgid "Theme by the" -msgstr "Тема от" - msgid "Source repository" msgstr "Исходный репозиторий" -msgid "Last updated on" -msgstr "Последнее обновление" - msgid "By the" msgstr "Посредством" +msgid "next page" +msgstr "Следующая страница" + +msgid "repository" +msgstr "хранилище" + msgid "Sphinx Book Theme" msgstr "Тема книги Сфинкс" -msgid "Open an issue" -msgstr "Открыть вопрос" +msgid "Download source file" +msgstr "Скачать исходный файл" -msgid "next page" -msgstr "Следующая страница" +msgid "Contents" +msgstr "Содержание" + +msgid "By" +msgstr "По" msgid "Copyright" msgstr "авторское право" -msgid "Search this book..." -msgstr "Искать в этой книге ..." - -msgid "Print to PDF" -msgstr "Распечатать в PDF" +msgid "Fullscreen mode" +msgstr "Полноэкранный режим" -msgid "By" -msgstr "По" +msgid "Open an issue" +msgstr "Открыть вопрос" msgid "previous page" msgstr "Предыдущая страница" -msgid "Search the docs ..." -msgstr "Искать в документах ..." - -msgid "Download notebook file" -msgstr "Скачать файл записной книжки" +msgid "Download this page" +msgstr "Загрузите эту страницу" -msgid "suggest edit" -msgstr "предложить редактировать" +msgid "Theme by the" +msgstr "Тема от" diff --git a/_static/locales/sk/LC_MESSAGES/booktheme.mo b/_static/locales/sk/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..59bd0ddfa341477cf5ccfdc88f4c3e6127046f7a GIT binary patch literal 1393 zcmZ9KKWrRD6vijSKyrit=ARHoJeoj?1A-``v#uc6mLesxmAg<-Am(Iw==v>7a08THd<;rm`=IpY4k&eh2g>u`gW~ryD0Tk|O5J~fa_(Nc zzXDUK|0PiBy9|o{Iw-jZpgi{xC@mLFS&OFRlMGV#=>h3w2I;R1(UBqg;w6239ut!4 z2~6=jJ)|#^@o`MFWBGp7wHbaCb5`#=8`;KyKjqAuERSl#ePRozQ?f4d$hk4?nu1TZ zgR6YP4{gTW1S)mLYBMzv(*G~Fs-g&qXSOtPDXSYgM5@YEM^4FEtSg)3YP-Y%ZOMdC zvD)#*Ld4O|#+Dj1ex6GgOmu#x24!ySK3$V+!<;9qmRA}zH4R;s6--u7O{SxPiRJy+ zq;ulan3SHU##L?XQ}Ut8GDb>9C5YnoIEmfsY4-#60ct&J{JY}cT{?GeUcb3{a{tPk zZ+F_pc89Z)dlV7it+LR@u2Yh0A2{}J54XBkPtJL5!!G;orcGRGY}TWzBNIC}w9P8? zwMSvx*(oZoi|&^5lh7kuE|;PI&N?-J`)^o!txs1juXogY6?)ZEJ1#xCtJU@>=)Bnr zU1l0t--9arjh>CyA! zZ|R}^TYP-iOeo=k_sEUBK5*0V4ADZtsjcUv$Fb6dIjHA}(Ucy4hGb%cXdqT-thpkjw8w z94mEnM;EAFODWoF<;0UM`ZS%T+8S2)Skfe~=jnmos~5@rll9m4U7_dmM!H@|Co1(H Di}h+h literal 0 HcmV?d00001 diff --git a/_static/locales/sk/LC_MESSAGES/booktheme.po b/_static/locales/sk/LC_MESSAGES/booktheme.po index 3e6fd9f..e44878b 100644 --- a/_static/locales/sk/LC_MESSAGES/booktheme.po +++ b/_static/locales/sk/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: sk\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "Úložisko" - -msgid "open issue" -msgstr "otvorené vydanie" - -msgid "Contents" -msgstr "Obsah" - -msgid "Fullscreen mode" -msgstr "Režim celej obrazovky" +msgid "suggest edit" +msgstr "navrhnúť úpravu" -msgid "Download this page" -msgstr "Stiahnite si túto stránku" +msgid "Last updated on" +msgstr "Posledná aktualizácia dňa" -msgid "Download source file" -msgstr "Stiahnite si zdrojový súbor" +msgid "Edit this page" +msgstr "Upraviť túto stránku" msgid "Launch" msgstr "Spustiť" -msgid "Edit this page" -msgstr "Upraviť túto stránku" +msgid "Print to PDF" +msgstr "Tlač do PDF" + +msgid "open issue" +msgstr "otvorené vydanie" + +msgid "Download notebook file" +msgstr "Stiahnite si zošit" msgid "Toggle navigation" msgstr "Prepnúť navigáciu" -msgid "Theme by the" -msgstr "Téma od" - msgid "Source repository" msgstr "Zdrojové úložisko" -msgid "Last updated on" -msgstr "Posledná aktualizácia dňa" - msgid "By the" msgstr "Podľa" +msgid "next page" +msgstr "ďalšia strana" + +msgid "repository" +msgstr "Úložisko" + msgid "Sphinx Book Theme" msgstr "Téma knihy Sfinga" -msgid "Open an issue" -msgstr "Otvorte problém" +msgid "Download source file" +msgstr "Stiahnite si zdrojový súbor" -msgid "next page" -msgstr "ďalšia strana" +msgid "Contents" +msgstr "Obsah" + +msgid "By" +msgstr "Autor:" msgid "Copyright" msgstr "Autorské práva" -msgid "Search this book..." -msgstr "Hľadať v tejto knihe ..." - -msgid "Print to PDF" -msgstr "Tlač do PDF" +msgid "Fullscreen mode" +msgstr "Režim celej obrazovky" -msgid "By" -msgstr "Autor:" +msgid "Open an issue" +msgstr "Otvorte problém" msgid "previous page" msgstr "predchádzajúca strana" -msgid "Search the docs ..." -msgstr "Hľadať v dokumentoch ..." - -msgid "Download notebook file" -msgstr "Stiahnite si zošit" +msgid "Download this page" +msgstr "Stiahnite si túto stránku" -msgid "suggest edit" -msgstr "navrhnúť úpravu" +msgid "Theme by the" +msgstr "Téma od" diff --git a/_static/locales/sl/LC_MESSAGES/booktheme.mo b/_static/locales/sl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..87bf26de683cb18c73bd23c2b4c57ef6a02545ec GIT binary patch literal 1374 zcmZ9KyKfXR5XQ}$9PjWFC=#aOAvj*5h%UN@MVlwf1j4YtMW$vtK7Sz7QA(F{dy;VIIMJx(*A* z*7ZW*5ffN8gWJKa;9hV7oB|Jk$H0AH8=M61fIC3~cY(3y6OjEp2X}z4!0q5`a1Z#l z=EvIprQUx7Io@xu0dCk(-QNlFehOqi$H8~tMQ{`NqvlU=3--Uk-Qc>7LL34o!NcHb zkab@J`TGNq^T|Ly_ZVc|FG1Eh0$KkXa4+~CYpSj^k88a!&*8idy!V z`%t7QK_wv*NO67Y#^!v|yiY#BTT52)n;gGcMsD1kzd5`1{rs78jk>VS#g&{|GD5)F z+$e2lWVfe$pxC~*IM2jgT5~@lP4MDpz zCx-(XW@_w<9uAzh?%#>APv}sH5H9X{E*5diD#H~rZm5EBHe?#D`0z|yaZ3$VV*3d1 zf=gV-^ojji64%jMWljW5^x#&@4 literal 0 HcmV?d00001 diff --git a/_static/locales/sl/LC_MESSAGES/booktheme.po b/_static/locales/sl/LC_MESSAGES/booktheme.po index dd99bbe..228939b 100644 --- a/_static/locales/sl/LC_MESSAGES/booktheme.po +++ b/_static/locales/sl/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: sl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "odlagališče" - -msgid "open issue" -msgstr "odprto vprašanje" - -msgid "Contents" -msgstr "Vsebina" - -msgid "Fullscreen mode" -msgstr "Celozaslonski način" +msgid "suggest edit" +msgstr "predlagajte urejanje" -msgid "Download this page" -msgstr "Prenesite to stran" +msgid "Last updated on" +msgstr "Nazadnje posodobljeno dne" -msgid "Download source file" -msgstr "Prenesite izvorno datoteko" +msgid "Edit this page" +msgstr "Uredite to stran" msgid "Launch" msgstr "Kosilo" -msgid "Edit this page" -msgstr "Uredite to stran" +msgid "Print to PDF" +msgstr "Natisni v PDF" + +msgid "open issue" +msgstr "odprto vprašanje" + +msgid "Download notebook file" +msgstr "Prenesite datoteko zvezka" msgid "Toggle navigation" msgstr "Preklopi navigacijo" -msgid "Theme by the" -msgstr "Tema avtorja" - msgid "Source repository" msgstr "Izvorno skladišče" -msgid "Last updated on" -msgstr "Nazadnje posodobljeno dne" - msgid "By the" msgstr "Avtor" +msgid "next page" +msgstr "Naslednja stran" + +msgid "repository" +msgstr "odlagališče" + msgid "Sphinx Book Theme" msgstr "Tema knjige Sphinx" -msgid "Open an issue" -msgstr "Odprite številko" +msgid "Download source file" +msgstr "Prenesite izvorno datoteko" -msgid "next page" -msgstr "Naslednja stran" +msgid "Contents" +msgstr "Vsebina" + +msgid "By" +msgstr "Avtor" msgid "Copyright" msgstr "avtorske pravice" -msgid "Search this book..." -msgstr "Poiščite to knjigo ..." - -msgid "Print to PDF" -msgstr "Natisni v PDF" +msgid "Fullscreen mode" +msgstr "Celozaslonski način" -msgid "By" -msgstr "Avtor" +msgid "Open an issue" +msgstr "Odprite številko" msgid "previous page" msgstr "Prejšnja stran" -msgid "Search the docs ..." -msgstr "Poiščite dokumente ..." - -msgid "Download notebook file" -msgstr "Prenesite datoteko zvezka" +msgid "Download this page" +msgstr "Prenesite to stran" -msgid "suggest edit" -msgstr "predlagajte urejanje" +msgid "Theme by the" +msgstr "Tema avtorja" diff --git a/_static/locales/sr/LC_MESSAGES/booktheme.mo b/_static/locales/sr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..ec740f4852f3973fa72ed0c7f7cf59273b8dba41 GIT binary patch literal 1679 zcmZ{i&2Jk;7>5TMpf#n12FigTrXZCM$qB70R5|j2(nPA%iiifpt=iZVd#SU#+K*9wix4UV%CCk|YD;tzleJn!xzyAg~$`^-$R zf|BP7d;(sF`{57pDcCFcOL6{NvA++c-k-1p_w32;FeHVeLgQ7^hJ zGdzy`B&?ZThjG)5bl^0MnyI@nssG*1CaqRf3ytygl3zFKtP{mL3F=O4>e~0%Ctj_o z-VO+GJncqNV$@vddL;4n-04|$KCc&=z>nP650};Xpy_&-^(oOd-!w}`WnaCJdz$wf zjh4}#bIENuu}cxpT#j>fzSPN!1fjX)`bi;sBz=@L8U~dHCrI%>FtxaRre1!}gb~>) zID-xfGsC|hn|!@gG`2jy9GHrZ5ik|B9M_xHwWbqBCa%6aKU+RIj0+tv zS~OvK#;f^t*K1Vt$ptqqoproMLSHL73QKdXBy?KkSwCEgD%uOOZB#uzt@CB|6;B_j z>SM1?mz2F>J33uW*U}Z+wmY_)ohZA>uESZ+w$lw|zev~9H9JUG(p9@{2io4t;AJmR@7g|5U2Qwul5jS5J6+fI7K$b?*B^Gym(vvm#N%kCu@EWomq3c>6awm HD*E*gL}ZXP literal 0 HcmV?d00001 diff --git a/_static/locales/sr/LC_MESSAGES/booktheme.po b/_static/locales/sr/LC_MESSAGES/booktheme.po index 12284e0..1a712a1 100644 --- a/_static/locales/sr/LC_MESSAGES/booktheme.po +++ b/_static/locales/sr/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: sr\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "спремиште" - -msgid "open issue" -msgstr "отворено издање" - -msgid "Contents" -msgstr "Садржај" - -msgid "Fullscreen mode" -msgstr "Режим целог екрана" +msgid "suggest edit" +msgstr "предложи уређивање" -msgid "Download this page" -msgstr "Преузмите ову страницу" +msgid "Last updated on" +msgstr "Последње ажурирање" -msgid "Download source file" -msgstr "Преузми изворну датотеку" +msgid "Edit this page" +msgstr "Уредите ову страницу" msgid "Launch" msgstr "Лансирање" -msgid "Edit this page" -msgstr "Уредите ову страницу" +msgid "Print to PDF" +msgstr "Испис у ПДФ" + +msgid "open issue" +msgstr "отворено издање" + +msgid "Download notebook file" +msgstr "Преузмите датотеку бележнице" msgid "Toggle navigation" msgstr "Укључи / искључи навигацију" -msgid "Theme by the" -msgstr "Тхеме би" - msgid "Source repository" msgstr "Изворно спремиште" -msgid "Last updated on" -msgstr "Последње ажурирање" - msgid "By the" msgstr "Од" +msgid "next page" +msgstr "Следећа страна" + +msgid "repository" +msgstr "спремиште" + msgid "Sphinx Book Theme" msgstr "Тема књиге Спхинк" -msgid "Open an issue" -msgstr "Отворите издање" +msgid "Download source file" +msgstr "Преузми изворну датотеку" -msgid "next page" -msgstr "Следећа страна" +msgid "Contents" +msgstr "Садржај" + +msgid "By" +msgstr "Од стране" msgid "Copyright" msgstr "Ауторско право" -msgid "Search this book..." -msgstr "Претражите ову књигу ..." - -msgid "Print to PDF" -msgstr "Испис у ПДФ" +msgid "Fullscreen mode" +msgstr "Режим целог екрана" -msgid "By" -msgstr "Од стране" +msgid "Open an issue" +msgstr "Отворите издање" msgid "previous page" msgstr "Претходна страница" -msgid "Search the docs ..." -msgstr "Претражите документе ..." - -msgid "Download notebook file" -msgstr "Преузмите датотеку бележнице" +msgid "Download this page" +msgstr "Преузмите ову страницу" -msgid "suggest edit" -msgstr "предложи уређивање" +msgid "Theme by the" +msgstr "Тхеме би" diff --git a/_static/locales/sv/LC_MESSAGES/booktheme.mo b/_static/locales/sv/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..be951bec201ccd86d534499749af1df8938a14e3 GIT binary patch literal 1349 zcmZ9KF>Dk^6ow}lVsj7(m^c(h3{4=#1{0;Q&N?YF_DNQZu<*qa<=pM_?&RiXHZ!vq zyG4|gNfap!#koiw$x6S9lsZb4B2p?uK}P|i;eWel+45*-zMVHS@BQ=U{de{3PXg^z z^hNZ4&~KtY`v3#l+!-P8iSrmf1TTVf;5>L9Tm%=u&%kS72fPYC0xy9CUIycoPeJzc zBlr>cD|iw74ZH##PWji={_k}D0_1pa!4^0()11Eq@_Z3wKexd@z^_1#^9sZ#USr_% zZ$RF6=ByAmz{?=(O~C8m*C6NOG59g~J@^Uu1e^tb0eSy(koEo!vcEq;zVF{4@B4qc z{t~=^`Mc@*?78OL0?7OBfSk7_kWCc-)qQ+2<|OVr8_C9ipJLzZERSN%{a}q#skAOq-?^dO)rOAE z!IgeMr;IVzK^7__v7YJ(*GJQCX-pV+A}dEOC9$bOlx2~sNU3xd^U@A-@vy)KWu*?G zB(deSg%c;Y*1BT5iRY(iF%a%=1x7AWrn0xW1Xp}5yaA7 zY}7f9(*!9zjkPPMvQM}VWtI_C5^e%1?mHU9WFt*>$Om|9%O-xp@sm1o>%qo@_2cz> zUo5qziA{R@1+`^_fV+iJ+OEh!u6&@_`L@?hmXG&&Wy3D{WZe#2s%_Sm%Y7YNo62S- z^4gYR+}bjwS0?E?KMHMWi+UP5U#`gJw{yqJTOE1t^Oct9R)@Z?#g0zJhP9Me2gZo9 zC~`LrzM8~{)TgPEmOK(4X)v^i8v1U?&&>~Wv^uON#=v;Olp>3HHSsd&R9W!|smjPJ zdCFctK8{1KsU|3nZL-b#*9G8FWH;fu2BfNV<5 S2DY&GdIic4q;D?Bp56m!5lvG7 literal 0 HcmV?d00001 diff --git a/_static/locales/sv/LC_MESSAGES/booktheme.po b/_static/locales/sv/LC_MESSAGES/booktheme.po index 203c917..7d2b56d 100644 --- a/_static/locales/sv/LC_MESSAGES/booktheme.po +++ b/_static/locales/sv/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "förvar" - -msgid "open issue" -msgstr "öppet problem" - -msgid "Contents" -msgstr "Innehåll" - -msgid "Fullscreen mode" -msgstr "Fullskärmsläge" +msgid "suggest edit" +msgstr "föreslå redigering" -msgid "Download this page" -msgstr "Ladda ner den här sidan" +msgid "Last updated on" +msgstr "Senast uppdaterad den" -msgid "Download source file" -msgstr "Ladda ner källfil" +msgid "Edit this page" +msgstr "Redigera den här sidan" msgid "Launch" msgstr "Lansera" -msgid "Edit this page" -msgstr "Redigera den här sidan" +msgid "Print to PDF" +msgstr "Skriv ut till PDF" + +msgid "open issue" +msgstr "öppet problem" + +msgid "Download notebook file" +msgstr "Ladda ner anteckningsbokfilen" msgid "Toggle navigation" msgstr "Växla navigering" -msgid "Theme by the" -msgstr "Tema av" - msgid "Source repository" msgstr "Källförvar" -msgid "Last updated on" -msgstr "Senast uppdaterad den" - msgid "By the" msgstr "Vid" +msgid "next page" +msgstr "nästa sida" + +msgid "repository" +msgstr "förvar" + msgid "Sphinx Book Theme" msgstr "Sphinx boktema" -msgid "Open an issue" -msgstr "Öppna ett problem" +msgid "Download source file" +msgstr "Ladda ner källfil" -msgid "next page" -msgstr "nästa sida" +msgid "Contents" +msgstr "Innehåll" + +msgid "By" +msgstr "Förbi" msgid "Copyright" msgstr "upphovsrätt" -msgid "Search this book..." -msgstr "Sök i den här boken ..." - -msgid "Print to PDF" -msgstr "Skriv ut till PDF" +msgid "Fullscreen mode" +msgstr "Fullskärmsläge" -msgid "By" -msgstr "Förbi" +msgid "Open an issue" +msgstr "Öppna ett problem" msgid "previous page" msgstr "föregående sida" -msgid "Search the docs ..." -msgstr "Sök i dokumenten ..." - -msgid "Download notebook file" -msgstr "Ladda ner anteckningsbokfilen" +msgid "Download this page" +msgstr "Ladda ner den här sidan" -msgid "suggest edit" -msgstr "föreslå redigering" +msgid "Theme by the" +msgstr "Tema av" diff --git a/_static/locales/ta/LC_MESSAGES/booktheme.mo b/_static/locales/ta/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..29f52e1f6f1ec96aceb0f883d8ccc82c23eb35c2 GIT binary patch literal 1928 zcmbW0%ZnUE9LGzIuko2E;=xEoRN`S0qn9x23T7V=+2G=?qL54POr@uFQq^?#B-xX0 zK#htA4J0RHRwJIJFG|WNq7Z50sn;0!@U&o7(5PV;9F4M{{RobKj41& z@a;;?!xtbeX@>OX{(5y6M3y47A9wJS8l@l7I~meb8I-3U@UzelnM(bH_d|LjeI~u4 zB&Ck5^3z4%s2P{8W=Y&H)T}#g2QKPq>k6~t+?)DDGB7*axf^C(bKPdqPja0`u~Boq zq#)vWxe(=r9;UshFg@+8T8M_W+gC58#_GuGB+rLNEoOcl%M6n_~Kv<@xsE9lI>D`3aM?=WN&Y5*v5);gzIlEkrgR(mY~Bt;NAGiw5m^ zmz~Tz+NOS)Pd_uI!*qJT)%&LPp{J%=sw%gu@~f)+wA%QnDo0iMT~%)Q%}sWAT~-@s zt8&XvWPPzJFLmFFj3kCLZVZKXbJg6qObpgpYXhKc{dPQvXD4*l1`&-oR|ZVWnD5S zLMPGk+4yL_MW)wWJ7GI+sWh)Cq}dE7ao%TGqX8uPK%$P%oUIVNaozG6uhIA~XTs-( z77E8j3VKIkNhd=@QrBItuMs9x^kr3kK4HautE;{2cexG}GQN=#P4;o6q{&7}8xZ++ zl w$ZZQ&WaeX;?9mtGBq&}escqTfGyJc(*W8(47(T)#0?{xcP9tpFr||Or2L57y?*IS* literal 0 HcmV?d00001 diff --git a/_static/locales/ta/LC_MESSAGES/booktheme.po b/_static/locales/ta/LC_MESSAGES/booktheme.po index eefce8a..c75ffe1 100644 --- a/_static/locales/ta/LC_MESSAGES/booktheme.po +++ b/_static/locales/ta/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: ta\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "திறந்த பிரச்சினை" +msgid "suggest edit" +msgstr "திருத்த பரிந்துரைக்கவும்" -msgid "Download this page" -msgstr "இந்தப் பக்கத்தைப் பதிவிறக்கவும்" +msgid "Last updated on" +msgstr "கடைசியாக புதுப்பிக்கப்பட்டது" -msgid "Download source file" -msgstr "மூல கோப்பைப் பதிவிறக்குக" +msgid "Edit this page" +msgstr "இந்தப் பக்கத்தைத் திருத்தவும்" msgid "Launch" msgstr "தொடங்க" -msgid "Edit this page" -msgstr "இந்தப் பக்கத்தைத் திருத்தவும்" +msgid "Print to PDF" +msgstr "PDF இல் அச்சிடுக" + +msgid "open issue" +msgstr "திறந்த பிரச்சினை" + +msgid "Download notebook file" +msgstr "நோட்புக் கோப்பைப் பதிவிறக்கவும்" msgid "Toggle navigation" msgstr "வழிசெலுத்தலை நிலைமாற்று" -msgid "Theme by the" -msgstr "வழங்கிய தீம்" - msgid "Source repository" msgstr "மூல களஞ்சியம்" -msgid "Last updated on" -msgstr "கடைசியாக புதுப்பிக்கப்பட்டது" - msgid "By the" msgstr "மூலம்" +msgid "next page" +msgstr "அடுத்த பக்கம்" + msgid "Sphinx Book Theme" msgstr "ஸ்பிங்க்ஸ் புத்தக தீம்" -msgid "Open an issue" -msgstr "சிக்கலைத் திறக்கவும்" +msgid "Download source file" +msgstr "மூல கோப்பைப் பதிவிறக்குக" -msgid "next page" -msgstr "அடுத்த பக்கம்" +msgid "By" +msgstr "வழங்கியவர்" msgid "Copyright" msgstr "பதிப்புரிமை" -msgid "Search this book..." -msgstr "இந்த புத்தகத்தைத் தேடுங்கள் ..." - -msgid "Print to PDF" -msgstr "PDF இல் அச்சிடுக" - -msgid "By" -msgstr "வழங்கியவர்" +msgid "Open an issue" +msgstr "சிக்கலைத் திறக்கவும்" msgid "previous page" msgstr "முந்தைய பக்கம்" -msgid "Download notebook file" -msgstr "நோட்புக் கோப்பைப் பதிவிறக்கவும்" +msgid "Download this page" +msgstr "இந்தப் பக்கத்தைப் பதிவிறக்கவும்" -msgid "suggest edit" -msgstr "திருத்த பரிந்துரைக்கவும்" +msgid "Theme by the" +msgstr "வழங்கிய தீம்" diff --git a/_static/locales/te/LC_MESSAGES/booktheme.mo b/_static/locales/te/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..0a5f4b46adfda1551ae6791c3c3782525b61be04 GIT binary patch literal 1806 zcmbu8?`s@I7{^DgzpiR+74e1QD2kPOYU&G1LO_}((2{DPsaEjK=5D&TdYxHz_mbva zT2L$M3z1kXg(AcfwAS4~Neb5f0lujqQV?VieD5FN3qLcn=UrpK7cRH^*?DH3U*CQ1 zw_V$o1=qvek8yv`{W$mAxAEY*0dI#t!Motk@Lu>Ud<6aho$p_87u?C=2jJ6i2YeYi zzX^ChJOuB9$KXz=YA)3F59{^k(B)Z$4Y&rK|263Re}o(GCUki}y(4f1KFWF>z6o!@ z*Wm7LLQKL1xEEf7ufjj!vvA~2A@;zx;Pdc3_zYZw?)**o1l&$Dhu|Lg6r6|7{snaU zU4^f}Um%kFbGaHHtXJD1WeGz1>mHu2N2iC=&RtGZchR1B$iD?W+^g&V?%L)waXOPu z(25ZI7x~Geqr`+s7qcYp6yktc&|MR?r8b3{Gv-}+Jn5=|IXAtmr8XIhPLj(sij|mb zCj}Av%jqaDWG`(;g=$Nq#dOrut&Vs-Ra!<`CVAddVkS#8PDaigm=Z@q{7j`LPYRPQ ziX&+!(I@48SIcZiolwF*xU=VM^?@zFv*l@L zDz6jwvaMLG-4f{crQm*REN}ghN#a8coKPu>p z%YTFt$m|qAXTDh&g5gT~hljsJ*ry=A+<9Nb1sA(o5-xGw{Z;?6OlS@gI#jemLQG%z zrpf6>XY=H3-bW;Qrf>v2>%ZN4n4aM|U<|2-ZBn^mBghuhM0)Dv2+@ei()B(V2&(za uuMrF7ToguSy%w`N&3+IHSt#2LVBfiP)B5iT;9Jx)h5&elIS4O(ZT|-CPABOA literal 0 HcmV?d00001 diff --git a/_static/locales/te/LC_MESSAGES/booktheme.po b/_static/locales/te/LC_MESSAGES/booktheme.po index 0373b70..2595c03 100644 --- a/_static/locales/te/LC_MESSAGES/booktheme.po +++ b/_static/locales/te/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: te\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "ఓపెన్ ఇష్యూ" +msgid "suggest edit" +msgstr "సవరించమని సూచించండి" -msgid "Download this page" -msgstr "ఈ పేజీని డౌన్‌లోడ్ చేయండి" +msgid "Last updated on" +msgstr "చివరిగా నవీకరించబడింది" -msgid "Download source file" -msgstr "మూల ఫైల్‌ను డౌన్‌లోడ్ చేయండి" +msgid "Edit this page" +msgstr "ఈ పేజీని సవరించండి" msgid "Launch" msgstr "ప్రారంభించండి" -msgid "Edit this page" -msgstr "ఈ పేజీని సవరించండి" +msgid "Print to PDF" +msgstr "PDF కి ముద్రించండి" + +msgid "open issue" +msgstr "ఓపెన్ ఇష్యూ" + +msgid "Download notebook file" +msgstr "నోట్బుక్ ఫైల్ను డౌన్లోడ్ చేయండి" msgid "Toggle navigation" msgstr "నావిగేషన్‌ను టోగుల్ చేయండి" -msgid "Theme by the" -msgstr "ద్వారా థీమ్" - msgid "Source repository" msgstr "మూల రిపోజిటరీ" -msgid "Last updated on" -msgstr "చివరిగా నవీకరించబడింది" - msgid "By the" msgstr "ద్వారా" +msgid "next page" +msgstr "తరువాతి పేజీ" + msgid "Sphinx Book Theme" msgstr "సింహిక పుస్తక థీమ్" -msgid "Open an issue" -msgstr "సమస్యను తెరవండి" +msgid "Download source file" +msgstr "మూల ఫైల్‌ను డౌన్‌లోడ్ చేయండి" -msgid "next page" -msgstr "తరువాతి పేజీ" +msgid "By" +msgstr "ద్వారా" msgid "Copyright" msgstr "కాపీరైట్" -msgid "Search this book..." -msgstr "ఈ పుస్తకాన్ని శోధించండి ..." - -msgid "Print to PDF" -msgstr "PDF కి ముద్రించండి" - -msgid "By" -msgstr "ద్వారా" +msgid "Open an issue" +msgstr "సమస్యను తెరవండి" msgid "previous page" msgstr "ముందు పేజి" -msgid "Download notebook file" -msgstr "నోట్బుక్ ఫైల్ను డౌన్లోడ్ చేయండి" +msgid "Download this page" +msgstr "ఈ పేజీని డౌన్‌లోడ్ చేయండి" -msgid "suggest edit" -msgstr "సవరించమని సూచించండి" +msgid "Theme by the" +msgstr "ద్వారా థీమ్" diff --git a/_static/locales/tg/LC_MESSAGES/booktheme.mo b/_static/locales/tg/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..b21c6c6340194fdf35f7e5660deb42479c8dbff9 GIT binary patch literal 1628 zcmaiyO^6gn6vxZY=tNE8S5Q|hA#9RE$8XSGCI@vF1jR*HLCB?drtIlBTh(+|t9#pZ z_b^Dr#19Y@K@`-J?Yg?{x;qOwd8{6D@{o&%oP^*d#K?f}Wpw_pnH1Q&v@ z3%&tK*FWF}u!PNBU}wRfz%8&Zfe!dP_zn0sxE@@yD9?KJ9kAteKMU^WF zJC>CiI~?GEE4d#GJ20M-!R?)~ z>>S<1-6l7a<}oHySZKVs&CQhc{Mbyqb88w7X3RqzI{&F#*USvhMoiLrM6s>Hk4E|6 zc@o%qM9F2t?V4KSrinZf?58}t0JXzb84{b#Mr}$-{y{=+V#Xn)X(lNzTPtR6wl32O zGdJL5Bs-5oxB+T`zIGRrAt`^lPLZT?M?g!0angPB{%GR5vxHp0oR8Arqi zbZiRp&%w__8!lf*NbDpe;WA2%r?Xi$atSF8VXr;q_FB@_W_A(5kPfr&0p+;^8?eY= pg1vVOUqyoB&tBYSn9xh&7BjPW`v%MukJU629MMs5Ow+8v{s(GpYQg{j literal 0 HcmV?d00001 diff --git a/_static/locales/tg/LC_MESSAGES/booktheme.po b/_static/locales/tg/LC_MESSAGES/booktheme.po index 1807ae2..73cd30e 100644 --- a/_static/locales/tg/LC_MESSAGES/booktheme.po +++ b/_static/locales/tg/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: tg\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "анбор" - -msgid "open issue" -msgstr "барориши кушод" - -msgid "Contents" -msgstr "Мундариҷа" - -msgid "Fullscreen mode" -msgstr "Ҳолати экрани пурра" +msgid "suggest edit" +msgstr "пешниҳод вироиш" -msgid "Download this page" -msgstr "Ин саҳифаро зеркашӣ кунед" +msgid "Last updated on" +msgstr "Last навсозӣ дар" -msgid "Download source file" -msgstr "Файли манбаъро зеркашӣ кунед" +msgid "Edit this page" +msgstr "Ин саҳифаро таҳрир кунед" msgid "Launch" msgstr "Оғоз" -msgid "Edit this page" -msgstr "Ин саҳифаро таҳрир кунед" +msgid "Print to PDF" +msgstr "Чоп ба PDF" + +msgid "open issue" +msgstr "барориши кушод" + +msgid "Download notebook file" +msgstr "Файли дафтарро зеркашӣ кунед" msgid "Toggle navigation" msgstr "Гузаришро иваз кунед" -msgid "Theme by the" -msgstr "Мавзӯъи аз" - msgid "Source repository" msgstr "Анбори манбаъ" -msgid "Last updated on" -msgstr "Last навсозӣ дар" - msgid "By the" msgstr "Бо" +msgid "next page" +msgstr "саҳифаи оянда" + +msgid "repository" +msgstr "анбор" + msgid "Sphinx Book Theme" msgstr "Сфинкс Мавзӯи китоб" -msgid "Open an issue" -msgstr "Масъаларо кушоед" +msgid "Download source file" +msgstr "Файли манбаъро зеркашӣ кунед" -msgid "next page" -msgstr "саҳифаи оянда" +msgid "Contents" +msgstr "Мундариҷа" + +msgid "By" +msgstr "Бо" msgid "Copyright" msgstr "Ҳуқуқи муаллиф" -msgid "Search this book..." -msgstr "Ин китобро ҷустуҷӯ кунед ..." - -msgid "Print to PDF" -msgstr "Чоп ба PDF" +msgid "Fullscreen mode" +msgstr "Ҳолати экрани пурра" -msgid "By" -msgstr "Бо" +msgid "Open an issue" +msgstr "Масъаларо кушоед" msgid "previous page" msgstr "саҳифаи қаблӣ" -msgid "Search the docs ..." -msgstr "Ҷустуҷӯи ҳуҷҷатҳо ..." - -msgid "Download notebook file" -msgstr "Файли дафтарро зеркашӣ кунед" +msgid "Download this page" +msgstr "Ин саҳифаро зеркашӣ кунед" -msgid "suggest edit" -msgstr "пешниҳод вироиш" +msgid "Theme by the" +msgstr "Мавзӯъи аз" diff --git a/_static/locales/th/LC_MESSAGES/booktheme.mo b/_static/locales/th/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..abede98aa11b163e580a26b545980ace31e61ccf GIT binary patch literal 1766 zcma)*-)|K~6vqcarB^@&)CU_K663GrYB9uM>wQ7mgal$EMW46#4trN`XEwWgD~&H; zNI=2(Qi7!k28|(VOaz2Z{{sC3d@_d21Bp*Q8{hn#*{fZQQ8%6a%*>u2-*e9G?VVdL zD4xeyEM|9;NtGW4!Kz+u&BX3y#5Y_$YiD?uH$>6TSg=Km#9y)rhB| z#94;h;VRq)zl0CNTOLHf&S01Tf9_gR-TKX!nk)j@8 z$!wbssp1UphqNWmR~=a5Pgi}TUURlGwkp}=OGTFUD|OJlYX>grY3nL8@7z23cs4K_ z*QFa4UGulgs-KlQPg0|%ds#*3KaVrR!JzCG##p`JdPW^i%1RIOUQ(H!c9!$dcKhn} z9D~H_tSpB{%@&y@h|{wNXVlR;Utw}rW|b?J)X}`3*%SJJXq)Ss1*76y&(}50xilRZ zZIi_;O{$C})|{wnbx!isN%F!hW^Oo=-3VU})6}5SPzh4p+ooH!5B1t_nxZ7yq^|R~ zC4W0+ZXG#vWP0QK-WMiXqsF%9mU1(xD+Iil50cDI>25zMN>g=?&CRs;Z`c)yEsvX` zJ#D+Lm)Ueu@1M`A*5SmaL;6aLert9xERsQc#uW?Yq_%lHmYtWTbiM67YxSOv-uv8C zONI6KgI^B*v*yl!75w$!KM(#=@YjO>NCp2z@ZSZGG2hr+4E__@te@u_{+M44euZ<4 z_;qwx4(q3b|5Wzei|3W#eYCFwuf#yNf&j$Yu0#;+cXcn64J%wUT=~$4O>SO5=h=^

cLPeiV0|6qlnFzL#U0qn`*`iT?nxl@xb2Mx-{rpyeF$L|PmGL73Xj zjT&US*r9DL+Oc6=XyNi4J`IP)4~3RpiSp}N5WkMWZ=`O(hjnrBo?i;ppCMASYj{fI qV*6MBqwc03(drtRAFXAoSBd=B?a4S*sk|OB^ZqtY{YJQZ;_45RC*i9A literal 0 HcmV?d00001 diff --git a/_static/locales/th/LC_MESSAGES/booktheme.po b/_static/locales/th/LC_MESSAGES/booktheme.po index a286feb..0392b4a 100644 --- a/_static/locales/th/LC_MESSAGES/booktheme.po +++ b/_static/locales/th/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: th\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "ที่เก็บ" - -msgid "open issue" -msgstr "เปิดปัญหา" - -msgid "Contents" -msgstr "สารบัญ" - -msgid "Fullscreen mode" -msgstr "โหมดเต็มหน้าจอ" +msgid "suggest edit" +msgstr "แนะนำแก้ไข" -msgid "Download this page" -msgstr "ดาวน์โหลดหน้านี้" +msgid "Last updated on" +msgstr "ปรับปรุงล่าสุดเมื่อ" -msgid "Download source file" -msgstr "ดาวน์โหลดไฟล์ต้นฉบับ" +msgid "Edit this page" +msgstr "แก้ไขหน้านี้" msgid "Launch" msgstr "เปิด" -msgid "Edit this page" -msgstr "แก้ไขหน้านี้" +msgid "Print to PDF" +msgstr "พิมพ์เป็น PDF" + +msgid "open issue" +msgstr "เปิดปัญหา" + +msgid "Download notebook file" +msgstr "ดาวน์โหลดไฟล์สมุดบันทึก" msgid "Toggle navigation" msgstr "ไม่ต้องสลับช่องทาง" -msgid "Theme by the" -msgstr "ธีมโดย" - msgid "Source repository" msgstr "ที่เก็บซอร์ส" -msgid "Last updated on" -msgstr "ปรับปรุงล่าสุดเมื่อ" - msgid "By the" msgstr "โดย" +msgid "next page" +msgstr "หน้าต่อไป" + +msgid "repository" +msgstr "ที่เก็บ" + msgid "Sphinx Book Theme" msgstr "ธีมหนังสือสฟิงซ์" -msgid "Open an issue" -msgstr "เปิดปัญหา" +msgid "Download source file" +msgstr "ดาวน์โหลดไฟล์ต้นฉบับ" -msgid "next page" -msgstr "หน้าต่อไป" +msgid "Contents" +msgstr "สารบัญ" + +msgid "By" +msgstr "โดย" msgid "Copyright" msgstr "ลิขสิทธิ์" -msgid "Search this book..." -msgstr "ค้นหาหนังสือเล่มนี้ ..." - -msgid "Print to PDF" -msgstr "พิมพ์เป็น PDF" +msgid "Fullscreen mode" +msgstr "โหมดเต็มหน้าจอ" -msgid "By" -msgstr "โดย" +msgid "Open an issue" +msgstr "เปิดปัญหา" msgid "previous page" msgstr "หน้าที่แล้ว" -msgid "Search the docs ..." -msgstr "ค้นหาเอกสาร ..." - -msgid "Download notebook file" -msgstr "ดาวน์โหลดไฟล์สมุดบันทึก" +msgid "Download this page" +msgstr "ดาวน์โหลดหน้านี้" -msgid "suggest edit" -msgstr "แนะนำแก้ไข" +msgid "Theme by the" +msgstr "ธีมโดย" diff --git a/_static/locales/tl/LC_MESSAGES/booktheme.mo b/_static/locales/tl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..8df1b73310e0c606251d1abff7e6033d1f6b273f GIT binary patch literal 1273 zcmZ{iJ#P~+7{?8ixA4}MHz7bWh@lJz6qYJggw!_(YD=U9)PcpxxsJ)jKAr8h8TbH< zl>mt^fEW=h3@|dWP{DwN#01}fk%9knmnKyup2YV%`|Ricw;%r;A9>CYr_e5-eL%a2 z_Gk|th%ew?a0@&DeghAKKfp8KZ;;mh1;@cLOg;`?0Z)LpKw38o9s}=zN5K_v43vGY z_s5_1`!7J!c@37pw;-+m2-5n`;Ct{ph(FuhSLAyJ(z;h52j75~!7cDS_y;@-j*b-m zC%}W~-v&p)J0SUA0Z)SpJPAGlY2GGy4txoc|92qy`UKMYuOOYrFAzsE2s#`3PH_Yc zHrRgZAP%9?9w{GbQ&0{H+8gOp(7q^W|Kx>&wCSAbj3LR`Ob>tV+mg-Nw3lhs_H53s zo5YHk8|!7$+74gUi5w0)8?u(%HR#*g@l+_u=40)Val5-HoaZ5pg_kk6hAoOEtD7`fpKHxt1^q`P0PmGs4|~w zYF}CuMg<%mawMf%5;BoQ3pVSzGB;`7b(Ndbym+ll7=Ee3C$CPI*s^AIft_~oQ`+M| zjoMMlC845tP)?QC3^N9mW&fLyY9mxPB*L)jFaumd3$>sZlm_4E_)y1P<99=X&7mSu zQF#bj7^^11I1!U-GjxO_E86t}@}&6i_@% literal 0 HcmV?d00001 diff --git a/_static/locales/tl/LC_MESSAGES/booktheme.po b/_static/locales/tl/LC_MESSAGES/booktheme.po index 2e09439..c8375b5 100644 --- a/_static/locales/tl/LC_MESSAGES/booktheme.po +++ b/_static/locales/tl/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: tl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "bukas na isyu" +msgid "suggest edit" +msgstr "iminumungkahi i-edit" -msgid "Download this page" -msgstr "I-download ang pahinang ito" +msgid "Last updated on" +msgstr "Huling na-update noong" -msgid "Download source file" -msgstr "Mag-download ng file ng pinagmulan" +msgid "Edit this page" +msgstr "I-edit ang pahinang ito" msgid "Launch" msgstr "Ilunsad" -msgid "Edit this page" -msgstr "I-edit ang pahinang ito" +msgid "Print to PDF" +msgstr "I-print sa PDF" + +msgid "open issue" +msgstr "bukas na isyu" + +msgid "Download notebook file" +msgstr "Mag-download ng file ng notebook" msgid "Toggle navigation" msgstr "I-toggle ang pag-navigate" -msgid "Theme by the" -msgstr "Tema ng" - msgid "Source repository" msgstr "Pinagmulan ng imbakan" -msgid "Last updated on" -msgstr "Huling na-update noong" - msgid "By the" msgstr "Sa pamamagitan ng" +msgid "next page" +msgstr "Susunod na pahina" + msgid "Sphinx Book Theme" msgstr "Tema ng Sphinx Book" -msgid "Open an issue" -msgstr "Magbukas ng isyu" +msgid "Download source file" +msgstr "Mag-download ng file ng pinagmulan" -msgid "next page" -msgstr "Susunod na pahina" +msgid "By" +msgstr "Ni" msgid "Copyright" msgstr "Copyright" -msgid "Search this book..." -msgstr "Maghanap sa librong ito ..." - -msgid "Print to PDF" -msgstr "I-print sa PDF" - -msgid "By" -msgstr "Ni" +msgid "Open an issue" +msgstr "Magbukas ng isyu" msgid "previous page" msgstr "Nakaraang pahina" -msgid "Download notebook file" -msgstr "Mag-download ng file ng notebook" +msgid "Download this page" +msgstr "I-download ang pahinang ito" -msgid "suggest edit" -msgstr "iminumungkahi i-edit" +msgid "Theme by the" +msgstr "Tema ng" diff --git a/_static/locales/tr/LC_MESSAGES/booktheme.mo b/_static/locales/tr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..029ae18afb5360a8c238a052e8d3971761759d3d GIT binary patch literal 1373 zcmZ{izi%8x6vqdWKynFz!~~?sQXUOIiX{o62)3@sVLOWA2n!$dC&=i7J19yL{j6T0W2%?d)gY?96-L@67yl{`g~s z_CESD`XA_*&>y~r7uw0!mBOP=;q?Z120RHafv3P_@ICND@LjMEo(I1M&w>oT4aSc5 zLCNz7d<%R6o&kRZ&w(7D`FN2cjBk&jSbMQ3yvf}|L z^-dgb=PiL35fdohSHUH48x$WIDEhw##oq%^>ihtT&YwW>`D+*d4$8W}!FRxeF7BOZ z>s|syPtwI-fS96gfHHp*lr0wzl2>wx9;q$97n`h;HKI?N=#nP7WUs~N1$3mG*A#z? zP4-{T@J)1V%lv%Rpus~iXZ5ACk!=k4s2XpwJgPPKoh_YC$-2lp&J{E^B_9n3SNjqF zXE5d_P^B|g>#2!IeHd=kWf?}E+0w+NtTuIsR9C5voRYJMYdgx-R~05`OD2Sx)s{CF zNgQphZK&MIp`-&XC zw^i0&m&u0nldwXznunqP*($Z4{f{ku(5I`PtoGDUdp(}*+f>_seb0WLJ~cMw0*C6= zkV`YBTo=V`U#;;tvZvIAMh7gN?Gt7i9EQ538>@@sDR7=_PxgBv?;s7aXZ*rps`o&(U<3tx~U_1rqYg?0^K7|^E%RsJ#t%4f8 zo6h$Ap{&BCl*;`;;xXGI&@B^nMMIv5kwyPFiiuV?c-PnoHwMdQd*;PnG+qT~k=xL= f7*f}zXhDUuwVFPIQ2d!&RZ>YE8iRKH#ZJBgJpfrQ literal 0 HcmV?d00001 diff --git a/_static/locales/tr/LC_MESSAGES/booktheme.po b/_static/locales/tr/LC_MESSAGES/booktheme.po index fe21499..47d7bdf 100644 --- a/_static/locales/tr/LC_MESSAGES/booktheme.po +++ b/_static/locales/tr/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: tr\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "depo" - -msgid "open issue" -msgstr "Açık konu" - -msgid "Contents" -msgstr "İçindekiler" - -msgid "Fullscreen mode" -msgstr "Tam ekran modu" +msgid "suggest edit" +msgstr "düzenleme öner" -msgid "Download this page" -msgstr "Bu sayfayı indirin" +msgid "Last updated on" +msgstr "Son güncelleme tarihi" -msgid "Download source file" -msgstr "Kaynak dosyayı indirin" +msgid "Edit this page" +msgstr "Bu sayfayı düzenle" msgid "Launch" msgstr "Başlatmak" -msgid "Edit this page" -msgstr "Bu sayfayı düzenle" +msgid "Print to PDF" +msgstr "PDF olarak yazdır" + +msgid "open issue" +msgstr "Açık konu" + +msgid "Download notebook file" +msgstr "Defter dosyasını indirin" msgid "Toggle navigation" msgstr "Gezinmeyi değiştir" -msgid "Theme by the" -msgstr "Tarafından tema" - msgid "Source repository" msgstr "Kaynak kod deposu" -msgid "Last updated on" -msgstr "Son güncelleme tarihi" - msgid "By the" msgstr "Tarafından" +msgid "next page" +msgstr "sonraki Sayfa" + +msgid "repository" +msgstr "depo" + msgid "Sphinx Book Theme" msgstr "Sfenks Kitap Teması" -msgid "Open an issue" -msgstr "Bir sorunu açın" +msgid "Download source file" +msgstr "Kaynak dosyayı indirin" -msgid "next page" -msgstr "sonraki Sayfa" +msgid "Contents" +msgstr "İçindekiler" + +msgid "By" +msgstr "Tarafından" msgid "Copyright" msgstr "Telif hakkı" -msgid "Search this book..." -msgstr "Bu kitabı ara ..." - -msgid "Print to PDF" -msgstr "PDF olarak yazdır" +msgid "Fullscreen mode" +msgstr "Tam ekran modu" -msgid "By" -msgstr "Tarafından" +msgid "Open an issue" +msgstr "Bir sorunu açın" msgid "previous page" msgstr "önceki sayfa" -msgid "Search the docs ..." -msgstr "Belgelerde ara ..." - -msgid "Download notebook file" -msgstr "Defter dosyasını indirin" +msgid "Download this page" +msgstr "Bu sayfayı indirin" -msgid "suggest edit" -msgstr "düzenleme öner" +msgid "Theme by the" +msgstr "Tarafından tema" diff --git a/_static/locales/uk/LC_MESSAGES/booktheme.mo b/_static/locales/uk/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..16ab78909cfbaba7fa199f47fdfc2934426ac699 GIT binary patch literal 1681 zcmZvaO>7%Q6vv0QKx#^WmXAw-X;52=V^7yhotb5Kwlue- zPJ@uD1fdWPh|e20*TKPc;zZ)a@r}d@A+B8DUJjM|f4dvvq>McK+j;xuef*#QJbLI0 zf%O{p5cY4_Z(`qj3JD;1Tdg@Fj3P=dZc__x$`9$oc*S3*fo^agnKo4Zexd+ydwLFH++H&9h3nhscvH3nP?w=Ry$GKV8 zSFn*%JcrG*?O#Zh&hS|fa-{PW7iaO4wx+~;Mq8zAjF)gW3jCTCm(0hyZoI10#;R#! zZps@$UG17A`bVb!y$DvicD z(UqEbKZJv)We~@S5))CN5yZ%eOXK2NmM>DFi34k*S#d3_1^TwU$hA$?)Ql48Q%+|+ zO&Q;>E2+I(f$!M>Nwm6cv+4}z$&!STx)qotFS{>%ocO*%l?t7p6!W2~*y81C@dFjb zh*pwW{vziurkM*@FJB$o{eEubY#|r6I5iuplC&t`Oj!2O`(TSv<;z`$dL~;A5u^%qBgBK^s=!h>rLI6)qdpT zRwLUoA{Qc+BL{@CNd#$~fM}{TM=rgzQV%n0sfS7&;BP2WpLe~9L#0ZLy!)G(eLtS} z@uTBCHyGACc;3gei{}G8S6;vi>pu7*_yBwvdd_{ zw7^~PH24qrDR`oXv3~FiknZO|ioXGV2*%(?;Gf{z;NRf8;J+FBUg~@w04eVRNO2|b zJ#Z2H7+e8i$-yFT-pWp-6LJ_r(sdMXnvv>}ceKb;S{N^_PkZu%7R~=ky6bpCK9k3g z$k@3h{CHRvY(#lWzU!1jHmVk6McE}TRVZeZy2@wWis)VkD)Nisnai;32Hdk9!Ny8% zh>H8iNjnI6>?(vD=Y%)au3|&?BFFX~vq4Jm5 zMX&72MShO7Oqazq!O}OM=}4bej#Cj_+Vieshc22(u^4vLDC*N`;`w6URZ%80h#W^i znt)vNS978mS`#JfvhV|x$n#E9i<(+#yWIJS^JCrbgJ(X=jVKuk8Cugzp2+hMT?f31 z?aE=i4%v6}~kli>l;GC(nmw+%Pw3ODBSPc^>(>sY>MA6>D7i z*MdBkUV01)pAYlSw$Ly6$pRnzWH`t4n!cr5?Pa~wuCipkz0CC=x@BmuW3xx+mX7tR z*NZtNFp)tbr@2L4}dj%B? z$~?F1e_~CYdU3r0$=I6uq5ePVO_Bn=P}riFSZ}qf6oE57w5w3K+FoX+hEW?y<4|&p zx|p)Aw=sGx%}Vw#el49X^(ARiaRizwH+vA!fH?=_BQ=JATO9Uo!rm6_g(Z9Fvrf~J ziFzY}!KTjO`w9hS|3mkKY2Z8hBsWpwH*$FgF5fip{lMp#&N|*Vkp4MHrJJsNw1%8D c^9?3>eEmE8GP@z_uy-`khW>?G>aA{%rxd0lq5uE@ literal 0 HcmV?d00001 diff --git a/_static/locales/ur/LC_MESSAGES/booktheme.po b/_static/locales/ur/LC_MESSAGES/booktheme.po index 4c4c637..0f90726 100644 --- a/_static/locales/ur/LC_MESSAGES/booktheme.po +++ b/_static/locales/ur/LC_MESSAGES/booktheme.po @@ -8,62 +8,59 @@ msgstr "" "Language: ur\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "open issue" -msgstr "کھلا مسئلہ" +msgid "suggest edit" +msgstr "ترمیم کی تجویز کریں" -msgid "Download this page" -msgstr "اس صفحے کو ڈاؤن لوڈ کریں" +msgid "Last updated on" +msgstr "آخری بار تازہ کاری ہوئی" -msgid "Download source file" -msgstr "سورس فائل ڈاؤن لوڈ کریں" +msgid "Edit this page" +msgstr "اس صفحے میں ترمیم کریں" msgid "Launch" msgstr "لانچ کریں" -msgid "Edit this page" -msgstr "اس صفحے میں ترمیم کریں" +msgid "Print to PDF" +msgstr "پی ڈی ایف پرنٹ کریں" + +msgid "open issue" +msgstr "کھلا مسئلہ" + +msgid "Download notebook file" +msgstr "نوٹ بک فائل ڈاؤن لوڈ کریں" msgid "Toggle navigation" msgstr "نیویگیشن ٹوگل کریں" -msgid "Theme by the" -msgstr "کے ذریعہ تھیم" - msgid "Source repository" msgstr "ماخذ ذخیرہ" -msgid "Last updated on" -msgstr "آخری بار تازہ کاری ہوئی" - msgid "By the" msgstr "کی طرف" +msgid "next page" +msgstr "اگلا صفحہ" + msgid "Sphinx Book Theme" msgstr "سپنکس بک تھیم" -msgid "Open an issue" -msgstr "ایک مسئلہ کھولیں" +msgid "Download source file" +msgstr "سورس فائل ڈاؤن لوڈ کریں" -msgid "next page" -msgstr "اگلا صفحہ" +msgid "By" +msgstr "بذریعہ" msgid "Copyright" msgstr "کاپی رائٹ" -msgid "Search this book..." -msgstr "اس کتاب کو تلاش کریں…" - -msgid "Print to PDF" -msgstr "پی ڈی ایف پرنٹ کریں" - -msgid "By" -msgstr "بذریعہ" +msgid "Open an issue" +msgstr "ایک مسئلہ کھولیں" msgid "previous page" msgstr "سابقہ ​​صفحہ" -msgid "Download notebook file" -msgstr "نوٹ بک فائل ڈاؤن لوڈ کریں" +msgid "Download this page" +msgstr "اس صفحے کو ڈاؤن لوڈ کریں" -msgid "suggest edit" -msgstr "ترمیم کی تجویز کریں" +msgid "Theme by the" +msgstr "کے ذریعہ تھیم" diff --git a/_static/locales/vi/LC_MESSAGES/booktheme.mo b/_static/locales/vi/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..2bb32555c3ea0dab08ed37b71cb863fbe75698c6 GIT binary patch literal 1431 zcmZvb&x;&I6vr#s{2bR9catc(#OK8%htWiG2(!#(H#@MntBVvV&v#)!JFr^_{KP>F`@nJV05}OA1gF4b;9KAkunA6pAA*NK z3BCmSiq}An^CkEqxCxGf--9oMKUe&tTK}_}KL%Ov30MQi#>)GLK%P&59Onf13wRdX z3;qSN-ajCp`xj*0y?e@hC&AY-KMlSLE>x7&{%7EEtZ#xGrw?+zzkx4+4=O$aInLi8 z=P?fP6X0=>=PmFs_%X6t9{djXqq7H;REU`#e&m%Dv(|WNyu(A%OLe5YIB!2Su?;$8te4By zUZxct%bjIsvow_dS@cRfN`gp=xsLV-{cPIG;@E|$l!jJqM~a2OdCHPb;AMxb!8|je z5+5Wu5E#l0;esOMR|IFK`YgJ+E?Oq}qlDRK7TFmDND~hLNUKno*_5*I#duC ze1pUH?uya95XS7fK6vqb$6da&5d>$e(Tqr%5FL8(*`2r*YiH`^Z>aE(?ll6i#v)Y{nLNAmS zVZLM|@+Cqff{+L(H9>+X*h#n|&YXJarQWrDsNf1G{?EIRgwekJ?VFu>|Np%Cx20*2 zVQfXTBHkmmBW^Fl3uEes3ZOb zQk?;C9XJZE1)qXHfzuJ+M)Utfc@-qRPhbpOu_D~R9;Cb#q&h!?W$*w<>pw>P43chB zQ^;m;Gx8RY{OyX^7V!v3^?n6uod9Y7@6r5Kko@OC(isEk+)qHNR|2Y~glBh97KqDQIoyw}Q#g=trLPD*?? zsWX<#ZNn6-BW-Dv{+f1r*{qv#gpj;Xr3E`?xSD%*+R!4+l|=5zREC|jvA~era$Qfb zF2|B6qIlQgPIfxfbA+v2ODm_JowhTUyu=TZx9*JS6Rh#(J>i+Um1$-Lm&OIlG_(Z~ zDK6>Iog$r3#CF65OL>v)Mde-3GzDA=oCH?XIg!%wqv`lr;kc-l;Guq;^y3ZX*zu#s zI~M-$+r2jyH8$SeZ;J%iFtEqY8kTJ5sf^*cLMP93cgEWm);WfBdxaD4kSUe6q?zDt zJ(i9gGoRpuVl zu3Y;tdw+Y?BAIRa)rh7%Q6vqb|O6z_>OFs^gI=uiz7%1XUIrvhVNR?8ES{E)zXk$;;3!9nM?rdo| zg(?BJNt;NGU78fyR1pmy`2barI!U>5;l_yr7d&hG1XmCT{?EI?hS9$L&6|(+{`20i zd%MaE;~=aX_A~4-Y~m68Ft$C)7(TWgzpda-a2vP}+zxhw2f(Mnr@$<@7d!**1_ihW z)CosHiZc!F0%yUU;1}SN;CBgsOxAx%{5nYa{sdFtmM!u9-5~khAjNqGTmxSL>HHrF z{{ks*S695g10>!1LDKhp!dDaaCwv>+k9`-U`l4+X18A zb`E+6_3&{R%F^mDJ28xp>!M(W-N{d0I-s9&TSG1P{ z75aJczeQbi0`6J1V7&!LBlM=*7rJhc_l1yrNEHO@w*t*WuV86W;7Y;|WxmMX@NmGA z+zEnEumRtZ2%`AF$v$>A&gTnH1&&t!FgxoN9eI(TAZ@v#7!s`Y=Y#Q^a>}+{!KHP< zu`TT&i4+%gtWHs$IEm+r3yumC*&X47(6$9s3cLhT)Vm_D)29mQH-#S{T878@)098m z%A7iV>U3{=|JVyJrINy?bHkpi>0X&v z1xMN$etgi;seVh^A?ljp9~9roy_FhpL*H`KeaasSGF*BsH^{!+!{cf8S;>!N`LUxt zDOTIK)fgH3eSM~5R-avJPKqIR9T5`UTRjZlMYk9ZN|&2 zSsBNyvAEKln_#AN!(3g7N>iJPqMOUL)it`->9il( zoLjEXSEEv;IrB~9#-v%f*7$q_8AyL^bp+y>8T%Uf>ocRKJlP7gdS!Fx->lK(l=-+? P`(Y`Xeqh$BP|E%Rvo4ks literal 0 HcmV?d00001 diff --git a/_static/locales/zh_TW/LC_MESSAGES/booktheme.po b/_static/locales/zh_TW/LC_MESSAGES/booktheme.po index 52cff5e..7833d90 100644 --- a/_static/locales/zh_TW/LC_MESSAGES/booktheme.po +++ b/_static/locales/zh_TW/LC_MESSAGES/booktheme.po @@ -8,74 +8,68 @@ msgstr "" "Language: zh_TW\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "repository" -msgstr "資料庫" - -msgid "open issue" -msgstr "公開的問題" +msgid "suggest edit" +msgstr "提出修改建議" -msgid "Contents" -msgstr "內容" +msgid "Last updated on" +msgstr "最後更新時間:" -msgid "Fullscreen mode" -msgstr "全屏模式" +msgid "Edit this page" +msgstr "編輯此頁面" -msgid "Download this page" -msgstr "下載此頁面" +msgid "Launch" +msgstr "啟動" -msgid "Download source file" -msgstr "下載源文件" +msgid "Print to PDF" +msgstr "列印成 PDF" -msgid "Launch" -msgstr "發射" +msgid "open issue" +msgstr "公開的問題" -msgid "Edit this page" -msgstr "編輯這個頁面" +msgid "Download notebook file" +msgstr "下載 Notebook 檔案" msgid "Toggle navigation" -msgstr "切換導航" - -msgid "Theme by the" -msgstr "主題由" +msgstr "顯示或隱藏導覽列" msgid "Source repository" -msgstr "源庫" - -msgid "Last updated on" -msgstr "上次更新時間:" +msgstr "來源儲存庫" msgid "By the" -msgstr "由" - -msgid "Sphinx Book Theme" -msgstr "獅身人面像書主題" - -msgid "Open an issue" -msgstr "打開一個問題" +msgstr "作者:" msgid "next page" msgstr "下一頁" -msgid "Copyright" -msgstr "版權" +msgid "repository" +msgstr "儲存庫" -msgid "Search this book..." -msgstr "搜索這本書..." +msgid "Sphinx Book Theme" +msgstr "Sphinx Book 佈景主題" -msgid "Print to PDF" -msgstr "列印成PDF" +msgid "Download source file" +msgstr "下載原始檔" + +msgid "Contents" +msgstr "目錄" msgid "By" -msgstr "通過" +msgstr "作者:" + +msgid "Copyright" +msgstr "Copyright" + +msgid "Fullscreen mode" +msgstr "全螢幕模式" + +msgid "Open an issue" +msgstr "開啟議題" msgid "previous page" msgstr "上一頁" -msgid "Search the docs ..." -msgstr "搜索文檔..." - -msgid "Download notebook file" -msgstr "下載筆記本文件" +msgid "Download this page" +msgstr "下載此頁面" -msgid "suggest edit" -msgstr "建議編輯" +msgid "Theme by the" +msgstr "佈景主題作者:" diff --git a/_static/mystnb.css b/_static/mystnb.4510f1fc1dee50b3e5859aac5469c37c29e427902b24a333a5f9fcb2f0b3ac41.css similarity index 87% rename from _static/mystnb.css rename to _static/mystnb.4510f1fc1dee50b3e5859aac5469c37c29e427902b24a333a5f9fcb2f0b3ac41.css index e0ca0e1..3356631 100644 --- a/_static/mystnb.css +++ b/_static/mystnb.4510f1fc1dee50b3e5859aac5469c37c29e427902b24a333a5f9fcb2f0b3ac41.css @@ -1,3 +1,19 @@ +/* Variables */ +:root { + --mystnb-source-bg-color: #f7f7f7; + --mystnb-stdout-bg-color: #fcfcfc; + --mystnb-stderr-bg-color: #fdd; + --mystnb-traceback-bg-color: #fcfcfc; + --mystnb-source-border-color: #ccc; + --mystnb-source-margin-color: green; + --mystnb-stdout-border-color: #f7f7f7; + --mystnb-stderr-border-color: #f7f7f7; + --mystnb-traceback-border-color: #ffd6d6; + --mystnb-hide-prompt-opacity: 70%; + --mystnb-source-border-radius: .4em; + --mystnb-source-border-width: 1px; +} + /* Whole cell */ div.container.cell { padding-left: 0; @@ -5,26 +21,33 @@ div.container.cell { } /* Removing all background formatting so we can control at the div level */ -.cell_input div.highlight, .cell_output pre, .cell_input pre, .cell_output .output { +.cell_input div.highlight, +.cell_output pre, +.cell_input pre, +.cell_output .output { border: none; box-shadow: none; } -.cell_output .output pre, .cell_input pre { +.cell_output .output pre, +.cell_input pre { margin: 0px; } /* Input cells */ -div.cell div.cell_input { +div.cell div.cell_input, +div.cell details.above-input>summary { padding-left: 0em; padding-right: 0em; - border: 1px #ccc solid; - background-color: #f7f7f7; - border-left-color: green; + border: var(--mystnb-source-border-width) var(--mystnb-source-border-color) solid; + background-color: var(--mystnb-source-bg-color); + border-left-color: var(--mystnb-source-margin-color); border-left-width: medium; + border-radius: var(--mystnb-source-border-radius); } -div.cell_input > div, div.cell_output div.output > div.highlight { +div.cell_input>div, +div.cell_output div.output>div.highlight { margin: 0em !important; border: none !important; } @@ -36,41 +59,99 @@ div.cell_input > div, div.cell_output div.output > div.highlight { margin-top: 1em; } -/* Outputs from jupyter_sphinx overrides to remove extra CSS */ -div.section div.jupyter_container { - padding: .4em; - margin: 0 0 .4em 0; - background-color: none; - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - /* Text outputs from cells */ .cell_output .output.text_plain, .cell_output .output.traceback, .cell_output .output.stream, -.cell_output .output.stderr - { - background: #fcfcfc; +.cell_output .output.stderr { margin-top: 1em; margin-bottom: 0em; box-shadow: none; } .cell_output .output.text_plain, -.cell_output .output.stream, -.cell_output .output.stderr { - border: 1px solid #f7f7f7; +.cell_output .output.stream { + background: var(--mystnb-stdout-bg-color); + border: 1px solid var(--mystnb-stdout-border-color); } .cell_output .output.stderr { - background: #fdd; + background: var(--mystnb-stderr-bg-color); + border: 1px solid var(--mystnb-stderr-border-color); } .cell_output .output.traceback { - border: 1px solid #ffd6d6; + background: var(--mystnb-traceback-bg-color); + border: 1px solid var(--mystnb-traceback-border-color); +} + +/* Collapsible cell content */ +div.cell details.above-input div.cell_input { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-top: var(--mystnb-source-border-width) var(--mystnb-source-border-color) dashed; +} + +div.cell div.cell_input.above-output-prompt { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +div.cell details.above-input>summary { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom: var(--mystnb-source-border-width) var(--mystnb-source-border-color) dashed; + padding-left: 1em; + margin-bottom: 0; +} + +div.cell details.above-output>summary { + background-color: var(--mystnb-source-bg-color); + padding-left: 1em; + padding-right: 0em; + border: var(--mystnb-source-border-width) var(--mystnb-source-border-color) solid; + border-radius: var(--mystnb-source-border-radius); + border-left-color: var(--mystnb-source-margin-color); + border-left-width: medium; +} + +div.cell details.below-input>summary { + background-color: var(--mystnb-source-bg-color); + padding-left: 1em; + padding-right: 0em; + border: var(--mystnb-source-border-width) var(--mystnb-source-border-color) solid; + border-top: none; + border-bottom-left-radius: var(--mystnb-source-border-radius); + border-bottom-right-radius: var(--mystnb-source-border-radius); + border-left-color: var(--mystnb-source-margin-color); + border-left-width: medium; +} + +div.cell details.hide>summary>span { + opacity: var(--mystnb-hide-prompt-opacity); +} + +div.cell details.hide[open]>summary>span.collapsed { + display: none; +} + +div.cell details.hide:not([open])>summary>span.expanded { + display: none; +} + +@keyframes collapsed-fade-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} +div.cell details.hide[open]>summary~* { + -moz-animation: collapsed-fade-in 0.3s ease-in-out; + -webkit-animation: collapsed-fade-in 0.3s ease-in-out; + animation: collapsed-fade-in 0.3s ease-in-out; } /* Math align to the left */ @@ -80,38 +161,47 @@ div.section div.jupyter_container { /* Pandas tables. Pulled from the Jupyter / nbsphinx CSS */ div.cell_output table { - border: none; - border-collapse: collapse; - border-spacing: 0; - color: black; - font-size: 1em; - table-layout: fixed; - } - div.cell_output thead { - border-bottom: 1px solid black; - vertical-align: bottom; - } - div.cell_output tr, - div.cell_output th, - div.cell_output td { - text-align: right; - vertical-align: middle; - padding: 0.5em 0.5em; - line-height: normal; - white-space: normal; - max-width: none; - border: none; - } - div.cell_output th { - font-weight: bold; - } - div.cell_output tbody tr:nth-child(odd) { - background: #f5f5f5; - } - div.cell_output tbody tr:hover { - background: rgba(66, 165, 245, 0.2); - } + border: none; + border-collapse: collapse; + border-spacing: 0; + color: black; + font-size: 1em; + table-layout: fixed; +} + +div.cell_output thead { + border-bottom: 1px solid black; + vertical-align: bottom; +} +div.cell_output tr, +div.cell_output th, +div.cell_output td { + text-align: right; + vertical-align: middle; + padding: 0.5em 0.5em; + line-height: normal; + white-space: normal; + max-width: none; + border: none; +} + +div.cell_output th { + font-weight: bold; +} + +div.cell_output tbody tr:nth-child(odd) { + background: #f5f5f5; +} + +div.cell_output tbody tr:hover { + background: rgba(66, 165, 245, 0.2); +} + +/** source code line numbers **/ +span.linenos { + opacity: 0.5; +} /* Inline text from `paste` operation */ @@ -128,56 +218,75 @@ tbody span.pasted-inline img { } /* Font colors for translated ANSI escape sequences -Color values are adapted from share/jupyter/nbconvert/templates/classic/static/style.css +Color values are copied from Jupyter Notebook +https://github.com/jupyter/notebook/blob/52581f8eda9b319eb0390ac77fe5903c38f81e3e/notebook/static/notebook/less/ansicolors.less#L14-L21 +Background colors from +https://nbsphinx.readthedocs.io/en/latest/code-cells.html#ANSI-Colors */ div.highlight .-Color-Bold { font-weight: bold; } + div.highlight .-Color[class*=-Black] { - color :#3E424D + color: #3E424D } + div.highlight .-Color[class*=-Red] { color: #E75C58 } + div.highlight .-Color[class*=-Green] { color: #00A250 } + div.highlight .-Color[class*=-Yellow] { - color: yellow + color: #DDB62B } + div.highlight .-Color[class*=-Blue] { color: #208FFB } + div.highlight .-Color[class*=-Magenta] { color: #D160C4 } + div.highlight .-Color[class*=-Cyan] { color: #60C6C8 } + div.highlight .-Color[class*=-White] { color: #C5C1B4 } + div.highlight .-Color[class*=-BGBlack] { background-color: #3E424D } + div.highlight .-Color[class*=-BGRed] { background-color: #E75C58 } + div.highlight .-Color[class*=-BGGreen] { background-color: #00A250 } + div.highlight .-Color[class*=-BGYellow] { - background-color: yellow + background-color: #DDB62B } + div.highlight .-Color[class*=-BGBlue] { background-color: #208FFB } + div.highlight .-Color[class*=-BGMagenta] { background-color: #D160C4 } + div.highlight .-Color[class*=-BGCyan] { background-color: #60C6C8 } + div.highlight .-Color[class*=-BGWhite] { background-color: #C5C1B4 } @@ -187,1536 +296,2047 @@ div.highlight .-Color[class*=-BGWhite] { div.highlight .-Color[class*=-C0] { color: #000000 } + div.highlight .-Color[class*=-BGC0] { background-color: #000000 } + div.highlight .-Color[class*=-C1] { color: #800000 } + div.highlight .-Color[class*=-BGC1] { background-color: #800000 } + div.highlight .-Color[class*=-C2] { color: #008000 } + div.highlight .-Color[class*=-BGC2] { background-color: #008000 } + div.highlight .-Color[class*=-C3] { color: #808000 } + div.highlight .-Color[class*=-BGC3] { background-color: #808000 } + div.highlight .-Color[class*=-C4] { color: #000080 } + div.highlight .-Color[class*=-BGC4] { background-color: #000080 } + div.highlight .-Color[class*=-C5] { color: #800080 } + div.highlight .-Color[class*=-BGC5] { background-color: #800080 } + div.highlight .-Color[class*=-C6] { color: #008080 } + div.highlight .-Color[class*=-BGC6] { background-color: #008080 } + div.highlight .-Color[class*=-C7] { color: #C0C0C0 } + div.highlight .-Color[class*=-BGC7] { background-color: #C0C0C0 } + div.highlight .-Color[class*=-C8] { color: #808080 } + div.highlight .-Color[class*=-BGC8] { background-color: #808080 } + div.highlight .-Color[class*=-C9] { color: #FF0000 } + div.highlight .-Color[class*=-BGC9] { background-color: #FF0000 } + div.highlight .-Color[class*=-C10] { color: #00FF00 } + div.highlight .-Color[class*=-BGC10] { background-color: #00FF00 } + div.highlight .-Color[class*=-C11] { color: #FFFF00 } + div.highlight .-Color[class*=-BGC11] { background-color: #FFFF00 } + div.highlight .-Color[class*=-C12] { color: #0000FF } + div.highlight .-Color[class*=-BGC12] { background-color: #0000FF } + div.highlight .-Color[class*=-C13] { color: #FF00FF } + div.highlight .-Color[class*=-BGC13] { background-color: #FF00FF } + div.highlight .-Color[class*=-C14] { color: #00FFFF } + div.highlight .-Color[class*=-BGC14] { background-color: #00FFFF } + div.highlight .-Color[class*=-C15] { color: #FFFFFF } + div.highlight .-Color[class*=-BGC15] { background-color: #FFFFFF } + div.highlight .-Color[class*=-C16] { color: #000000 } + div.highlight .-Color[class*=-BGC16] { background-color: #000000 } + div.highlight .-Color[class*=-C17] { color: #00005F } + div.highlight .-Color[class*=-BGC17] { background-color: #00005F } + div.highlight .-Color[class*=-C18] { color: #000087 } + div.highlight .-Color[class*=-BGC18] { background-color: #000087 } + div.highlight .-Color[class*=-C19] { color: #0000AF } + div.highlight .-Color[class*=-BGC19] { background-color: #0000AF } + div.highlight .-Color[class*=-C20] { color: #0000D7 } + div.highlight .-Color[class*=-BGC20] { background-color: #0000D7 } + div.highlight .-Color[class*=-C21] { color: #0000FF } + div.highlight .-Color[class*=-BGC21] { background-color: #0000FF } + div.highlight .-Color[class*=-C22] { color: #005F00 } + div.highlight .-Color[class*=-BGC22] { background-color: #005F00 } + div.highlight .-Color[class*=-C23] { color: #005F5F } + div.highlight .-Color[class*=-BGC23] { background-color: #005F5F } + div.highlight .-Color[class*=-C24] { color: #005F87 } + div.highlight .-Color[class*=-BGC24] { background-color: #005F87 } + div.highlight .-Color[class*=-C25] { color: #005FAF } + div.highlight .-Color[class*=-BGC25] { background-color: #005FAF } + div.highlight .-Color[class*=-C26] { color: #005FD7 } + div.highlight .-Color[class*=-BGC26] { background-color: #005FD7 } + div.highlight .-Color[class*=-C27] { color: #005FFF } + div.highlight .-Color[class*=-BGC27] { background-color: #005FFF } + div.highlight .-Color[class*=-C28] { color: #008700 } + div.highlight .-Color[class*=-BGC28] { background-color: #008700 } + div.highlight .-Color[class*=-C29] { color: #00875F } + div.highlight .-Color[class*=-BGC29] { background-color: #00875F } + div.highlight .-Color[class*=-C30] { color: #008787 } + div.highlight .-Color[class*=-BGC30] { background-color: #008787 } + div.highlight .-Color[class*=-C31] { color: #0087AF } + div.highlight .-Color[class*=-BGC31] { background-color: #0087AF } + div.highlight .-Color[class*=-C32] { color: #0087D7 } + div.highlight .-Color[class*=-BGC32] { background-color: #0087D7 } + div.highlight .-Color[class*=-C33] { color: #0087FF } + div.highlight .-Color[class*=-BGC33] { background-color: #0087FF } + div.highlight .-Color[class*=-C34] { color: #00AF00 } + div.highlight .-Color[class*=-BGC34] { background-color: #00AF00 } + div.highlight .-Color[class*=-C35] { color: #00AF5F } + div.highlight .-Color[class*=-BGC35] { background-color: #00AF5F } + div.highlight .-Color[class*=-C36] { color: #00AF87 } + div.highlight .-Color[class*=-BGC36] { background-color: #00AF87 } + div.highlight .-Color[class*=-C37] { color: #00AFAF } + div.highlight .-Color[class*=-BGC37] { background-color: #00AFAF } + div.highlight .-Color[class*=-C38] { color: #00AFD7 } + div.highlight .-Color[class*=-BGC38] { background-color: #00AFD7 } + div.highlight .-Color[class*=-C39] { color: #00AFFF } + div.highlight .-Color[class*=-BGC39] { background-color: #00AFFF } + div.highlight .-Color[class*=-C40] { color: #00D700 } + div.highlight .-Color[class*=-BGC40] { background-color: #00D700 } + div.highlight .-Color[class*=-C41] { color: #00D75F } + div.highlight .-Color[class*=-BGC41] { background-color: #00D75F } + div.highlight .-Color[class*=-C42] { color: #00D787 } + div.highlight .-Color[class*=-BGC42] { background-color: #00D787 } + div.highlight .-Color[class*=-C43] { color: #00D7AF } + div.highlight .-Color[class*=-BGC43] { background-color: #00D7AF } + div.highlight .-Color[class*=-C44] { color: #00D7D7 } + div.highlight .-Color[class*=-BGC44] { background-color: #00D7D7 } + div.highlight .-Color[class*=-C45] { color: #00D7FF } + div.highlight .-Color[class*=-BGC45] { background-color: #00D7FF } + div.highlight .-Color[class*=-C46] { color: #00FF00 } + div.highlight .-Color[class*=-BGC46] { background-color: #00FF00 } + div.highlight .-Color[class*=-C47] { color: #00FF5F } + div.highlight .-Color[class*=-BGC47] { background-color: #00FF5F } + div.highlight .-Color[class*=-C48] { color: #00FF87 } + div.highlight .-Color[class*=-BGC48] { background-color: #00FF87 } + div.highlight .-Color[class*=-C49] { color: #00FFAF } + div.highlight .-Color[class*=-BGC49] { background-color: #00FFAF } + div.highlight .-Color[class*=-C50] { color: #00FFD7 } + div.highlight .-Color[class*=-BGC50] { background-color: #00FFD7 } + div.highlight .-Color[class*=-C51] { color: #00FFFF } + div.highlight .-Color[class*=-BGC51] { background-color: #00FFFF } + div.highlight .-Color[class*=-C52] { color: #5F0000 } + div.highlight .-Color[class*=-BGC52] { background-color: #5F0000 } + div.highlight .-Color[class*=-C53] { color: #5F005F } + div.highlight .-Color[class*=-BGC53] { background-color: #5F005F } + div.highlight .-Color[class*=-C54] { color: #5F0087 } + div.highlight .-Color[class*=-BGC54] { background-color: #5F0087 } + div.highlight .-Color[class*=-C55] { color: #5F00AF } + div.highlight .-Color[class*=-BGC55] { background-color: #5F00AF } + div.highlight .-Color[class*=-C56] { color: #5F00D7 } + div.highlight .-Color[class*=-BGC56] { background-color: #5F00D7 } + div.highlight .-Color[class*=-C57] { color: #5F00FF } + div.highlight .-Color[class*=-BGC57] { background-color: #5F00FF } + div.highlight .-Color[class*=-C58] { color: #5F5F00 } + div.highlight .-Color[class*=-BGC58] { background-color: #5F5F00 } + div.highlight .-Color[class*=-C59] { color: #5F5F5F } + div.highlight .-Color[class*=-BGC59] { background-color: #5F5F5F } + div.highlight .-Color[class*=-C60] { color: #5F5F87 } + div.highlight .-Color[class*=-BGC60] { background-color: #5F5F87 } + div.highlight .-Color[class*=-C61] { color: #5F5FAF } + div.highlight .-Color[class*=-BGC61] { background-color: #5F5FAF } + div.highlight .-Color[class*=-C62] { color: #5F5FD7 } + div.highlight .-Color[class*=-BGC62] { background-color: #5F5FD7 } + div.highlight .-Color[class*=-C63] { color: #5F5FFF } + div.highlight .-Color[class*=-BGC63] { background-color: #5F5FFF } + div.highlight .-Color[class*=-C64] { color: #5F8700 } + div.highlight .-Color[class*=-BGC64] { background-color: #5F8700 } + div.highlight .-Color[class*=-C65] { color: #5F875F } + div.highlight .-Color[class*=-BGC65] { background-color: #5F875F } + div.highlight .-Color[class*=-C66] { color: #5F8787 } + div.highlight .-Color[class*=-BGC66] { background-color: #5F8787 } + div.highlight .-Color[class*=-C67] { color: #5F87AF } + div.highlight .-Color[class*=-BGC67] { background-color: #5F87AF } + div.highlight .-Color[class*=-C68] { color: #5F87D7 } + div.highlight .-Color[class*=-BGC68] { background-color: #5F87D7 } + div.highlight .-Color[class*=-C69] { color: #5F87FF } + div.highlight .-Color[class*=-BGC69] { background-color: #5F87FF } + div.highlight .-Color[class*=-C70] { color: #5FAF00 } + div.highlight .-Color[class*=-BGC70] { background-color: #5FAF00 } + div.highlight .-Color[class*=-C71] { color: #5FAF5F } + div.highlight .-Color[class*=-BGC71] { background-color: #5FAF5F } + div.highlight .-Color[class*=-C72] { color: #5FAF87 } + div.highlight .-Color[class*=-BGC72] { background-color: #5FAF87 } + div.highlight .-Color[class*=-C73] { color: #5FAFAF } + div.highlight .-Color[class*=-BGC73] { background-color: #5FAFAF } + div.highlight .-Color[class*=-C74] { color: #5FAFD7 } + div.highlight .-Color[class*=-BGC74] { background-color: #5FAFD7 } + div.highlight .-Color[class*=-C75] { color: #5FAFFF } + div.highlight .-Color[class*=-BGC75] { background-color: #5FAFFF } + div.highlight .-Color[class*=-C76] { color: #5FD700 } + div.highlight .-Color[class*=-BGC76] { background-color: #5FD700 } + div.highlight .-Color[class*=-C77] { color: #5FD75F } + div.highlight .-Color[class*=-BGC77] { background-color: #5FD75F } + div.highlight .-Color[class*=-C78] { color: #5FD787 } + div.highlight .-Color[class*=-BGC78] { background-color: #5FD787 } + div.highlight .-Color[class*=-C79] { color: #5FD7AF } + div.highlight .-Color[class*=-BGC79] { background-color: #5FD7AF } + div.highlight .-Color[class*=-C80] { color: #5FD7D7 } + div.highlight .-Color[class*=-BGC80] { background-color: #5FD7D7 } + div.highlight .-Color[class*=-C81] { color: #5FD7FF } + div.highlight .-Color[class*=-BGC81] { background-color: #5FD7FF } + div.highlight .-Color[class*=-C82] { color: #5FFF00 } + div.highlight .-Color[class*=-BGC82] { background-color: #5FFF00 } + div.highlight .-Color[class*=-C83] { color: #5FFF5F } + div.highlight .-Color[class*=-BGC83] { background-color: #5FFF5F } + div.highlight .-Color[class*=-C84] { color: #5FFF87 } + div.highlight .-Color[class*=-BGC84] { background-color: #5FFF87 } + div.highlight .-Color[class*=-C85] { color: #5FFFAF } + div.highlight .-Color[class*=-BGC85] { background-color: #5FFFAF } + div.highlight .-Color[class*=-C86] { color: #5FFFD7 } + div.highlight .-Color[class*=-BGC86] { background-color: #5FFFD7 } + div.highlight .-Color[class*=-C87] { color: #5FFFFF } + div.highlight .-Color[class*=-BGC87] { background-color: #5FFFFF } + div.highlight .-Color[class*=-C88] { color: #870000 } + div.highlight .-Color[class*=-BGC88] { background-color: #870000 } + div.highlight .-Color[class*=-C89] { color: #87005F } + div.highlight .-Color[class*=-BGC89] { background-color: #87005F } + div.highlight .-Color[class*=-C90] { color: #870087 } + div.highlight .-Color[class*=-BGC90] { background-color: #870087 } + div.highlight .-Color[class*=-C91] { color: #8700AF } + div.highlight .-Color[class*=-BGC91] { background-color: #8700AF } + div.highlight .-Color[class*=-C92] { color: #8700D7 } + div.highlight .-Color[class*=-BGC92] { background-color: #8700D7 } + div.highlight .-Color[class*=-C93] { color: #8700FF } + div.highlight .-Color[class*=-BGC93] { background-color: #8700FF } + div.highlight .-Color[class*=-C94] { color: #875F00 } + div.highlight .-Color[class*=-BGC94] { background-color: #875F00 } + div.highlight .-Color[class*=-C95] { color: #875F5F } + div.highlight .-Color[class*=-BGC95] { background-color: #875F5F } + div.highlight .-Color[class*=-C96] { color: #875F87 } + div.highlight .-Color[class*=-BGC96] { background-color: #875F87 } + div.highlight .-Color[class*=-C97] { color: #875FAF } + div.highlight .-Color[class*=-BGC97] { background-color: #875FAF } + div.highlight .-Color[class*=-C98] { color: #875FD7 } + div.highlight .-Color[class*=-BGC98] { background-color: #875FD7 } + div.highlight .-Color[class*=-C99] { color: #875FFF } + div.highlight .-Color[class*=-BGC99] { background-color: #875FFF } + div.highlight .-Color[class*=-C100] { color: #878700 } + div.highlight .-Color[class*=-BGC100] { background-color: #878700 } + div.highlight .-Color[class*=-C101] { color: #87875F } + div.highlight .-Color[class*=-BGC101] { background-color: #87875F } + div.highlight .-Color[class*=-C102] { color: #878787 } + div.highlight .-Color[class*=-BGC102] { background-color: #878787 } + div.highlight .-Color[class*=-C103] { color: #8787AF } + div.highlight .-Color[class*=-BGC103] { background-color: #8787AF } + div.highlight .-Color[class*=-C104] { color: #8787D7 } + div.highlight .-Color[class*=-BGC104] { background-color: #8787D7 } + div.highlight .-Color[class*=-C105] { color: #8787FF } + div.highlight .-Color[class*=-BGC105] { background-color: #8787FF } + div.highlight .-Color[class*=-C106] { color: #87AF00 } + div.highlight .-Color[class*=-BGC106] { background-color: #87AF00 } + div.highlight .-Color[class*=-C107] { color: #87AF5F } + div.highlight .-Color[class*=-BGC107] { background-color: #87AF5F } + div.highlight .-Color[class*=-C108] { color: #87AF87 } + div.highlight .-Color[class*=-BGC108] { background-color: #87AF87 } + div.highlight .-Color[class*=-C109] { color: #87AFAF } + div.highlight .-Color[class*=-BGC109] { background-color: #87AFAF } + div.highlight .-Color[class*=-C110] { color: #87AFD7 } + div.highlight .-Color[class*=-BGC110] { background-color: #87AFD7 } + div.highlight .-Color[class*=-C111] { color: #87AFFF } + div.highlight .-Color[class*=-BGC111] { background-color: #87AFFF } + div.highlight .-Color[class*=-C112] { color: #87D700 } + div.highlight .-Color[class*=-BGC112] { background-color: #87D700 } + div.highlight .-Color[class*=-C113] { color: #87D75F } + div.highlight .-Color[class*=-BGC113] { background-color: #87D75F } + div.highlight .-Color[class*=-C114] { color: #87D787 } + div.highlight .-Color[class*=-BGC114] { background-color: #87D787 } + div.highlight .-Color[class*=-C115] { color: #87D7AF } + div.highlight .-Color[class*=-BGC115] { background-color: #87D7AF } + div.highlight .-Color[class*=-C116] { color: #87D7D7 } + div.highlight .-Color[class*=-BGC116] { background-color: #87D7D7 } + div.highlight .-Color[class*=-C117] { color: #87D7FF } + div.highlight .-Color[class*=-BGC117] { background-color: #87D7FF } + div.highlight .-Color[class*=-C118] { color: #87FF00 } + div.highlight .-Color[class*=-BGC118] { background-color: #87FF00 } + div.highlight .-Color[class*=-C119] { color: #87FF5F } + div.highlight .-Color[class*=-BGC119] { background-color: #87FF5F } + div.highlight .-Color[class*=-C120] { color: #87FF87 } + div.highlight .-Color[class*=-BGC120] { background-color: #87FF87 } + div.highlight .-Color[class*=-C121] { color: #87FFAF } + div.highlight .-Color[class*=-BGC121] { background-color: #87FFAF } + div.highlight .-Color[class*=-C122] { color: #87FFD7 } + div.highlight .-Color[class*=-BGC122] { background-color: #87FFD7 } + div.highlight .-Color[class*=-C123] { color: #87FFFF } + div.highlight .-Color[class*=-BGC123] { background-color: #87FFFF } + div.highlight .-Color[class*=-C124] { color: #AF0000 } + div.highlight .-Color[class*=-BGC124] { background-color: #AF0000 } + div.highlight .-Color[class*=-C125] { color: #AF005F } + div.highlight .-Color[class*=-BGC125] { background-color: #AF005F } + div.highlight .-Color[class*=-C126] { color: #AF0087 } + div.highlight .-Color[class*=-BGC126] { background-color: #AF0087 } + div.highlight .-Color[class*=-C127] { color: #AF00AF } + div.highlight .-Color[class*=-BGC127] { background-color: #AF00AF } + div.highlight .-Color[class*=-C128] { color: #AF00D7 } + div.highlight .-Color[class*=-BGC128] { background-color: #AF00D7 } + div.highlight .-Color[class*=-C129] { color: #AF00FF } + div.highlight .-Color[class*=-BGC129] { background-color: #AF00FF } + div.highlight .-Color[class*=-C130] { color: #AF5F00 } + div.highlight .-Color[class*=-BGC130] { background-color: #AF5F00 } + div.highlight .-Color[class*=-C131] { color: #AF5F5F } + div.highlight .-Color[class*=-BGC131] { background-color: #AF5F5F } + div.highlight .-Color[class*=-C132] { color: #AF5F87 } + div.highlight .-Color[class*=-BGC132] { background-color: #AF5F87 } + div.highlight .-Color[class*=-C133] { color: #AF5FAF } + div.highlight .-Color[class*=-BGC133] { background-color: #AF5FAF } + div.highlight .-Color[class*=-C134] { color: #AF5FD7 } + div.highlight .-Color[class*=-BGC134] { background-color: #AF5FD7 } + div.highlight .-Color[class*=-C135] { color: #AF5FFF } + div.highlight .-Color[class*=-BGC135] { background-color: #AF5FFF } + div.highlight .-Color[class*=-C136] { color: #AF8700 } + div.highlight .-Color[class*=-BGC136] { background-color: #AF8700 } + div.highlight .-Color[class*=-C137] { color: #AF875F } + div.highlight .-Color[class*=-BGC137] { background-color: #AF875F } + div.highlight .-Color[class*=-C138] { color: #AF8787 } + div.highlight .-Color[class*=-BGC138] { background-color: #AF8787 } + div.highlight .-Color[class*=-C139] { color: #AF87AF } + div.highlight .-Color[class*=-BGC139] { background-color: #AF87AF } + div.highlight .-Color[class*=-C140] { color: #AF87D7 } + div.highlight .-Color[class*=-BGC140] { background-color: #AF87D7 } + div.highlight .-Color[class*=-C141] { color: #AF87FF } + div.highlight .-Color[class*=-BGC141] { background-color: #AF87FF } + div.highlight .-Color[class*=-C142] { color: #AFAF00 } + div.highlight .-Color[class*=-BGC142] { background-color: #AFAF00 } + div.highlight .-Color[class*=-C143] { color: #AFAF5F } + div.highlight .-Color[class*=-BGC143] { background-color: #AFAF5F } + div.highlight .-Color[class*=-C144] { color: #AFAF87 } + div.highlight .-Color[class*=-BGC144] { background-color: #AFAF87 } + div.highlight .-Color[class*=-C145] { color: #AFAFAF } + div.highlight .-Color[class*=-BGC145] { background-color: #AFAFAF } + div.highlight .-Color[class*=-C146] { color: #AFAFD7 } + div.highlight .-Color[class*=-BGC146] { background-color: #AFAFD7 } + div.highlight .-Color[class*=-C147] { color: #AFAFFF } + div.highlight .-Color[class*=-BGC147] { background-color: #AFAFFF } + div.highlight .-Color[class*=-C148] { color: #AFD700 } + div.highlight .-Color[class*=-BGC148] { background-color: #AFD700 } + div.highlight .-Color[class*=-C149] { color: #AFD75F } + div.highlight .-Color[class*=-BGC149] { background-color: #AFD75F } + div.highlight .-Color[class*=-C150] { color: #AFD787 } + div.highlight .-Color[class*=-BGC150] { background-color: #AFD787 } + div.highlight .-Color[class*=-C151] { color: #AFD7AF } + div.highlight .-Color[class*=-BGC151] { background-color: #AFD7AF } + div.highlight .-Color[class*=-C152] { color: #AFD7D7 } + div.highlight .-Color[class*=-BGC152] { background-color: #AFD7D7 } + div.highlight .-Color[class*=-C153] { color: #AFD7FF } + div.highlight .-Color[class*=-BGC153] { background-color: #AFD7FF } + div.highlight .-Color[class*=-C154] { color: #AFFF00 } + div.highlight .-Color[class*=-BGC154] { background-color: #AFFF00 } + div.highlight .-Color[class*=-C155] { color: #AFFF5F } + div.highlight .-Color[class*=-BGC155] { background-color: #AFFF5F } + div.highlight .-Color[class*=-C156] { color: #AFFF87 } + div.highlight .-Color[class*=-BGC156] { background-color: #AFFF87 } + div.highlight .-Color[class*=-C157] { color: #AFFFAF } + div.highlight .-Color[class*=-BGC157] { background-color: #AFFFAF } + div.highlight .-Color[class*=-C158] { color: #AFFFD7 } + div.highlight .-Color[class*=-BGC158] { background-color: #AFFFD7 } + div.highlight .-Color[class*=-C159] { color: #AFFFFF } + div.highlight .-Color[class*=-BGC159] { background-color: #AFFFFF } + div.highlight .-Color[class*=-C160] { color: #D70000 } + div.highlight .-Color[class*=-BGC160] { background-color: #D70000 } + div.highlight .-Color[class*=-C161] { color: #D7005F } + div.highlight .-Color[class*=-BGC161] { background-color: #D7005F } + div.highlight .-Color[class*=-C162] { color: #D70087 } + div.highlight .-Color[class*=-BGC162] { background-color: #D70087 } + div.highlight .-Color[class*=-C163] { color: #D700AF } + div.highlight .-Color[class*=-BGC163] { background-color: #D700AF } + div.highlight .-Color[class*=-C164] { color: #D700D7 } + div.highlight .-Color[class*=-BGC164] { background-color: #D700D7 } + div.highlight .-Color[class*=-C165] { color: #D700FF } + div.highlight .-Color[class*=-BGC165] { background-color: #D700FF } + div.highlight .-Color[class*=-C166] { color: #D75F00 } + div.highlight .-Color[class*=-BGC166] { background-color: #D75F00 } + div.highlight .-Color[class*=-C167] { color: #D75F5F } + div.highlight .-Color[class*=-BGC167] { background-color: #D75F5F } + div.highlight .-Color[class*=-C168] { color: #D75F87 } + div.highlight .-Color[class*=-BGC168] { background-color: #D75F87 } + div.highlight .-Color[class*=-C169] { color: #D75FAF } + div.highlight .-Color[class*=-BGC169] { background-color: #D75FAF } + div.highlight .-Color[class*=-C170] { color: #D75FD7 } + div.highlight .-Color[class*=-BGC170] { background-color: #D75FD7 } + div.highlight .-Color[class*=-C171] { color: #D75FFF } + div.highlight .-Color[class*=-BGC171] { background-color: #D75FFF } + div.highlight .-Color[class*=-C172] { color: #D78700 } + div.highlight .-Color[class*=-BGC172] { background-color: #D78700 } + div.highlight .-Color[class*=-C173] { color: #D7875F } + div.highlight .-Color[class*=-BGC173] { background-color: #D7875F } + div.highlight .-Color[class*=-C174] { color: #D78787 } + div.highlight .-Color[class*=-BGC174] { background-color: #D78787 } + div.highlight .-Color[class*=-C175] { color: #D787AF } + div.highlight .-Color[class*=-BGC175] { background-color: #D787AF } + div.highlight .-Color[class*=-C176] { color: #D787D7 } + div.highlight .-Color[class*=-BGC176] { background-color: #D787D7 } + div.highlight .-Color[class*=-C177] { color: #D787FF } + div.highlight .-Color[class*=-BGC177] { background-color: #D787FF } + div.highlight .-Color[class*=-C178] { color: #D7AF00 } + div.highlight .-Color[class*=-BGC178] { background-color: #D7AF00 } + div.highlight .-Color[class*=-C179] { color: #D7AF5F } + div.highlight .-Color[class*=-BGC179] { background-color: #D7AF5F } + div.highlight .-Color[class*=-C180] { color: #D7AF87 } + div.highlight .-Color[class*=-BGC180] { background-color: #D7AF87 } + div.highlight .-Color[class*=-C181] { color: #D7AFAF } + div.highlight .-Color[class*=-BGC181] { background-color: #D7AFAF } + div.highlight .-Color[class*=-C182] { color: #D7AFD7 } + div.highlight .-Color[class*=-BGC182] { background-color: #D7AFD7 } + div.highlight .-Color[class*=-C183] { color: #D7AFFF } + div.highlight .-Color[class*=-BGC183] { background-color: #D7AFFF } + div.highlight .-Color[class*=-C184] { color: #D7D700 } + div.highlight .-Color[class*=-BGC184] { background-color: #D7D700 } + div.highlight .-Color[class*=-C185] { color: #D7D75F } + div.highlight .-Color[class*=-BGC185] { background-color: #D7D75F } + div.highlight .-Color[class*=-C186] { color: #D7D787 } + div.highlight .-Color[class*=-BGC186] { background-color: #D7D787 } + div.highlight .-Color[class*=-C187] { color: #D7D7AF } + div.highlight .-Color[class*=-BGC187] { background-color: #D7D7AF } + div.highlight .-Color[class*=-C188] { color: #D7D7D7 } + div.highlight .-Color[class*=-BGC188] { background-color: #D7D7D7 } + div.highlight .-Color[class*=-C189] { color: #D7D7FF } + div.highlight .-Color[class*=-BGC189] { background-color: #D7D7FF } + div.highlight .-Color[class*=-C190] { color: #D7FF00 } + div.highlight .-Color[class*=-BGC190] { background-color: #D7FF00 } + div.highlight .-Color[class*=-C191] { color: #D7FF5F } + div.highlight .-Color[class*=-BGC191] { background-color: #D7FF5F } + div.highlight .-Color[class*=-C192] { color: #D7FF87 } + div.highlight .-Color[class*=-BGC192] { background-color: #D7FF87 } + div.highlight .-Color[class*=-C193] { color: #D7FFAF } + div.highlight .-Color[class*=-BGC193] { background-color: #D7FFAF } + div.highlight .-Color[class*=-C194] { color: #D7FFD7 } + div.highlight .-Color[class*=-BGC194] { background-color: #D7FFD7 } + div.highlight .-Color[class*=-C195] { color: #D7FFFF } + div.highlight .-Color[class*=-BGC195] { background-color: #D7FFFF } + div.highlight .-Color[class*=-C196] { color: #FF0000 } + div.highlight .-Color[class*=-BGC196] { background-color: #FF0000 } + div.highlight .-Color[class*=-C197] { color: #FF005F } + div.highlight .-Color[class*=-BGC197] { background-color: #FF005F } + div.highlight .-Color[class*=-C198] { color: #FF0087 } + div.highlight .-Color[class*=-BGC198] { background-color: #FF0087 } + div.highlight .-Color[class*=-C199] { color: #FF00AF } + div.highlight .-Color[class*=-BGC199] { background-color: #FF00AF } + div.highlight .-Color[class*=-C200] { color: #FF00D7 } + div.highlight .-Color[class*=-BGC200] { background-color: #FF00D7 } + div.highlight .-Color[class*=-C201] { color: #FF00FF } + div.highlight .-Color[class*=-BGC201] { background-color: #FF00FF } + div.highlight .-Color[class*=-C202] { color: #FF5F00 } + div.highlight .-Color[class*=-BGC202] { background-color: #FF5F00 } + div.highlight .-Color[class*=-C203] { color: #FF5F5F } + div.highlight .-Color[class*=-BGC203] { background-color: #FF5F5F } + div.highlight .-Color[class*=-C204] { color: #FF5F87 } + div.highlight .-Color[class*=-BGC204] { background-color: #FF5F87 } + div.highlight .-Color[class*=-C205] { color: #FF5FAF } + div.highlight .-Color[class*=-BGC205] { background-color: #FF5FAF } + div.highlight .-Color[class*=-C206] { color: #FF5FD7 } + div.highlight .-Color[class*=-BGC206] { background-color: #FF5FD7 } + div.highlight .-Color[class*=-C207] { color: #FF5FFF } + div.highlight .-Color[class*=-BGC207] { background-color: #FF5FFF } + div.highlight .-Color[class*=-C208] { color: #FF8700 } + div.highlight .-Color[class*=-BGC208] { background-color: #FF8700 } + div.highlight .-Color[class*=-C209] { color: #FF875F } + div.highlight .-Color[class*=-BGC209] { background-color: #FF875F } + div.highlight .-Color[class*=-C210] { color: #FF8787 } + div.highlight .-Color[class*=-BGC210] { background-color: #FF8787 } + div.highlight .-Color[class*=-C211] { color: #FF87AF } + div.highlight .-Color[class*=-BGC211] { background-color: #FF87AF } + div.highlight .-Color[class*=-C212] { color: #FF87D7 } + div.highlight .-Color[class*=-BGC212] { background-color: #FF87D7 } + div.highlight .-Color[class*=-C213] { color: #FF87FF } + div.highlight .-Color[class*=-BGC213] { background-color: #FF87FF } + div.highlight .-Color[class*=-C214] { color: #FFAF00 } + div.highlight .-Color[class*=-BGC214] { background-color: #FFAF00 } + div.highlight .-Color[class*=-C215] { color: #FFAF5F } + div.highlight .-Color[class*=-BGC215] { background-color: #FFAF5F } + div.highlight .-Color[class*=-C216] { color: #FFAF87 } + div.highlight .-Color[class*=-BGC216] { background-color: #FFAF87 } + div.highlight .-Color[class*=-C217] { color: #FFAFAF } + div.highlight .-Color[class*=-BGC217] { background-color: #FFAFAF } + div.highlight .-Color[class*=-C218] { color: #FFAFD7 } + div.highlight .-Color[class*=-BGC218] { background-color: #FFAFD7 } + div.highlight .-Color[class*=-C219] { color: #FFAFFF } + div.highlight .-Color[class*=-BGC219] { background-color: #FFAFFF } + div.highlight .-Color[class*=-C220] { color: #FFD700 } + div.highlight .-Color[class*=-BGC220] { background-color: #FFD700 } + div.highlight .-Color[class*=-C221] { color: #FFD75F } + div.highlight .-Color[class*=-BGC221] { background-color: #FFD75F } + div.highlight .-Color[class*=-C222] { color: #FFD787 } + div.highlight .-Color[class*=-BGC222] { background-color: #FFD787 } + div.highlight .-Color[class*=-C223] { color: #FFD7AF } + div.highlight .-Color[class*=-BGC223] { background-color: #FFD7AF } + div.highlight .-Color[class*=-C224] { color: #FFD7D7 } + div.highlight .-Color[class*=-BGC224] { background-color: #FFD7D7 } + div.highlight .-Color[class*=-C225] { color: #FFD7FF } + div.highlight .-Color[class*=-BGC225] { background-color: #FFD7FF } + div.highlight .-Color[class*=-C226] { color: #FFFF00 } + div.highlight .-Color[class*=-BGC226] { background-color: #FFFF00 } + div.highlight .-Color[class*=-C227] { color: #FFFF5F } + div.highlight .-Color[class*=-BGC227] { background-color: #FFFF5F } + div.highlight .-Color[class*=-C228] { color: #FFFF87 } + div.highlight .-Color[class*=-BGC228] { background-color: #FFFF87 } + div.highlight .-Color[class*=-C229] { color: #FFFFAF } + div.highlight .-Color[class*=-BGC229] { background-color: #FFFFAF } + div.highlight .-Color[class*=-C230] { color: #FFFFD7 } + div.highlight .-Color[class*=-BGC230] { background-color: #FFFFD7 } + div.highlight .-Color[class*=-C231] { color: #FFFFFF } + div.highlight .-Color[class*=-BGC231] { background-color: #FFFFFF } + div.highlight .-Color[class*=-C232] { color: #080808 } + div.highlight .-Color[class*=-BGC232] { background-color: #080808 } + div.highlight .-Color[class*=-C233] { color: #121212 } + div.highlight .-Color[class*=-BGC233] { background-color: #121212 } + div.highlight .-Color[class*=-C234] { color: #1C1C1C } + div.highlight .-Color[class*=-BGC234] { background-color: #1C1C1C } + div.highlight .-Color[class*=-C235] { color: #262626 } + div.highlight .-Color[class*=-BGC235] { background-color: #262626 } + div.highlight .-Color[class*=-C236] { color: #303030 } + div.highlight .-Color[class*=-BGC236] { background-color: #303030 } + div.highlight .-Color[class*=-C237] { color: #3A3A3A } + div.highlight .-Color[class*=-BGC237] { background-color: #3A3A3A } + div.highlight .-Color[class*=-C238] { color: #444444 } + div.highlight .-Color[class*=-BGC238] { background-color: #444444 } + div.highlight .-Color[class*=-C239] { color: #4E4E4E } + div.highlight .-Color[class*=-BGC239] { background-color: #4E4E4E } + div.highlight .-Color[class*=-C240] { color: #585858 } + div.highlight .-Color[class*=-BGC240] { background-color: #585858 } + div.highlight .-Color[class*=-C241] { color: #626262 } + div.highlight .-Color[class*=-BGC241] { background-color: #626262 } + div.highlight .-Color[class*=-C242] { color: #6C6C6C } + div.highlight .-Color[class*=-BGC242] { background-color: #6C6C6C } + div.highlight .-Color[class*=-C243] { color: #767676 } + div.highlight .-Color[class*=-BGC243] { background-color: #767676 } + div.highlight .-Color[class*=-C244] { color: #808080 } + div.highlight .-Color[class*=-BGC244] { background-color: #808080 } + div.highlight .-Color[class*=-C245] { color: #8A8A8A } + div.highlight .-Color[class*=-BGC245] { background-color: #8A8A8A } + div.highlight .-Color[class*=-C246] { color: #949494 } + div.highlight .-Color[class*=-BGC246] { background-color: #949494 } + div.highlight .-Color[class*=-C247] { color: #9E9E9E } + div.highlight .-Color[class*=-BGC247] { background-color: #9E9E9E } + div.highlight .-Color[class*=-C248] { color: #A8A8A8 } + div.highlight .-Color[class*=-BGC248] { background-color: #A8A8A8 } + div.highlight .-Color[class*=-C249] { color: #B2B2B2 } + div.highlight .-Color[class*=-BGC249] { background-color: #B2B2B2 } + div.highlight .-Color[class*=-C250] { color: #BCBCBC } + div.highlight .-Color[class*=-BGC250] { background-color: #BCBCBC } + div.highlight .-Color[class*=-C251] { color: #C6C6C6 } + div.highlight .-Color[class*=-BGC251] { background-color: #C6C6C6 } + div.highlight .-Color[class*=-C252] { color: #D0D0D0 } + div.highlight .-Color[class*=-BGC252] { background-color: #D0D0D0 } + div.highlight .-Color[class*=-C253] { color: #DADADA } + div.highlight .-Color[class*=-BGC253] { background-color: #DADADA } + div.highlight .-Color[class*=-C254] { color: #E4E4E4 } + div.highlight .-Color[class*=-BGC254] { background-color: #E4E4E4 } + div.highlight .-Color[class*=-C255] { color: #EEEEEE } + div.highlight .-Color[class*=-BGC255] { background-color: #EEEEEE } diff --git a/_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css b/_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css deleted file mode 100644 index fc14abc..0000000 --- a/_static/panels-main.c949a650a448cc0ae9fd3441c0e17fb0.css +++ /dev/null @@ -1 +0,0 @@ -details.dropdown .summary-title{padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.dropdown:hover{cursor:pointer}details.dropdown .summary-content{cursor:default}details.dropdown summary{list-style:none;padding:1em}details.dropdown summary .octicon.no-title{vertical-align:middle}details.dropdown[open] summary .octicon.no-title{visibility:hidden}details.dropdown summary::-webkit-details-marker{display:none}details.dropdown summary:focus{outline:none}details.dropdown summary:hover .summary-up svg,details.dropdown summary:hover .summary-down svg{opacity:1}details.dropdown .summary-up svg,details.dropdown .summary-down svg{display:block;opacity:.6}details.dropdown .summary-up,details.dropdown .summary-down{pointer-events:none;position:absolute;right:1em;top:.75em}details.dropdown[open] .summary-down{visibility:hidden}details.dropdown:not([open]) .summary-up{visibility:hidden}details.dropdown.fade-in[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out;animation:panels-fade-in .5s ease-in-out}details.dropdown.fade-in-slide-down[open] summary~*{-moz-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;-webkit-animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out;animation:panels-fade-in .5s ease-in-out, panels-slide-down .5s ease-in-out}@keyframes panels-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes panels-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.octicon{display:inline-block;fill:currentColor;vertical-align:text-top}.tabbed-content{box-shadow:0 -.0625rem var(--tabs-color-overline),0 .0625rem var(--tabs-color-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.tabbed-content>:first-child{margin-top:0 !important}.tabbed-content>:last-child{margin-bottom:0 !important}.tabbed-content>.tabbed-set{margin:0}.tabbed-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.tabbed-set>input{opacity:0;position:absolute}.tabbed-set>input:checked+label{border-color:var(--tabs-color-label-active);color:var(--tabs-color-label-active)}.tabbed-set>input:checked+label+.tabbed-content{display:block}.tabbed-set>input:focus+label{outline-style:auto}.tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.tabbed-set>label{border-bottom:.125rem solid transparent;color:var(--tabs-color-label-inactive);cursor:pointer;font-size:var(--tabs-size-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .tabbed-set>label:hover{color:var(--tabs-color-label-active)} diff --git a/_static/panels-variables.06eb56fa6e07937060861dad626602ad.css b/_static/panels-variables.06eb56fa6e07937060861dad626602ad.css deleted file mode 100644 index adc6166..0000000 --- a/_static/panels-variables.06eb56fa6e07937060861dad626602ad.css +++ /dev/null @@ -1,7 +0,0 @@ -:root { ---tabs-color-label-active: hsla(231, 99%, 66%, 1); ---tabs-color-label-inactive: rgba(178, 206, 245, 0.62); ---tabs-color-overline: rgb(207, 236, 238); ---tabs-color-underline: rgb(207, 236, 238); ---tabs-size-label: 1rem; -} \ No newline at end of file diff --git a/_static/pygments.css b/_static/pygments.css index 691aeb8..997797f 100644 --- a/_static/pygments.css +++ b/_static/pygments.css @@ -1,74 +1,152 @@ -pre { line-height: 125%; } -td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.highlight .hll { background-color: #ffffcc } -.highlight { background: #eeffcc; } -.highlight .c { color: #408090; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #007020; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #007020 } /* Comment.Preproc */ -.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #333333 } /* Generic.Output */ -.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0044DD } /* Generic.Traceback */ -.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #007020 } /* Keyword.Pseudo */ -.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #902000 } /* Keyword.Type */ -.highlight .m { color: #208050 } /* Literal.Number */ -.highlight .s { color: #4070a0 } /* Literal.String */ -.highlight .na { color: #4070a0 } /* Name.Attribute */ -.highlight .nb { color: #007020 } /* Name.Builtin */ -.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ -.highlight .no { color: #60add5 } /* Name.Constant */ -.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ -.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #007020 } /* Name.Exception */ -.highlight .nf { color: #06287e } /* Name.Function */ -.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ -.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #bb60d5 } /* Name.Variable */ -.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mb { color: #208050 } /* Literal.Number.Bin */ -.highlight .mf { color: #208050 } /* Literal.Number.Float */ -.highlight .mh { color: #208050 } /* Literal.Number.Hex */ -.highlight .mi { color: #208050 } /* Literal.Number.Integer */ -.highlight .mo { color: #208050 } /* Literal.Number.Oct */ -.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ -.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ -.highlight .sc { color: #4070a0 } /* Literal.String.Char */ -.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ -.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ -.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ -.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ -.highlight .sx { color: #c65d09 } /* Literal.String.Other */ -.highlight .sr { color: #235388 } /* Literal.String.Regex */ -.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ -.highlight .ss { color: #517918 } /* Literal.String.Symbol */ -.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ -.highlight .fm { color: #06287e } /* Name.Function.Magic */ -.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ -.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ -.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ -.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ -.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file +html[data-theme="light"] .highlight pre { line-height: 125%; } +html[data-theme="light"] .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight .hll { background-color: #7971292e } +html[data-theme="light"] .highlight { background: #fefefe; color: #545454 } +html[data-theme="light"] .highlight .c { color: #797129 } /* Comment */ +html[data-theme="light"] .highlight .err { color: #d91e18 } /* Error */ +html[data-theme="light"] .highlight .k { color: #7928a1 } /* Keyword */ +html[data-theme="light"] .highlight .l { color: #797129 } /* Literal */ +html[data-theme="light"] .highlight .n { color: #545454 } /* Name */ +html[data-theme="light"] .highlight .o { color: #008000 } /* Operator */ +html[data-theme="light"] .highlight .p { color: #545454 } /* Punctuation */ +html[data-theme="light"] .highlight .ch { color: #797129 } /* Comment.Hashbang */ +html[data-theme="light"] .highlight .cm { color: #797129 } /* Comment.Multiline */ +html[data-theme="light"] .highlight .cp { color: #797129 } /* Comment.Preproc */ +html[data-theme="light"] .highlight .cpf { color: #797129 } /* Comment.PreprocFile */ +html[data-theme="light"] .highlight .c1 { color: #797129 } /* Comment.Single */ +html[data-theme="light"] .highlight .cs { color: #797129 } /* Comment.Special */ +html[data-theme="light"] .highlight .gd { color: #007faa } /* Generic.Deleted */ +html[data-theme="light"] .highlight .ge { font-style: italic } /* Generic.Emph */ +html[data-theme="light"] .highlight .gh { color: #007faa } /* Generic.Heading */ +html[data-theme="light"] .highlight .gs { font-weight: bold } /* Generic.Strong */ +html[data-theme="light"] .highlight .gu { color: #007faa } /* Generic.Subheading */ +html[data-theme="light"] .highlight .kc { color: #7928a1 } /* Keyword.Constant */ +html[data-theme="light"] .highlight .kd { color: #7928a1 } /* Keyword.Declaration */ +html[data-theme="light"] .highlight .kn { color: #7928a1 } /* Keyword.Namespace */ +html[data-theme="light"] .highlight .kp { color: #7928a1 } /* Keyword.Pseudo */ +html[data-theme="light"] .highlight .kr { color: #7928a1 } /* Keyword.Reserved */ +html[data-theme="light"] .highlight .kt { color: #797129 } /* Keyword.Type */ +html[data-theme="light"] .highlight .ld { color: #797129 } /* Literal.Date */ +html[data-theme="light"] .highlight .m { color: #797129 } /* Literal.Number */ +html[data-theme="light"] .highlight .s { color: #008000 } /* Literal.String */ +html[data-theme="light"] .highlight .na { color: #797129 } /* Name.Attribute */ +html[data-theme="light"] .highlight .nb { color: #797129 } /* Name.Builtin */ +html[data-theme="light"] .highlight .nc { color: #007faa } /* Name.Class */ +html[data-theme="light"] .highlight .no { color: #007faa } /* Name.Constant */ +html[data-theme="light"] .highlight .nd { color: #797129 } /* Name.Decorator */ +html[data-theme="light"] .highlight .ni { color: #008000 } /* Name.Entity */ +html[data-theme="light"] .highlight .ne { color: #7928a1 } /* Name.Exception */ +html[data-theme="light"] .highlight .nf { color: #007faa } /* Name.Function */ +html[data-theme="light"] .highlight .nl { color: #797129 } /* Name.Label */ +html[data-theme="light"] .highlight .nn { color: #545454 } /* Name.Namespace */ +html[data-theme="light"] .highlight .nx { color: #545454 } /* Name.Other */ +html[data-theme="light"] .highlight .py { color: #007faa } /* Name.Property */ +html[data-theme="light"] .highlight .nt { color: #007faa } /* Name.Tag */ +html[data-theme="light"] .highlight .nv { color: #d91e18 } /* Name.Variable */ +html[data-theme="light"] .highlight .ow { color: #7928a1 } /* Operator.Word */ +html[data-theme="light"] .highlight .pm { color: #545454 } /* Punctuation.Marker */ +html[data-theme="light"] .highlight .w { color: #545454 } /* Text.Whitespace */ +html[data-theme="light"] .highlight .mb { color: #797129 } /* Literal.Number.Bin */ +html[data-theme="light"] .highlight .mf { color: #797129 } /* Literal.Number.Float */ +html[data-theme="light"] .highlight .mh { color: #797129 } /* Literal.Number.Hex */ +html[data-theme="light"] .highlight .mi { color: #797129 } /* Literal.Number.Integer */ +html[data-theme="light"] .highlight .mo { color: #797129 } /* Literal.Number.Oct */ +html[data-theme="light"] .highlight .sa { color: #008000 } /* Literal.String.Affix */ +html[data-theme="light"] .highlight .sb { color: #008000 } /* Literal.String.Backtick */ +html[data-theme="light"] .highlight .sc { color: #008000 } /* Literal.String.Char */ +html[data-theme="light"] .highlight .dl { color: #008000 } /* Literal.String.Delimiter */ +html[data-theme="light"] .highlight .sd { color: #008000 } /* Literal.String.Doc */ +html[data-theme="light"] .highlight .s2 { color: #008000 } /* Literal.String.Double */ +html[data-theme="light"] .highlight .se { color: #008000 } /* Literal.String.Escape */ +html[data-theme="light"] .highlight .sh { color: #008000 } /* Literal.String.Heredoc */ +html[data-theme="light"] .highlight .si { color: #008000 } /* Literal.String.Interpol */ +html[data-theme="light"] .highlight .sx { color: #008000 } /* Literal.String.Other */ +html[data-theme="light"] .highlight .sr { color: #d91e18 } /* Literal.String.Regex */ +html[data-theme="light"] .highlight .s1 { color: #008000 } /* Literal.String.Single */ +html[data-theme="light"] .highlight .ss { color: #007faa } /* Literal.String.Symbol */ +html[data-theme="light"] .highlight .bp { color: #797129 } /* Name.Builtin.Pseudo */ +html[data-theme="light"] .highlight .fm { color: #007faa } /* Name.Function.Magic */ +html[data-theme="light"] .highlight .vc { color: #d91e18 } /* Name.Variable.Class */ +html[data-theme="light"] .highlight .vg { color: #d91e18 } /* Name.Variable.Global */ +html[data-theme="light"] .highlight .vi { color: #d91e18 } /* Name.Variable.Instance */ +html[data-theme="light"] .highlight .vm { color: #797129 } /* Name.Variable.Magic */ +html[data-theme="light"] .highlight .il { color: #797129 } /* Literal.Number.Integer.Long */ +html[data-theme="dark"] .highlight pre { line-height: 125%; } +html[data-theme="dark"] .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight .hll { background-color: #ffd9002e } +html[data-theme="dark"] .highlight { background: #2b2b2b; color: #f8f8f2 } +html[data-theme="dark"] .highlight .c { color: #ffd900 } /* Comment */ +html[data-theme="dark"] .highlight .err { color: #ffa07a } /* Error */ +html[data-theme="dark"] .highlight .k { color: #dcc6e0 } /* Keyword */ +html[data-theme="dark"] .highlight .l { color: #ffd900 } /* Literal */ +html[data-theme="dark"] .highlight .n { color: #f8f8f2 } /* Name */ +html[data-theme="dark"] .highlight .o { color: #abe338 } /* Operator */ +html[data-theme="dark"] .highlight .p { color: #f8f8f2 } /* Punctuation */ +html[data-theme="dark"] .highlight .ch { color: #ffd900 } /* Comment.Hashbang */ +html[data-theme="dark"] .highlight .cm { color: #ffd900 } /* Comment.Multiline */ +html[data-theme="dark"] .highlight .cp { color: #ffd900 } /* Comment.Preproc */ +html[data-theme="dark"] .highlight .cpf { color: #ffd900 } /* Comment.PreprocFile */ +html[data-theme="dark"] .highlight .c1 { color: #ffd900 } /* Comment.Single */ +html[data-theme="dark"] .highlight .cs { color: #ffd900 } /* Comment.Special */ +html[data-theme="dark"] .highlight .gd { color: #00e0e0 } /* Generic.Deleted */ +html[data-theme="dark"] .highlight .ge { font-style: italic } /* Generic.Emph */ +html[data-theme="dark"] .highlight .gh { color: #00e0e0 } /* Generic.Heading */ +html[data-theme="dark"] .highlight .gs { font-weight: bold } /* Generic.Strong */ +html[data-theme="dark"] .highlight .gu { color: #00e0e0 } /* Generic.Subheading */ +html[data-theme="dark"] .highlight .kc { color: #dcc6e0 } /* Keyword.Constant */ +html[data-theme="dark"] .highlight .kd { color: #dcc6e0 } /* Keyword.Declaration */ +html[data-theme="dark"] .highlight .kn { color: #dcc6e0 } /* Keyword.Namespace */ +html[data-theme="dark"] .highlight .kp { color: #dcc6e0 } /* Keyword.Pseudo */ +html[data-theme="dark"] .highlight .kr { color: #dcc6e0 } /* Keyword.Reserved */ +html[data-theme="dark"] .highlight .kt { color: #ffd900 } /* Keyword.Type */ +html[data-theme="dark"] .highlight .ld { color: #ffd900 } /* Literal.Date */ +html[data-theme="dark"] .highlight .m { color: #ffd900 } /* Literal.Number */ +html[data-theme="dark"] .highlight .s { color: #abe338 } /* Literal.String */ +html[data-theme="dark"] .highlight .na { color: #ffd900 } /* Name.Attribute */ +html[data-theme="dark"] .highlight .nb { color: #ffd900 } /* Name.Builtin */ +html[data-theme="dark"] .highlight .nc { color: #00e0e0 } /* Name.Class */ +html[data-theme="dark"] .highlight .no { color: #00e0e0 } /* Name.Constant */ +html[data-theme="dark"] .highlight .nd { color: #ffd900 } /* Name.Decorator */ +html[data-theme="dark"] .highlight .ni { color: #abe338 } /* Name.Entity */ +html[data-theme="dark"] .highlight .ne { color: #dcc6e0 } /* Name.Exception */ +html[data-theme="dark"] .highlight .nf { color: #00e0e0 } /* Name.Function */ +html[data-theme="dark"] .highlight .nl { color: #ffd900 } /* Name.Label */ +html[data-theme="dark"] .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ +html[data-theme="dark"] .highlight .nx { color: #f8f8f2 } /* Name.Other */ +html[data-theme="dark"] .highlight .py { color: #00e0e0 } /* Name.Property */ +html[data-theme="dark"] .highlight .nt { color: #00e0e0 } /* Name.Tag */ +html[data-theme="dark"] .highlight .nv { color: #ffa07a } /* Name.Variable */ +html[data-theme="dark"] .highlight .ow { color: #dcc6e0 } /* Operator.Word */ +html[data-theme="dark"] .highlight .pm { color: #f8f8f2 } /* Punctuation.Marker */ +html[data-theme="dark"] .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ +html[data-theme="dark"] .highlight .mb { color: #ffd900 } /* Literal.Number.Bin */ +html[data-theme="dark"] .highlight .mf { color: #ffd900 } /* Literal.Number.Float */ +html[data-theme="dark"] .highlight .mh { color: #ffd900 } /* Literal.Number.Hex */ +html[data-theme="dark"] .highlight .mi { color: #ffd900 } /* Literal.Number.Integer */ +html[data-theme="dark"] .highlight .mo { color: #ffd900 } /* Literal.Number.Oct */ +html[data-theme="dark"] .highlight .sa { color: #abe338 } /* Literal.String.Affix */ +html[data-theme="dark"] .highlight .sb { color: #abe338 } /* Literal.String.Backtick */ +html[data-theme="dark"] .highlight .sc { color: #abe338 } /* Literal.String.Char */ +html[data-theme="dark"] .highlight .dl { color: #abe338 } /* Literal.String.Delimiter */ +html[data-theme="dark"] .highlight .sd { color: #abe338 } /* Literal.String.Doc */ +html[data-theme="dark"] .highlight .s2 { color: #abe338 } /* Literal.String.Double */ +html[data-theme="dark"] .highlight .se { color: #abe338 } /* Literal.String.Escape */ +html[data-theme="dark"] .highlight .sh { color: #abe338 } /* Literal.String.Heredoc */ +html[data-theme="dark"] .highlight .si { color: #abe338 } /* Literal.String.Interpol */ +html[data-theme="dark"] .highlight .sx { color: #abe338 } /* Literal.String.Other */ +html[data-theme="dark"] .highlight .sr { color: #ffa07a } /* Literal.String.Regex */ +html[data-theme="dark"] .highlight .s1 { color: #abe338 } /* Literal.String.Single */ +html[data-theme="dark"] .highlight .ss { color: #00e0e0 } /* Literal.String.Symbol */ +html[data-theme="dark"] .highlight .bp { color: #ffd900 } /* Name.Builtin.Pseudo */ +html[data-theme="dark"] .highlight .fm { color: #00e0e0 } /* Name.Function.Magic */ +html[data-theme="dark"] .highlight .vc { color: #ffa07a } /* Name.Variable.Class */ +html[data-theme="dark"] .highlight .vg { color: #ffa07a } /* Name.Variable.Global */ +html[data-theme="dark"] .highlight .vi { color: #ffa07a } /* Name.Variable.Instance */ +html[data-theme="dark"] .highlight .vm { color: #ffd900 } /* Name.Variable.Magic */ +html[data-theme="dark"] .highlight .il { color: #ffd900 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/scripts/bootstrap.js b/_static/scripts/bootstrap.js new file mode 100644 index 0000000..bda8a60 --- /dev/null +++ b/_static/scripts/bootstrap.js @@ -0,0 +1,3 @@ +/*! For license information please see bootstrap.js.LICENSE.txt */ +(()=>{"use strict";var t={d:(e,i)=>{for(var n in i)t.o(i,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:i[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{afterMain:()=>w,afterRead:()=>b,afterWrite:()=>T,applyStyles:()=>D,arrow:()=>G,auto:()=>r,basePlacements:()=>a,beforeMain:()=>v,beforeRead:()=>g,beforeWrite:()=>E,bottom:()=>n,clippingParents:()=>h,computeStyles:()=>et,createPopper:()=>St,createPopperBase:()=>Lt,createPopperLite:()=>Dt,detectOverflow:()=>gt,end:()=>c,eventListeners:()=>nt,flip:()=>_t,hide:()=>yt,left:()=>o,main:()=>y,modifierPhases:()=>C,offset:()=>wt,placements:()=>m,popper:()=>u,popperGenerator:()=>kt,popperOffsets:()=>Et,preventOverflow:()=>At,read:()=>_,reference:()=>f,right:()=>s,start:()=>l,top:()=>i,variationPlacements:()=>p,viewport:()=>d,write:()=>A});var i="top",n="bottom",s="right",o="left",r="auto",a=[i,n,s,o],l="start",c="end",h="clippingParents",d="viewport",u="popper",f="reference",p=a.reduce((function(t,e){return t.concat([e+"-"+l,e+"-"+c])}),[]),m=[].concat(a,[r]).reduce((function(t,e){return t.concat([e,e+"-"+l,e+"-"+c])}),[]),g="beforeRead",_="read",b="afterRead",v="beforeMain",y="main",w="afterMain",E="beforeWrite",A="write",T="afterWrite",C=[g,_,b,v,y,w,E,A,T];function O(t){return t?(t.nodeName||"").toLowerCase():null}function x(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function k(t){return t instanceof x(t).Element||t instanceof Element}function L(t){return t instanceof x(t).HTMLElement||t instanceof HTMLElement}function S(t){return"undefined"!=typeof ShadowRoot&&(t instanceof x(t).ShadowRoot||t instanceof ShadowRoot)}const D={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];L(s)&&O(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});L(n)&&O(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function $(t){return t.split("-")[0]}var I=Math.max,N=Math.min,P=Math.round;function M(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function j(){return!/^((?!chrome|android).)*safari/i.test(M())}function F(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&L(t)&&(s=t.offsetWidth>0&&P(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&P(n.height)/t.offsetHeight||1);var r=(k(t)?x(t):window).visualViewport,a=!j()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function H(t){var e=F(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function B(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&S(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function W(t){return x(t).getComputedStyle(t)}function z(t){return["table","td","th"].indexOf(O(t))>=0}function R(t){return((k(t)?t.ownerDocument:t.document)||window.document).documentElement}function q(t){return"html"===O(t)?t:t.assignedSlot||t.parentNode||(S(t)?t.host:null)||R(t)}function V(t){return L(t)&&"fixed"!==W(t).position?t.offsetParent:null}function Y(t){for(var e=x(t),i=V(t);i&&z(i)&&"static"===W(i).position;)i=V(i);return i&&("html"===O(i)||"body"===O(i)&&"static"===W(i).position)?e:i||function(t){var e=/firefox/i.test(M());if(/Trident/i.test(M())&&L(t)&&"fixed"===W(t).position)return null;var i=q(t);for(S(i)&&(i=i.host);L(i)&&["html","body"].indexOf(O(i))<0;){var n=W(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function K(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Q(t,e,i){return I(t,N(e,i))}function X(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function U(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const G={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,r=t.state,l=t.name,c=t.options,h=r.elements.arrow,d=r.modifiersData.popperOffsets,u=$(r.placement),f=K(u),p=[o,s].indexOf(u)>=0?"height":"width";if(h&&d){var m=function(t,e){return X("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:U(t,a))}(c.padding,r),g=H(h),_="y"===f?i:o,b="y"===f?n:s,v=r.rects.reference[p]+r.rects.reference[f]-d[f]-r.rects.popper[p],y=d[f]-r.rects.reference[f],w=Y(h),E=w?"y"===f?w.clientHeight||0:w.clientWidth||0:0,A=v/2-y/2,T=m[_],C=E-g[p]-m[b],O=E/2-g[p]/2+A,x=Q(T,O,C),k=f;r.modifiersData[l]=((e={})[k]=x,e.centerOffset=x-O,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&B(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function J(t){return t.split("-")[1]}var Z={top:"auto",right:"auto",bottom:"auto",left:"auto"};function tt(t){var e,r=t.popper,a=t.popperRect,l=t.placement,h=t.variation,d=t.offsets,u=t.position,f=t.gpuAcceleration,p=t.adaptive,m=t.roundOffsets,g=t.isFixed,_=d.x,b=void 0===_?0:_,v=d.y,y=void 0===v?0:v,w="function"==typeof m?m({x:b,y}):{x:b,y};b=w.x,y=w.y;var E=d.hasOwnProperty("x"),A=d.hasOwnProperty("y"),T=o,C=i,O=window;if(p){var k=Y(r),L="clientHeight",S="clientWidth";k===x(r)&&"static"!==W(k=R(r)).position&&"absolute"===u&&(L="scrollHeight",S="scrollWidth"),(l===i||(l===o||l===s)&&h===c)&&(C=n,y-=(g&&k===O&&O.visualViewport?O.visualViewport.height:k[L])-a.height,y*=f?1:-1),l!==o&&(l!==i&&l!==n||h!==c)||(T=s,b-=(g&&k===O&&O.visualViewport?O.visualViewport.width:k[S])-a.width,b*=f?1:-1)}var D,$=Object.assign({position:u},p&&Z),I=!0===m?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:P(i*s)/s||0,y:P(n*s)/s||0}}({x:b,y},x(r)):{x:b,y};return b=I.x,y=I.y,f?Object.assign({},$,((D={})[C]=A?"0":"",D[T]=E?"0":"",D.transform=(O.devicePixelRatio||1)<=1?"translate("+b+"px, "+y+"px)":"translate3d("+b+"px, "+y+"px, 0)",D)):Object.assign({},$,((e={})[C]=A?y+"px":"",e[T]=E?b+"px":"",e.transform="",e))}const et={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:$(e.placement),variation:J(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,tt(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,tt(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var it={passive:!0};const nt={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=x(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,it)})),a&&l.addEventListener("resize",i.update,it),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,it)})),a&&l.removeEventListener("resize",i.update,it)}},data:{}};var st={left:"right",right:"left",bottom:"top",top:"bottom"};function ot(t){return t.replace(/left|right|bottom|top/g,(function(t){return st[t]}))}var rt={start:"end",end:"start"};function at(t){return t.replace(/start|end/g,(function(t){return rt[t]}))}function lt(t){var e=x(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ct(t){return F(R(t)).left+lt(t).scrollLeft}function ht(t){var e=W(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function dt(t){return["html","body","#document"].indexOf(O(t))>=0?t.ownerDocument.body:L(t)&&ht(t)?t:dt(q(t))}function ut(t,e){var i;void 0===e&&(e=[]);var n=dt(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=x(n),r=s?[o].concat(o.visualViewport||[],ht(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(ut(q(r)))}function ft(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function pt(t,e,i){return e===d?ft(function(t,e){var i=x(t),n=R(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=j();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+ct(t),y:l}}(t,i)):k(e)?function(t,e){var i=F(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):ft(function(t){var e,i=R(t),n=lt(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=I(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=I(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+ct(t),l=-n.scrollTop;return"rtl"===W(s||i).direction&&(a+=I(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(R(t)))}function mt(t){var e,r=t.reference,a=t.element,h=t.placement,d=h?$(h):null,u=h?J(h):null,f=r.x+r.width/2-a.width/2,p=r.y+r.height/2-a.height/2;switch(d){case i:e={x:f,y:r.y-a.height};break;case n:e={x:f,y:r.y+r.height};break;case s:e={x:r.x+r.width,y:p};break;case o:e={x:r.x-a.width,y:p};break;default:e={x:r.x,y:r.y}}var m=d?K(d):null;if(null!=m){var g="y"===m?"height":"width";switch(u){case l:e[m]=e[m]-(r[g]/2-a[g]/2);break;case c:e[m]=e[m]+(r[g]/2-a[g]/2)}}return e}function gt(t,e){void 0===e&&(e={});var o=e,r=o.placement,l=void 0===r?t.placement:r,c=o.strategy,p=void 0===c?t.strategy:c,m=o.boundary,g=void 0===m?h:m,_=o.rootBoundary,b=void 0===_?d:_,v=o.elementContext,y=void 0===v?u:v,w=o.altBoundary,E=void 0!==w&&w,A=o.padding,T=void 0===A?0:A,C=X("number"!=typeof T?T:U(T,a)),x=y===u?f:u,S=t.rects.popper,D=t.elements[E?x:y],$=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=ut(q(t)),i=["absolute","fixed"].indexOf(W(t).position)>=0&&L(t)?Y(t):t;return k(i)?e.filter((function(t){return k(t)&&B(t,i)&&"body"!==O(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=pt(t,i,n);return e.top=I(s.top,e.top),e.right=N(s.right,e.right),e.bottom=N(s.bottom,e.bottom),e.left=I(s.left,e.left),e}),pt(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(k(D)?D:D.contextElement||R(t.elements.popper),g,b,p),P=F(t.elements.reference),M=mt({reference:P,element:S,strategy:"absolute",placement:l}),j=ft(Object.assign({},S,M)),H=y===u?j:P,z={top:$.top-H.top+C.top,bottom:H.bottom-$.bottom+C.bottom,left:$.left-H.left+C.left,right:H.right-$.right+C.right},V=t.modifiersData.offset;if(y===u&&V){var K=V[l];Object.keys(z).forEach((function(t){var e=[s,n].indexOf(t)>=0?1:-1,o=[i,n].indexOf(t)>=0?"y":"x";z[t]+=K[o]*e}))}return z}const _t={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,c=t.options,h=t.name;if(!e.modifiersData[h]._skip){for(var d=c.mainAxis,u=void 0===d||d,f=c.altAxis,g=void 0===f||f,_=c.fallbackPlacements,b=c.padding,v=c.boundary,y=c.rootBoundary,w=c.altBoundary,E=c.flipVariations,A=void 0===E||E,T=c.allowedAutoPlacements,C=e.options.placement,O=$(C),x=_||(O!==C&&A?function(t){if($(t)===r)return[];var e=ot(t);return[at(t),e,at(e)]}(C):[ot(C)]),k=[C].concat(x).reduce((function(t,i){return t.concat($(i)===r?function(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,l=i.flipVariations,c=i.allowedAutoPlacements,h=void 0===c?m:c,d=J(n),u=d?l?p:p.filter((function(t){return J(t)===d})):a,f=u.filter((function(t){return h.indexOf(t)>=0}));0===f.length&&(f=u);var g=f.reduce((function(e,i){return e[i]=gt(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[$(i)],e}),{});return Object.keys(g).sort((function(t,e){return g[t]-g[e]}))}(e,{placement:i,boundary:v,rootBoundary:y,padding:b,flipVariations:A,allowedAutoPlacements:T}):i)}),[]),L=e.rects.reference,S=e.rects.popper,D=new Map,I=!0,N=k[0],P=0;P=0,B=H?"width":"height",W=gt(e,{placement:M,boundary:v,rootBoundary:y,altBoundary:w,padding:b}),z=H?F?s:o:F?n:i;L[B]>S[B]&&(z=ot(z));var R=ot(z),q=[];if(u&&q.push(W[j]<=0),g&&q.push(W[z]<=0,W[R]<=0),q.every((function(t){return t}))){N=M,I=!1;break}D.set(M,q)}if(I)for(var V=function(t){var e=k.find((function(e){var i=D.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return N=e,"break"},Y=A?3:1;Y>0&&"break"!==V(Y);Y--);e.placement!==N&&(e.modifiersData[h]._skip=!0,e.placement=N,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function bt(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function vt(t){return[i,s,n,o].some((function(e){return t[e]>=0}))}const yt={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=gt(e,{elementContext:"reference"}),a=gt(e,{altBoundary:!0}),l=bt(r,n),c=bt(a,s,o),h=vt(l),d=vt(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},wt={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,n=t.options,r=t.name,a=n.offset,l=void 0===a?[0,0]:a,c=m.reduce((function(t,n){return t[n]=function(t,e,n){var r=$(t),a=[o,i].indexOf(r)>=0?-1:1,l="function"==typeof n?n(Object.assign({},e,{placement:t})):n,c=l[0],h=l[1];return c=c||0,h=(h||0)*a,[o,s].indexOf(r)>=0?{x:h,y:c}:{x:c,y:h}}(n,e.rects,l),t}),{}),h=c[e.placement],d=h.x,u=h.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=d,e.modifiersData.popperOffsets.y+=u),e.modifiersData[r]=c}},Et={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=mt({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},At={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,r=t.options,a=t.name,c=r.mainAxis,h=void 0===c||c,d=r.altAxis,u=void 0!==d&&d,f=r.boundary,p=r.rootBoundary,m=r.altBoundary,g=r.padding,_=r.tether,b=void 0===_||_,v=r.tetherOffset,y=void 0===v?0:v,w=gt(e,{boundary:f,rootBoundary:p,padding:g,altBoundary:m}),E=$(e.placement),A=J(e.placement),T=!A,C=K(E),O="x"===C?"y":"x",x=e.modifiersData.popperOffsets,k=e.rects.reference,L=e.rects.popper,S="function"==typeof y?y(Object.assign({},e.rects,{placement:e.placement})):y,D="number"==typeof S?{mainAxis:S,altAxis:S}:Object.assign({mainAxis:0,altAxis:0},S),P=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,M={x:0,y:0};if(x){if(h){var j,F="y"===C?i:o,B="y"===C?n:s,W="y"===C?"height":"width",z=x[C],R=z+w[F],q=z-w[B],V=b?-L[W]/2:0,X=A===l?k[W]:L[W],U=A===l?-L[W]:-k[W],G=e.elements.arrow,Z=b&&G?H(G):{width:0,height:0},tt=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},et=tt[F],it=tt[B],nt=Q(0,k[W],Z[W]),st=T?k[W]/2-V-nt-et-D.mainAxis:X-nt-et-D.mainAxis,ot=T?-k[W]/2+V+nt+it+D.mainAxis:U+nt+it+D.mainAxis,rt=e.elements.arrow&&Y(e.elements.arrow),at=rt?"y"===C?rt.clientTop||0:rt.clientLeft||0:0,lt=null!=(j=null==P?void 0:P[C])?j:0,ct=z+ot-lt,ht=Q(b?N(R,z+st-lt-at):R,z,b?I(q,ct):q);x[C]=ht,M[C]=ht-z}if(u){var dt,ut="x"===C?i:o,ft="x"===C?n:s,pt=x[O],mt="y"===O?"height":"width",_t=pt+w[ut],bt=pt-w[ft],vt=-1!==[i,o].indexOf(E),yt=null!=(dt=null==P?void 0:P[O])?dt:0,wt=vt?_t:pt-k[mt]-L[mt]-yt+D.altAxis,Et=vt?pt+k[mt]+L[mt]-yt-D.altAxis:bt,At=b&&vt?function(t,e,i){var n=Q(t,e,i);return n>i?i:n}(wt,pt,Et):Q(b?wt:_t,pt,b?Et:bt);x[O]=At,M[O]=At-pt}e.modifiersData[a]=M}},requiresIfExists:["offset"]};function Tt(t,e,i){void 0===i&&(i=!1);var n,s,o=L(e),r=L(e)&&function(t){var e=t.getBoundingClientRect(),i=P(e.width)/t.offsetWidth||1,n=P(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=R(e),l=F(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==O(e)||ht(a))&&(c=(n=e)!==x(n)&&L(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:lt(n)),L(e)?((h=F(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=ct(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function Ct(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Ot={placement:"bottom",modifiers:[],strategy:"absolute"};function xt(){for(var t=arguments.length,e=new Array(t),i=0;i$t.has(t)&&$t.get(t).get(e)||null,remove(t,e){if(!$t.has(t))return;const i=$t.get(t);i.delete(e),0===i.size&&$t.delete(t)}},Nt="transitionend",Pt=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),Mt=t=>{t.dispatchEvent(new Event(Nt))},jt=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),Ft=t=>jt(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(Pt(t)):null,Ht=t=>{if(!jt(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},Bt=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),Wt=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?Wt(t.parentNode):null},zt=()=>{},Rt=t=>{t.offsetHeight},qt=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,Vt=[],Yt=()=>"rtl"===document.documentElement.dir,Kt=t=>{var e;e=()=>{const e=qt();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(Vt.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of Vt)t()})),Vt.push(e)):e()},Qt=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,Xt=(t,e,i=!0)=>{if(!i)return void Qt(t);const n=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let s=!1;const o=({target:i})=>{i===e&&(s=!0,e.removeEventListener(Nt,o),Qt(t))};e.addEventListener(Nt,o),setTimeout((()=>{s||Mt(e)}),n)},Ut=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},Gt=/[^.]*(?=\..*)\.|.*/,Jt=/\..*/,Zt=/::\d+$/,te={};let ee=1;const ie={mouseenter:"mouseover",mouseleave:"mouseout"},ne=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function se(t,e){return e&&`${e}::${ee++}`||t.uidEvent||ee++}function oe(t){const e=se(t);return t.uidEvent=e,te[e]=te[e]||{},te[e]}function re(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function ae(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=de(t);return ne.has(o)||(o=t),[n,s,o]}function le(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=ae(e,i,n);if(e in ie){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=oe(t),c=l[a]||(l[a]={}),h=re(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=se(r,e.replace(Gt,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return fe(s,{delegateTarget:r}),n.oneOff&&ue.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return fe(n,{delegateTarget:t}),i.oneOff&&ue.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function ce(t,e,i,n,s){const o=re(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function he(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&ce(t,e,i,r.callable,r.delegationSelector)}function de(t){return t=t.replace(Jt,""),ie[t]||t}const ue={on(t,e,i,n){le(t,e,i,n,!1)},one(t,e,i,n){le(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=ae(e,i,n),a=r!==e,l=oe(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))he(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(Zt,"");a&&!e.includes(s)||ce(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;ce(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=qt();let s=null,o=!0,r=!0,a=!1;e!==de(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=fe(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function fe(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function pe(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function me(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const ge={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${me(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${me(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=pe(t.dataset[n])}return e},getDataAttribute:(t,e)=>pe(t.getAttribute(`data-bs-${me(e)}`))};class _e{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=jt(e)?ge.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...jt(e)?ge.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],o=jt(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(o))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${o}" but expected type "${s}".`)}var i}}class be extends _e{constructor(t,e){super(),(t=Ft(t))&&(this._element=t,this._config=this._getConfig(e),It.set(this._element,this.constructor.DATA_KEY,this))}dispose(){It.remove(this._element,this.constructor.DATA_KEY),ue.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){Xt(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return It.get(Ft(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.2"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const ve=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?Pt(i.trim()):null}return e},ye={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!Bt(t)&&Ht(t)))},getSelectorFromElement(t){const e=ve(t);return e&&ye.findOne(e)?e:null},getElementFromSelector(t){const e=ve(t);return e?ye.findOne(e):null},getMultipleElementsFromSelector(t){const e=ve(t);return e?ye.find(e):[]}},we=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;ue.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),Bt(this))return;const s=ye.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},Ee=".bs.alert",Ae=`close${Ee}`,Te=`closed${Ee}`;class Ce extends be{static get NAME(){return"alert"}close(){if(ue.trigger(this._element,Ae).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),ue.trigger(this._element,Te),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Ce.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}we(Ce,"close"),Kt(Ce);const Oe='[data-bs-toggle="button"]';class xe extends be{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=xe.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}ue.on(document,"click.bs.button.data-api",Oe,(t=>{t.preventDefault();const e=t.target.closest(Oe);xe.getOrCreateInstance(e).toggle()})),Kt(xe);const ke=".bs.swipe",Le=`touchstart${ke}`,Se=`touchmove${ke}`,De=`touchend${ke}`,$e=`pointerdown${ke}`,Ie=`pointerup${ke}`,Ne={endCallback:null,leftCallback:null,rightCallback:null},Pe={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class Me extends _e{constructor(t,e){super(),this._element=t,t&&Me.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return Ne}static get DefaultType(){return Pe}static get NAME(){return"swipe"}dispose(){ue.off(this._element,ke)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),Qt(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&Qt(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(ue.on(this._element,$e,(t=>this._start(t))),ue.on(this._element,Ie,(t=>this._end(t))),this._element.classList.add("pointer-event")):(ue.on(this._element,Le,(t=>this._start(t))),ue.on(this._element,Se,(t=>this._move(t))),ue.on(this._element,De,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const je=".bs.carousel",Fe=".data-api",He="next",Be="prev",We="left",ze="right",Re=`slide${je}`,qe=`slid${je}`,Ve=`keydown${je}`,Ye=`mouseenter${je}`,Ke=`mouseleave${je}`,Qe=`dragstart${je}`,Xe=`load${je}${Fe}`,Ue=`click${je}${Fe}`,Ge="carousel",Je="active",Ze=".active",ti=".carousel-item",ei=Ze+ti,ii={ArrowLeft:ze,ArrowRight:We},ni={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},si={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class oi extends be{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=ye.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===Ge&&this.cycle()}static get Default(){return ni}static get DefaultType(){return si}static get NAME(){return"carousel"}next(){this._slide(He)}nextWhenVisible(){!document.hidden&&Ht(this._element)&&this.next()}prev(){this._slide(Be)}pause(){this._isSliding&&Mt(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?ue.one(this._element,qe,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void ue.one(this._element,qe,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?He:Be;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&ue.on(this._element,Ve,(t=>this._keydown(t))),"hover"===this._config.pause&&(ue.on(this._element,Ye,(()=>this.pause())),ue.on(this._element,Ke,(()=>this._maybeEnableCycle()))),this._config.touch&&Me.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of ye.find(".carousel-item img",this._element))ue.on(t,Qe,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(We)),rightCallback:()=>this._slide(this._directionToOrder(ze)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new Me(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=ii[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=ye.findOne(Ze,this._indicatorsElement);e.classList.remove(Je),e.removeAttribute("aria-current");const i=ye.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(Je),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===He,s=e||Ut(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>ue.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(Re).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),Rt(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(Je),i.classList.remove(Je,c,l),this._isSliding=!1,r(qe)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return ye.findOne(ei,this._element)}_getItems(){return ye.find(ti,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return Yt()?t===We?Be:He:t===We?He:Be}_orderToDirection(t){return Yt()?t===Be?We:ze:t===Be?ze:We}static jQueryInterface(t){return this.each((function(){const e=oi.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}ue.on(document,Ue,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=ye.getElementFromSelector(this);if(!e||!e.classList.contains(Ge))return;t.preventDefault();const i=oi.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===ge.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),ue.on(window,Xe,(()=>{const t=ye.find('[data-bs-ride="carousel"]');for(const e of t)oi.getOrCreateInstance(e)})),Kt(oi);const ri=".bs.collapse",ai=`show${ri}`,li=`shown${ri}`,ci=`hide${ri}`,hi=`hidden${ri}`,di=`click${ri}.data-api`,ui="show",fi="collapse",pi="collapsing",mi=`:scope .${fi} .${fi}`,gi='[data-bs-toggle="collapse"]',_i={parent:null,toggle:!0},bi={parent:"(null|element)",toggle:"boolean"};class vi extends be{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=ye.find(gi);for(const t of i){const e=ye.getSelectorFromElement(t),i=ye.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return _i}static get DefaultType(){return bi}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>vi.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(ue.trigger(this._element,ai).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(fi),this._element.classList.add(pi),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(pi),this._element.classList.add(fi,ui),this._element.style[e]="",ue.trigger(this._element,li)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(ue.trigger(this._element,ci).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,Rt(this._element),this._element.classList.add(pi),this._element.classList.remove(fi,ui);for(const t of this._triggerArray){const e=ye.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(pi),this._element.classList.add(fi),ue.trigger(this._element,hi)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(ui)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=Ft(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(gi);for(const e of t){const t=ye.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=ye.find(mi,this._config.parent);return ye.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=vi.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}ue.on(document,di,gi,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of ye.getMultipleElementsFromSelector(this))vi.getOrCreateInstance(t,{toggle:!1}).toggle()})),Kt(vi);const yi="dropdown",wi=".bs.dropdown",Ei=".data-api",Ai="ArrowUp",Ti="ArrowDown",Ci=`hide${wi}`,Oi=`hidden${wi}`,xi=`show${wi}`,ki=`shown${wi}`,Li=`click${wi}${Ei}`,Si=`keydown${wi}${Ei}`,Di=`keyup${wi}${Ei}`,$i="show",Ii='[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)',Ni=`${Ii}.${$i}`,Pi=".dropdown-menu",Mi=Yt()?"top-end":"top-start",ji=Yt()?"top-start":"top-end",Fi=Yt()?"bottom-end":"bottom-start",Hi=Yt()?"bottom-start":"bottom-end",Bi=Yt()?"left-start":"right-start",Wi=Yt()?"right-start":"left-start",zi={autoClose:!0,boundary:"clippingParents",display:"dynamic",offset:[0,2],popperConfig:null,reference:"toggle"},Ri={autoClose:"(boolean|string)",boundary:"(string|element)",display:"string",offset:"(array|string|function)",popperConfig:"(null|object|function)",reference:"(string|element|object)"};class qi extends be{constructor(t,e){super(t,e),this._popper=null,this._parent=this._element.parentNode,this._menu=ye.next(this._element,Pi)[0]||ye.prev(this._element,Pi)[0]||ye.findOne(Pi,this._parent),this._inNavbar=this._detectNavbar()}static get Default(){return zi}static get DefaultType(){return Ri}static get NAME(){return yi}toggle(){return this._isShown()?this.hide():this.show()}show(){if(Bt(this._element)||this._isShown())return;const t={relatedTarget:this._element};if(!ue.trigger(this._element,xi,t).defaultPrevented){if(this._createPopper(),"ontouchstart"in document.documentElement&&!this._parent.closest(".navbar-nav"))for(const t of[].concat(...document.body.children))ue.on(t,"mouseover",zt);this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add($i),this._element.classList.add($i),ue.trigger(this._element,ki,t)}}hide(){if(Bt(this._element)||!this._isShown())return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){if(!ue.trigger(this._element,Ci,t).defaultPrevented){if("ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))ue.off(t,"mouseover",zt);this._popper&&this._popper.destroy(),this._menu.classList.remove($i),this._element.classList.remove($i),this._element.setAttribute("aria-expanded","false"),ge.removeDataAttribute(this._menu,"popper"),ue.trigger(this._element,Oi,t)}}_getConfig(t){if("object"==typeof(t=super._getConfig(t)).reference&&!jt(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${yi.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(){if(void 0===e)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let t=this._element;"parent"===this._config.reference?t=this._parent:jt(this._config.reference)?t=Ft(this._config.reference):"object"==typeof this._config.reference&&(t=this._config.reference);const i=this._getPopperConfig();this._popper=St(t,this._menu,i)}_isShown(){return this._menu.classList.contains($i)}_getPlacement(){const t=this._parent;if(t.classList.contains("dropend"))return Bi;if(t.classList.contains("dropstart"))return Wi;if(t.classList.contains("dropup-center"))return"top";if(t.classList.contains("dropdown-center"))return"bottom";const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?ji:Mi:e?Hi:Fi}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(ge.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...Qt(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=ye.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>Ht(t)));i.length&&Ut(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=ye.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ai,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:ye.prev(this,Ii)[0]||ye.next(this,Ii)[0]||ye.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}ue.on(document,Si,Ii,qi.dataApiKeydownHandler),ue.on(document,Si,Pi,qi.dataApiKeydownHandler),ue.on(document,Li,qi.clearMenus),ue.on(document,Di,qi.clearMenus),ue.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),Kt(qi);const Vi="backdrop",Yi="show",Ki=`mousedown.bs.${Vi}`,Qi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Xi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends _e{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Qi}static get DefaultType(){return Xi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void Qt(t);this._append();const e=this._getElement();this._config.isAnimated&&Rt(e),e.classList.add(Yi),this._emulateAnimation((()=>{Qt(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Yi),this._emulateAnimation((()=>{this.dispose(),Qt(t)}))):Qt(t)}dispose(){this._isAppended&&(ue.off(this._element,Ki),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=Ft(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),ue.on(t,Ki,(()=>{Qt(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){Xt(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends _e{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),ue.off(document,Gi),ue.on(document,Ji,(t=>this._handleFocusin(t))),ue.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,ue.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=ye.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&ge.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=ge.getDataAttribute(t,e);null!==i?(ge.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(jt(t))e(t);else for(const i of ye.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",En="show",An="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends be{constructor(t,e){super(t,e),this._dialog=ye.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||ue.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(ue.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(En),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){ue.off(window,hn),ue.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=ye.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),Rt(this._element),this._element.classList.add(En),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,ue.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){ue.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),ue.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),ue.on(this._element,bn,(t=>{ue.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),ue.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(ue.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(An)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(An),this._queueCallback((()=>{this._element.classList.remove(An),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=Yt()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=Yt()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}ue.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=ye.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),ue.one(e,pn,(t=>{t.defaultPrevented||ue.one(e,fn,(()=>{Ht(this)&&this.focus()}))}));const i=ye.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),we(On),Kt(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Bn=`click${xn}${kn}`,Wn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends be{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||ue.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),ue.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(ue.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),ue.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():ue.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){ue.on(this._element,Wn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():ue.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}ue.on(document,Bn,'[data-bs-toggle="offcanvas"]',(function(t){const e=ye.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),Bt(this))return;ue.one(e,Fn,(()=>{Ht(this)&&this.focus()}));const i=ye.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),ue.on(window,Ln,(()=>{for(const t of ye.find(In))qn.getOrCreateInstance(t).show()})),ue.on(window,Hn,(()=>{for(const t of ye.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),we(qn),Kt(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Yn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Kn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Qn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Yn.has(i)||Boolean(Kn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Xn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"

"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends _e{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Xn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=ye.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?jt(e)?this._putElementInTemplate(Ft(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Qn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return Qt(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:Yt()?"left":"right",BOTTOM:"bottom",LEFT:Yt()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends be{constructor(t,i){if(void 0===e)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,i),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),ue.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=ue.trigger(this._element,this.constructor.eventName("show")),e=(Wt(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),ue.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))ue.on(t,"mouseover",zt);this._queueCallback((()=>{ue.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!ue.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))ue.off(t,"mouseover",zt);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),ue.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=Qt(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return St(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return Qt(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...Qt(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)ue.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");ue.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),ue.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},ue.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=ge.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:Ft(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}Kt(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}Kt(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},Es={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class As extends be{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return Es}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=Ft(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(ue.off(this._config.target,ms),ue.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=ye.find(bs,this._config.target);for(const e of t){if(!e.hash||Bt(e))continue;const t=ye.findOne(decodeURI(e.hash),this._element);Ht(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),ue.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))ye.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of ye.parents(t,".nav, .list-group"))for(const t of ye.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=ye.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=As.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}ue.on(window,gs,(()=>{for(const t of ye.find('[data-bs-spy="scroll"]'))As.getOrCreateInstance(t)})),Kt(As);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Bs="show",Ws=".dropdown-toggle",zs=`:not(${Ws})`,Rs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',qs=`.nav-link${zs}, .list-group-item${zs}, [role="tab"]${zs}, ${Rs}`,Vs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Ys extends be{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),ue.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?ue.trigger(e,Cs,{relatedTarget:t}):null;ue.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(ye.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),ue.trigger(t,ks,{relatedTarget:e})):t.classList.add(Bs)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(ye.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),ue.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Bs)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!Bt(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=Ut(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Ys.getOrCreateInstance(i).show())}_getChildren(){return ye.find(qs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=ye.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=ye.findOne(t,i);s&&s.classList.toggle(n,e)};n(Ws,Fs),n(".dropdown-menu",Bs),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(qs)?t:ye.findOne(qs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Ys.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}ue.on(document,Ls,Rs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),Bt(this)||Ys.getOrCreateInstance(this).show()})),ue.on(window,Ds,(()=>{for(const t of ye.find(Vs))Ys.getOrCreateInstance(t)})),Kt(Ys);const Ks=".bs.toast",Qs=`mouseover${Ks}`,Xs=`mouseout${Ks}`,Us=`focusin${Ks}`,Gs=`focusout${Ks}`,Js=`hide${Ks}`,Zs=`hidden${Ks}`,to=`show${Ks}`,eo=`shown${Ks}`,io="hide",no="show",so="showing",oo={animation:"boolean",autohide:"boolean",delay:"number"},ro={animation:!0,autohide:!0,delay:5e3};class ao extends be{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return ro}static get DefaultType(){return oo}static get NAME(){return"toast"}show(){ue.trigger(this._element,to).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(io),Rt(this._element),this._element.classList.add(no,so),this._queueCallback((()=>{this._element.classList.remove(so),ue.trigger(this._element,eo),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(ue.trigger(this._element,Js).defaultPrevented||(this._element.classList.add(so),this._queueCallback((()=>{this._element.classList.add(io),this._element.classList.remove(so,no),ue.trigger(this._element,Zs)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(no),super.dispose()}isShown(){return this._element.classList.contains(no)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){ue.on(this._element,Qs,(t=>this._onInteraction(t,!0))),ue.on(this._element,Xs,(t=>this._onInteraction(t,!1))),ue.on(this._element,Us,(t=>this._onInteraction(t,!0))),ue.on(this._element,Gs,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ao.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}function lo(t){"loading"!=document.readyState?t():document.addEventListener("DOMContentLoaded",t)}we(ao),Kt(ao),lo((function(){[].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')).map((function(t){return new cs(t,{delay:{show:500,hide:100}})}))})),lo((function(){document.getElementById("pst-back-to-top").addEventListener("click",(function(){document.body.scrollTop=0,document.documentElement.scrollTop=0}))})),lo((function(){var t=document.getElementById("pst-back-to-top"),e=document.getElementsByClassName("bd-header")[0].getBoundingClientRect();window.addEventListener("scroll",(function(){this.oldScroll>this.scrollY&&this.scrollY>e.bottom?t.style.display="block":t.style.display="none",this.oldScroll=this.scrollY}))}))})(); +//# sourceMappingURL=bootstrap.js.map \ No newline at end of file diff --git a/_static/scripts/bootstrap.js.LICENSE.txt b/_static/scripts/bootstrap.js.LICENSE.txt new file mode 100644 index 0000000..10f979d --- /dev/null +++ b/_static/scripts/bootstrap.js.LICENSE.txt @@ -0,0 +1,5 @@ +/*! + * Bootstrap v5.3.2 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ diff --git a/_static/scripts/bootstrap.js.map b/_static/scripts/bootstrap.js.map new file mode 100644 index 0000000..e5bc157 --- /dev/null +++ b/_static/scripts/bootstrap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripts/bootstrap.js","mappings":";mBACA,IAAIA,EAAsB,CCA1BA,EAAwB,CAACC,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXF,EAAoBI,EAAEF,EAAYC,KAASH,EAAoBI,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDH,EAAwB,CAACS,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFV,EAAyBC,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,ipBCLvD,IAAI,EAAM,MACNC,EAAS,SACTC,EAAQ,QACRC,EAAO,OACPC,EAAO,OACPC,EAAiB,CAAC,EAAKJ,EAAQC,EAAOC,GACtCG,EAAQ,QACRC,EAAM,MACNC,EAAkB,kBAClBC,EAAW,WACXC,EAAS,SACTC,EAAY,YACZC,EAAmCP,EAAeQ,QAAO,SAAUC,EAAKC,GACjF,OAAOD,EAAIE,OAAO,CAACD,EAAY,IAAMT,EAAOS,EAAY,IAAMR,GAChE,GAAG,IACQ,EAA0B,GAAGS,OAAOX,EAAgB,CAACD,IAAOS,QAAO,SAAUC,EAAKC,GAC3F,OAAOD,EAAIE,OAAO,CAACD,EAAWA,EAAY,IAAMT,EAAOS,EAAY,IAAMR,GAC3E,GAAG,IAEQU,EAAa,aACbC,EAAO,OACPC,EAAY,YAEZC,EAAa,aACbC,EAAO,OACPC,EAAY,YAEZC,EAAc,cACdC,EAAQ,QACRC,EAAa,aACbC,EAAiB,CAACT,EAAYC,EAAMC,EAAWC,EAAYC,EAAMC,EAAWC,EAAaC,EAAOC,GC9B5F,SAASE,EAAYC,GAClC,OAAOA,GAAWA,EAAQC,UAAY,IAAIC,cAAgB,IAC5D,CCFe,SAASC,EAAUC,GAChC,GAAY,MAARA,EACF,OAAOC,OAGT,GAAwB,oBAApBD,EAAKE,WAAkC,CACzC,IAAIC,EAAgBH,EAAKG,cACzB,OAAOA,GAAgBA,EAAcC,aAAwBH,MAC/D,CAEA,OAAOD,CACT,CCTA,SAASK,EAAUL,GAEjB,OAAOA,aADUD,EAAUC,GAAMM,SACIN,aAAgBM,OACvD,CAEA,SAASC,EAAcP,GAErB,OAAOA,aADUD,EAAUC,GAAMQ,aACIR,aAAgBQ,WACvD,CAEA,SAASC,EAAaT,GAEpB,MAA0B,oBAAfU,aAKJV,aADUD,EAAUC,GAAMU,YACIV,aAAgBU,WACvD,CCwDA,SACEC,KAAM,cACNC,SAAS,EACTC,MAAO,QACPC,GA5EF,SAAqBC,GACnB,IAAIC,EAAQD,EAAKC,MACjB3D,OAAO4D,KAAKD,EAAME,UAAUC,SAAQ,SAAUR,GAC5C,IAAIS,EAAQJ,EAAMK,OAAOV,IAAS,CAAC,EAC/BW,EAAaN,EAAMM,WAAWX,IAAS,CAAC,EACxCf,EAAUoB,EAAME,SAASP,GAExBJ,EAAcX,IAAaD,EAAYC,KAO5CvC,OAAOkE,OAAO3B,EAAQwB,MAAOA,GAC7B/D,OAAO4D,KAAKK,GAAYH,SAAQ,SAAUR,GACxC,IAAI3C,EAAQsD,EAAWX,IAET,IAAV3C,EACF4B,EAAQ4B,gBAAgBb,GAExBf,EAAQ6B,aAAad,GAAgB,IAAV3C,EAAiB,GAAKA,EAErD,IACF,GACF,EAoDE0D,OAlDF,SAAgBC,GACd,IAAIX,EAAQW,EAAMX,MACdY,EAAgB,CAClBlD,OAAQ,CACNmD,SAAUb,EAAMc,QAAQC,SACxB5D,KAAM,IACN6D,IAAK,IACLC,OAAQ,KAEVC,MAAO,CACLL,SAAU,YAEZlD,UAAW,CAAC,GASd,OAPAtB,OAAOkE,OAAOP,EAAME,SAASxC,OAAO0C,MAAOQ,EAAclD,QACzDsC,EAAMK,OAASO,EAEXZ,EAAME,SAASgB,OACjB7E,OAAOkE,OAAOP,EAAME,SAASgB,MAAMd,MAAOQ,EAAcM,OAGnD,WACL7E,OAAO4D,KAAKD,EAAME,UAAUC,SAAQ,SAAUR,GAC5C,IAAIf,EAAUoB,EAAME,SAASP,GACzBW,EAAaN,EAAMM,WAAWX,IAAS,CAAC,EAGxCS,EAFkB/D,OAAO4D,KAAKD,EAAMK,OAAOzD,eAAe+C,GAAQK,EAAMK,OAAOV,GAAQiB,EAAcjB,IAE7E9B,QAAO,SAAUuC,EAAOe,GAElD,OADAf,EAAMe,GAAY,GACXf,CACT,GAAG,CAAC,GAECb,EAAcX,IAAaD,EAAYC,KAI5CvC,OAAOkE,OAAO3B,EAAQwB,MAAOA,GAC7B/D,OAAO4D,KAAKK,GAAYH,SAAQ,SAAUiB,GACxCxC,EAAQ4B,gBAAgBY,EAC1B,IACF,GACF,CACF,EASEC,SAAU,CAAC,kBCjFE,SAASC,EAAiBvD,GACvC,OAAOA,EAAUwD,MAAM,KAAK,EAC9B,CCHO,IAAI,EAAMC,KAAKC,IACX,EAAMD,KAAKE,IACXC,EAAQH,KAAKG,MCFT,SAASC,IACtB,IAAIC,EAASC,UAAUC,cAEvB,OAAc,MAAVF,GAAkBA,EAAOG,QAAUC,MAAMC,QAAQL,EAAOG,QACnDH,EAAOG,OAAOG,KAAI,SAAUC,GACjC,OAAOA,EAAKC,MAAQ,IAAMD,EAAKE,OACjC,IAAGC,KAAK,KAGHT,UAAUU,SACnB,CCTe,SAASC,IACtB,OAAQ,iCAAiCC,KAAKd,IAChD,CCCe,SAASe,EAAsB/D,EAASgE,EAAcC,QAC9C,IAAjBD,IACFA,GAAe,QAGO,IAApBC,IACFA,GAAkB,GAGpB,IAAIC,EAAalE,EAAQ+D,wBACrBI,EAAS,EACTC,EAAS,EAETJ,GAAgBrD,EAAcX,KAChCmE,EAASnE,EAAQqE,YAAc,GAAItB,EAAMmB,EAAWI,OAAStE,EAAQqE,aAAmB,EACxFD,EAASpE,EAAQuE,aAAe,GAAIxB,EAAMmB,EAAWM,QAAUxE,EAAQuE,cAAoB,GAG7F,IACIE,GADOhE,EAAUT,GAAWG,EAAUH,GAAWK,QAC3BoE,eAEtBC,GAAoBb,KAAsBI,EAC1CU,GAAKT,EAAW3F,MAAQmG,GAAoBD,EAAiBA,EAAeG,WAAa,IAAMT,EAC/FU,GAAKX,EAAW9B,KAAOsC,GAAoBD,EAAiBA,EAAeK,UAAY,IAAMV,EAC7FE,EAAQJ,EAAWI,MAAQH,EAC3BK,EAASN,EAAWM,OAASJ,EACjC,MAAO,CACLE,MAAOA,EACPE,OAAQA,EACRpC,IAAKyC,EACLvG,MAAOqG,EAAIL,EACXjG,OAAQwG,EAAIL,EACZjG,KAAMoG,EACNA,EAAGA,EACHE,EAAGA,EAEP,CCrCe,SAASE,EAAc/E,GACpC,IAAIkE,EAAaH,EAAsB/D,GAGnCsE,EAAQtE,EAAQqE,YAChBG,EAASxE,EAAQuE,aAUrB,OARI3B,KAAKoC,IAAId,EAAWI,MAAQA,IAAU,IACxCA,EAAQJ,EAAWI,OAGjB1B,KAAKoC,IAAId,EAAWM,OAASA,IAAW,IAC1CA,EAASN,EAAWM,QAGf,CACLG,EAAG3E,EAAQ4E,WACXC,EAAG7E,EAAQ8E,UACXR,MAAOA,EACPE,OAAQA,EAEZ,CCvBe,SAASS,EAASC,EAAQC,GACvC,IAAIC,EAAWD,EAAME,aAAeF,EAAME,cAE1C,GAAIH,EAAOD,SAASE,GAClB,OAAO,EAEJ,GAAIC,GAAYvE,EAAauE,GAAW,CACzC,IAAIE,EAAOH,EAEX,EAAG,CACD,GAAIG,GAAQJ,EAAOK,WAAWD,GAC5B,OAAO,EAITA,EAAOA,EAAKE,YAAcF,EAAKG,IACjC,OAASH,EACX,CAGF,OAAO,CACT,CCrBe,SAAS,EAAiBtF,GACvC,OAAOG,EAAUH,GAAS0F,iBAAiB1F,EAC7C,CCFe,SAAS2F,EAAe3F,GACrC,MAAO,CAAC,QAAS,KAAM,MAAM4F,QAAQ7F,EAAYC,KAAa,CAChE,CCFe,SAAS6F,EAAmB7F,GAEzC,QAASS,EAAUT,GAAWA,EAAQO,cACtCP,EAAQ8F,WAAazF,OAAOyF,UAAUC,eACxC,CCFe,SAASC,EAAchG,GACpC,MAA6B,SAAzBD,EAAYC,GACPA,EAMPA,EAAQiG,cACRjG,EAAQwF,aACR3E,EAAab,GAAWA,EAAQyF,KAAO,OAEvCI,EAAmB7F,EAGvB,CCVA,SAASkG,EAAoBlG,GAC3B,OAAKW,EAAcX,IACoB,UAAvC,EAAiBA,GAASiC,SAInBjC,EAAQmG,aAHN,IAIX,CAwCe,SAASC,EAAgBpG,GAItC,IAHA,IAAIK,EAASF,EAAUH,GACnBmG,EAAeD,EAAoBlG,GAEhCmG,GAAgBR,EAAeQ,IAA6D,WAA5C,EAAiBA,GAAclE,UACpFkE,EAAeD,EAAoBC,GAGrC,OAAIA,IAA+C,SAA9BpG,EAAYoG,IAA0D,SAA9BpG,EAAYoG,IAAwE,WAA5C,EAAiBA,GAAclE,UAC3H5B,EAGF8F,GAhDT,SAA4BnG,GAC1B,IAAIqG,EAAY,WAAWvC,KAAKd,KAGhC,GAFW,WAAWc,KAAKd,MAEfrC,EAAcX,IAII,UAFX,EAAiBA,GAEnBiC,SACb,OAAO,KAIX,IAAIqE,EAAcN,EAAchG,GAMhC,IAJIa,EAAayF,KACfA,EAAcA,EAAYb,MAGrB9E,EAAc2F,IAAgB,CAAC,OAAQ,QAAQV,QAAQ7F,EAAYuG,IAAgB,GAAG,CAC3F,IAAIC,EAAM,EAAiBD,GAI3B,GAAsB,SAAlBC,EAAIC,WAA4C,SAApBD,EAAIE,aAA0C,UAAhBF,EAAIG,UAAiF,IAA1D,CAAC,YAAa,eAAed,QAAQW,EAAII,aAAsBN,GAAgC,WAAnBE,EAAII,YAA2BN,GAAaE,EAAIK,QAAyB,SAAfL,EAAIK,OACjO,OAAON,EAEPA,EAAcA,EAAYd,UAE9B,CAEA,OAAO,IACT,CAgByBqB,CAAmB7G,IAAYK,CACxD,CCpEe,SAASyG,EAAyB3H,GAC/C,MAAO,CAAC,MAAO,UAAUyG,QAAQzG,IAAc,EAAI,IAAM,GAC3D,CCDO,SAAS4H,EAAOjE,EAAK1E,EAAOyE,GACjC,OAAO,EAAQC,EAAK,EAAQ1E,EAAOyE,GACrC,CCFe,SAASmE,EAAmBC,GACzC,OAAOxJ,OAAOkE,OAAO,CAAC,ECDf,CACLS,IAAK,EACL9D,MAAO,EACPD,OAAQ,EACRE,KAAM,GDHuC0I,EACjD,CEHe,SAASC,EAAgB9I,EAAOiD,GAC7C,OAAOA,EAAKpC,QAAO,SAAUkI,EAAS5J,GAEpC,OADA4J,EAAQ5J,GAAOa,EACR+I,CACT,GAAG,CAAC,EACN,CC4EA,SACEpG,KAAM,QACNC,SAAS,EACTC,MAAO,OACPC,GApEF,SAAeC,GACb,IAAIiG,EAEAhG,EAAQD,EAAKC,MACbL,EAAOI,EAAKJ,KACZmB,EAAUf,EAAKe,QACfmF,EAAejG,EAAME,SAASgB,MAC9BgF,EAAgBlG,EAAMmG,cAAcD,cACpCE,EAAgB9E,EAAiBtB,EAAMjC,WACvCsI,EAAOX,EAAyBU,GAEhCE,EADa,CAACnJ,EAAMD,GAAOsH,QAAQ4B,IAAkB,EAClC,SAAW,QAElC,GAAKH,GAAiBC,EAAtB,CAIA,IAAIL,EAxBgB,SAAyBU,EAASvG,GAItD,OAAO4F,EAAsC,iBAH7CW,EAA6B,mBAAZA,EAAyBA,EAAQlK,OAAOkE,OAAO,CAAC,EAAGP,EAAMwG,MAAO,CAC/EzI,UAAWiC,EAAMjC,aACbwI,GACkDA,EAAUT,EAAgBS,EAASlJ,GAC7F,CAmBsBoJ,CAAgB3F,EAAQyF,QAASvG,GACjD0G,EAAY/C,EAAcsC,GAC1BU,EAAmB,MAATN,EAAe,EAAMlJ,EAC/ByJ,EAAmB,MAATP,EAAepJ,EAASC,EAClC2J,EAAU7G,EAAMwG,MAAM7I,UAAU2I,GAAOtG,EAAMwG,MAAM7I,UAAU0I,GAAQH,EAAcG,GAAQrG,EAAMwG,MAAM9I,OAAO4I,GAC9GQ,EAAYZ,EAAcG,GAAQrG,EAAMwG,MAAM7I,UAAU0I,GACxDU,EAAoB/B,EAAgBiB,GACpCe,EAAaD,EAA6B,MAATV,EAAeU,EAAkBE,cAAgB,EAAIF,EAAkBG,aAAe,EAAI,EAC3HC,EAAoBN,EAAU,EAAIC,EAAY,EAG9CpF,EAAMmE,EAAcc,GACpBlF,EAAMuF,EAAaN,EAAUJ,GAAOT,EAAce,GAClDQ,EAASJ,EAAa,EAAIN,EAAUJ,GAAO,EAAIa,EAC/CE,EAAS1B,EAAOjE,EAAK0F,EAAQ3F,GAE7B6F,EAAWjB,EACfrG,EAAMmG,cAAcxG,KAASqG,EAAwB,CAAC,GAAyBsB,GAAYD,EAAQrB,EAAsBuB,aAAeF,EAASD,EAAQpB,EAnBzJ,CAoBF,EAkCEtF,OAhCF,SAAgBC,GACd,IAAIX,EAAQW,EAAMX,MAEdwH,EADU7G,EAAMG,QACWlC,QAC3BqH,OAAoC,IAArBuB,EAA8B,sBAAwBA,EAErD,MAAhBvB,IAKwB,iBAAjBA,IACTA,EAAejG,EAAME,SAASxC,OAAO+J,cAAcxB,MAOhDpC,EAAS7D,EAAME,SAASxC,OAAQuI,KAIrCjG,EAAME,SAASgB,MAAQ+E,EACzB,EASE5E,SAAU,CAAC,iBACXqG,iBAAkB,CAAC,oBCxFN,SAASC,EAAa5J,GACnC,OAAOA,EAAUwD,MAAM,KAAK,EAC9B,CCOA,IAAIqG,EAAa,CACf5G,IAAK,OACL9D,MAAO,OACPD,OAAQ,OACRE,KAAM,QAeD,SAAS0K,GAAYlH,GAC1B,IAAImH,EAEApK,EAASiD,EAAMjD,OACfqK,EAAapH,EAAMoH,WACnBhK,EAAY4C,EAAM5C,UAClBiK,EAAYrH,EAAMqH,UAClBC,EAAUtH,EAAMsH,QAChBpH,EAAWF,EAAME,SACjBqH,EAAkBvH,EAAMuH,gBACxBC,EAAWxH,EAAMwH,SACjBC,EAAezH,EAAMyH,aACrBC,EAAU1H,EAAM0H,QAChBC,EAAaL,EAAQ1E,EACrBA,OAAmB,IAAf+E,EAAwB,EAAIA,EAChCC,EAAaN,EAAQxE,EACrBA,OAAmB,IAAf8E,EAAwB,EAAIA,EAEhCC,EAAgC,mBAAjBJ,EAA8BA,EAAa,CAC5D7E,EAAGA,EACHE,IACG,CACHF,EAAGA,EACHE,GAGFF,EAAIiF,EAAMjF,EACVE,EAAI+E,EAAM/E,EACV,IAAIgF,EAAOR,EAAQrL,eAAe,KAC9B8L,EAAOT,EAAQrL,eAAe,KAC9B+L,EAAQxL,EACRyL,EAAQ,EACRC,EAAM5J,OAEV,GAAIkJ,EAAU,CACZ,IAAIpD,EAAeC,EAAgBtH,GAC/BoL,EAAa,eACbC,EAAY,cAEZhE,IAAiBhG,EAAUrB,IAGmB,WAA5C,EAFJqH,EAAeN,EAAmB/G,IAECmD,UAAsC,aAAbA,IAC1DiI,EAAa,eACbC,EAAY,gBAOZhL,IAAc,IAAQA,IAAcZ,GAAQY,IAAcb,IAAU8K,IAAczK,KACpFqL,EAAQ3L,EAGRwG,IAFc4E,GAAWtD,IAAiB8D,GAAOA,EAAIxF,eAAiBwF,EAAIxF,eAAeD,OACzF2B,EAAa+D,IACEf,EAAW3E,OAC1BK,GAAKyE,EAAkB,GAAK,GAG1BnK,IAAcZ,IAASY,IAAc,GAAOA,IAAcd,GAAW+K,IAAczK,KACrFoL,EAAQzL,EAGRqG,IAFc8E,GAAWtD,IAAiB8D,GAAOA,EAAIxF,eAAiBwF,EAAIxF,eAAeH,MACzF6B,EAAagE,IACEhB,EAAW7E,MAC1BK,GAAK2E,EAAkB,GAAK,EAEhC,CAEA,IAgBMc,EAhBFC,EAAe5M,OAAOkE,OAAO,CAC/BM,SAAUA,GACTsH,GAAYP,GAEXsB,GAAyB,IAAjBd,EAlFd,SAA2BrI,EAAM8I,GAC/B,IAAItF,EAAIxD,EAAKwD,EACTE,EAAI1D,EAAK0D,EACT0F,EAAMN,EAAIO,kBAAoB,EAClC,MAAO,CACL7F,EAAG5B,EAAM4B,EAAI4F,GAAOA,GAAO,EAC3B1F,EAAG9B,EAAM8B,EAAI0F,GAAOA,GAAO,EAE/B,CA0EsCE,CAAkB,CACpD9F,EAAGA,EACHE,GACC1E,EAAUrB,IAAW,CACtB6F,EAAGA,EACHE,GAMF,OAHAF,EAAI2F,EAAM3F,EACVE,EAAIyF,EAAMzF,EAENyE,EAGK7L,OAAOkE,OAAO,CAAC,EAAG0I,IAAeD,EAAiB,CAAC,GAAkBJ,GAASF,EAAO,IAAM,GAAIM,EAAeL,GAASF,EAAO,IAAM,GAAIO,EAAe5D,WAAayD,EAAIO,kBAAoB,IAAM,EAAI,aAAe7F,EAAI,OAASE,EAAI,MAAQ,eAAiBF,EAAI,OAASE,EAAI,SAAUuF,IAG5R3M,OAAOkE,OAAO,CAAC,EAAG0I,IAAenB,EAAkB,CAAC,GAAmBc,GAASF,EAAOjF,EAAI,KAAO,GAAIqE,EAAgBa,GAASF,EAAOlF,EAAI,KAAO,GAAIuE,EAAgB1C,UAAY,GAAI0C,GAC9L,CA4CA,UACEnI,KAAM,gBACNC,SAAS,EACTC,MAAO,cACPC,GA9CF,SAAuBwJ,GACrB,IAAItJ,EAAQsJ,EAAMtJ,MACdc,EAAUwI,EAAMxI,QAChByI,EAAwBzI,EAAQoH,gBAChCA,OAA4C,IAA1BqB,GAA0CA,EAC5DC,EAAoB1I,EAAQqH,SAC5BA,OAAiC,IAAtBqB,GAAsCA,EACjDC,EAAwB3I,EAAQsH,aAChCA,OAAyC,IAA1BqB,GAA0CA,EACzDR,EAAe,CACjBlL,UAAWuD,EAAiBtB,EAAMjC,WAClCiK,UAAWL,EAAa3H,EAAMjC,WAC9BL,OAAQsC,EAAME,SAASxC,OACvBqK,WAAY/H,EAAMwG,MAAM9I,OACxBwK,gBAAiBA,EACjBG,QAAoC,UAA3BrI,EAAMc,QAAQC,UAGgB,MAArCf,EAAMmG,cAAcD,gBACtBlG,EAAMK,OAAO3C,OAASrB,OAAOkE,OAAO,CAAC,EAAGP,EAAMK,OAAO3C,OAAQmK,GAAYxL,OAAOkE,OAAO,CAAC,EAAG0I,EAAc,CACvGhB,QAASjI,EAAMmG,cAAcD,cAC7BrF,SAAUb,EAAMc,QAAQC,SACxBoH,SAAUA,EACVC,aAAcA,OAIe,MAA7BpI,EAAMmG,cAAcjF,QACtBlB,EAAMK,OAAOa,MAAQ7E,OAAOkE,OAAO,CAAC,EAAGP,EAAMK,OAAOa,MAAO2G,GAAYxL,OAAOkE,OAAO,CAAC,EAAG0I,EAAc,CACrGhB,QAASjI,EAAMmG,cAAcjF,MAC7BL,SAAU,WACVsH,UAAU,EACVC,aAAcA,OAIlBpI,EAAMM,WAAW5C,OAASrB,OAAOkE,OAAO,CAAC,EAAGP,EAAMM,WAAW5C,OAAQ,CACnE,wBAAyBsC,EAAMjC,WAEnC,EAQE2L,KAAM,CAAC,GCrKT,IAAIC,GAAU,CACZA,SAAS,GAsCX,UACEhK,KAAM,iBACNC,SAAS,EACTC,MAAO,QACPC,GAAI,WAAe,EACnBY,OAxCF,SAAgBX,GACd,IAAIC,EAAQD,EAAKC,MACb4J,EAAW7J,EAAK6J,SAChB9I,EAAUf,EAAKe,QACf+I,EAAkB/I,EAAQgJ,OAC1BA,OAA6B,IAApBD,GAAoCA,EAC7CE,EAAkBjJ,EAAQkJ,OAC1BA,OAA6B,IAApBD,GAAoCA,EAC7C9K,EAASF,EAAUiB,EAAME,SAASxC,QAClCuM,EAAgB,GAAGjM,OAAOgC,EAAMiK,cAActM,UAAWqC,EAAMiK,cAAcvM,QAYjF,OAVIoM,GACFG,EAAc9J,SAAQ,SAAU+J,GAC9BA,EAAaC,iBAAiB,SAAUP,EAASQ,OAAQT,GAC3D,IAGEK,GACF/K,EAAOkL,iBAAiB,SAAUP,EAASQ,OAAQT,IAG9C,WACDG,GACFG,EAAc9J,SAAQ,SAAU+J,GAC9BA,EAAaG,oBAAoB,SAAUT,EAASQ,OAAQT,GAC9D,IAGEK,GACF/K,EAAOoL,oBAAoB,SAAUT,EAASQ,OAAQT,GAE1D,CACF,EASED,KAAM,CAAC,GC/CT,IAAIY,GAAO,CACTnN,KAAM,QACND,MAAO,OACPD,OAAQ,MACR+D,IAAK,UAEQ,SAASuJ,GAAqBxM,GAC3C,OAAOA,EAAUyM,QAAQ,0BAA0B,SAAUC,GAC3D,OAAOH,GAAKG,EACd,GACF,CCVA,IAAI,GAAO,CACTnN,MAAO,MACPC,IAAK,SAEQ,SAASmN,GAA8B3M,GACpD,OAAOA,EAAUyM,QAAQ,cAAc,SAAUC,GAC/C,OAAO,GAAKA,EACd,GACF,CCPe,SAASE,GAAgB3L,GACtC,IAAI6J,EAAM9J,EAAUC,GAGpB,MAAO,CACL4L,WAHe/B,EAAIgC,YAInBC,UAHcjC,EAAIkC,YAKtB,CCNe,SAASC,GAAoBpM,GAQ1C,OAAO+D,EAAsB8B,EAAmB7F,IAAUzB,KAAOwN,GAAgB/L,GAASgM,UAC5F,CCXe,SAASK,GAAerM,GAErC,IAAIsM,EAAoB,EAAiBtM,GACrCuM,EAAWD,EAAkBC,SAC7BC,EAAYF,EAAkBE,UAC9BC,EAAYH,EAAkBG,UAElC,MAAO,6BAA6B3I,KAAKyI,EAAWE,EAAYD,EAClE,CCLe,SAASE,GAAgBtM,GACtC,MAAI,CAAC,OAAQ,OAAQ,aAAawF,QAAQ7F,EAAYK,KAAU,EAEvDA,EAAKG,cAAcoM,KAGxBhM,EAAcP,IAASiM,GAAejM,GACjCA,EAGFsM,GAAgB1G,EAAc5F,GACvC,CCJe,SAASwM,GAAkB5M,EAAS6M,GACjD,IAAIC,OAES,IAATD,IACFA,EAAO,IAGT,IAAIvB,EAAeoB,GAAgB1M,GAC/B+M,EAASzB,KAAqE,OAAlDwB,EAAwB9M,EAAQO,oBAAyB,EAASuM,EAAsBH,MACpH1C,EAAM9J,EAAUmL,GAChB0B,EAASD,EAAS,CAAC9C,GAAK7K,OAAO6K,EAAIxF,gBAAkB,GAAI4H,GAAef,GAAgBA,EAAe,IAAMA,EAC7G2B,EAAcJ,EAAKzN,OAAO4N,GAC9B,OAAOD,EAASE,EAChBA,EAAY7N,OAAOwN,GAAkB5G,EAAcgH,IACrD,CCzBe,SAASE,GAAiBC,GACvC,OAAO1P,OAAOkE,OAAO,CAAC,EAAGwL,EAAM,CAC7B5O,KAAM4O,EAAKxI,EACXvC,IAAK+K,EAAKtI,EACVvG,MAAO6O,EAAKxI,EAAIwI,EAAK7I,MACrBjG,OAAQ8O,EAAKtI,EAAIsI,EAAK3I,QAE1B,CCqBA,SAAS4I,GAA2BpN,EAASqN,EAAgBlL,GAC3D,OAAOkL,IAAmBxO,EAAWqO,GCzBxB,SAAyBlN,EAASmC,GAC/C,IAAI8H,EAAM9J,EAAUH,GAChBsN,EAAOzH,EAAmB7F,GAC1ByE,EAAiBwF,EAAIxF,eACrBH,EAAQgJ,EAAKhF,YACb9D,EAAS8I,EAAKjF,aACd1D,EAAI,EACJE,EAAI,EAER,GAAIJ,EAAgB,CAClBH,EAAQG,EAAeH,MACvBE,EAASC,EAAeD,OACxB,IAAI+I,EAAiB1J,KAEjB0J,IAAmBA,GAA+B,UAAbpL,KACvCwC,EAAIF,EAAeG,WACnBC,EAAIJ,EAAeK,UAEvB,CAEA,MAAO,CACLR,MAAOA,EACPE,OAAQA,EACRG,EAAGA,EAAIyH,GAAoBpM,GAC3B6E,EAAGA,EAEP,CDDwD2I,CAAgBxN,EAASmC,IAAa1B,EAAU4M,GAdxG,SAAoCrN,EAASmC,GAC3C,IAAIgL,EAAOpJ,EAAsB/D,GAAS,EAAoB,UAAbmC,GASjD,OARAgL,EAAK/K,IAAM+K,EAAK/K,IAAMpC,EAAQyN,UAC9BN,EAAK5O,KAAO4O,EAAK5O,KAAOyB,EAAQ0N,WAChCP,EAAK9O,OAAS8O,EAAK/K,IAAMpC,EAAQqI,aACjC8E,EAAK7O,MAAQ6O,EAAK5O,KAAOyB,EAAQsI,YACjC6E,EAAK7I,MAAQtE,EAAQsI,YACrB6E,EAAK3I,OAASxE,EAAQqI,aACtB8E,EAAKxI,EAAIwI,EAAK5O,KACd4O,EAAKtI,EAAIsI,EAAK/K,IACP+K,CACT,CAG0HQ,CAA2BN,EAAgBlL,GAAY+K,GEtBlK,SAAyBlN,GACtC,IAAI8M,EAEAQ,EAAOzH,EAAmB7F,GAC1B4N,EAAY7B,GAAgB/L,GAC5B2M,EAA0D,OAAlDG,EAAwB9M,EAAQO,oBAAyB,EAASuM,EAAsBH,KAChGrI,EAAQ,EAAIgJ,EAAKO,YAAaP,EAAKhF,YAAaqE,EAAOA,EAAKkB,YAAc,EAAGlB,EAAOA,EAAKrE,YAAc,GACvG9D,EAAS,EAAI8I,EAAKQ,aAAcR,EAAKjF,aAAcsE,EAAOA,EAAKmB,aAAe,EAAGnB,EAAOA,EAAKtE,aAAe,GAC5G1D,GAAKiJ,EAAU5B,WAAaI,GAAoBpM,GAChD6E,GAAK+I,EAAU1B,UAMnB,MAJiD,QAA7C,EAAiBS,GAAQW,GAAMS,YACjCpJ,GAAK,EAAI2I,EAAKhF,YAAaqE,EAAOA,EAAKrE,YAAc,GAAKhE,GAGrD,CACLA,MAAOA,EACPE,OAAQA,EACRG,EAAGA,EACHE,EAAGA,EAEP,CFCkMmJ,CAAgBnI,EAAmB7F,IACrO,CG1Be,SAASiO,GAAe9M,GACrC,IAOIkI,EAPAtK,EAAYoC,EAAKpC,UACjBiB,EAAUmB,EAAKnB,QACfb,EAAYgC,EAAKhC,UACjBqI,EAAgBrI,EAAYuD,EAAiBvD,GAAa,KAC1DiK,EAAYjK,EAAY4J,EAAa5J,GAAa,KAClD+O,EAAUnP,EAAU4F,EAAI5F,EAAUuF,MAAQ,EAAItE,EAAQsE,MAAQ,EAC9D6J,EAAUpP,EAAU8F,EAAI9F,EAAUyF,OAAS,EAAIxE,EAAQwE,OAAS,EAGpE,OAAQgD,GACN,KAAK,EACH6B,EAAU,CACR1E,EAAGuJ,EACHrJ,EAAG9F,EAAU8F,EAAI7E,EAAQwE,QAE3B,MAEF,KAAKnG,EACHgL,EAAU,CACR1E,EAAGuJ,EACHrJ,EAAG9F,EAAU8F,EAAI9F,EAAUyF,QAE7B,MAEF,KAAKlG,EACH+K,EAAU,CACR1E,EAAG5F,EAAU4F,EAAI5F,EAAUuF,MAC3BO,EAAGsJ,GAEL,MAEF,KAAK5P,EACH8K,EAAU,CACR1E,EAAG5F,EAAU4F,EAAI3E,EAAQsE,MACzBO,EAAGsJ,GAEL,MAEF,QACE9E,EAAU,CACR1E,EAAG5F,EAAU4F,EACbE,EAAG9F,EAAU8F,GAInB,IAAIuJ,EAAW5G,EAAgBV,EAAyBU,GAAiB,KAEzE,GAAgB,MAAZ4G,EAAkB,CACpB,IAAI1G,EAAmB,MAAb0G,EAAmB,SAAW,QAExC,OAAQhF,GACN,KAAK1K,EACH2K,EAAQ+E,GAAY/E,EAAQ+E,IAAarP,EAAU2I,GAAO,EAAI1H,EAAQ0H,GAAO,GAC7E,MAEF,KAAK/I,EACH0K,EAAQ+E,GAAY/E,EAAQ+E,IAAarP,EAAU2I,GAAO,EAAI1H,EAAQ0H,GAAO,GAKnF,CAEA,OAAO2B,CACT,CC3De,SAASgF,GAAejN,EAAOc,QAC5B,IAAZA,IACFA,EAAU,CAAC,GAGb,IAAIoM,EAAWpM,EACXqM,EAAqBD,EAASnP,UAC9BA,OAAmC,IAAvBoP,EAAgCnN,EAAMjC,UAAYoP,EAC9DC,EAAoBF,EAASnM,SAC7BA,OAAiC,IAAtBqM,EAA+BpN,EAAMe,SAAWqM,EAC3DC,EAAoBH,EAASI,SAC7BA,OAAiC,IAAtBD,EAA+B7P,EAAkB6P,EAC5DE,EAAwBL,EAASM,aACjCA,OAAyC,IAA1BD,EAAmC9P,EAAW8P,EAC7DE,EAAwBP,EAASQ,eACjCA,OAA2C,IAA1BD,EAAmC/P,EAAS+P,EAC7DE,EAAuBT,EAASU,YAChCA,OAAuC,IAAzBD,GAA0CA,EACxDE,EAAmBX,EAAS3G,QAC5BA,OAA+B,IAArBsH,EAA8B,EAAIA,EAC5ChI,EAAgBD,EAAsC,iBAAZW,EAAuBA,EAAUT,EAAgBS,EAASlJ,IACpGyQ,EAAaJ,IAAmBhQ,EAASC,EAAYD,EACrDqK,EAAa/H,EAAMwG,MAAM9I,OACzBkB,EAAUoB,EAAME,SAAS0N,EAAcE,EAAaJ,GACpDK,EJkBS,SAAyBnP,EAAS0O,EAAUE,EAAczM,GACvE,IAAIiN,EAAmC,oBAAbV,EAlB5B,SAA4B1O,GAC1B,IAAIpB,EAAkBgO,GAAkB5G,EAAchG,IAElDqP,EADoB,CAAC,WAAY,SAASzJ,QAAQ,EAAiB5F,GAASiC,WAAa,GACnDtB,EAAcX,GAAWoG,EAAgBpG,GAAWA,EAE9F,OAAKS,EAAU4O,GAKRzQ,EAAgBgI,QAAO,SAAUyG,GACtC,OAAO5M,EAAU4M,IAAmBpI,EAASoI,EAAgBgC,IAAmD,SAAhCtP,EAAYsN,EAC9F,IANS,EAOX,CAK6DiC,CAAmBtP,GAAW,GAAGZ,OAAOsP,GAC/F9P,EAAkB,GAAGQ,OAAOgQ,EAAqB,CAACR,IAClDW,EAAsB3Q,EAAgB,GACtC4Q,EAAe5Q,EAAgBK,QAAO,SAAUwQ,EAASpC,GAC3D,IAAIF,EAAOC,GAA2BpN,EAASqN,EAAgBlL,GAK/D,OAJAsN,EAAQrN,IAAM,EAAI+K,EAAK/K,IAAKqN,EAAQrN,KACpCqN,EAAQnR,MAAQ,EAAI6O,EAAK7O,MAAOmR,EAAQnR,OACxCmR,EAAQpR,OAAS,EAAI8O,EAAK9O,OAAQoR,EAAQpR,QAC1CoR,EAAQlR,KAAO,EAAI4O,EAAK5O,KAAMkR,EAAQlR,MAC/BkR,CACT,GAAGrC,GAA2BpN,EAASuP,EAAqBpN,IAK5D,OAJAqN,EAAalL,MAAQkL,EAAalR,MAAQkR,EAAajR,KACvDiR,EAAahL,OAASgL,EAAanR,OAASmR,EAAapN,IACzDoN,EAAa7K,EAAI6K,EAAajR,KAC9BiR,EAAa3K,EAAI2K,EAAapN,IACvBoN,CACT,CInC2BE,CAAgBjP,EAAUT,GAAWA,EAAUA,EAAQ2P,gBAAkB9J,EAAmBzE,EAAME,SAASxC,QAAS4P,EAAUE,EAAczM,GACjKyN,EAAsB7L,EAAsB3C,EAAME,SAASvC,WAC3DuI,EAAgB2G,GAAe,CACjClP,UAAW6Q,EACX5P,QAASmJ,EACThH,SAAU,WACVhD,UAAWA,IAET0Q,EAAmB3C,GAAiBzP,OAAOkE,OAAO,CAAC,EAAGwH,EAAY7B,IAClEwI,EAAoBhB,IAAmBhQ,EAAS+Q,EAAmBD,EAGnEG,EAAkB,CACpB3N,IAAK+M,EAAmB/M,IAAM0N,EAAkB1N,IAAM6E,EAAc7E,IACpE/D,OAAQyR,EAAkBzR,OAAS8Q,EAAmB9Q,OAAS4I,EAAc5I,OAC7EE,KAAM4Q,EAAmB5Q,KAAOuR,EAAkBvR,KAAO0I,EAAc1I,KACvED,MAAOwR,EAAkBxR,MAAQ6Q,EAAmB7Q,MAAQ2I,EAAc3I,OAExE0R,EAAa5O,EAAMmG,cAAckB,OAErC,GAAIqG,IAAmBhQ,GAAUkR,EAAY,CAC3C,IAAIvH,EAASuH,EAAW7Q,GACxB1B,OAAO4D,KAAK0O,GAAiBxO,SAAQ,SAAUhE,GAC7C,IAAI0S,EAAW,CAAC3R,EAAOD,GAAQuH,QAAQrI,IAAQ,EAAI,GAAK,EACpDkK,EAAO,CAAC,EAAKpJ,GAAQuH,QAAQrI,IAAQ,EAAI,IAAM,IACnDwS,EAAgBxS,IAAQkL,EAAOhB,GAAQwI,CACzC,GACF,CAEA,OAAOF,CACT,CCyEA,UACEhP,KAAM,OACNC,SAAS,EACTC,MAAO,OACPC,GA5HF,SAAcC,GACZ,IAAIC,EAAQD,EAAKC,MACbc,EAAUf,EAAKe,QACfnB,EAAOI,EAAKJ,KAEhB,IAAIK,EAAMmG,cAAcxG,GAAMmP,MAA9B,CAoCA,IAhCA,IAAIC,EAAoBjO,EAAQkM,SAC5BgC,OAAsC,IAAtBD,GAAsCA,EACtDE,EAAmBnO,EAAQoO,QAC3BC,OAAoC,IAArBF,GAAqCA,EACpDG,EAA8BtO,EAAQuO,mBACtC9I,EAAUzF,EAAQyF,QAClB+G,EAAWxM,EAAQwM,SACnBE,EAAe1M,EAAQ0M,aACvBI,EAAc9M,EAAQ8M,YACtB0B,EAAwBxO,EAAQyO,eAChCA,OAA2C,IAA1BD,GAA0CA,EAC3DE,EAAwB1O,EAAQ0O,sBAChCC,EAAqBzP,EAAMc,QAAQ/C,UACnCqI,EAAgB9E,EAAiBmO,GAEjCJ,EAAqBD,IADHhJ,IAAkBqJ,GACqCF,EAjC/E,SAAuCxR,GACrC,GAAIuD,EAAiBvD,KAAeX,EAClC,MAAO,GAGT,IAAIsS,EAAoBnF,GAAqBxM,GAC7C,MAAO,CAAC2M,GAA8B3M,GAAY2R,EAAmBhF,GAA8BgF,GACrG,CA0B6IC,CAA8BF,GAA3E,CAAClF,GAAqBkF,KAChHG,EAAa,CAACH,GAAoBzR,OAAOqR,GAAoBxR,QAAO,SAAUC,EAAKC,GACrF,OAAOD,EAAIE,OAAOsD,EAAiBvD,KAAeX,ECvCvC,SAA8B4C,EAAOc,QAClC,IAAZA,IACFA,EAAU,CAAC,GAGb,IAAIoM,EAAWpM,EACX/C,EAAYmP,EAASnP,UACrBuP,EAAWJ,EAASI,SACpBE,EAAeN,EAASM,aACxBjH,EAAU2G,EAAS3G,QACnBgJ,EAAiBrC,EAASqC,eAC1BM,EAAwB3C,EAASsC,sBACjCA,OAAkD,IAA1BK,EAAmC,EAAgBA,EAC3E7H,EAAYL,EAAa5J,GACzB6R,EAAa5H,EAAYuH,EAAiB3R,EAAsBA,EAAoB4H,QAAO,SAAUzH,GACvG,OAAO4J,EAAa5J,KAAeiK,CACrC,IAAK3K,EACDyS,EAAoBF,EAAWpK,QAAO,SAAUzH,GAClD,OAAOyR,EAAsBhL,QAAQzG,IAAc,CACrD,IAEiC,IAA7B+R,EAAkBC,SACpBD,EAAoBF,GAItB,IAAII,EAAYF,EAAkBjS,QAAO,SAAUC,EAAKC,GAOtD,OANAD,EAAIC,GAAakP,GAAejN,EAAO,CACrCjC,UAAWA,EACXuP,SAAUA,EACVE,aAAcA,EACdjH,QAASA,IACRjF,EAAiBvD,IACbD,CACT,GAAG,CAAC,GACJ,OAAOzB,OAAO4D,KAAK+P,GAAWC,MAAK,SAAUC,EAAGC,GAC9C,OAAOH,EAAUE,GAAKF,EAAUG,EAClC,GACF,CDC6DC,CAAqBpQ,EAAO,CACnFjC,UAAWA,EACXuP,SAAUA,EACVE,aAAcA,EACdjH,QAASA,EACTgJ,eAAgBA,EAChBC,sBAAuBA,IACpBzR,EACP,GAAG,IACCsS,EAAgBrQ,EAAMwG,MAAM7I,UAC5BoK,EAAa/H,EAAMwG,MAAM9I,OACzB4S,EAAY,IAAIC,IAChBC,GAAqB,EACrBC,EAAwBb,EAAW,GAE9Bc,EAAI,EAAGA,EAAId,EAAWG,OAAQW,IAAK,CAC1C,IAAI3S,EAAY6R,EAAWc,GAEvBC,EAAiBrP,EAAiBvD,GAElC6S,EAAmBjJ,EAAa5J,KAAeT,EAC/CuT,EAAa,CAAC,EAAK5T,GAAQuH,QAAQmM,IAAmB,EACtDrK,EAAMuK,EAAa,QAAU,SAC7B1F,EAAW8B,GAAejN,EAAO,CACnCjC,UAAWA,EACXuP,SAAUA,EACVE,aAAcA,EACdI,YAAaA,EACbrH,QAASA,IAEPuK,EAAoBD,EAAaD,EAAmB1T,EAAQC,EAAOyT,EAAmB3T,EAAS,EAE/FoT,EAAc/J,GAAOyB,EAAWzB,KAClCwK,EAAoBvG,GAAqBuG,IAG3C,IAAIC,EAAmBxG,GAAqBuG,GACxCE,EAAS,GAUb,GARIhC,GACFgC,EAAOC,KAAK9F,EAASwF,IAAmB,GAGtCxB,GACF6B,EAAOC,KAAK9F,EAAS2F,IAAsB,EAAG3F,EAAS4F,IAAqB,GAG1EC,EAAOE,OAAM,SAAUC,GACzB,OAAOA,CACT,IAAI,CACFV,EAAwB1S,EACxByS,GAAqB,EACrB,KACF,CAEAF,EAAUc,IAAIrT,EAAWiT,EAC3B,CAEA,GAAIR,EAqBF,IAnBA,IAEIa,EAAQ,SAAeC,GACzB,IAAIC,EAAmB3B,EAAW4B,MAAK,SAAUzT,GAC/C,IAAIiT,EAASV,EAAU9T,IAAIuB,GAE3B,GAAIiT,EACF,OAAOA,EAAOS,MAAM,EAAGH,GAAIJ,OAAM,SAAUC,GACzC,OAAOA,CACT,GAEJ,IAEA,GAAII,EAEF,OADAd,EAAwBc,EACjB,OAEX,EAESD,EAnBY/B,EAAiB,EAAI,EAmBZ+B,EAAK,GAGpB,UAFFD,EAAMC,GADmBA,KAOpCtR,EAAMjC,YAAc0S,IACtBzQ,EAAMmG,cAAcxG,GAAMmP,OAAQ,EAClC9O,EAAMjC,UAAY0S,EAClBzQ,EAAM0R,OAAQ,EA5GhB,CA8GF,EAQEhK,iBAAkB,CAAC,UACnBgC,KAAM,CACJoF,OAAO,IE7IX,SAAS6C,GAAexG,EAAUY,EAAM6F,GAQtC,YAPyB,IAArBA,IACFA,EAAmB,CACjBrO,EAAG,EACHE,EAAG,IAIA,CACLzC,IAAKmK,EAASnK,IAAM+K,EAAK3I,OAASwO,EAAiBnO,EACnDvG,MAAOiO,EAASjO,MAAQ6O,EAAK7I,MAAQ0O,EAAiBrO,EACtDtG,OAAQkO,EAASlO,OAAS8O,EAAK3I,OAASwO,EAAiBnO,EACzDtG,KAAMgO,EAAShO,KAAO4O,EAAK7I,MAAQ0O,EAAiBrO,EAExD,CAEA,SAASsO,GAAsB1G,GAC7B,MAAO,CAAC,EAAKjO,EAAOD,EAAQE,GAAM2U,MAAK,SAAUC,GAC/C,OAAO5G,EAAS4G,IAAS,CAC3B,GACF,CA+BA,UACEpS,KAAM,OACNC,SAAS,EACTC,MAAO,OACP6H,iBAAkB,CAAC,mBACnB5H,GAlCF,SAAcC,GACZ,IAAIC,EAAQD,EAAKC,MACbL,EAAOI,EAAKJ,KACZ0Q,EAAgBrQ,EAAMwG,MAAM7I,UAC5BoK,EAAa/H,EAAMwG,MAAM9I,OACzBkU,EAAmB5R,EAAMmG,cAAc6L,gBACvCC,EAAoBhF,GAAejN,EAAO,CAC5C0N,eAAgB,cAEdwE,EAAoBjF,GAAejN,EAAO,CAC5C4N,aAAa,IAEXuE,EAA2BR,GAAeM,EAAmB5B,GAC7D+B,EAAsBT,GAAeO,EAAmBnK,EAAY6J,GACpES,EAAoBR,GAAsBM,GAC1CG,EAAmBT,GAAsBO,GAC7CpS,EAAMmG,cAAcxG,GAAQ,CAC1BwS,yBAA0BA,EAC1BC,oBAAqBA,EACrBC,kBAAmBA,EACnBC,iBAAkBA,GAEpBtS,EAAMM,WAAW5C,OAASrB,OAAOkE,OAAO,CAAC,EAAGP,EAAMM,WAAW5C,OAAQ,CACnE,+BAAgC2U,EAChC,sBAAuBC,GAE3B,GCJA,IACE3S,KAAM,SACNC,SAAS,EACTC,MAAO,OACPwB,SAAU,CAAC,iBACXvB,GA5BF,SAAgBa,GACd,IAAIX,EAAQW,EAAMX,MACdc,EAAUH,EAAMG,QAChBnB,EAAOgB,EAAMhB,KACb4S,EAAkBzR,EAAQuG,OAC1BA,OAA6B,IAApBkL,EAA6B,CAAC,EAAG,GAAKA,EAC/C7I,EAAO,EAAW7L,QAAO,SAAUC,EAAKC,GAE1C,OADAD,EAAIC,GA5BD,SAAiCA,EAAWyI,EAAOa,GACxD,IAAIjB,EAAgB9E,EAAiBvD,GACjCyU,EAAiB,CAACrV,EAAM,GAAKqH,QAAQ4B,IAAkB,GAAK,EAAI,EAEhErG,EAAyB,mBAAXsH,EAAwBA,EAAOhL,OAAOkE,OAAO,CAAC,EAAGiG,EAAO,CACxEzI,UAAWA,KACPsJ,EACFoL,EAAW1S,EAAK,GAChB2S,EAAW3S,EAAK,GAIpB,OAFA0S,EAAWA,GAAY,EACvBC,GAAYA,GAAY,GAAKF,EACtB,CAACrV,EAAMD,GAAOsH,QAAQ4B,IAAkB,EAAI,CACjD7C,EAAGmP,EACHjP,EAAGgP,GACD,CACFlP,EAAGkP,EACHhP,EAAGiP,EAEP,CASqBC,CAAwB5U,EAAWiC,EAAMwG,MAAOa,GAC1DvJ,CACT,GAAG,CAAC,GACA8U,EAAwBlJ,EAAK1J,EAAMjC,WACnCwF,EAAIqP,EAAsBrP,EAC1BE,EAAImP,EAAsBnP,EAEW,MAArCzD,EAAMmG,cAAcD,gBACtBlG,EAAMmG,cAAcD,cAAc3C,GAAKA,EACvCvD,EAAMmG,cAAcD,cAAczC,GAAKA,GAGzCzD,EAAMmG,cAAcxG,GAAQ+J,CAC9B,GC1BA,IACE/J,KAAM,gBACNC,SAAS,EACTC,MAAO,OACPC,GApBF,SAAuBC,GACrB,IAAIC,EAAQD,EAAKC,MACbL,EAAOI,EAAKJ,KAKhBK,EAAMmG,cAAcxG,GAAQkN,GAAe,CACzClP,UAAWqC,EAAMwG,MAAM7I,UACvBiB,QAASoB,EAAMwG,MAAM9I,OACrBqD,SAAU,WACVhD,UAAWiC,EAAMjC,WAErB,EAQE2L,KAAM,CAAC,GCgHT,IACE/J,KAAM,kBACNC,SAAS,EACTC,MAAO,OACPC,GA/HF,SAAyBC,GACvB,IAAIC,EAAQD,EAAKC,MACbc,EAAUf,EAAKe,QACfnB,EAAOI,EAAKJ,KACZoP,EAAoBjO,EAAQkM,SAC5BgC,OAAsC,IAAtBD,GAAsCA,EACtDE,EAAmBnO,EAAQoO,QAC3BC,OAAoC,IAArBF,GAAsCA,EACrD3B,EAAWxM,EAAQwM,SACnBE,EAAe1M,EAAQ0M,aACvBI,EAAc9M,EAAQ8M,YACtBrH,EAAUzF,EAAQyF,QAClBsM,EAAkB/R,EAAQgS,OAC1BA,OAA6B,IAApBD,GAAoCA,EAC7CE,EAAwBjS,EAAQkS,aAChCA,OAAyC,IAA1BD,EAAmC,EAAIA,EACtD5H,EAAW8B,GAAejN,EAAO,CACnCsN,SAAUA,EACVE,aAAcA,EACdjH,QAASA,EACTqH,YAAaA,IAEXxH,EAAgB9E,EAAiBtB,EAAMjC,WACvCiK,EAAYL,EAAa3H,EAAMjC,WAC/BkV,GAAmBjL,EACnBgF,EAAWtH,EAAyBU,GACpC8I,ECrCY,MDqCSlC,ECrCH,IAAM,IDsCxB9G,EAAgBlG,EAAMmG,cAAcD,cACpCmK,EAAgBrQ,EAAMwG,MAAM7I,UAC5BoK,EAAa/H,EAAMwG,MAAM9I,OACzBwV,EAA4C,mBAAjBF,EAA8BA,EAAa3W,OAAOkE,OAAO,CAAC,EAAGP,EAAMwG,MAAO,CACvGzI,UAAWiC,EAAMjC,aACbiV,EACFG,EAA2D,iBAAtBD,EAAiC,CACxElG,SAAUkG,EACVhE,QAASgE,GACP7W,OAAOkE,OAAO,CAChByM,SAAU,EACVkC,QAAS,GACRgE,GACCE,EAAsBpT,EAAMmG,cAAckB,OAASrH,EAAMmG,cAAckB,OAAOrH,EAAMjC,WAAa,KACjG2L,EAAO,CACTnG,EAAG,EACHE,EAAG,GAGL,GAAKyC,EAAL,CAIA,GAAI8I,EAAe,CACjB,IAAIqE,EAEAC,EAAwB,MAAbtG,EAAmB,EAAM7P,EACpCoW,EAAuB,MAAbvG,EAAmB/P,EAASC,EACtCoJ,EAAmB,MAAb0G,EAAmB,SAAW,QACpC3F,EAASnB,EAAc8G,GACvBtL,EAAM2F,EAAS8D,EAASmI,GACxB7R,EAAM4F,EAAS8D,EAASoI,GACxBC,EAAWV,GAAU/K,EAAWzB,GAAO,EAAI,EAC3CmN,EAASzL,IAAc1K,EAAQ+S,EAAc/J,GAAOyB,EAAWzB,GAC/DoN,EAAS1L,IAAc1K,GAASyK,EAAWzB,IAAQ+J,EAAc/J,GAGjEL,EAAejG,EAAME,SAASgB,MAC9BwF,EAAYoM,GAAU7M,EAAetC,EAAcsC,GAAgB,CACrE/C,MAAO,EACPE,OAAQ,GAENuQ,GAAqB3T,EAAMmG,cAAc,oBAAsBnG,EAAMmG,cAAc,oBAAoBI,QxBhFtG,CACLvF,IAAK,EACL9D,MAAO,EACPD,OAAQ,EACRE,KAAM,GwB6EFyW,GAAkBD,GAAmBL,GACrCO,GAAkBF,GAAmBJ,GAMrCO,GAAWnO,EAAO,EAAG0K,EAAc/J,GAAMI,EAAUJ,IACnDyN,GAAYd,EAAkB5C,EAAc/J,GAAO,EAAIkN,EAAWM,GAAWF,GAAkBT,EAA4BnG,SAAWyG,EAASK,GAAWF,GAAkBT,EAA4BnG,SACxMgH,GAAYf,GAAmB5C,EAAc/J,GAAO,EAAIkN,EAAWM,GAAWD,GAAkBV,EAA4BnG,SAAW0G,EAASI,GAAWD,GAAkBV,EAA4BnG,SACzMjG,GAAoB/G,EAAME,SAASgB,OAAS8D,EAAgBhF,EAAME,SAASgB,OAC3E+S,GAAelN,GAAiC,MAAbiG,EAAmBjG,GAAkBsF,WAAa,EAAItF,GAAkBuF,YAAc,EAAI,EAC7H4H,GAAwH,OAAjGb,EAA+C,MAAvBD,OAA8B,EAASA,EAAoBpG,IAAqBqG,EAAwB,EAEvJc,GAAY9M,EAAS2M,GAAYE,GACjCE,GAAkBzO,EAAOmN,EAAS,EAAQpR,EAF9B2F,EAAS0M,GAAYG,GAAsBD,IAEKvS,EAAK2F,EAAQyL,EAAS,EAAQrR,EAAK0S,IAAa1S,GAChHyE,EAAc8G,GAAYoH,GAC1B1K,EAAKsD,GAAYoH,GAAkB/M,CACrC,CAEA,GAAI8H,EAAc,CAChB,IAAIkF,GAEAC,GAAyB,MAAbtH,EAAmB,EAAM7P,EAErCoX,GAAwB,MAAbvH,EAAmB/P,EAASC,EAEvCsX,GAAUtO,EAAcgJ,GAExBuF,GAAmB,MAAZvF,EAAkB,SAAW,QAEpCwF,GAAOF,GAAUrJ,EAASmJ,IAE1BK,GAAOH,GAAUrJ,EAASoJ,IAE1BK,IAAuD,IAAxC,CAAC,EAAKzX,GAAMqH,QAAQ4B,GAEnCyO,GAAyH,OAAjGR,GAAgD,MAAvBjB,OAA8B,EAASA,EAAoBlE,IAAoBmF,GAAyB,EAEzJS,GAAaF,GAAeF,GAAOF,GAAUnE,EAAcoE,IAAQ1M,EAAW0M,IAAQI,GAAuB1B,EAA4BjE,QAEzI6F,GAAaH,GAAeJ,GAAUnE,EAAcoE,IAAQ1M,EAAW0M,IAAQI,GAAuB1B,EAA4BjE,QAAUyF,GAE5IK,GAAmBlC,GAAU8B,G1BzH9B,SAAwBlT,EAAK1E,EAAOyE,GACzC,IAAIwT,EAAItP,EAAOjE,EAAK1E,EAAOyE,GAC3B,OAAOwT,EAAIxT,EAAMA,EAAMwT,CACzB,C0BsHoDC,CAAeJ,GAAYN,GAASO,IAAcpP,EAAOmN,EAASgC,GAAaJ,GAAMF,GAAS1B,EAASiC,GAAaJ,IAEpKzO,EAAcgJ,GAAW8F,GACzBtL,EAAKwF,GAAW8F,GAAmBR,EACrC,CAEAxU,EAAMmG,cAAcxG,GAAQ+J,CAvE5B,CAwEF,EAQEhC,iBAAkB,CAAC,WE1HN,SAASyN,GAAiBC,EAAyBrQ,EAAcsD,QAC9D,IAAZA,IACFA,GAAU,GAGZ,ICnBoCrJ,ECJOJ,EFuBvCyW,EAA0B9V,EAAcwF,GACxCuQ,EAAuB/V,EAAcwF,IAf3C,SAAyBnG,GACvB,IAAImN,EAAOnN,EAAQ+D,wBACfI,EAASpB,EAAMoK,EAAK7I,OAAStE,EAAQqE,aAAe,EACpDD,EAASrB,EAAMoK,EAAK3I,QAAUxE,EAAQuE,cAAgB,EAC1D,OAAkB,IAAXJ,GAA2B,IAAXC,CACzB,CAU4DuS,CAAgBxQ,GACtEJ,EAAkBF,EAAmBM,GACrCgH,EAAOpJ,EAAsByS,EAAyBE,EAAsBjN,GAC5EyB,EAAS,CACXc,WAAY,EACZE,UAAW,GAET7C,EAAU,CACZ1E,EAAG,EACHE,EAAG,GAkBL,OAfI4R,IAA4BA,IAA4BhN,MACxB,SAA9B1J,EAAYoG,IAChBkG,GAAetG,MACbmF,GCnCgC9K,EDmCT+F,KClCdhG,EAAUC,IAAUO,EAAcP,GCJxC,CACL4L,YAFyChM,EDQbI,GCNR4L,WACpBE,UAAWlM,EAAQkM,WDGZH,GAAgB3L,IDoCnBO,EAAcwF,KAChBkD,EAAUtF,EAAsBoC,GAAc,IACtCxB,GAAKwB,EAAauH,WAC1BrE,EAAQxE,GAAKsB,EAAasH,WACjB1H,IACTsD,EAAQ1E,EAAIyH,GAAoBrG,KAI7B,CACLpB,EAAGwI,EAAK5O,KAAO2M,EAAOc,WAAa3C,EAAQ1E,EAC3CE,EAAGsI,EAAK/K,IAAM8I,EAAOgB,UAAY7C,EAAQxE,EACzCP,MAAO6I,EAAK7I,MACZE,OAAQ2I,EAAK3I,OAEjB,CGvDA,SAASoS,GAAMC,GACb,IAAItT,EAAM,IAAIoO,IACVmF,EAAU,IAAIC,IACdC,EAAS,GAKb,SAAS3F,EAAK4F,GACZH,EAAQI,IAAID,EAASlW,MACN,GAAG3B,OAAO6X,EAASxU,UAAY,GAAIwU,EAASnO,kBAAoB,IACtEvH,SAAQ,SAAU4V,GACzB,IAAKL,EAAQM,IAAID,GAAM,CACrB,IAAIE,EAAc9T,EAAI3F,IAAIuZ,GAEtBE,GACFhG,EAAKgG,EAET,CACF,IACAL,EAAO3E,KAAK4E,EACd,CAQA,OAzBAJ,EAAUtV,SAAQ,SAAU0V,GAC1B1T,EAAIiP,IAAIyE,EAASlW,KAAMkW,EACzB,IAiBAJ,EAAUtV,SAAQ,SAAU0V,GACrBH,EAAQM,IAAIH,EAASlW,OAExBsQ,EAAK4F,EAET,IACOD,CACT,CCvBA,IAAIM,GAAkB,CACpBnY,UAAW,SACX0X,UAAW,GACX1U,SAAU,YAGZ,SAASoV,KACP,IAAK,IAAI1B,EAAO2B,UAAUrG,OAAQsG,EAAO,IAAIpU,MAAMwS,GAAO6B,EAAO,EAAGA,EAAO7B,EAAM6B,IAC/ED,EAAKC,GAAQF,UAAUE,GAGzB,OAAQD,EAAKvE,MAAK,SAAUlT,GAC1B,QAASA,GAAoD,mBAAlCA,EAAQ+D,sBACrC,GACF,CAEO,SAAS4T,GAAgBC,QACL,IAArBA,IACFA,EAAmB,CAAC,GAGtB,IAAIC,EAAoBD,EACpBE,EAAwBD,EAAkBE,iBAC1CA,OAA6C,IAA1BD,EAAmC,GAAKA,EAC3DE,EAAyBH,EAAkBI,eAC3CA,OAA4C,IAA3BD,EAAoCV,GAAkBU,EAC3E,OAAO,SAAsBjZ,EAAWD,EAAQoD,QAC9B,IAAZA,IACFA,EAAU+V,GAGZ,ICxC6B/W,EAC3BgX,EDuCE9W,EAAQ,CACVjC,UAAW,SACXgZ,iBAAkB,GAClBjW,QAASzE,OAAOkE,OAAO,CAAC,EAAG2V,GAAiBW,GAC5C1Q,cAAe,CAAC,EAChBjG,SAAU,CACRvC,UAAWA,EACXD,OAAQA,GAEV4C,WAAY,CAAC,EACbD,OAAQ,CAAC,GAEP2W,EAAmB,GACnBC,GAAc,EACdrN,EAAW,CACb5J,MAAOA,EACPkX,WAAY,SAAoBC,GAC9B,IAAIrW,EAAsC,mBAArBqW,EAAkCA,EAAiBnX,EAAMc,SAAWqW,EACzFC,IACApX,EAAMc,QAAUzE,OAAOkE,OAAO,CAAC,EAAGsW,EAAgB7W,EAAMc,QAASA,GACjEd,EAAMiK,cAAgB,CACpBtM,UAAW0B,EAAU1B,GAAa6N,GAAkB7N,GAAaA,EAAU4Q,eAAiB/C,GAAkB7N,EAAU4Q,gBAAkB,GAC1I7Q,OAAQ8N,GAAkB9N,IAI5B,IElE4B+X,EAC9B4B,EFiEMN,EDhCG,SAAwBtB,GAErC,IAAIsB,EAAmBvB,GAAMC,GAE7B,OAAO/W,EAAeb,QAAO,SAAUC,EAAK+B,GAC1C,OAAO/B,EAAIE,OAAO+Y,EAAiBvR,QAAO,SAAUqQ,GAClD,OAAOA,EAAShW,QAAUA,CAC5B,IACF,GAAG,GACL,CCuB+ByX,EElEK7B,EFkEsB,GAAGzX,OAAO2Y,EAAkB3W,EAAMc,QAAQ2U,WEjE9F4B,EAAS5B,EAAU5X,QAAO,SAAUwZ,EAAQE,GAC9C,IAAIC,EAAWH,EAAOE,EAAQ5X,MAK9B,OAJA0X,EAAOE,EAAQ5X,MAAQ6X,EAAWnb,OAAOkE,OAAO,CAAC,EAAGiX,EAAUD,EAAS,CACrEzW,QAASzE,OAAOkE,OAAO,CAAC,EAAGiX,EAAS1W,QAASyW,EAAQzW,SACrD4I,KAAMrN,OAAOkE,OAAO,CAAC,EAAGiX,EAAS9N,KAAM6N,EAAQ7N,QAC5C6N,EACEF,CACT,GAAG,CAAC,GAEGhb,OAAO4D,KAAKoX,GAAQlV,KAAI,SAAUhG,GACvC,OAAOkb,EAAOlb,EAChB,MF4DM,OAJA6D,EAAM+W,iBAAmBA,EAAiBvR,QAAO,SAAUiS,GACzD,OAAOA,EAAE7X,OACX,IA+FFI,EAAM+W,iBAAiB5W,SAAQ,SAAUJ,GACvC,IAAIJ,EAAOI,EAAKJ,KACZ+X,EAAe3X,EAAKe,QACpBA,OAA2B,IAAjB4W,EAA0B,CAAC,EAAIA,EACzChX,EAASX,EAAKW,OAElB,GAAsB,mBAAXA,EAAuB,CAChC,IAAIiX,EAAYjX,EAAO,CACrBV,MAAOA,EACPL,KAAMA,EACNiK,SAAUA,EACV9I,QAASA,IAKXkW,EAAiB/F,KAAK0G,GAFT,WAAmB,EAGlC,CACF,IA/GS/N,EAASQ,QAClB,EAMAwN,YAAa,WACX,IAAIX,EAAJ,CAIA,IAAIY,EAAkB7X,EAAME,SACxBvC,EAAYka,EAAgBla,UAC5BD,EAASma,EAAgBna,OAG7B,GAAKyY,GAAiBxY,EAAWD,GAAjC,CAKAsC,EAAMwG,MAAQ,CACZ7I,UAAWwX,GAAiBxX,EAAWqH,EAAgBtH,GAAoC,UAA3BsC,EAAMc,QAAQC,UAC9ErD,OAAQiG,EAAcjG,IAOxBsC,EAAM0R,OAAQ,EACd1R,EAAMjC,UAAYiC,EAAMc,QAAQ/C,UAKhCiC,EAAM+W,iBAAiB5W,SAAQ,SAAU0V,GACvC,OAAO7V,EAAMmG,cAAc0P,EAASlW,MAAQtD,OAAOkE,OAAO,CAAC,EAAGsV,EAASnM,KACzE,IAEA,IAAK,IAAIoO,EAAQ,EAAGA,EAAQ9X,EAAM+W,iBAAiBhH,OAAQ+H,IACzD,IAAoB,IAAhB9X,EAAM0R,MAAV,CAMA,IAAIqG,EAAwB/X,EAAM+W,iBAAiBe,GAC/ChY,EAAKiY,EAAsBjY,GAC3BkY,EAAyBD,EAAsBjX,QAC/CoM,OAAsC,IAA3B8K,EAAoC,CAAC,EAAIA,EACpDrY,EAAOoY,EAAsBpY,KAEf,mBAAPG,IACTE,EAAQF,EAAG,CACTE,MAAOA,EACPc,QAASoM,EACTvN,KAAMA,EACNiK,SAAUA,KACN5J,EAdR,MAHEA,EAAM0R,OAAQ,EACdoG,GAAS,CAzBb,CATA,CAqDF,EAGA1N,QC1I2BtK,ED0IV,WACf,OAAO,IAAImY,SAAQ,SAAUC,GAC3BtO,EAASgO,cACTM,EAAQlY,EACV,GACF,EC7IG,WAUL,OATK8W,IACHA,EAAU,IAAImB,SAAQ,SAAUC,GAC9BD,QAAQC,UAAUC,MAAK,WACrBrB,OAAUsB,EACVF,EAAQpY,IACV,GACF,KAGKgX,CACT,GDmIIuB,QAAS,WACPjB,IACAH,GAAc,CAChB,GAGF,IAAKd,GAAiBxY,EAAWD,GAC/B,OAAOkM,EAmCT,SAASwN,IACPJ,EAAiB7W,SAAQ,SAAUL,GACjC,OAAOA,GACT,IACAkX,EAAmB,EACrB,CAEA,OAvCApN,EAASsN,WAAWpW,GAASqX,MAAK,SAAUnY,IACrCiX,GAAenW,EAAQwX,eAC1BxX,EAAQwX,cAActY,EAE1B,IAmCO4J,CACT,CACF,CACO,IAAI2O,GAA4BhC,KGzLnC,GAA4BA,GAAgB,CAC9CI,iBAFqB,CAAC6B,GAAgB,GAAe,GAAe,EAAa,GAAQ,GAAM,GAAiB,EAAO,MCJrH,GAA4BjC,GAAgB,CAC9CI,iBAFqB,CAAC6B,GAAgB,GAAe,GAAe,KCatE,MAAMC,GAAa,IAAIlI,IACjBmI,GAAO,CACX,GAAAtH,CAAIxS,EAASzC,EAAKyN,GACX6O,GAAWzC,IAAIpX,IAClB6Z,GAAWrH,IAAIxS,EAAS,IAAI2R,KAE9B,MAAMoI,EAAcF,GAAWjc,IAAIoC,GAI9B+Z,EAAY3C,IAAI7Z,IAA6B,IAArBwc,EAAYC,KAKzCD,EAAYvH,IAAIjV,EAAKyN,GAHnBiP,QAAQC,MAAM,+EAA+E7W,MAAM8W,KAAKJ,EAAY1Y,QAAQ,MAIhI,EACAzD,IAAG,CAACoC,EAASzC,IACPsc,GAAWzC,IAAIpX,IACV6Z,GAAWjc,IAAIoC,GAASpC,IAAIL,IAE9B,KAET,MAAA6c,CAAOpa,EAASzC,GACd,IAAKsc,GAAWzC,IAAIpX,GAClB,OAEF,MAAM+Z,EAAcF,GAAWjc,IAAIoC,GACnC+Z,EAAYM,OAAO9c,GAGM,IAArBwc,EAAYC,MACdH,GAAWQ,OAAOra,EAEtB,GAYIsa,GAAiB,gBAOjBC,GAAgBC,IAChBA,GAAYna,OAAOoa,KAAOpa,OAAOoa,IAAIC,SAEvCF,EAAWA,EAAS5O,QAAQ,iBAAiB,CAAC+O,EAAOC,IAAO,IAAIH,IAAIC,OAAOE,QAEtEJ,GA4CHK,GAAuB7a,IAC3BA,EAAQ8a,cAAc,IAAIC,MAAMT,IAAgB,EAE5C,GAAYU,MACXA,GAA4B,iBAAXA,UAGO,IAAlBA,EAAOC,SAChBD,EAASA,EAAO,SAEgB,IAApBA,EAAOE,UAEjBC,GAAaH,GAEb,GAAUA,GACLA,EAAOC,OAASD,EAAO,GAAKA,EAEf,iBAAXA,GAAuBA,EAAO7J,OAAS,EACzCrL,SAAS+C,cAAc0R,GAAcS,IAEvC,KAEHI,GAAYpb,IAChB,IAAK,GAAUA,IAAgD,IAApCA,EAAQqb,iBAAiBlK,OAClD,OAAO,EAET,MAAMmK,EAAgF,YAA7D5V,iBAAiB1F,GAASub,iBAAiB,cAE9DC,EAAgBxb,EAAQyb,QAAQ,uBACtC,IAAKD,EACH,OAAOF,EAET,GAAIE,IAAkBxb,EAAS,CAC7B,MAAM0b,EAAU1b,EAAQyb,QAAQ,WAChC,GAAIC,GAAWA,EAAQlW,aAAegW,EACpC,OAAO,EAET,GAAgB,OAAZE,EACF,OAAO,CAEX,CACA,OAAOJ,CAAgB,EAEnBK,GAAa3b,IACZA,GAAWA,EAAQkb,WAAaU,KAAKC,gBAGtC7b,EAAQ8b,UAAU7W,SAAS,mBAGC,IAArBjF,EAAQ+b,SACV/b,EAAQ+b,SAEV/b,EAAQgc,aAAa,aAAoD,UAArChc,EAAQic,aAAa,aAE5DC,GAAiBlc,IACrB,IAAK8F,SAASC,gBAAgBoW,aAC5B,OAAO,KAIT,GAAmC,mBAAxBnc,EAAQqF,YAA4B,CAC7C,MAAM+W,EAAOpc,EAAQqF,cACrB,OAAO+W,aAAgBtb,WAAasb,EAAO,IAC7C,CACA,OAAIpc,aAAmBc,WACdd,EAIJA,EAAQwF,WAGN0W,GAAelc,EAAQwF,YAFrB,IAEgC,EAErC6W,GAAO,OAUPC,GAAStc,IACbA,EAAQuE,YAAY,EAGhBgY,GAAY,IACZlc,OAAOmc,SAAW1W,SAAS6G,KAAKqP,aAAa,qBACxC3b,OAAOmc,OAET,KAEHC,GAA4B,GAgB5BC,GAAQ,IAAuC,QAAjC5W,SAASC,gBAAgB4W,IACvCC,GAAqBC,IAhBAC,QAiBN,KACjB,MAAMC,EAAIR,KAEV,GAAIQ,EAAG,CACL,MAAMhc,EAAO8b,EAAOG,KACdC,EAAqBF,EAAE7b,GAAGH,GAChCgc,EAAE7b,GAAGH,GAAQ8b,EAAOK,gBACpBH,EAAE7b,GAAGH,GAAMoc,YAAcN,EACzBE,EAAE7b,GAAGH,GAAMqc,WAAa,KACtBL,EAAE7b,GAAGH,GAAQkc,EACNJ,EAAOK,gBAElB,GA5B0B,YAAxBpX,SAASuX,YAENZ,GAA0BtL,QAC7BrL,SAASyF,iBAAiB,oBAAoB,KAC5C,IAAK,MAAMuR,KAAYL,GACrBK,GACF,IAGJL,GAA0BpK,KAAKyK,IAE/BA,GAkBA,EAEEQ,GAAU,CAACC,EAAkB9F,EAAO,GAAI+F,EAAeD,IACxB,mBAArBA,EAAkCA,KAAoB9F,GAAQ+F,EAExEC,GAAyB,CAACX,EAAUY,EAAmBC,GAAoB,KAC/E,IAAKA,EAEH,YADAL,GAAQR,GAGV,MACMc,EAhKiC5d,KACvC,IAAKA,EACH,OAAO,EAIT,IAAI,mBACF6d,EAAkB,gBAClBC,GACEzd,OAAOqF,iBAAiB1F,GAC5B,MAAM+d,EAA0BC,OAAOC,WAAWJ,GAC5CK,EAAuBF,OAAOC,WAAWH,GAG/C,OAAKC,GAA4BG,GAKjCL,EAAqBA,EAAmBlb,MAAM,KAAK,GACnDmb,EAAkBA,EAAgBnb,MAAM,KAAK,GAtDf,KAuDtBqb,OAAOC,WAAWJ,GAAsBG,OAAOC,WAAWH,KANzD,CAMoG,EA2IpFK,CAAiCT,GADlC,EAExB,IAAIU,GAAS,EACb,MAAMC,EAAU,EACdrR,aAEIA,IAAW0Q,IAGfU,GAAS,EACTV,EAAkBjS,oBAAoB6O,GAAgB+D,GACtDf,GAAQR,GAAS,EAEnBY,EAAkBnS,iBAAiB+O,GAAgB+D,GACnDC,YAAW,KACJF,GACHvD,GAAqB6C,EACvB,GACCE,EAAiB,EAYhBW,GAAuB,CAAC1R,EAAM2R,EAAeC,EAAeC,KAChE,MAAMC,EAAa9R,EAAKsE,OACxB,IAAI+H,EAAQrM,EAAKjH,QAAQ4Y,GAIzB,OAAe,IAAXtF,GACMuF,GAAiBC,EAAiB7R,EAAK8R,EAAa,GAAK9R,EAAK,IAExEqM,GAASuF,EAAgB,GAAK,EAC1BC,IACFxF,GAASA,EAAQyF,GAAcA,GAE1B9R,EAAKjK,KAAKC,IAAI,EAAGD,KAAKE,IAAIoW,EAAOyF,EAAa,KAAI,EAerDC,GAAiB,qBACjBC,GAAiB,OACjBC,GAAgB,SAChBC,GAAgB,CAAC,EACvB,IAAIC,GAAW,EACf,MAAMC,GAAe,CACnBC,WAAY,YACZC,WAAY,YAERC,GAAe,IAAIrI,IAAI,CAAC,QAAS,WAAY,UAAW,YAAa,cAAe,aAAc,iBAAkB,YAAa,WAAY,YAAa,cAAe,YAAa,UAAW,WAAY,QAAS,oBAAqB,aAAc,YAAa,WAAY,cAAe,cAAe,cAAe,YAAa,eAAgB,gBAAiB,eAAgB,gBAAiB,aAAc,QAAS,OAAQ,SAAU,QAAS,SAAU,SAAU,UAAW,WAAY,OAAQ,SAAU,eAAgB,SAAU,OAAQ,mBAAoB,mBAAoB,QAAS,QAAS,WAM/lB,SAASsI,GAAarf,EAASsf,GAC7B,OAAOA,GAAO,GAAGA,MAAQN,QAAgBhf,EAAQgf,UAAYA,IAC/D,CACA,SAASO,GAAiBvf,GACxB,MAAMsf,EAAMD,GAAarf,GAGzB,OAFAA,EAAQgf,SAAWM,EACnBP,GAAcO,GAAOP,GAAcO,IAAQ,CAAC,EACrCP,GAAcO,EACvB,CAiCA,SAASE,GAAYC,EAAQC,EAAUC,EAAqB,MAC1D,OAAOliB,OAAOmiB,OAAOH,GAAQ7M,MAAKiN,GAASA,EAAMH,WAAaA,GAAYG,EAAMF,qBAAuBA,GACzG,CACA,SAASG,GAAoBC,EAAmB1B,EAAS2B,GACvD,MAAMC,EAAiC,iBAAZ5B,EAErBqB,EAAWO,EAAcD,EAAqB3B,GAAW2B,EAC/D,IAAIE,EAAYC,GAAaJ,GAI7B,OAHKX,GAAahI,IAAI8I,KACpBA,EAAYH,GAEP,CAACE,EAAaP,EAAUQ,EACjC,CACA,SAASE,GAAWpgB,EAAS+f,EAAmB1B,EAAS2B,EAAoBK,GAC3E,GAAiC,iBAAtBN,IAAmC/f,EAC5C,OAEF,IAAKigB,EAAaP,EAAUQ,GAAaJ,GAAoBC,EAAmB1B,EAAS2B,GAIzF,GAAID,KAAqBd,GAAc,CACrC,MAAMqB,EAAepf,GACZ,SAAU2e,GACf,IAAKA,EAAMU,eAAiBV,EAAMU,gBAAkBV,EAAMW,iBAAmBX,EAAMW,eAAevb,SAAS4a,EAAMU,eAC/G,OAAOrf,EAAGjD,KAAKwiB,KAAMZ,EAEzB,EAEFH,EAAWY,EAAaZ,EAC1B,CACA,MAAMD,EAASF,GAAiBvf,GAC1B0gB,EAAWjB,EAAOS,KAAeT,EAAOS,GAAa,CAAC,GACtDS,EAAmBnB,GAAYkB,EAAUhB,EAAUO,EAAc5B,EAAU,MACjF,GAAIsC,EAEF,YADAA,EAAiBN,OAASM,EAAiBN,QAAUA,GAGvD,MAAMf,EAAMD,GAAaK,EAAUK,EAAkBnU,QAAQgT,GAAgB,KACvE1d,EAAK+e,EA5Db,SAAoCjgB,EAASwa,EAAUtZ,GACrD,OAAO,SAASmd,EAAQwB,GACtB,MAAMe,EAAc5gB,EAAQ6gB,iBAAiBrG,GAC7C,IAAK,IAAI,OACPxN,GACE6S,EAAO7S,GAAUA,IAAWyT,KAAMzT,EAASA,EAAOxH,WACpD,IAAK,MAAMsb,KAAcF,EACvB,GAAIE,IAAe9T,EASnB,OANA+T,GAAWlB,EAAO,CAChBW,eAAgBxT,IAEdqR,EAAQgC,QACVW,GAAaC,IAAIjhB,EAAS6f,EAAMqB,KAAM1G,EAAUtZ,GAE3CA,EAAGigB,MAAMnU,EAAQ,CAAC6S,GAG/B,CACF,CAwC2BuB,CAA2BphB,EAASqe,EAASqB,GAvExE,SAA0B1f,EAASkB,GACjC,OAAO,SAASmd,EAAQwB,GAOtB,OANAkB,GAAWlB,EAAO,CAChBW,eAAgBxgB,IAEdqe,EAAQgC,QACVW,GAAaC,IAAIjhB,EAAS6f,EAAMqB,KAAMhgB,GAEjCA,EAAGigB,MAAMnhB,EAAS,CAAC6f,GAC5B,CACF,CA6DoFwB,CAAiBrhB,EAAS0f,GAC5Gxe,EAAGye,mBAAqBM,EAAc5B,EAAU,KAChDnd,EAAGwe,SAAWA,EACdxe,EAAGmf,OAASA,EACZnf,EAAG8d,SAAWM,EACdoB,EAASpB,GAAOpe,EAChBlB,EAAQuL,iBAAiB2U,EAAWhf,EAAI+e,EAC1C,CACA,SAASqB,GAActhB,EAASyf,EAAQS,EAAW7B,EAASsB,GAC1D,MAAMze,EAAKse,GAAYC,EAAOS,GAAY7B,EAASsB,GAC9Cze,IAGLlB,EAAQyL,oBAAoByU,EAAWhf,EAAIqgB,QAAQ5B,WAC5CF,EAAOS,GAAWhf,EAAG8d,UAC9B,CACA,SAASwC,GAAyBxhB,EAASyf,EAAQS,EAAWuB,GAC5D,MAAMC,EAAoBjC,EAAOS,IAAc,CAAC,EAChD,IAAK,MAAOyB,EAAY9B,KAAUpiB,OAAOmkB,QAAQF,GAC3CC,EAAWE,SAASJ,IACtBH,GAActhB,EAASyf,EAAQS,EAAWL,EAAMH,SAAUG,EAAMF,mBAGtE,CACA,SAASQ,GAAaN,GAGpB,OADAA,EAAQA,EAAMjU,QAAQiT,GAAgB,IAC/BI,GAAaY,IAAUA,CAChC,CACA,MAAMmB,GAAe,CACnB,EAAAc,CAAG9hB,EAAS6f,EAAOxB,EAAS2B,GAC1BI,GAAWpgB,EAAS6f,EAAOxB,EAAS2B,GAAoB,EAC1D,EACA,GAAA+B,CAAI/hB,EAAS6f,EAAOxB,EAAS2B,GAC3BI,GAAWpgB,EAAS6f,EAAOxB,EAAS2B,GAAoB,EAC1D,EACA,GAAAiB,CAAIjhB,EAAS+f,EAAmB1B,EAAS2B,GACvC,GAAiC,iBAAtBD,IAAmC/f,EAC5C,OAEF,MAAOigB,EAAaP,EAAUQ,GAAaJ,GAAoBC,EAAmB1B,EAAS2B,GACrFgC,EAAc9B,IAAcH,EAC5BN,EAASF,GAAiBvf,GAC1B0hB,EAAoBjC,EAAOS,IAAc,CAAC,EAC1C+B,EAAclC,EAAkBmC,WAAW,KACjD,QAAwB,IAAbxC,EAAX,CAQA,GAAIuC,EACF,IAAK,MAAME,KAAgB1kB,OAAO4D,KAAKoe,GACrC+B,GAAyBxhB,EAASyf,EAAQ0C,EAAcpC,EAAkBlN,MAAM,IAGpF,IAAK,MAAOuP,EAAavC,KAAUpiB,OAAOmkB,QAAQF,GAAoB,CACpE,MAAMC,EAAaS,EAAYxW,QAAQkT,GAAe,IACjDkD,IAAejC,EAAkB8B,SAASF,IAC7CL,GAActhB,EAASyf,EAAQS,EAAWL,EAAMH,SAAUG,EAAMF,mBAEpE,CAXA,KAPA,CAEE,IAAKliB,OAAO4D,KAAKqgB,GAAmBvQ,OAClC,OAEFmQ,GAActhB,EAASyf,EAAQS,EAAWR,EAAUO,EAAc5B,EAAU,KAE9E,CAYF,EACA,OAAAgE,CAAQriB,EAAS6f,EAAOpI,GACtB,GAAqB,iBAAVoI,IAAuB7f,EAChC,OAAO,KAET,MAAM+c,EAAIR,KAGV,IAAI+F,EAAc,KACdC,GAAU,EACVC,GAAiB,EACjBC,GAAmB,EAJH5C,IADFM,GAAaN,IAMZ9C,IACjBuF,EAAcvF,EAAEhC,MAAM8E,EAAOpI,GAC7BsF,EAAE/c,GAASqiB,QAAQC,GACnBC,GAAWD,EAAYI,uBACvBF,GAAkBF,EAAYK,gCAC9BF,EAAmBH,EAAYM,sBAEjC,MAAMC,EAAM9B,GAAW,IAAIhG,MAAM8E,EAAO,CACtC0C,UACAO,YAAY,IACVrL,GAUJ,OATIgL,GACFI,EAAIE,iBAEFP,GACFxiB,EAAQ8a,cAAc+H,GAEpBA,EAAIJ,kBAAoBH,GAC1BA,EAAYS,iBAEPF,CACT,GAEF,SAAS9B,GAAWljB,EAAKmlB,EAAO,CAAC,GAC/B,IAAK,MAAOzlB,EAAKa,KAAUX,OAAOmkB,QAAQoB,GACxC,IACEnlB,EAAIN,GAAOa,CACb,CAAE,MAAO6kB,GACPxlB,OAAOC,eAAeG,EAAKN,EAAK,CAC9B2lB,cAAc,EACdtlB,IAAG,IACMQ,GAGb,CAEF,OAAOP,CACT,CASA,SAASslB,GAAc/kB,GACrB,GAAc,SAAVA,EACF,OAAO,EAET,GAAc,UAAVA,EACF,OAAO,EAET,GAAIA,IAAU4f,OAAO5f,GAAOkC,WAC1B,OAAO0d,OAAO5f,GAEhB,GAAc,KAAVA,GAA0B,SAAVA,EAClB,OAAO,KAET,GAAqB,iBAAVA,EACT,OAAOA,EAET,IACE,OAAOglB,KAAKC,MAAMC,mBAAmBllB,GACvC,CAAE,MAAO6kB,GACP,OAAO7kB,CACT,CACF,CACA,SAASmlB,GAAiBhmB,GACxB,OAAOA,EAAIqO,QAAQ,UAAU4X,GAAO,IAAIA,EAAItjB,iBAC9C,CACA,MAAMujB,GAAc,CAClB,gBAAAC,CAAiB1jB,EAASzC,EAAKa,GAC7B4B,EAAQ6B,aAAa,WAAW0hB,GAAiBhmB,KAAQa,EAC3D,EACA,mBAAAulB,CAAoB3jB,EAASzC,GAC3ByC,EAAQ4B,gBAAgB,WAAW2hB,GAAiBhmB,KACtD,EACA,iBAAAqmB,CAAkB5jB,GAChB,IAAKA,EACH,MAAO,CAAC,EAEV,MAAM0B,EAAa,CAAC,EACdmiB,EAASpmB,OAAO4D,KAAKrB,EAAQ8jB,SAASld,QAAOrJ,GAAOA,EAAI2kB,WAAW,QAAU3kB,EAAI2kB,WAAW,cAClG,IAAK,MAAM3kB,KAAOsmB,EAAQ,CACxB,IAAIE,EAAUxmB,EAAIqO,QAAQ,MAAO,IACjCmY,EAAUA,EAAQC,OAAO,GAAG9jB,cAAgB6jB,EAAQlR,MAAM,EAAGkR,EAAQ5S,QACrEzP,EAAWqiB,GAAWZ,GAAcnjB,EAAQ8jB,QAAQvmB,GACtD,CACA,OAAOmE,CACT,EACAuiB,iBAAgB,CAACjkB,EAASzC,IACjB4lB,GAAcnjB,EAAQic,aAAa,WAAWsH,GAAiBhmB,QAgB1E,MAAM2mB,GAEJ,kBAAWC,GACT,MAAO,CAAC,CACV,CACA,sBAAWC,GACT,MAAO,CAAC,CACV,CACA,eAAWpH,GACT,MAAM,IAAIqH,MAAM,sEAClB,CACA,UAAAC,CAAWC,GAIT,OAHAA,EAAS9D,KAAK+D,gBAAgBD,GAC9BA,EAAS9D,KAAKgE,kBAAkBF,GAChC9D,KAAKiE,iBAAiBH,GACfA,CACT,CACA,iBAAAE,CAAkBF,GAChB,OAAOA,CACT,CACA,eAAAC,CAAgBD,EAAQvkB,GACtB,MAAM2kB,EAAa,GAAU3kB,GAAWyjB,GAAYQ,iBAAiBjkB,EAAS,UAAY,CAAC,EAE3F,MAAO,IACFygB,KAAKmE,YAAYT,WACM,iBAAfQ,EAA0BA,EAAa,CAAC,KAC/C,GAAU3kB,GAAWyjB,GAAYG,kBAAkB5jB,GAAW,CAAC,KAC7C,iBAAXukB,EAAsBA,EAAS,CAAC,EAE/C,CACA,gBAAAG,CAAiBH,EAAQM,EAAcpE,KAAKmE,YAAYR,aACtD,IAAK,MAAO7hB,EAAUuiB,KAAkBrnB,OAAOmkB,QAAQiD,GAAc,CACnE,MAAMzmB,EAAQmmB,EAAOhiB,GACfwiB,EAAY,GAAU3mB,GAAS,UAjiBrC4c,OADSA,EAkiB+C5c,GAhiBnD,GAAG4c,IAELvd,OAAOM,UAAUuC,SAASrC,KAAK+c,GAAQL,MAAM,eAAe,GAAGza,cA+hBlE,IAAK,IAAI8kB,OAAOF,GAAehhB,KAAKihB,GAClC,MAAM,IAAIE,UAAU,GAAGxE,KAAKmE,YAAY5H,KAAKkI,0BAA0B3iB,qBAA4BwiB,yBAAiCD,MAExI,CAtiBW9J,KAuiBb,EAqBF,MAAMmK,WAAsBjB,GAC1B,WAAAU,CAAY5kB,EAASukB,GACnBa,SACAplB,EAAUmb,GAAWnb,MAIrBygB,KAAK4E,SAAWrlB,EAChBygB,KAAK6E,QAAU7E,KAAK6D,WAAWC,GAC/BzK,GAAKtH,IAAIiO,KAAK4E,SAAU5E,KAAKmE,YAAYW,SAAU9E,MACrD,CAGA,OAAA+E,GACE1L,GAAKM,OAAOqG,KAAK4E,SAAU5E,KAAKmE,YAAYW,UAC5CvE,GAAaC,IAAIR,KAAK4E,SAAU5E,KAAKmE,YAAYa,WACjD,IAAK,MAAMC,KAAgBjoB,OAAOkoB,oBAAoBlF,MACpDA,KAAKiF,GAAgB,IAEzB,CACA,cAAAE,CAAe9I,EAAU9c,EAAS6lB,GAAa,GAC7CpI,GAAuBX,EAAU9c,EAAS6lB,EAC5C,CACA,UAAAvB,CAAWC,GAIT,OAHAA,EAAS9D,KAAK+D,gBAAgBD,EAAQ9D,KAAK4E,UAC3Cd,EAAS9D,KAAKgE,kBAAkBF,GAChC9D,KAAKiE,iBAAiBH,GACfA,CACT,CAGA,kBAAOuB,CAAY9lB,GACjB,OAAO8Z,GAAKlc,IAAIud,GAAWnb,GAAUygB,KAAK8E,SAC5C,CACA,0BAAOQ,CAAoB/lB,EAASukB,EAAS,CAAC,GAC5C,OAAO9D,KAAKqF,YAAY9lB,IAAY,IAAIygB,KAAKzgB,EAA2B,iBAAXukB,EAAsBA,EAAS,KAC9F,CACA,kBAAWyB,GACT,MA5CY,OA6Cd,CACA,mBAAWT,GACT,MAAO,MAAM9E,KAAKzD,MACpB,CACA,oBAAWyI,GACT,MAAO,IAAIhF,KAAK8E,UAClB,CACA,gBAAOU,CAAUllB,GACf,MAAO,GAAGA,IAAO0f,KAAKgF,WACxB,EAUF,MAAMS,GAAclmB,IAClB,IAAIwa,EAAWxa,EAAQic,aAAa,kBACpC,IAAKzB,GAAyB,MAAbA,EAAkB,CACjC,IAAI2L,EAAgBnmB,EAAQic,aAAa,QAMzC,IAAKkK,IAAkBA,EAActE,SAAS,OAASsE,EAAcjE,WAAW,KAC9E,OAAO,KAILiE,EAActE,SAAS,OAASsE,EAAcjE,WAAW,OAC3DiE,EAAgB,IAAIA,EAAcxjB,MAAM,KAAK,MAE/C6X,EAAW2L,GAAmC,MAAlBA,EAAwB5L,GAAc4L,EAAcC,QAAU,IAC5F,CACA,OAAO5L,CAAQ,EAEX6L,GAAiB,CACrBzT,KAAI,CAAC4H,EAAUxa,EAAU8F,SAASC,kBACzB,GAAG3G,UAAUsB,QAAQ3C,UAAU8iB,iBAAiB5iB,KAAK+B,EAASwa,IAEvE8L,QAAO,CAAC9L,EAAUxa,EAAU8F,SAASC,kBAC5BrF,QAAQ3C,UAAU8K,cAAc5K,KAAK+B,EAASwa,GAEvD+L,SAAQ,CAACvmB,EAASwa,IACT,GAAGpb,UAAUY,EAAQumB,UAAU3f,QAAOzB,GAASA,EAAMqhB,QAAQhM,KAEtE,OAAAiM,CAAQzmB,EAASwa,GACf,MAAMiM,EAAU,GAChB,IAAIC,EAAW1mB,EAAQwF,WAAWiW,QAAQjB,GAC1C,KAAOkM,GACLD,EAAQpU,KAAKqU,GACbA,EAAWA,EAASlhB,WAAWiW,QAAQjB,GAEzC,OAAOiM,CACT,EACA,IAAAE,CAAK3mB,EAASwa,GACZ,IAAIoM,EAAW5mB,EAAQ6mB,uBACvB,KAAOD,GAAU,CACf,GAAIA,EAASJ,QAAQhM,GACnB,MAAO,CAACoM,GAEVA,EAAWA,EAASC,sBACtB,CACA,MAAO,EACT,EAEA,IAAAvhB,CAAKtF,EAASwa,GACZ,IAAIlV,EAAOtF,EAAQ8mB,mBACnB,KAAOxhB,GAAM,CACX,GAAIA,EAAKkhB,QAAQhM,GACf,MAAO,CAAClV,GAEVA,EAAOA,EAAKwhB,kBACd,CACA,MAAO,EACT,EACA,iBAAAC,CAAkB/mB,GAChB,MAAMgnB,EAAa,CAAC,IAAK,SAAU,QAAS,WAAY,SAAU,UAAW,aAAc,4BAA4BzjB,KAAIiX,GAAY,GAAGA,2BAAiC7W,KAAK,KAChL,OAAO8c,KAAK7N,KAAKoU,EAAYhnB,GAAS4G,QAAOqgB,IAAOtL,GAAWsL,IAAO7L,GAAU6L,IAClF,EACA,sBAAAC,CAAuBlnB,GACrB,MAAMwa,EAAW0L,GAAYlmB,GAC7B,OAAIwa,GACK6L,GAAeC,QAAQ9L,GAAYA,EAErC,IACT,EACA,sBAAA2M,CAAuBnnB,GACrB,MAAMwa,EAAW0L,GAAYlmB,GAC7B,OAAOwa,EAAW6L,GAAeC,QAAQ9L,GAAY,IACvD,EACA,+BAAA4M,CAAgCpnB,GAC9B,MAAMwa,EAAW0L,GAAYlmB,GAC7B,OAAOwa,EAAW6L,GAAezT,KAAK4H,GAAY,EACpD,GAUI6M,GAAuB,CAACC,EAAWC,EAAS,UAChD,MAAMC,EAAa,gBAAgBF,EAAU7B,YACvC1kB,EAAOumB,EAAUtK,KACvBgE,GAAac,GAAGhc,SAAU0hB,EAAY,qBAAqBzmB,OAAU,SAAU8e,GAI7E,GAHI,CAAC,IAAK,QAAQgC,SAASpB,KAAKgH,UAC9B5H,EAAMkD,iBAEJpH,GAAW8E,MACb,OAEF,MAAMzT,EAASqZ,GAAec,uBAAuB1G,OAASA,KAAKhF,QAAQ,IAAI1a,KAC9DumB,EAAUvB,oBAAoB/Y,GAGtCua,IACX,GAAE,EAiBEG,GAAc,YACdC,GAAc,QAAQD,KACtBE,GAAe,SAASF,KAQ9B,MAAMG,WAAc1C,GAElB,eAAWnI,GACT,MAfW,OAgBb,CAGA,KAAA8K,GAEE,GADmB9G,GAAaqB,QAAQ5B,KAAK4E,SAAUsC,IACxClF,iBACb,OAEFhC,KAAK4E,SAASvJ,UAAU1B,OAlBF,QAmBtB,MAAMyL,EAAapF,KAAK4E,SAASvJ,UAAU7W,SApBrB,QAqBtBwb,KAAKmF,gBAAe,IAAMnF,KAAKsH,mBAAmBtH,KAAK4E,SAAUQ,EACnE,CAGA,eAAAkC,GACEtH,KAAK4E,SAASjL,SACd4G,GAAaqB,QAAQ5B,KAAK4E,SAAUuC,IACpCnH,KAAK+E,SACP,CAGA,sBAAOtI,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO+c,GAAM9B,oBAAoBtF,MACvC,GAAsB,iBAAX8D,EAAX,CAGA,QAAqB/K,IAAjB1O,EAAKyZ,IAAyBA,EAAOrC,WAAW,MAAmB,gBAAXqC,EAC1D,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,GAAQ9D,KAJb,CAKF,GACF,EAOF4G,GAAqBQ,GAAO,SAM5BjL,GAAmBiL,IAcnB,MAKMI,GAAyB,4BAO/B,MAAMC,WAAe/C,GAEnB,eAAWnI,GACT,MAfW,QAgBb,CAGA,MAAAmL,GAEE1H,KAAK4E,SAASxjB,aAAa,eAAgB4e,KAAK4E,SAASvJ,UAAUqM,OAjB3C,UAkB1B,CAGA,sBAAOjL,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAOod,GAAOnC,oBAAoBtF,MACzB,WAAX8D,GACFzZ,EAAKyZ,IAET,GACF,EAOFvD,GAAac,GAAGhc,SAjCe,2BAiCmBmiB,IAAwBpI,IACxEA,EAAMkD,iBACN,MAAMqF,EAASvI,EAAM7S,OAAOyO,QAAQwM,IACvBC,GAAOnC,oBAAoBqC,GACnCD,QAAQ,IAOfvL,GAAmBsL,IAcnB,MACMG,GAAc,YACdC,GAAmB,aAAaD,KAChCE,GAAkB,YAAYF,KAC9BG,GAAiB,WAAWH,KAC5BI,GAAoB,cAAcJ,KAClCK,GAAkB,YAAYL,KAK9BM,GAAY,CAChBC,YAAa,KACbC,aAAc,KACdC,cAAe,MAEXC,GAAgB,CACpBH,YAAa,kBACbC,aAAc,kBACdC,cAAe,mBAOjB,MAAME,WAAc9E,GAClB,WAAAU,CAAY5kB,EAASukB,GACnBa,QACA3E,KAAK4E,SAAWrlB,EACXA,GAAYgpB,GAAMC,gBAGvBxI,KAAK6E,QAAU7E,KAAK6D,WAAWC,GAC/B9D,KAAKyI,QAAU,EACfzI,KAAK0I,sBAAwB5H,QAAQlhB,OAAO+oB,cAC5C3I,KAAK4I,cACP,CAGA,kBAAWlF,GACT,OAAOwE,EACT,CACA,sBAAWvE,GACT,OAAO2E,EACT,CACA,eAAW/L,GACT,MA/CW,OAgDb,CAGA,OAAAwI,GACExE,GAAaC,IAAIR,KAAK4E,SAAUgD,GAClC,CAGA,MAAAiB,CAAOzJ,GACAY,KAAK0I,sBAIN1I,KAAK8I,wBAAwB1J,KAC/BY,KAAKyI,QAAUrJ,EAAM2J,SAJrB/I,KAAKyI,QAAUrJ,EAAM4J,QAAQ,GAAGD,OAMpC,CACA,IAAAE,CAAK7J,GACCY,KAAK8I,wBAAwB1J,KAC/BY,KAAKyI,QAAUrJ,EAAM2J,QAAU/I,KAAKyI,SAEtCzI,KAAKkJ,eACLrM,GAAQmD,KAAK6E,QAAQsD,YACvB,CACA,KAAAgB,CAAM/J,GACJY,KAAKyI,QAAUrJ,EAAM4J,SAAW5J,EAAM4J,QAAQtY,OAAS,EAAI,EAAI0O,EAAM4J,QAAQ,GAAGD,QAAU/I,KAAKyI,OACjG,CACA,YAAAS,GACE,MAAME,EAAYjnB,KAAKoC,IAAIyb,KAAKyI,SAChC,GAAIW,GAnEgB,GAoElB,OAEF,MAAM9b,EAAY8b,EAAYpJ,KAAKyI,QACnCzI,KAAKyI,QAAU,EACVnb,GAGLuP,GAAQvP,EAAY,EAAI0S,KAAK6E,QAAQwD,cAAgBrI,KAAK6E,QAAQuD,aACpE,CACA,WAAAQ,GACM5I,KAAK0I,uBACPnI,GAAac,GAAGrB,KAAK4E,SAAUoD,IAAmB5I,GAASY,KAAK6I,OAAOzJ,KACvEmB,GAAac,GAAGrB,KAAK4E,SAAUqD,IAAiB7I,GAASY,KAAKiJ,KAAK7J,KACnEY,KAAK4E,SAASvJ,UAAU5E,IAlFG,mBAoF3B8J,GAAac,GAAGrB,KAAK4E,SAAUiD,IAAkBzI,GAASY,KAAK6I,OAAOzJ,KACtEmB,GAAac,GAAGrB,KAAK4E,SAAUkD,IAAiB1I,GAASY,KAAKmJ,MAAM/J,KACpEmB,GAAac,GAAGrB,KAAK4E,SAAUmD,IAAgB3I,GAASY,KAAKiJ,KAAK7J,KAEtE,CACA,uBAAA0J,CAAwB1J,GACtB,OAAOY,KAAK0I,wBA3FS,QA2FiBtJ,EAAMiK,aA5FrB,UA4FyDjK,EAAMiK,YACxF,CAGA,kBAAOb,GACL,MAAO,iBAAkBnjB,SAASC,iBAAmB7C,UAAU6mB,eAAiB,CAClF,EAeF,MAEMC,GAAc,eACdC,GAAiB,YAKjBC,GAAa,OACbC,GAAa,OACbC,GAAiB,OACjBC,GAAkB,QAClBC,GAAc,QAAQN,KACtBO,GAAa,OAAOP,KACpBQ,GAAkB,UAAUR,KAC5BS,GAAqB,aAAaT,KAClCU,GAAqB,aAAaV,KAClCW,GAAmB,YAAYX,KAC/BY,GAAwB,OAAOZ,KAAcC,KAC7CY,GAAyB,QAAQb,KAAcC,KAC/Ca,GAAsB,WACtBC,GAAsB,SAMtBC,GAAkB,UAClBC,GAAgB,iBAChBC,GAAuBF,GAAkBC,GAKzCE,GAAmB,CACvB,UAAoBd,GACpB,WAAqBD,IAEjBgB,GAAY,CAChBC,SAAU,IACVC,UAAU,EACVC,MAAO,QACPC,MAAM,EACNC,OAAO,EACPC,MAAM,GAEFC,GAAgB,CACpBN,SAAU,mBAEVC,SAAU,UACVC,MAAO,mBACPC,KAAM,mBACNC,MAAO,UACPC,KAAM,WAOR,MAAME,WAAiBzG,GACrB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKoL,UAAY,KACjBpL,KAAKqL,eAAiB,KACtBrL,KAAKsL,YAAa,EAClBtL,KAAKuL,aAAe,KACpBvL,KAAKwL,aAAe,KACpBxL,KAAKyL,mBAAqB7F,GAAeC,QArCjB,uBAqC8C7F,KAAK4E,UAC3E5E,KAAK0L,qBACD1L,KAAK6E,QAAQkG,OAASV,IACxBrK,KAAK2L,OAET,CAGA,kBAAWjI,GACT,OAAOiH,EACT,CACA,sBAAWhH,GACT,OAAOuH,EACT,CACA,eAAW3O,GACT,MAnFW,UAoFb,CAGA,IAAA1X,GACEmb,KAAK4L,OAAOnC,GACd,CACA,eAAAoC,IAIOxmB,SAASymB,QAAUnR,GAAUqF,KAAK4E,WACrC5E,KAAKnb,MAET,CACA,IAAAqhB,GACElG,KAAK4L,OAAOlC,GACd,CACA,KAAAoB,GACM9K,KAAKsL,YACPlR,GAAqB4F,KAAK4E,UAE5B5E,KAAK+L,gBACP,CACA,KAAAJ,GACE3L,KAAK+L,iBACL/L,KAAKgM,kBACLhM,KAAKoL,UAAYa,aAAY,IAAMjM,KAAK6L,mBAAmB7L,KAAK6E,QAAQ+F,SAC1E,CACA,iBAAAsB,GACOlM,KAAK6E,QAAQkG,OAGd/K,KAAKsL,WACP/K,GAAae,IAAItB,KAAK4E,SAAUkF,IAAY,IAAM9J,KAAK2L,UAGzD3L,KAAK2L,QACP,CACA,EAAAQ,CAAG1T,GACD,MAAM2T,EAAQpM,KAAKqM,YACnB,GAAI5T,EAAQ2T,EAAM1b,OAAS,GAAK+H,EAAQ,EACtC,OAEF,GAAIuH,KAAKsL,WAEP,YADA/K,GAAae,IAAItB,KAAK4E,SAAUkF,IAAY,IAAM9J,KAAKmM,GAAG1T,KAG5D,MAAM6T,EAActM,KAAKuM,cAAcvM,KAAKwM,cAC5C,GAAIF,IAAgB7T,EAClB,OAEF,MAAMtC,EAAQsC,EAAQ6T,EAAc7C,GAAaC,GACjD1J,KAAK4L,OAAOzV,EAAOiW,EAAM3T,GAC3B,CACA,OAAAsM,GACM/E,KAAKwL,cACPxL,KAAKwL,aAAazG,UAEpBJ,MAAMI,SACR,CAGA,iBAAAf,CAAkBF,GAEhB,OADAA,EAAO2I,gBAAkB3I,EAAO8G,SACzB9G,CACT,CACA,kBAAA4H,GACM1L,KAAK6E,QAAQgG,UACftK,GAAac,GAAGrB,KAAK4E,SAAUmF,IAAiB3K,GAASY,KAAK0M,SAAStN,KAE9C,UAAvBY,KAAK6E,QAAQiG,QACfvK,GAAac,GAAGrB,KAAK4E,SAAUoF,IAAoB,IAAMhK,KAAK8K,UAC9DvK,GAAac,GAAGrB,KAAK4E,SAAUqF,IAAoB,IAAMjK,KAAKkM,uBAE5DlM,KAAK6E,QAAQmG,OAASzC,GAAMC,eAC9BxI,KAAK2M,yBAET,CACA,uBAAAA,GACE,IAAK,MAAMC,KAAOhH,GAAezT,KArIX,qBAqImC6N,KAAK4E,UAC5DrE,GAAac,GAAGuL,EAAK1C,IAAkB9K,GAASA,EAAMkD,mBAExD,MAmBMuK,EAAc,CAClBzE,aAAc,IAAMpI,KAAK4L,OAAO5L,KAAK8M,kBAAkBnD,KACvDtB,cAAe,IAAMrI,KAAK4L,OAAO5L,KAAK8M,kBAAkBlD,KACxDzB,YAtBkB,KACS,UAAvBnI,KAAK6E,QAAQiG,QAYjB9K,KAAK8K,QACD9K,KAAKuL,cACPwB,aAAa/M,KAAKuL,cAEpBvL,KAAKuL,aAAe1N,YAAW,IAAMmC,KAAKkM,qBAjLjB,IAiL+DlM,KAAK6E,QAAQ+F,UAAS,GAOhH5K,KAAKwL,aAAe,IAAIjD,GAAMvI,KAAK4E,SAAUiI,EAC/C,CACA,QAAAH,CAAStN,GACP,GAAI,kBAAkB/b,KAAK+b,EAAM7S,OAAOya,SACtC,OAEF,MAAM1Z,EAAYod,GAAiBtL,EAAMtiB,KACrCwQ,IACF8R,EAAMkD,iBACNtC,KAAK4L,OAAO5L,KAAK8M,kBAAkBxf,IAEvC,CACA,aAAAif,CAAchtB,GACZ,OAAOygB,KAAKqM,YAAYlnB,QAAQ5F,EAClC,CACA,0BAAAytB,CAA2BvU,GACzB,IAAKuH,KAAKyL,mBACR,OAEF,MAAMwB,EAAkBrH,GAAeC,QAAQ0E,GAAiBvK,KAAKyL,oBACrEwB,EAAgB5R,UAAU1B,OAAO2Q,IACjC2C,EAAgB9rB,gBAAgB,gBAChC,MAAM+rB,EAAqBtH,GAAeC,QAAQ,sBAAsBpN,MAAWuH,KAAKyL,oBACpFyB,IACFA,EAAmB7R,UAAU5E,IAAI6T,IACjC4C,EAAmB9rB,aAAa,eAAgB,QAEpD,CACA,eAAA4qB,GACE,MAAMzsB,EAAUygB,KAAKqL,gBAAkBrL,KAAKwM,aAC5C,IAAKjtB,EACH,OAEF,MAAM4tB,EAAkB5P,OAAO6P,SAAS7tB,EAAQic,aAAa,oBAAqB,IAClFwE,KAAK6E,QAAQ+F,SAAWuC,GAAmBnN,KAAK6E,QAAQ4H,eAC1D,CACA,MAAAb,CAAOzV,EAAO5W,EAAU,MACtB,GAAIygB,KAAKsL,WACP,OAEF,MAAMvN,EAAgBiC,KAAKwM,aACrBa,EAASlX,IAAUsT,GACnB6D,EAAc/tB,GAAWue,GAAqBkC,KAAKqM,YAAatO,EAAesP,EAAQrN,KAAK6E,QAAQoG,MAC1G,GAAIqC,IAAgBvP,EAClB,OAEF,MAAMwP,EAAmBvN,KAAKuM,cAAce,GACtCE,EAAehI,GACZjF,GAAaqB,QAAQ5B,KAAK4E,SAAUY,EAAW,CACpD1F,cAAewN,EACfhgB,UAAW0S,KAAKyN,kBAAkBtX,GAClCuD,KAAMsG,KAAKuM,cAAcxO,GACzBoO,GAAIoB,IAIR,GADmBC,EAAa3D,IACjB7H,iBACb,OAEF,IAAKjE,IAAkBuP,EAGrB,OAEF,MAAMI,EAAY5M,QAAQd,KAAKoL,WAC/BpL,KAAK8K,QACL9K,KAAKsL,YAAa,EAClBtL,KAAKgN,2BAA2BO,GAChCvN,KAAKqL,eAAiBiC,EACtB,MAAMK,EAAuBN,EA3OR,sBADF,oBA6ObO,EAAiBP,EA3OH,qBACA,qBA2OpBC,EAAYjS,UAAU5E,IAAImX,GAC1B/R,GAAOyR,GACPvP,EAAc1C,UAAU5E,IAAIkX,GAC5BL,EAAYjS,UAAU5E,IAAIkX,GAQ1B3N,KAAKmF,gBAPoB,KACvBmI,EAAYjS,UAAU1B,OAAOgU,EAAsBC,GACnDN,EAAYjS,UAAU5E,IAAI6T,IAC1BvM,EAAc1C,UAAU1B,OAAO2Q,GAAqBsD,EAAgBD,GACpE3N,KAAKsL,YAAa,EAClBkC,EAAa1D,GAAW,GAEY/L,EAAeiC,KAAK6N,eACtDH,GACF1N,KAAK2L,OAET,CACA,WAAAkC,GACE,OAAO7N,KAAK4E,SAASvJ,UAAU7W,SAhQV,QAiQvB,CACA,UAAAgoB,GACE,OAAO5G,GAAeC,QAAQ4E,GAAsBzK,KAAK4E,SAC3D,CACA,SAAAyH,GACE,OAAOzG,GAAezT,KAAKqY,GAAexK,KAAK4E,SACjD,CACA,cAAAmH,GACM/L,KAAKoL,YACP0C,cAAc9N,KAAKoL,WACnBpL,KAAKoL,UAAY,KAErB,CACA,iBAAA0B,CAAkBxf,GAChB,OAAI2O,KACK3O,IAAcqc,GAAiBD,GAAaD,GAE9Cnc,IAAcqc,GAAiBF,GAAaC,EACrD,CACA,iBAAA+D,CAAkBtX,GAChB,OAAI8F,KACK9F,IAAUuT,GAAaC,GAAiBC,GAE1CzT,IAAUuT,GAAaE,GAAkBD,EAClD,CAGA,sBAAOlN,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO8gB,GAAS7F,oBAAoBtF,KAAM8D,GAChD,GAAsB,iBAAXA,GAIX,GAAsB,iBAAXA,EAAqB,CAC9B,QAAqB/K,IAAjB1O,EAAKyZ,IAAyBA,EAAOrC,WAAW,MAAmB,gBAAXqC,EAC1D,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IACP,OAREzZ,EAAK8hB,GAAGrI,EASZ,GACF,EAOFvD,GAAac,GAAGhc,SAAU+kB,GAvSE,uCAuS2C,SAAUhL,GAC/E,MAAM7S,EAASqZ,GAAec,uBAAuB1G,MACrD,IAAKzT,IAAWA,EAAO8O,UAAU7W,SAAS6lB,IACxC,OAEFjL,EAAMkD,iBACN,MAAMyL,EAAW5C,GAAS7F,oBAAoB/Y,GACxCyhB,EAAahO,KAAKxE,aAAa,oBACrC,OAAIwS,GACFD,EAAS5B,GAAG6B,QACZD,EAAS7B,qBAGyC,SAAhDlJ,GAAYQ,iBAAiBxD,KAAM,UACrC+N,EAASlpB,YACTkpB,EAAS7B,sBAGX6B,EAAS7H,YACT6H,EAAS7B,oBACX,IACA3L,GAAac,GAAGzhB,OAAQuqB,IAAuB,KAC7C,MAAM8D,EAAYrI,GAAezT,KA5TR,6BA6TzB,IAAK,MAAM4b,KAAYE,EACrB9C,GAAS7F,oBAAoByI,EAC/B,IAOF5R,GAAmBgP,IAcnB,MAEM+C,GAAc,eAEdC,GAAe,OAAOD,KACtBE,GAAgB,QAAQF,KACxBG,GAAe,OAAOH,KACtBI,GAAiB,SAASJ,KAC1BK,GAAyB,QAAQL,cACjCM,GAAoB,OACpBC,GAAsB,WACtBC,GAAwB,aAExBC,GAA6B,WAAWF,OAAwBA,KAKhEG,GAAyB,8BACzBC,GAAY,CAChBpqB,OAAQ,KACRijB,QAAQ,GAEJoH,GAAgB,CACpBrqB,OAAQ,iBACRijB,OAAQ,WAOV,MAAMqH,WAAiBrK,GACrB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKgP,kBAAmB,EACxBhP,KAAKiP,cAAgB,GACrB,MAAMC,EAAatJ,GAAezT,KAAKyc,IACvC,IAAK,MAAMO,KAAQD,EAAY,CAC7B,MAAMnV,EAAW6L,GAAea,uBAAuB0I,GACjDC,EAAgBxJ,GAAezT,KAAK4H,GAAU5T,QAAOkpB,GAAgBA,IAAiBrP,KAAK4E,WAChF,OAAb7K,GAAqBqV,EAAc1e,QACrCsP,KAAKiP,cAAcrd,KAAKud,EAE5B,CACAnP,KAAKsP,sBACAtP,KAAK6E,QAAQpgB,QAChBub,KAAKuP,0BAA0BvP,KAAKiP,cAAejP,KAAKwP,YAEtDxP,KAAK6E,QAAQ6C,QACf1H,KAAK0H,QAET,CAGA,kBAAWhE,GACT,OAAOmL,EACT,CACA,sBAAWlL,GACT,OAAOmL,EACT,CACA,eAAWvS,GACT,MA9DW,UA+Db,CAGA,MAAAmL,GACM1H,KAAKwP,WACPxP,KAAKyP,OAELzP,KAAK0P,MAET,CACA,IAAAA,GACE,GAAI1P,KAAKgP,kBAAoBhP,KAAKwP,WAChC,OAEF,IAAIG,EAAiB,GAQrB,GALI3P,KAAK6E,QAAQpgB,SACfkrB,EAAiB3P,KAAK4P,uBAhEH,wCAgE4CzpB,QAAO5G,GAAWA,IAAYygB,KAAK4E,WAAU9hB,KAAIvD,GAAWwvB,GAASzJ,oBAAoB/lB,EAAS,CAC/JmoB,QAAQ,OAGRiI,EAAejf,QAAUif,EAAe,GAAGX,iBAC7C,OAGF,GADmBzO,GAAaqB,QAAQ5B,KAAK4E,SAAUuJ,IACxCnM,iBACb,OAEF,IAAK,MAAM6N,KAAkBF,EAC3BE,EAAeJ,OAEjB,MAAMK,EAAY9P,KAAK+P,gBACvB/P,KAAK4E,SAASvJ,UAAU1B,OAAO8U,IAC/BzO,KAAK4E,SAASvJ,UAAU5E,IAAIiY,IAC5B1O,KAAK4E,SAAS7jB,MAAM+uB,GAAa,EACjC9P,KAAKuP,0BAA0BvP,KAAKiP,eAAe,GACnDjP,KAAKgP,kBAAmB,EACxB,MAQMgB,EAAa,SADUF,EAAU,GAAGrL,cAAgBqL,EAAU1d,MAAM,KAE1E4N,KAAKmF,gBATY,KACfnF,KAAKgP,kBAAmB,EACxBhP,KAAK4E,SAASvJ,UAAU1B,OAAO+U,IAC/B1O,KAAK4E,SAASvJ,UAAU5E,IAAIgY,GAAqBD,IACjDxO,KAAK4E,SAAS7jB,MAAM+uB,GAAa,GACjCvP,GAAaqB,QAAQ5B,KAAK4E,SAAUwJ,GAAc,GAItBpO,KAAK4E,UAAU,GAC7C5E,KAAK4E,SAAS7jB,MAAM+uB,GAAa,GAAG9P,KAAK4E,SAASoL,MACpD,CACA,IAAAP,GACE,GAAIzP,KAAKgP,mBAAqBhP,KAAKwP,WACjC,OAGF,GADmBjP,GAAaqB,QAAQ5B,KAAK4E,SAAUyJ,IACxCrM,iBACb,OAEF,MAAM8N,EAAY9P,KAAK+P,gBACvB/P,KAAK4E,SAAS7jB,MAAM+uB,GAAa,GAAG9P,KAAK4E,SAASthB,wBAAwBwsB,OAC1EjU,GAAOmE,KAAK4E,UACZ5E,KAAK4E,SAASvJ,UAAU5E,IAAIiY,IAC5B1O,KAAK4E,SAASvJ,UAAU1B,OAAO8U,GAAqBD,IACpD,IAAK,MAAM5M,KAAW5B,KAAKiP,cAAe,CACxC,MAAM1vB,EAAUqmB,GAAec,uBAAuB9E,GAClDriB,IAAYygB,KAAKwP,SAASjwB,IAC5BygB,KAAKuP,0BAA0B,CAAC3N,IAAU,EAE9C,CACA5B,KAAKgP,kBAAmB,EAOxBhP,KAAK4E,SAAS7jB,MAAM+uB,GAAa,GACjC9P,KAAKmF,gBAPY,KACfnF,KAAKgP,kBAAmB,EACxBhP,KAAK4E,SAASvJ,UAAU1B,OAAO+U,IAC/B1O,KAAK4E,SAASvJ,UAAU5E,IAAIgY,IAC5BlO,GAAaqB,QAAQ5B,KAAK4E,SAAU0J,GAAe,GAGvBtO,KAAK4E,UAAU,EAC/C,CACA,QAAA4K,CAASjwB,EAAUygB,KAAK4E,UACtB,OAAOrlB,EAAQ8b,UAAU7W,SAASgqB,GACpC,CAGA,iBAAAxK,CAAkBF,GAGhB,OAFAA,EAAO4D,OAAS5G,QAAQgD,EAAO4D,QAC/B5D,EAAOrf,OAASiW,GAAWoJ,EAAOrf,QAC3Bqf,CACT,CACA,aAAAiM,GACE,OAAO/P,KAAK4E,SAASvJ,UAAU7W,SA3IL,uBAChB,QACC,QA0Ib,CACA,mBAAA8qB,GACE,IAAKtP,KAAK6E,QAAQpgB,OAChB,OAEF,MAAMqhB,EAAW9F,KAAK4P,uBAAuBhB,IAC7C,IAAK,MAAMrvB,KAAWumB,EAAU,CAC9B,MAAMmK,EAAWrK,GAAec,uBAAuBnnB,GACnD0wB,GACFjQ,KAAKuP,0BAA0B,CAAChwB,GAAUygB,KAAKwP,SAASS,GAE5D,CACF,CACA,sBAAAL,CAAuB7V,GACrB,MAAM+L,EAAWF,GAAezT,KAAKwc,GAA4B3O,KAAK6E,QAAQpgB,QAE9E,OAAOmhB,GAAezT,KAAK4H,EAAUiG,KAAK6E,QAAQpgB,QAAQ0B,QAAO5G,IAAYumB,EAAS1E,SAAS7hB,IACjG,CACA,yBAAAgwB,CAA0BW,EAAcC,GACtC,GAAKD,EAAaxf,OAGlB,IAAK,MAAMnR,KAAW2wB,EACpB3wB,EAAQ8b,UAAUqM,OArKK,aAqKyByI,GAChD5wB,EAAQ6B,aAAa,gBAAiB+uB,EAE1C,CAGA,sBAAO1T,CAAgBqH,GACrB,MAAMe,EAAU,CAAC,EAIjB,MAHsB,iBAAXf,GAAuB,YAAYzgB,KAAKygB,KACjDe,EAAQ6C,QAAS,GAEZ1H,KAAKuH,MAAK,WACf,MAAMld,EAAO0kB,GAASzJ,oBAAoBtF,KAAM6E,GAChD,GAAsB,iBAAXf,EAAqB,CAC9B,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IACP,CACF,GACF,EAOFvD,GAAac,GAAGhc,SAAUkpB,GAAwBK,IAAwB,SAAUxP,IAErD,MAAzBA,EAAM7S,OAAOya,SAAmB5H,EAAMW,gBAAmD,MAAjCX,EAAMW,eAAeiH,UAC/E5H,EAAMkD,iBAER,IAAK,MAAM/iB,KAAWqmB,GAAee,gCAAgC3G,MACnE+O,GAASzJ,oBAAoB/lB,EAAS,CACpCmoB,QAAQ,IACPA,QAEP,IAMAvL,GAAmB4S,IAcnB,MAAMqB,GAAS,WAETC,GAAc,eACdC,GAAiB,YAGjBC,GAAiB,UACjBC,GAAmB,YAGnBC,GAAe,OAAOJ,KACtBK,GAAiB,SAASL,KAC1BM,GAAe,OAAON,KACtBO,GAAgB,QAAQP,KACxBQ,GAAyB,QAAQR,KAAcC,KAC/CQ,GAAyB,UAAUT,KAAcC,KACjDS,GAAuB,QAAQV,KAAcC,KAC7CU,GAAoB,OAMpBC,GAAyB,4DACzBC,GAA6B,GAAGD,MAA0BD,KAC1DG,GAAgB,iBAIhBC,GAAgBnV,KAAU,UAAY,YACtCoV,GAAmBpV,KAAU,YAAc,UAC3CqV,GAAmBrV,KAAU,aAAe,eAC5CsV,GAAsBtV,KAAU,eAAiB,aACjDuV,GAAkBvV,KAAU,aAAe,cAC3CwV,GAAiBxV,KAAU,cAAgB,aAG3CyV,GAAY,CAChBC,WAAW,EACX1jB,SAAU,kBACV2jB,QAAS,UACT5pB,OAAQ,CAAC,EAAG,GACZ6pB,aAAc,KACdvzB,UAAW,UAEPwzB,GAAgB,CACpBH,UAAW,mBACX1jB,SAAU,mBACV2jB,QAAS,SACT5pB,OAAQ,0BACR6pB,aAAc,yBACdvzB,UAAW,2BAOb,MAAMyzB,WAAiBrN,GACrB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKgS,QAAU,KACfhS,KAAKiS,QAAUjS,KAAK4E,SAAS7f,WAE7Bib,KAAKkS,MAAQtM,GAAe/gB,KAAKmb,KAAK4E,SAAUuM,IAAe,IAAMvL,GAAeM,KAAKlG,KAAK4E,SAAUuM,IAAe,IAAMvL,GAAeC,QAAQsL,GAAenR,KAAKiS,SACxKjS,KAAKmS,UAAYnS,KAAKoS,eACxB,CAGA,kBAAW1O,GACT,OAAOgO,EACT,CACA,sBAAW/N,GACT,OAAOmO,EACT,CACA,eAAWvV,GACT,OAAO6T,EACT,CAGA,MAAA1I,GACE,OAAO1H,KAAKwP,WAAaxP,KAAKyP,OAASzP,KAAK0P,MAC9C,CACA,IAAAA,GACE,GAAIxU,GAAW8E,KAAK4E,WAAa5E,KAAKwP,WACpC,OAEF,MAAM1P,EAAgB,CACpBA,cAAeE,KAAK4E,UAGtB,IADkBrE,GAAaqB,QAAQ5B,KAAK4E,SAAU+L,GAAc7Q,GACtDkC,iBAAd,CASA,GANAhC,KAAKqS,gBAMD,iBAAkBhtB,SAASC,kBAAoB0a,KAAKiS,QAAQjX,QAzExC,eA0EtB,IAAK,MAAMzb,IAAW,GAAGZ,UAAU0G,SAAS6G,KAAK4Z,UAC/CvF,GAAac,GAAG9hB,EAAS,YAAaqc,IAG1CoE,KAAK4E,SAAS0N,QACdtS,KAAK4E,SAASxjB,aAAa,iBAAiB,GAC5C4e,KAAKkS,MAAM7W,UAAU5E,IAAIua,IACzBhR,KAAK4E,SAASvJ,UAAU5E,IAAIua,IAC5BzQ,GAAaqB,QAAQ5B,KAAK4E,SAAUgM,GAAe9Q,EAhBnD,CAiBF,CACA,IAAA2P,GACE,GAAIvU,GAAW8E,KAAK4E,YAAc5E,KAAKwP,WACrC,OAEF,MAAM1P,EAAgB,CACpBA,cAAeE,KAAK4E,UAEtB5E,KAAKuS,cAAczS,EACrB,CACA,OAAAiF,GACM/E,KAAKgS,SACPhS,KAAKgS,QAAQhZ,UAEf2L,MAAMI,SACR,CACA,MAAAha,GACEiV,KAAKmS,UAAYnS,KAAKoS,gBAClBpS,KAAKgS,SACPhS,KAAKgS,QAAQjnB,QAEjB,CAGA,aAAAwnB,CAAczS,GAEZ,IADkBS,GAAaqB,QAAQ5B,KAAK4E,SAAU6L,GAAc3Q,GACtDkC,iBAAd,CAMA,GAAI,iBAAkB3c,SAASC,gBAC7B,IAAK,MAAM/F,IAAW,GAAGZ,UAAU0G,SAAS6G,KAAK4Z,UAC/CvF,GAAaC,IAAIjhB,EAAS,YAAaqc,IAGvCoE,KAAKgS,SACPhS,KAAKgS,QAAQhZ,UAEfgH,KAAKkS,MAAM7W,UAAU1B,OAAOqX,IAC5BhR,KAAK4E,SAASvJ,UAAU1B,OAAOqX,IAC/BhR,KAAK4E,SAASxjB,aAAa,gBAAiB,SAC5C4hB,GAAYE,oBAAoBlD,KAAKkS,MAAO,UAC5C3R,GAAaqB,QAAQ5B,KAAK4E,SAAU8L,GAAgB5Q,EAhBpD,CAiBF,CACA,UAAA+D,CAAWC,GAET,GAAgC,iBADhCA,EAASa,MAAMd,WAAWC,IACRxlB,YAA2B,GAAUwlB,EAAOxlB,YAAgE,mBAA3CwlB,EAAOxlB,UAAUgF,sBAElG,MAAM,IAAIkhB,UAAU,GAAG4L,GAAO3L,+GAEhC,OAAOX,CACT,CACA,aAAAuO,GACE,QAAsB,IAAX,EACT,MAAM,IAAI7N,UAAU,gEAEtB,IAAIgO,EAAmBxS,KAAK4E,SACG,WAA3B5E,KAAK6E,QAAQvmB,UACfk0B,EAAmBxS,KAAKiS,QACf,GAAUjS,KAAK6E,QAAQvmB,WAChCk0B,EAAmB9X,GAAWsF,KAAK6E,QAAQvmB,WACA,iBAA3B0hB,KAAK6E,QAAQvmB,YAC7Bk0B,EAAmBxS,KAAK6E,QAAQvmB,WAElC,MAAMuzB,EAAe7R,KAAKyS,mBAC1BzS,KAAKgS,QAAU,GAAoBQ,EAAkBxS,KAAKkS,MAAOL,EACnE,CACA,QAAArC,GACE,OAAOxP,KAAKkS,MAAM7W,UAAU7W,SAASwsB,GACvC,CACA,aAAA0B,GACE,MAAMC,EAAiB3S,KAAKiS,QAC5B,GAAIU,EAAetX,UAAU7W,SArKN,WAsKrB,OAAOgtB,GAET,GAAImB,EAAetX,UAAU7W,SAvKJ,aAwKvB,OAAOitB,GAET,GAAIkB,EAAetX,UAAU7W,SAzKA,iBA0K3B,MA5JsB,MA8JxB,GAAImuB,EAAetX,UAAU7W,SA3KE,mBA4K7B,MA9JyB,SAkK3B,MAAMouB,EAAkF,QAA1E3tB,iBAAiB+a,KAAKkS,OAAOpX,iBAAiB,iBAAiB6K,OAC7E,OAAIgN,EAAetX,UAAU7W,SArLP,UAsLbouB,EAAQvB,GAAmBD,GAE7BwB,EAAQrB,GAAsBD,EACvC,CACA,aAAAc,GACE,OAAkD,OAA3CpS,KAAK4E,SAAS5J,QAnLD,UAoLtB,CACA,UAAA6X,GACE,MAAM,OACJ7qB,GACEgY,KAAK6E,QACT,MAAsB,iBAAX7c,EACFA,EAAO9F,MAAM,KAAKY,KAAInF,GAAS4f,OAAO6P,SAASzvB,EAAO,MAEzC,mBAAXqK,EACF8qB,GAAc9qB,EAAO8qB,EAAY9S,KAAK4E,UAExC5c,CACT,CACA,gBAAAyqB,GACE,MAAMM,EAAwB,CAC5Br0B,UAAWshB,KAAK0S,gBAChBtc,UAAW,CAAC,CACV9V,KAAM,kBACNmB,QAAS,CACPwM,SAAU+R,KAAK6E,QAAQ5W,WAExB,CACD3N,KAAM,SACNmB,QAAS,CACPuG,OAAQgY,KAAK6S,iBAanB,OAPI7S,KAAKmS,WAAsC,WAAzBnS,KAAK6E,QAAQ+M,WACjC5O,GAAYC,iBAAiBjD,KAAKkS,MAAO,SAAU,UACnDa,EAAsB3c,UAAY,CAAC,CACjC9V,KAAM,cACNC,SAAS,KAGN,IACFwyB,KACAlW,GAAQmD,KAAK6E,QAAQgN,aAAc,CAACkB,IAE3C,CACA,eAAAC,EAAgB,IACdl2B,EAAG,OACHyP,IAEA,MAAM6f,EAAQxG,GAAezT,KAhOF,8DAgO+B6N,KAAKkS,OAAO/rB,QAAO5G,GAAWob,GAAUpb,KAC7F6sB,EAAM1b,QAMXoN,GAAqBsO,EAAO7f,EAAQzP,IAAQ0zB,IAAmBpE,EAAMhL,SAAS7U,IAAS+lB,OACzF,CAGA,sBAAO7V,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO0nB,GAASzM,oBAAoBtF,KAAM8D,GAChD,GAAsB,iBAAXA,EAAX,CAGA,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IAJL,CAKF,GACF,CACA,iBAAOmP,CAAW7T,GAChB,GA5QuB,IA4QnBA,EAAMuI,QAAgD,UAAfvI,EAAMqB,MA/QnC,QA+QuDrB,EAAMtiB,IACzE,OAEF,MAAMo2B,EAActN,GAAezT,KAAK+e,IACxC,IAAK,MAAMxJ,KAAUwL,EAAa,CAChC,MAAMC,EAAUpB,GAAS1M,YAAYqC,GACrC,IAAKyL,IAAyC,IAA9BA,EAAQtO,QAAQ8M,UAC9B,SAEF,MAAMyB,EAAehU,EAAMgU,eACrBC,EAAeD,EAAahS,SAAS+R,EAAQjB,OACnD,GAAIkB,EAAahS,SAAS+R,EAAQvO,WAA2C,WAA9BuO,EAAQtO,QAAQ8M,YAA2B0B,GAA8C,YAA9BF,EAAQtO,QAAQ8M,WAA2B0B,EACnJ,SAIF,GAAIF,EAAQjB,MAAM1tB,SAAS4a,EAAM7S,UAA2B,UAAf6S,EAAMqB,MA/RvC,QA+R2DrB,EAAMtiB,KAAqB,qCAAqCuG,KAAK+b,EAAM7S,OAAOya,UACvJ,SAEF,MAAMlH,EAAgB,CACpBA,cAAeqT,EAAQvO,UAEN,UAAfxF,EAAMqB,OACRX,EAAciH,WAAa3H,GAE7B+T,EAAQZ,cAAczS,EACxB,CACF,CACA,4BAAOwT,CAAsBlU,GAI3B,MAAMmU,EAAU,kBAAkBlwB,KAAK+b,EAAM7S,OAAOya,SAC9CwM,EAjTW,WAiTKpU,EAAMtiB,IACtB22B,EAAkB,CAAClD,GAAgBC,IAAkBpP,SAAShC,EAAMtiB,KAC1E,IAAK22B,IAAoBD,EACvB,OAEF,GAAID,IAAYC,EACd,OAEFpU,EAAMkD,iBAGN,MAAMoR,EAAkB1T,KAAK+F,QAAQkL,IAA0BjR,KAAO4F,GAAeM,KAAKlG,KAAMiR,IAAwB,IAAMrL,GAAe/gB,KAAKmb,KAAMiR,IAAwB,IAAMrL,GAAeC,QAAQoL,GAAwB7R,EAAMW,eAAehb,YACpPwF,EAAWwnB,GAASzM,oBAAoBoO,GAC9C,GAAID,EAIF,OAHArU,EAAMuU,kBACNppB,EAASmlB,YACTnlB,EAASyoB,gBAAgB5T,GAGvB7U,EAASilB,aAEXpQ,EAAMuU,kBACNppB,EAASklB,OACTiE,EAAgBpB,QAEpB,EAOF/R,GAAac,GAAGhc,SAAUyrB,GAAwBG,GAAwBc,GAASuB,uBACnF/S,GAAac,GAAGhc,SAAUyrB,GAAwBK,GAAeY,GAASuB,uBAC1E/S,GAAac,GAAGhc,SAAUwrB,GAAwBkB,GAASkB,YAC3D1S,GAAac,GAAGhc,SAAU0rB,GAAsBgB,GAASkB,YACzD1S,GAAac,GAAGhc,SAAUwrB,GAAwBI,IAAwB,SAAU7R,GAClFA,EAAMkD,iBACNyP,GAASzM,oBAAoBtF,MAAM0H,QACrC,IAMAvL,GAAmB4V,IAcnB,MAAM6B,GAAS,WAETC,GAAoB,OACpBC,GAAkB,gBAAgBF,KAClCG,GAAY,CAChBC,UAAW,iBACXC,cAAe,KACf7O,YAAY,EACZzK,WAAW,EAEXuZ,YAAa,QAGTC,GAAgB,CACpBH,UAAW,SACXC,cAAe,kBACf7O,WAAY,UACZzK,UAAW,UACXuZ,YAAa,oBAOf,MAAME,WAAiB3Q,GACrB,WAAAU,CAAYL,GACVa,QACA3E,KAAK6E,QAAU7E,KAAK6D,WAAWC,GAC/B9D,KAAKqU,aAAc,EACnBrU,KAAK4E,SAAW,IAClB,CAGA,kBAAWlB,GACT,OAAOqQ,EACT,CACA,sBAAWpQ,GACT,OAAOwQ,EACT,CACA,eAAW5X,GACT,OAAOqX,EACT,CAGA,IAAAlE,CAAKrT,GACH,IAAK2D,KAAK6E,QAAQlK,UAEhB,YADAkC,GAAQR,GAGV2D,KAAKsU,UACL,MAAM/0B,EAAUygB,KAAKuU,cACjBvU,KAAK6E,QAAQO,YACfvJ,GAAOtc,GAETA,EAAQ8b,UAAU5E,IAAIod,IACtB7T,KAAKwU,mBAAkB,KACrB3X,GAAQR,EAAS,GAErB,CACA,IAAAoT,CAAKpT,GACE2D,KAAK6E,QAAQlK,WAIlBqF,KAAKuU,cAAclZ,UAAU1B,OAAOka,IACpC7T,KAAKwU,mBAAkB,KACrBxU,KAAK+E,UACLlI,GAAQR,EAAS,KANjBQ,GAAQR,EAQZ,CACA,OAAA0I,GACO/E,KAAKqU,cAGV9T,GAAaC,IAAIR,KAAK4E,SAAUkP,IAChC9T,KAAK4E,SAASjL,SACdqG,KAAKqU,aAAc,EACrB,CAGA,WAAAE,GACE,IAAKvU,KAAK4E,SAAU,CAClB,MAAM6P,EAAWpvB,SAASqvB,cAAc,OACxCD,EAAST,UAAYhU,KAAK6E,QAAQmP,UAC9BhU,KAAK6E,QAAQO,YACfqP,EAASpZ,UAAU5E,IArFD,QAuFpBuJ,KAAK4E,SAAW6P,CAClB,CACA,OAAOzU,KAAK4E,QACd,CACA,iBAAAZ,CAAkBF,GAGhB,OADAA,EAAOoQ,YAAcxZ,GAAWoJ,EAAOoQ,aAChCpQ,CACT,CACA,OAAAwQ,GACE,GAAItU,KAAKqU,YACP,OAEF,MAAM90B,EAAUygB,KAAKuU,cACrBvU,KAAK6E,QAAQqP,YAAYS,OAAOp1B,GAChCghB,GAAac,GAAG9hB,EAASu0B,IAAiB,KACxCjX,GAAQmD,KAAK6E,QAAQoP,cAAc,IAErCjU,KAAKqU,aAAc,CACrB,CACA,iBAAAG,CAAkBnY,GAChBW,GAAuBX,EAAU2D,KAAKuU,cAAevU,KAAK6E,QAAQO,WACpE,EAeF,MAEMwP,GAAc,gBACdC,GAAkB,UAAUD,KAC5BE,GAAoB,cAAcF,KAGlCG,GAAmB,WACnBC,GAAY,CAChBC,WAAW,EACXC,YAAa,MAGTC,GAAgB,CACpBF,UAAW,UACXC,YAAa,WAOf,MAAME,WAAkB3R,GACtB,WAAAU,CAAYL,GACVa,QACA3E,KAAK6E,QAAU7E,KAAK6D,WAAWC,GAC/B9D,KAAKqV,WAAY,EACjBrV,KAAKsV,qBAAuB,IAC9B,CAGA,kBAAW5R,GACT,OAAOsR,EACT,CACA,sBAAWrR,GACT,OAAOwR,EACT,CACA,eAAW5Y,GACT,MAtCW,WAuCb,CAGA,QAAAgZ,GACMvV,KAAKqV,YAGLrV,KAAK6E,QAAQoQ,WACfjV,KAAK6E,QAAQqQ,YAAY5C,QAE3B/R,GAAaC,IAAInb,SAAUuvB,IAC3BrU,GAAac,GAAGhc,SAAUwvB,IAAiBzV,GAASY,KAAKwV,eAAepW,KACxEmB,GAAac,GAAGhc,SAAUyvB,IAAmB1V,GAASY,KAAKyV,eAAerW,KAC1EY,KAAKqV,WAAY,EACnB,CACA,UAAAK,GACO1V,KAAKqV,YAGVrV,KAAKqV,WAAY,EACjB9U,GAAaC,IAAInb,SAAUuvB,IAC7B,CAGA,cAAAY,CAAepW,GACb,MAAM,YACJ8V,GACElV,KAAK6E,QACT,GAAIzF,EAAM7S,SAAWlH,UAAY+Z,EAAM7S,SAAW2oB,GAAeA,EAAY1wB,SAAS4a,EAAM7S,QAC1F,OAEF,MAAM1L,EAAW+kB,GAAeU,kBAAkB4O,GAC1B,IAApBr0B,EAAS6P,OACXwkB,EAAY5C,QACHtS,KAAKsV,uBAAyBP,GACvCl0B,EAASA,EAAS6P,OAAS,GAAG4hB,QAE9BzxB,EAAS,GAAGyxB,OAEhB,CACA,cAAAmD,CAAerW,GA1ED,QA2ERA,EAAMtiB,MAGVkjB,KAAKsV,qBAAuBlW,EAAMuW,SAAWZ,GA7EzB,UA8EtB,EAeF,MAAMa,GAAyB,oDACzBC,GAA0B,cAC1BC,GAAmB,gBACnBC,GAAkB,eAMxB,MAAMC,GACJ,WAAA7R,GACEnE,KAAK4E,SAAWvf,SAAS6G,IAC3B,CAGA,QAAA+pB,GAEE,MAAMC,EAAgB7wB,SAASC,gBAAgBuC,YAC/C,OAAO1F,KAAKoC,IAAI3E,OAAOu2B,WAAaD,EACtC,CACA,IAAAzG,GACE,MAAM5rB,EAAQmc,KAAKiW,WACnBjW,KAAKoW,mBAELpW,KAAKqW,sBAAsBrW,KAAK4E,SAAUkR,IAAkBQ,GAAmBA,EAAkBzyB,IAEjGmc,KAAKqW,sBAAsBT,GAAwBE,IAAkBQ,GAAmBA,EAAkBzyB,IAC1Gmc,KAAKqW,sBAAsBR,GAAyBE,IAAiBO,GAAmBA,EAAkBzyB,GAC5G,CACA,KAAAwO,GACE2N,KAAKuW,wBAAwBvW,KAAK4E,SAAU,YAC5C5E,KAAKuW,wBAAwBvW,KAAK4E,SAAUkR,IAC5C9V,KAAKuW,wBAAwBX,GAAwBE,IACrD9V,KAAKuW,wBAAwBV,GAAyBE,GACxD,CACA,aAAAS,GACE,OAAOxW,KAAKiW,WAAa,CAC3B,CAGA,gBAAAG,GACEpW,KAAKyW,sBAAsBzW,KAAK4E,SAAU,YAC1C5E,KAAK4E,SAAS7jB,MAAM+K,SAAW,QACjC,CACA,qBAAAuqB,CAAsBtc,EAAU2c,EAAera,GAC7C,MAAMsa,EAAiB3W,KAAKiW,WAS5BjW,KAAK4W,2BAA2B7c,GARHxa,IAC3B,GAAIA,IAAYygB,KAAK4E,UAAYhlB,OAAOu2B,WAAa52B,EAAQsI,YAAc8uB,EACzE,OAEF3W,KAAKyW,sBAAsBl3B,EAASm3B,GACpC,MAAMJ,EAAkB12B,OAAOqF,iBAAiB1F,GAASub,iBAAiB4b,GAC1En3B,EAAQwB,MAAM81B,YAAYH,EAAe,GAAGra,EAASkB,OAAOC,WAAW8Y,QAAsB,GAGjG,CACA,qBAAAG,CAAsBl3B,EAASm3B,GAC7B,MAAMI,EAAcv3B,EAAQwB,MAAM+Z,iBAAiB4b,GAC/CI,GACF9T,GAAYC,iBAAiB1jB,EAASm3B,EAAeI,EAEzD,CACA,uBAAAP,CAAwBxc,EAAU2c,GAWhC1W,KAAK4W,2BAA2B7c,GAVHxa,IAC3B,MAAM5B,EAAQqlB,GAAYQ,iBAAiBjkB,EAASm3B,GAEtC,OAAV/4B,GAIJqlB,GAAYE,oBAAoB3jB,EAASm3B,GACzCn3B,EAAQwB,MAAM81B,YAAYH,EAAe/4B,IAJvC4B,EAAQwB,MAAMg2B,eAAeL,EAIgB,GAGnD,CACA,0BAAAE,CAA2B7c,EAAUid,GACnC,GAAI,GAAUjd,GACZid,EAASjd,QAGX,IAAK,MAAMkd,KAAOrR,GAAezT,KAAK4H,EAAUiG,KAAK4E,UACnDoS,EAASC,EAEb,EAeF,MAEMC,GAAc,YAGdC,GAAe,OAAOD,KACtBE,GAAyB,gBAAgBF,KACzCG,GAAiB,SAASH,KAC1BI,GAAe,OAAOJ,KACtBK,GAAgB,QAAQL,KACxBM,GAAiB,SAASN,KAC1BO,GAAsB,gBAAgBP,KACtCQ,GAA0B,oBAAoBR,KAC9CS,GAA0B,kBAAkBT,KAC5CU,GAAyB,QAAQV,cACjCW,GAAkB,aAElBC,GAAoB,OACpBC,GAAoB,eAKpBC,GAAY,CAChBvD,UAAU,EACVnC,OAAO,EACPzH,UAAU,GAENoN,GAAgB,CACpBxD,SAAU,mBACVnC,MAAO,UACPzH,SAAU,WAOZ,MAAMqN,WAAcxT,GAClB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKmY,QAAUvS,GAAeC,QArBV,gBAqBmC7F,KAAK4E,UAC5D5E,KAAKoY,UAAYpY,KAAKqY,sBACtBrY,KAAKsY,WAAatY,KAAKuY,uBACvBvY,KAAKwP,UAAW,EAChBxP,KAAKgP,kBAAmB,EACxBhP,KAAKwY,WAAa,IAAIxC,GACtBhW,KAAK0L,oBACP,CAGA,kBAAWhI,GACT,OAAOsU,EACT,CACA,sBAAWrU,GACT,OAAOsU,EACT,CACA,eAAW1b,GACT,MA1DW,OA2Db,CAGA,MAAAmL,CAAO5H,GACL,OAAOE,KAAKwP,SAAWxP,KAAKyP,OAASzP,KAAK0P,KAAK5P,EACjD,CACA,IAAA4P,CAAK5P,GACCE,KAAKwP,UAAYxP,KAAKgP,kBAGRzO,GAAaqB,QAAQ5B,KAAK4E,SAAU0S,GAAc,CAClExX,kBAEYkC,mBAGdhC,KAAKwP,UAAW,EAChBxP,KAAKgP,kBAAmB,EACxBhP,KAAKwY,WAAW/I,OAChBpqB,SAAS6G,KAAKmP,UAAU5E,IAAIohB,IAC5B7X,KAAKyY,gBACLzY,KAAKoY,UAAU1I,MAAK,IAAM1P,KAAK0Y,aAAa5Y,KAC9C,CACA,IAAA2P,GACOzP,KAAKwP,WAAYxP,KAAKgP,mBAGTzO,GAAaqB,QAAQ5B,KAAK4E,SAAUuS,IACxCnV,mBAGdhC,KAAKwP,UAAW,EAChBxP,KAAKgP,kBAAmB,EACxBhP,KAAKsY,WAAW5C,aAChB1V,KAAK4E,SAASvJ,UAAU1B,OAAOme,IAC/B9X,KAAKmF,gBAAe,IAAMnF,KAAK2Y,cAAc3Y,KAAK4E,SAAU5E,KAAK6N,gBACnE,CACA,OAAA9I,GACExE,GAAaC,IAAI5gB,OAAQs3B,IACzB3W,GAAaC,IAAIR,KAAKmY,QAASjB,IAC/BlX,KAAKoY,UAAUrT,UACf/E,KAAKsY,WAAW5C,aAChB/Q,MAAMI,SACR,CACA,YAAA6T,GACE5Y,KAAKyY,eACP,CAGA,mBAAAJ,GACE,OAAO,IAAIjE,GAAS,CAClBzZ,UAAWmG,QAAQd,KAAK6E,QAAQ4P,UAEhCrP,WAAYpF,KAAK6N,eAErB,CACA,oBAAA0K,GACE,OAAO,IAAInD,GAAU,CACnBF,YAAalV,KAAK4E,UAEtB,CACA,YAAA8T,CAAa5Y,GAENza,SAAS6G,KAAK1H,SAASwb,KAAK4E,WAC/Bvf,SAAS6G,KAAKyoB,OAAO3U,KAAK4E,UAE5B5E,KAAK4E,SAAS7jB,MAAM6wB,QAAU,QAC9B5R,KAAK4E,SAASzjB,gBAAgB,eAC9B6e,KAAK4E,SAASxjB,aAAa,cAAc,GACzC4e,KAAK4E,SAASxjB,aAAa,OAAQ,UACnC4e,KAAK4E,SAASnZ,UAAY,EAC1B,MAAMotB,EAAYjT,GAAeC,QA7GT,cA6GsC7F,KAAKmY,SAC/DU,IACFA,EAAUptB,UAAY,GAExBoQ,GAAOmE,KAAK4E,UACZ5E,KAAK4E,SAASvJ,UAAU5E,IAAIqhB,IAU5B9X,KAAKmF,gBATsB,KACrBnF,KAAK6E,QAAQyN,OACftS,KAAKsY,WAAW/C,WAElBvV,KAAKgP,kBAAmB,EACxBzO,GAAaqB,QAAQ5B,KAAK4E,SAAU2S,GAAe,CACjDzX,iBACA,GAEoCE,KAAKmY,QAASnY,KAAK6N,cAC7D,CACA,kBAAAnC,GACEnL,GAAac,GAAGrB,KAAK4E,SAAU+S,IAAyBvY,IAhJvC,WAiJXA,EAAMtiB,MAGNkjB,KAAK6E,QAAQgG,SACf7K,KAAKyP,OAGPzP,KAAK8Y,6BAA4B,IAEnCvY,GAAac,GAAGzhB,OAAQ43B,IAAgB,KAClCxX,KAAKwP,WAAaxP,KAAKgP,kBACzBhP,KAAKyY,eACP,IAEFlY,GAAac,GAAGrB,KAAK4E,SAAU8S,IAAyBtY,IAEtDmB,GAAae,IAAItB,KAAK4E,SAAU6S,IAAqBsB,IAC/C/Y,KAAK4E,WAAaxF,EAAM7S,QAAUyT,KAAK4E,WAAamU,EAAOxsB,SAGjC,WAA1ByT,KAAK6E,QAAQ4P,SAIbzU,KAAK6E,QAAQ4P,UACfzU,KAAKyP,OAJLzP,KAAK8Y,6BAKP,GACA,GAEN,CACA,UAAAH,GACE3Y,KAAK4E,SAAS7jB,MAAM6wB,QAAU,OAC9B5R,KAAK4E,SAASxjB,aAAa,eAAe,GAC1C4e,KAAK4E,SAASzjB,gBAAgB,cAC9B6e,KAAK4E,SAASzjB,gBAAgB,QAC9B6e,KAAKgP,kBAAmB,EACxBhP,KAAKoY,UAAU3I,MAAK,KAClBpqB,SAAS6G,KAAKmP,UAAU1B,OAAOke,IAC/B7X,KAAKgZ,oBACLhZ,KAAKwY,WAAWnmB,QAChBkO,GAAaqB,QAAQ5B,KAAK4E,SAAUyS,GAAe,GAEvD,CACA,WAAAxJ,GACE,OAAO7N,KAAK4E,SAASvJ,UAAU7W,SAjLT,OAkLxB,CACA,0BAAAs0B,GAEE,GADkBvY,GAAaqB,QAAQ5B,KAAK4E,SAAUwS,IACxCpV,iBACZ,OAEF,MAAMiX,EAAqBjZ,KAAK4E,SAASvX,aAAehI,SAASC,gBAAgBsC,aAC3EsxB,EAAmBlZ,KAAK4E,SAAS7jB,MAAMiL,UAEpB,WAArBktB,GAAiClZ,KAAK4E,SAASvJ,UAAU7W,SAASuzB,MAGjEkB,IACHjZ,KAAK4E,SAAS7jB,MAAMiL,UAAY,UAElCgU,KAAK4E,SAASvJ,UAAU5E,IAAIshB,IAC5B/X,KAAKmF,gBAAe,KAClBnF,KAAK4E,SAASvJ,UAAU1B,OAAOoe,IAC/B/X,KAAKmF,gBAAe,KAClBnF,KAAK4E,SAAS7jB,MAAMiL,UAAYktB,CAAgB,GAC/ClZ,KAAKmY,QAAQ,GACfnY,KAAKmY,SACRnY,KAAK4E,SAAS0N,QAChB,CAMA,aAAAmG,GACE,MAAMQ,EAAqBjZ,KAAK4E,SAASvX,aAAehI,SAASC,gBAAgBsC,aAC3E+uB,EAAiB3W,KAAKwY,WAAWvC,WACjCkD,EAAoBxC,EAAiB,EAC3C,GAAIwC,IAAsBF,EAAoB,CAC5C,MAAMn3B,EAAWma,KAAU,cAAgB,eAC3C+D,KAAK4E,SAAS7jB,MAAMe,GAAY,GAAG60B,KACrC,CACA,IAAKwC,GAAqBF,EAAoB,CAC5C,MAAMn3B,EAAWma,KAAU,eAAiB,cAC5C+D,KAAK4E,SAAS7jB,MAAMe,GAAY,GAAG60B,KACrC,CACF,CACA,iBAAAqC,GACEhZ,KAAK4E,SAAS7jB,MAAMq4B,YAAc,GAClCpZ,KAAK4E,SAAS7jB,MAAMs4B,aAAe,EACrC,CAGA,sBAAO5c,CAAgBqH,EAAQhE,GAC7B,OAAOE,KAAKuH,MAAK,WACf,MAAMld,EAAO6tB,GAAM5S,oBAAoBtF,KAAM8D,GAC7C,GAAsB,iBAAXA,EAAX,CAGA,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,GAAQhE,EAJb,CAKF,GACF,EAOFS,GAAac,GAAGhc,SAAUuyB,GA9OK,4BA8O2C,SAAUxY,GAClF,MAAM7S,EAASqZ,GAAec,uBAAuB1G,MACjD,CAAC,IAAK,QAAQoB,SAASpB,KAAKgH,UAC9B5H,EAAMkD,iBAER/B,GAAae,IAAI/U,EAAQ+qB,IAAcgC,IACjCA,EAAUtX,kBAIdzB,GAAae,IAAI/U,EAAQ8qB,IAAgB,KACnC1c,GAAUqF,OACZA,KAAKsS,OACP,GACA,IAIJ,MAAMiH,EAAc3T,GAAeC,QAnQb,eAoQlB0T,GACFrB,GAAM7S,YAAYkU,GAAa9J,OAEpByI,GAAM5S,oBAAoB/Y,GAClCmb,OAAO1H,KACd,IACA4G,GAAqBsR,IAMrB/b,GAAmB+b,IAcnB,MAEMsB,GAAc,gBACdC,GAAiB,YACjBC,GAAwB,OAAOF,KAAcC,KAE7CE,GAAoB,OACpBC,GAAuB,UACvBC,GAAoB,SAEpBC,GAAgB,kBAChBC,GAAe,OAAOP,KACtBQ,GAAgB,QAAQR,KACxBS,GAAe,OAAOT,KACtBU,GAAuB,gBAAgBV,KACvCW,GAAiB,SAASX,KAC1BY,GAAe,SAASZ,KACxBa,GAAyB,QAAQb,KAAcC,KAC/Ca,GAAwB,kBAAkBd,KAE1Ce,GAAY,CAChB9F,UAAU,EACV5J,UAAU,EACVpgB,QAAQ,GAEJ+vB,GAAgB,CACpB/F,SAAU,mBACV5J,SAAU,UACVpgB,OAAQ,WAOV,MAAMgwB,WAAkB/V,GACtB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKwP,UAAW,EAChBxP,KAAKoY,UAAYpY,KAAKqY,sBACtBrY,KAAKsY,WAAatY,KAAKuY,uBACvBvY,KAAK0L,oBACP,CAGA,kBAAWhI,GACT,OAAO6W,EACT,CACA,sBAAW5W,GACT,OAAO6W,EACT,CACA,eAAWje,GACT,MApDW,WAqDb,CAGA,MAAAmL,CAAO5H,GACL,OAAOE,KAAKwP,SAAWxP,KAAKyP,OAASzP,KAAK0P,KAAK5P,EACjD,CACA,IAAA4P,CAAK5P,GACCE,KAAKwP,UAGSjP,GAAaqB,QAAQ5B,KAAK4E,SAAUmV,GAAc,CAClEja,kBAEYkC,mBAGdhC,KAAKwP,UAAW,EAChBxP,KAAKoY,UAAU1I,OACV1P,KAAK6E,QAAQpa,SAChB,IAAIurB,IAAkBvG,OAExBzP,KAAK4E,SAASxjB,aAAa,cAAc,GACzC4e,KAAK4E,SAASxjB,aAAa,OAAQ,UACnC4e,KAAK4E,SAASvJ,UAAU5E,IAAImjB,IAW5B5Z,KAAKmF,gBAVoB,KAClBnF,KAAK6E,QAAQpa,SAAUuV,KAAK6E,QAAQ4P,UACvCzU,KAAKsY,WAAW/C,WAElBvV,KAAK4E,SAASvJ,UAAU5E,IAAIkjB,IAC5B3Z,KAAK4E,SAASvJ,UAAU1B,OAAOigB,IAC/BrZ,GAAaqB,QAAQ5B,KAAK4E,SAAUoV,GAAe,CACjDla,iBACA,GAEkCE,KAAK4E,UAAU,GACvD,CACA,IAAA6K,GACOzP,KAAKwP,WAGQjP,GAAaqB,QAAQ5B,KAAK4E,SAAUqV,IACxCjY,mBAGdhC,KAAKsY,WAAW5C,aAChB1V,KAAK4E,SAAS8V,OACd1a,KAAKwP,UAAW,EAChBxP,KAAK4E,SAASvJ,UAAU5E,IAAIojB,IAC5B7Z,KAAKoY,UAAU3I,OAUfzP,KAAKmF,gBAToB,KACvBnF,KAAK4E,SAASvJ,UAAU1B,OAAOggB,GAAmBE,IAClD7Z,KAAK4E,SAASzjB,gBAAgB,cAC9B6e,KAAK4E,SAASzjB,gBAAgB,QACzB6e,KAAK6E,QAAQpa,SAChB,IAAIurB,IAAkB3jB,QAExBkO,GAAaqB,QAAQ5B,KAAK4E,SAAUuV,GAAe,GAEfna,KAAK4E,UAAU,IACvD,CACA,OAAAG,GACE/E,KAAKoY,UAAUrT,UACf/E,KAAKsY,WAAW5C,aAChB/Q,MAAMI,SACR,CAGA,mBAAAsT,GACE,MASM1d,EAAYmG,QAAQd,KAAK6E,QAAQ4P,UACvC,OAAO,IAAIL,GAAS,CAClBJ,UA3HsB,qBA4HtBrZ,YACAyK,YAAY,EACZ8O,YAAalU,KAAK4E,SAAS7f,WAC3BkvB,cAAetZ,EAfK,KACU,WAA1BqF,KAAK6E,QAAQ4P,SAIjBzU,KAAKyP,OAHHlP,GAAaqB,QAAQ5B,KAAK4E,SAAUsV,GAG3B,EAUgC,MAE/C,CACA,oBAAA3B,GACE,OAAO,IAAInD,GAAU,CACnBF,YAAalV,KAAK4E,UAEtB,CACA,kBAAA8G,GACEnL,GAAac,GAAGrB,KAAK4E,SAAU0V,IAAuBlb,IA5IvC,WA6ITA,EAAMtiB,MAGNkjB,KAAK6E,QAAQgG,SACf7K,KAAKyP,OAGPlP,GAAaqB,QAAQ5B,KAAK4E,SAAUsV,IAAqB,GAE7D,CAGA,sBAAOzd,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAOowB,GAAUnV,oBAAoBtF,KAAM8D,GACjD,GAAsB,iBAAXA,EAAX,CAGA,QAAqB/K,IAAjB1O,EAAKyZ,IAAyBA,EAAOrC,WAAW,MAAmB,gBAAXqC,EAC1D,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,GAAQ9D,KAJb,CAKF,GACF,EAOFO,GAAac,GAAGhc,SAAUg1B,GA7JK,gCA6J2C,SAAUjb,GAClF,MAAM7S,EAASqZ,GAAec,uBAAuB1G,MAIrD,GAHI,CAAC,IAAK,QAAQoB,SAASpB,KAAKgH,UAC9B5H,EAAMkD,iBAEJpH,GAAW8E,MACb,OAEFO,GAAae,IAAI/U,EAAQ4tB,IAAgB,KAEnCxf,GAAUqF,OACZA,KAAKsS,OACP,IAIF,MAAMiH,EAAc3T,GAAeC,QAAQiU,IACvCP,GAAeA,IAAgBhtB,GACjCkuB,GAAUpV,YAAYkU,GAAa9J,OAExBgL,GAAUnV,oBAAoB/Y,GACtCmb,OAAO1H,KACd,IACAO,GAAac,GAAGzhB,OAAQ85B,IAAuB,KAC7C,IAAK,MAAM3f,KAAY6L,GAAezT,KAAK2nB,IACzCW,GAAUnV,oBAAoBvL,GAAU2V,MAC1C,IAEFnP,GAAac,GAAGzhB,OAAQw6B,IAAc,KACpC,IAAK,MAAM76B,KAAWqmB,GAAezT,KAAK,gDACG,UAAvClN,iBAAiB1F,GAASiC,UAC5Bi5B,GAAUnV,oBAAoB/lB,GAASkwB,MAE3C,IAEF7I,GAAqB6T,IAMrBte,GAAmBse,IAUnB,MACME,GAAmB,CAEvB,IAAK,CAAC,QAAS,MAAO,KAAM,OAAQ,OAHP,kBAI7B9pB,EAAG,CAAC,SAAU,OAAQ,QAAS,OAC/B+pB,KAAM,GACN9pB,EAAG,GACH+pB,GAAI,GACJC,IAAK,GACLC,KAAM,GACNC,IAAK,GACLC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJC,GAAI,GACJnqB,EAAG,GACHub,IAAK,CAAC,MAAO,SAAU,MAAO,QAAS,QAAS,UAChD6O,GAAI,GACJC,GAAI,GACJC,EAAG,GACHC,IAAK,GACLC,EAAG,GACHC,MAAO,GACPC,KAAM,GACNC,IAAK,GACLC,IAAK,GACLC,OAAQ,GACRC,EAAG,GACHC,GAAI,IAIAC,GAAgB,IAAI/lB,IAAI,CAAC,aAAc,OAAQ,OAAQ,WAAY,WAAY,SAAU,MAAO,eAShGgmB,GAAmB,0DACnBC,GAAmB,CAACx6B,EAAWy6B,KACnC,MAAMC,EAAgB16B,EAAUvC,SAASC,cACzC,OAAI+8B,EAAqBpb,SAASqb,IAC5BJ,GAAc1lB,IAAI8lB,IACb3b,QAAQwb,GAAiBj5B,KAAKtB,EAAU26B,YAM5CF,EAAqBr2B,QAAOw2B,GAAkBA,aAA0BpY,SAAQ9R,MAAKmqB,GAASA,EAAMv5B,KAAKo5B,IAAe,EA0C3HI,GAAY,CAChBC,UAAWnC,GACXoC,QAAS,CAAC,EAEVC,WAAY,GACZnwB,MAAM,EACNowB,UAAU,EACVC,WAAY,KACZC,SAAU,eAENC,GAAgB,CACpBN,UAAW,SACXC,QAAS,SACTC,WAAY,oBACZnwB,KAAM,UACNowB,SAAU,UACVC,WAAY,kBACZC,SAAU,UAENE,GAAqB,CACzBC,MAAO,iCACPvjB,SAAU,oBAOZ,MAAMwjB,WAAwB9Z,GAC5B,WAAAU,CAAYL,GACVa,QACA3E,KAAK6E,QAAU7E,KAAK6D,WAAWC,EACjC,CAGA,kBAAWJ,GACT,OAAOmZ,EACT,CACA,sBAAWlZ,GACT,OAAOyZ,EACT,CACA,eAAW7gB,GACT,MA3CW,iBA4Cb,CAGA,UAAAihB,GACE,OAAOxgC,OAAOmiB,OAAOa,KAAK6E,QAAQkY,SAASj6B,KAAIghB,GAAU9D,KAAKyd,yBAAyB3Z,KAAS3d,OAAO2a,QACzG,CACA,UAAA4c,GACE,OAAO1d,KAAKwd,aAAa9sB,OAAS,CACpC,CACA,aAAAitB,CAAcZ,GAMZ,OALA/c,KAAK4d,cAAcb,GACnB/c,KAAK6E,QAAQkY,QAAU,IAClB/c,KAAK6E,QAAQkY,WACbA,GAEE/c,IACT,CACA,MAAA6d,GACE,MAAMC,EAAkBz4B,SAASqvB,cAAc,OAC/CoJ,EAAgBC,UAAY/d,KAAKge,eAAehe,KAAK6E,QAAQsY,UAC7D,IAAK,MAAOpjB,EAAUkkB,KAASjhC,OAAOmkB,QAAQnB,KAAK6E,QAAQkY,SACzD/c,KAAKke,YAAYJ,EAAiBG,EAAMlkB,GAE1C,MAAMojB,EAAWW,EAAgBhY,SAAS,GACpCkX,EAAahd,KAAKyd,yBAAyBzd,KAAK6E,QAAQmY,YAI9D,OAHIA,GACFG,EAAS9hB,UAAU5E,OAAOumB,EAAW96B,MAAM,MAEtCi7B,CACT,CAGA,gBAAAlZ,CAAiBH,GACfa,MAAMV,iBAAiBH,GACvB9D,KAAK4d,cAAc9Z,EAAOiZ,QAC5B,CACA,aAAAa,CAAcO,GACZ,IAAK,MAAOpkB,EAAUgjB,KAAY//B,OAAOmkB,QAAQgd,GAC/CxZ,MAAMV,iBAAiB,CACrBlK,WACAujB,MAAOP,GACNM,GAEP,CACA,WAAAa,CAAYf,EAAUJ,EAAShjB,GAC7B,MAAMqkB,EAAkBxY,GAAeC,QAAQ9L,EAAUojB,GACpDiB,KAGLrB,EAAU/c,KAAKyd,yBAAyBV,IAKpC,GAAUA,GACZ/c,KAAKqe,sBAAsB3jB,GAAWqiB,GAAUqB,GAG9Cpe,KAAK6E,QAAQhY,KACfuxB,EAAgBL,UAAY/d,KAAKge,eAAejB,GAGlDqB,EAAgBE,YAAcvB,EAX5BqB,EAAgBzkB,SAYpB,CACA,cAAAqkB,CAAeG,GACb,OAAOne,KAAK6E,QAAQoY,SApJxB,SAAsBsB,EAAYzB,EAAW0B,GAC3C,IAAKD,EAAW7tB,OACd,OAAO6tB,EAET,GAAIC,GAAgD,mBAArBA,EAC7B,OAAOA,EAAiBD,GAE1B,MACME,GADY,IAAI7+B,OAAO8+B,WACKC,gBAAgBJ,EAAY,aACxD19B,EAAW,GAAGlC,UAAU8/B,EAAgBvyB,KAAKkU,iBAAiB,MACpE,IAAK,MAAM7gB,KAAWsB,EAAU,CAC9B,MAAM+9B,EAAcr/B,EAAQC,SAASC,cACrC,IAAKzC,OAAO4D,KAAKk8B,GAAW1b,SAASwd,GAAc,CACjDr/B,EAAQoa,SACR,QACF,CACA,MAAMklB,EAAgB,GAAGlgC,UAAUY,EAAQ0B,YACrC69B,EAAoB,GAAGngC,OAAOm+B,EAAU,MAAQ,GAAIA,EAAU8B,IAAgB,IACpF,IAAK,MAAM78B,KAAa88B,EACjBtC,GAAiBx6B,EAAW+8B,IAC/Bv/B,EAAQ4B,gBAAgBY,EAAUvC,SAGxC,CACA,OAAOi/B,EAAgBvyB,KAAK6xB,SAC9B,CA2HmCgB,CAAaZ,EAAKne,KAAK6E,QAAQiY,UAAW9c,KAAK6E,QAAQqY,YAAciB,CACtG,CACA,wBAAAV,CAAyBU,GACvB,OAAOthB,GAAQshB,EAAK,CAACne,MACvB,CACA,qBAAAqe,CAAsB9+B,EAAS6+B,GAC7B,GAAIpe,KAAK6E,QAAQhY,KAGf,OAFAuxB,EAAgBL,UAAY,QAC5BK,EAAgBzJ,OAAOp1B,GAGzB6+B,EAAgBE,YAAc/+B,EAAQ++B,WACxC,EAeF,MACMU,GAAwB,IAAI1oB,IAAI,CAAC,WAAY,YAAa,eAC1D2oB,GAAoB,OAEpBC,GAAoB,OAEpBC,GAAiB,SACjBC,GAAmB,gBACnBC,GAAgB,QAChBC,GAAgB,QAahBC,GAAgB,CACpBC,KAAM,OACNC,IAAK,MACLC,MAAOzjB,KAAU,OAAS,QAC1B0jB,OAAQ,SACRC,KAAM3jB,KAAU,QAAU,QAEtB4jB,GAAY,CAChB/C,UAAWnC,GACXmF,WAAW,EACX7xB,SAAU,kBACV8xB,WAAW,EACXC,YAAa,GACbC,MAAO,EACPjwB,mBAAoB,CAAC,MAAO,QAAS,SAAU,QAC/CnD,MAAM,EACN7E,OAAQ,CAAC,EAAG,GACZtJ,UAAW,MACXmzB,aAAc,KACdoL,UAAU,EACVC,WAAY,KACZnjB,UAAU,EACVojB,SAAU,+GACV+C,MAAO,GACPte,QAAS,eAELue,GAAgB,CACpBrD,UAAW,SACXgD,UAAW,UACX7xB,SAAU,mBACV8xB,UAAW,2BACXC,YAAa,oBACbC,MAAO,kBACPjwB,mBAAoB,QACpBnD,KAAM,UACN7E,OAAQ,0BACRtJ,UAAW,oBACXmzB,aAAc,yBACdoL,SAAU,UACVC,WAAY,kBACZnjB,SAAU,mBACVojB,SAAU,SACV+C,MAAO,4BACPte,QAAS,UAOX,MAAMwe,WAAgB1b,GACpB,WAAAP,CAAY5kB,EAASukB,GACnB,QAAsB,IAAX,EACT,MAAM,IAAIU,UAAU,+DAEtBG,MAAMplB,EAASukB,GAGf9D,KAAKqgB,YAAa,EAClBrgB,KAAKsgB,SAAW,EAChBtgB,KAAKugB,WAAa,KAClBvgB,KAAKwgB,eAAiB,CAAC,EACvBxgB,KAAKgS,QAAU,KACfhS,KAAKygB,iBAAmB,KACxBzgB,KAAK0gB,YAAc,KAGnB1gB,KAAK2gB,IAAM,KACX3gB,KAAK4gB,gBACA5gB,KAAK6E,QAAQ9K,UAChBiG,KAAK6gB,WAET,CAGA,kBAAWnd,GACT,OAAOmc,EACT,CACA,sBAAWlc,GACT,OAAOwc,EACT,CACA,eAAW5jB,GACT,MAxGW,SAyGb,CAGA,MAAAukB,GACE9gB,KAAKqgB,YAAa,CACpB,CACA,OAAAU,GACE/gB,KAAKqgB,YAAa,CACpB,CACA,aAAAW,GACEhhB,KAAKqgB,YAAcrgB,KAAKqgB,UAC1B,CACA,MAAA3Y,GACO1H,KAAKqgB,aAGVrgB,KAAKwgB,eAAeS,OAASjhB,KAAKwgB,eAAeS,MAC7CjhB,KAAKwP,WACPxP,KAAKkhB,SAGPlhB,KAAKmhB,SACP,CACA,OAAApc,GACEgI,aAAa/M,KAAKsgB,UAClB/f,GAAaC,IAAIR,KAAK4E,SAAS5J,QAAQmkB,IAAiBC,GAAkBpf,KAAKohB,mBAC3EphB,KAAK4E,SAASpJ,aAAa,2BAC7BwE,KAAK4E,SAASxjB,aAAa,QAAS4e,KAAK4E,SAASpJ,aAAa,2BAEjEwE,KAAKqhB,iBACL1c,MAAMI,SACR,CACA,IAAA2K,GACE,GAAoC,SAAhC1P,KAAK4E,SAAS7jB,MAAM6wB,QACtB,MAAM,IAAIhO,MAAM,uCAElB,IAAM5D,KAAKshB,mBAAoBthB,KAAKqgB,WAClC,OAEF,MAAM/G,EAAY/Y,GAAaqB,QAAQ5B,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UAlItD,SAoIX+b,GADa9lB,GAAeuE,KAAK4E,WACL5E,KAAK4E,SAAS9kB,cAAcwF,iBAAiBd,SAASwb,KAAK4E,UAC7F,GAAI0U,EAAUtX,mBAAqBuf,EACjC,OAIFvhB,KAAKqhB,iBACL,MAAMV,EAAM3gB,KAAKwhB,iBACjBxhB,KAAK4E,SAASxjB,aAAa,mBAAoBu/B,EAAInlB,aAAa,OAChE,MAAM,UACJukB,GACE/f,KAAK6E,QAYT,GAXK7E,KAAK4E,SAAS9kB,cAAcwF,gBAAgBd,SAASwb,KAAK2gB,OAC7DZ,EAAUpL,OAAOgM,GACjBpgB,GAAaqB,QAAQ5B,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UAhJpC,cAkJnBxF,KAAKgS,QAAUhS,KAAKqS,cAAcsO,GAClCA,EAAItlB,UAAU5E,IAAIyoB,IAMd,iBAAkB75B,SAASC,gBAC7B,IAAK,MAAM/F,IAAW,GAAGZ,UAAU0G,SAAS6G,KAAK4Z,UAC/CvF,GAAac,GAAG9hB,EAAS,YAAaqc,IAU1CoE,KAAKmF,gBAPY,KACf5E,GAAaqB,QAAQ5B,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UAhKrC,WAiKQ,IAApBxF,KAAKugB,YACPvgB,KAAKkhB,SAEPlhB,KAAKugB,YAAa,CAAK,GAEKvgB,KAAK2gB,IAAK3gB,KAAK6N,cAC/C,CACA,IAAA4B,GACE,GAAKzP,KAAKwP,aAGQjP,GAAaqB,QAAQ5B,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UA/KtD,SAgLHxD,iBAAd,CAQA,GALYhC,KAAKwhB,iBACbnmB,UAAU1B,OAAOulB,IAIjB,iBAAkB75B,SAASC,gBAC7B,IAAK,MAAM/F,IAAW,GAAGZ,UAAU0G,SAAS6G,KAAK4Z,UAC/CvF,GAAaC,IAAIjhB,EAAS,YAAaqc,IAG3CoE,KAAKwgB,eAA4B,OAAI,EACrCxgB,KAAKwgB,eAAelB,KAAiB,EACrCtf,KAAKwgB,eAAenB,KAAiB,EACrCrf,KAAKugB,WAAa,KAYlBvgB,KAAKmF,gBAVY,KACXnF,KAAKyhB,yBAGJzhB,KAAKugB,YACRvgB,KAAKqhB,iBAEPrhB,KAAK4E,SAASzjB,gBAAgB,oBAC9Bof,GAAaqB,QAAQ5B,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UAzMpC,WAyM8D,GAEnDxF,KAAK2gB,IAAK3gB,KAAK6N,cA1B7C,CA2BF,CACA,MAAA9iB,GACMiV,KAAKgS,SACPhS,KAAKgS,QAAQjnB,QAEjB,CAGA,cAAAu2B,GACE,OAAOxgB,QAAQd,KAAK0hB,YACtB,CACA,cAAAF,GAIE,OAHKxhB,KAAK2gB,MACR3gB,KAAK2gB,IAAM3gB,KAAK2hB,kBAAkB3hB,KAAK0gB,aAAe1gB,KAAK4hB,2BAEtD5hB,KAAK2gB,GACd,CACA,iBAAAgB,CAAkB5E,GAChB,MAAM4D,EAAM3gB,KAAK6hB,oBAAoB9E,GAASc,SAG9C,IAAK8C,EACH,OAAO,KAETA,EAAItlB,UAAU1B,OAAOslB,GAAmBC,IAExCyB,EAAItlB,UAAU5E,IAAI,MAAMuJ,KAAKmE,YAAY5H,aACzC,MAAMulB,EAvuGKC,KACb,GACEA,GAAU5/B,KAAK6/B,MA/BH,IA+BS7/B,KAAK8/B,gBACnB58B,SAAS68B,eAAeH,IACjC,OAAOA,CAAM,EAmuGGI,CAAOniB,KAAKmE,YAAY5H,MAAM1c,WAK5C,OAJA8gC,EAAIv/B,aAAa,KAAM0gC,GACnB9hB,KAAK6N,eACP8S,EAAItlB,UAAU5E,IAAIwoB,IAEb0B,CACT,CACA,UAAAyB,CAAWrF,GACT/c,KAAK0gB,YAAc3D,EACf/c,KAAKwP,aACPxP,KAAKqhB,iBACLrhB,KAAK0P,OAET,CACA,mBAAAmS,CAAoB9E,GAYlB,OAXI/c,KAAKygB,iBACPzgB,KAAKygB,iBAAiB9C,cAAcZ,GAEpC/c,KAAKygB,iBAAmB,IAAIlD,GAAgB,IACvCvd,KAAK6E,QAGRkY,UACAC,WAAYhd,KAAKyd,yBAAyBzd,KAAK6E,QAAQmb,eAGpDhgB,KAAKygB,gBACd,CACA,sBAAAmB,GACE,MAAO,CACL,iBAA0B5hB,KAAK0hB,YAEnC,CACA,SAAAA,GACE,OAAO1hB,KAAKyd,yBAAyBzd,KAAK6E,QAAQqb,QAAUlgB,KAAK4E,SAASpJ,aAAa,yBACzF,CAGA,4BAAA6mB,CAA6BjjB,GAC3B,OAAOY,KAAKmE,YAAYmB,oBAAoBlG,EAAMW,eAAgBC,KAAKsiB,qBACzE,CACA,WAAAzU,GACE,OAAO7N,KAAK6E,QAAQib,WAAa9f,KAAK2gB,KAAO3gB,KAAK2gB,IAAItlB,UAAU7W,SAASy6B,GAC3E,CACA,QAAAzP,GACE,OAAOxP,KAAK2gB,KAAO3gB,KAAK2gB,IAAItlB,UAAU7W,SAAS06B,GACjD,CACA,aAAA7M,CAAcsO,GACZ,MAAMjiC,EAAYme,GAAQmD,KAAK6E,QAAQnmB,UAAW,CAACshB,KAAM2gB,EAAK3gB,KAAK4E,WAC7D2d,EAAahD,GAAc7gC,EAAU+lB,eAC3C,OAAO,GAAoBzE,KAAK4E,SAAU+b,EAAK3gB,KAAKyS,iBAAiB8P,GACvE,CACA,UAAA1P,GACE,MAAM,OACJ7qB,GACEgY,KAAK6E,QACT,MAAsB,iBAAX7c,EACFA,EAAO9F,MAAM,KAAKY,KAAInF,GAAS4f,OAAO6P,SAASzvB,EAAO,MAEzC,mBAAXqK,EACF8qB,GAAc9qB,EAAO8qB,EAAY9S,KAAK4E,UAExC5c,CACT,CACA,wBAAAy1B,CAAyBU,GACvB,OAAOthB,GAAQshB,EAAK,CAACne,KAAK4E,UAC5B,CACA,gBAAA6N,CAAiB8P,GACf,MAAMxP,EAAwB,CAC5Br0B,UAAW6jC,EACXnsB,UAAW,CAAC,CACV9V,KAAM,OACNmB,QAAS,CACPuO,mBAAoBgQ,KAAK6E,QAAQ7U,qBAElC,CACD1P,KAAM,SACNmB,QAAS,CACPuG,OAAQgY,KAAK6S,eAEd,CACDvyB,KAAM,kBACNmB,QAAS,CACPwM,SAAU+R,KAAK6E,QAAQ5W,WAExB,CACD3N,KAAM,QACNmB,QAAS,CACPlC,QAAS,IAAIygB,KAAKmE,YAAY5H,eAE/B,CACDjc,KAAM,kBACNC,SAAS,EACTC,MAAO,aACPC,GAAI4J,IAGF2V,KAAKwhB,iBAAiBpgC,aAAa,wBAAyBiJ,EAAK1J,MAAMjC,UAAU,KAIvF,MAAO,IACFq0B,KACAlW,GAAQmD,KAAK6E,QAAQgN,aAAc,CAACkB,IAE3C,CACA,aAAA6N,GACE,MAAM4B,EAAWxiB,KAAK6E,QAAQjD,QAAQ1f,MAAM,KAC5C,IAAK,MAAM0f,KAAW4gB,EACpB,GAAgB,UAAZ5gB,EACFrB,GAAac,GAAGrB,KAAK4E,SAAU5E,KAAKmE,YAAYqB,UAjVlC,SAiV4DxF,KAAK6E,QAAQ9K,UAAUqF,IAC/EY,KAAKqiB,6BAA6BjjB,GAC1CsI,QAAQ,SAEb,GA3VU,WA2VN9F,EAA4B,CACrC,MAAM6gB,EAAU7gB,IAAYyd,GAAgBrf,KAAKmE,YAAYqB,UAnV5C,cAmV0ExF,KAAKmE,YAAYqB,UArV5F,WAsVVkd,EAAW9gB,IAAYyd,GAAgBrf,KAAKmE,YAAYqB,UAnV7C,cAmV2ExF,KAAKmE,YAAYqB,UArV5F,YAsVjBjF,GAAac,GAAGrB,KAAK4E,SAAU6d,EAASziB,KAAK6E,QAAQ9K,UAAUqF,IAC7D,MAAM+T,EAAUnT,KAAKqiB,6BAA6BjjB,GAClD+T,EAAQqN,eAA8B,YAAfphB,EAAMqB,KAAqB6e,GAAgBD,KAAiB,EACnFlM,EAAQgO,QAAQ,IAElB5gB,GAAac,GAAGrB,KAAK4E,SAAU8d,EAAU1iB,KAAK6E,QAAQ9K,UAAUqF,IAC9D,MAAM+T,EAAUnT,KAAKqiB,6BAA6BjjB,GAClD+T,EAAQqN,eAA8B,aAAfphB,EAAMqB,KAAsB6e,GAAgBD,IAAiBlM,EAAQvO,SAASpgB,SAAS4a,EAAMU,eACpHqT,EAAQ+N,QAAQ,GAEpB,CAEFlhB,KAAKohB,kBAAoB,KACnBphB,KAAK4E,UACP5E,KAAKyP,MACP,EAEFlP,GAAac,GAAGrB,KAAK4E,SAAS5J,QAAQmkB,IAAiBC,GAAkBpf,KAAKohB,kBAChF,CACA,SAAAP,GACE,MAAMX,EAAQlgB,KAAK4E,SAASpJ,aAAa,SACpC0kB,IAGAlgB,KAAK4E,SAASpJ,aAAa,eAAkBwE,KAAK4E,SAAS0Z,YAAY3Y,QAC1E3F,KAAK4E,SAASxjB,aAAa,aAAc8+B,GAE3ClgB,KAAK4E,SAASxjB,aAAa,yBAA0B8+B,GACrDlgB,KAAK4E,SAASzjB,gBAAgB,SAChC,CACA,MAAAggC,GACMnhB,KAAKwP,YAAcxP,KAAKugB,WAC1BvgB,KAAKugB,YAAa,GAGpBvgB,KAAKugB,YAAa,EAClBvgB,KAAK2iB,aAAY,KACX3iB,KAAKugB,YACPvgB,KAAK0P,MACP,GACC1P,KAAK6E,QAAQob,MAAMvQ,MACxB,CACA,MAAAwR,GACMlhB,KAAKyhB,yBAGTzhB,KAAKugB,YAAa,EAClBvgB,KAAK2iB,aAAY,KACV3iB,KAAKugB,YACRvgB,KAAKyP,MACP,GACCzP,KAAK6E,QAAQob,MAAMxQ,MACxB,CACA,WAAAkT,CAAY/kB,EAASglB,GACnB7V,aAAa/M,KAAKsgB,UAClBtgB,KAAKsgB,SAAWziB,WAAWD,EAASglB,EACtC,CACA,oBAAAnB,GACE,OAAOzkC,OAAOmiB,OAAOa,KAAKwgB,gBAAgBpf,UAAS,EACrD,CACA,UAAAyC,CAAWC,GACT,MAAM+e,EAAiB7f,GAAYG,kBAAkBnD,KAAK4E,UAC1D,IAAK,MAAMke,KAAiB9lC,OAAO4D,KAAKiiC,GAClC7D,GAAsBroB,IAAImsB,WACrBD,EAAeC,GAU1B,OAPAhf,EAAS,IACJ+e,KACmB,iBAAX/e,GAAuBA,EAASA,EAAS,CAAC,GAEvDA,EAAS9D,KAAK+D,gBAAgBD,GAC9BA,EAAS9D,KAAKgE,kBAAkBF,GAChC9D,KAAKiE,iBAAiBH,GACfA,CACT,CACA,iBAAAE,CAAkBF,GAchB,OAbAA,EAAOic,WAAiC,IAArBjc,EAAOic,UAAsB16B,SAAS6G,KAAOwO,GAAWoJ,EAAOic,WACtD,iBAAjBjc,EAAOmc,QAChBnc,EAAOmc,MAAQ,CACbvQ,KAAM5L,EAAOmc,MACbxQ,KAAM3L,EAAOmc,QAGW,iBAAjBnc,EAAOoc,QAChBpc,EAAOoc,MAAQpc,EAAOoc,MAAMrgC,YAEA,iBAAnBikB,EAAOiZ,UAChBjZ,EAAOiZ,QAAUjZ,EAAOiZ,QAAQl9B,YAE3BikB,CACT,CACA,kBAAAwe,GACE,MAAMxe,EAAS,CAAC,EAChB,IAAK,MAAOhnB,EAAKa,KAAUX,OAAOmkB,QAAQnB,KAAK6E,SACzC7E,KAAKmE,YAAYT,QAAQ5mB,KAASa,IACpCmmB,EAAOhnB,GAAOa,GASlB,OANAmmB,EAAO/J,UAAW,EAClB+J,EAAOlC,QAAU,SAKVkC,CACT,CACA,cAAAud,GACMrhB,KAAKgS,UACPhS,KAAKgS,QAAQhZ,UACbgH,KAAKgS,QAAU,MAEbhS,KAAK2gB,MACP3gB,KAAK2gB,IAAIhnB,SACTqG,KAAK2gB,IAAM,KAEf,CAGA,sBAAOlkB,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO+1B,GAAQ9a,oBAAoBtF,KAAM8D,GAC/C,GAAsB,iBAAXA,EAAX,CAGA,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IAJL,CAKF,GACF,EAOF3H,GAAmBikB,IAcnB,MAGM2C,GAAY,IACb3C,GAAQ1c,QACXqZ,QAAS,GACT/0B,OAAQ,CAAC,EAAG,GACZtJ,UAAW,QACXy+B,SAAU,8IACVvb,QAAS,SAELohB,GAAgB,IACjB5C,GAAQzc,YACXoZ,QAAS,kCAOX,MAAMkG,WAAgB7C,GAEpB,kBAAW1c,GACT,OAAOqf,EACT,CACA,sBAAWpf,GACT,OAAOqf,EACT,CACA,eAAWzmB,GACT,MA7BW,SA8Bb,CAGA,cAAA+kB,GACE,OAAOthB,KAAK0hB,aAAe1hB,KAAKkjB,aAClC,CAGA,sBAAAtB,GACE,MAAO,CACL,kBAAkB5hB,KAAK0hB,YACvB,gBAAoB1hB,KAAKkjB,cAE7B,CACA,WAAAA,GACE,OAAOljB,KAAKyd,yBAAyBzd,KAAK6E,QAAQkY,QACpD,CAGA,sBAAOtgB,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO44B,GAAQ3d,oBAAoBtF,KAAM8D,GAC/C,GAAsB,iBAAXA,EAAX,CAGA,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IAJL,CAKF,GACF,EAOF3H,GAAmB8mB,IAcnB,MAEME,GAAc,gBAEdC,GAAiB,WAAWD,KAC5BE,GAAc,QAAQF,KACtBG,GAAwB,OAAOH,cAE/BI,GAAsB,SAEtBC,GAAwB,SAExBC,GAAqB,YAGrBC,GAAsB,GAAGD,mBAA+CA,uBAGxEE,GAAY,CAChB37B,OAAQ,KAER47B,WAAY,eACZC,cAAc,EACdt3B,OAAQ,KACRu3B,UAAW,CAAC,GAAK,GAAK,IAElBC,GAAgB,CACpB/7B,OAAQ,gBAER47B,WAAY,SACZC,aAAc,UACdt3B,OAAQ,UACRu3B,UAAW,SAOb,MAAME,WAAkBtf,GACtB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GAGf9D,KAAKikB,aAAe,IAAI/yB,IACxB8O,KAAKkkB,oBAAsB,IAAIhzB,IAC/B8O,KAAKmkB,aAA6D,YAA9Cl/B,iBAAiB+a,KAAK4E,UAAU5Y,UAA0B,KAAOgU,KAAK4E,SAC1F5E,KAAKokB,cAAgB,KACrBpkB,KAAKqkB,UAAY,KACjBrkB,KAAKskB,oBAAsB,CACzBC,gBAAiB,EACjBC,gBAAiB,GAEnBxkB,KAAKykB,SACP,CAGA,kBAAW/gB,GACT,OAAOigB,EACT,CACA,sBAAWhgB,GACT,OAAOogB,EACT,CACA,eAAWxnB,GACT,MAhEW,WAiEb,CAGA,OAAAkoB,GACEzkB,KAAK0kB,mCACL1kB,KAAK2kB,2BACD3kB,KAAKqkB,UACPrkB,KAAKqkB,UAAUO,aAEf5kB,KAAKqkB,UAAYrkB,KAAK6kB,kBAExB,IAAK,MAAMC,KAAW9kB,KAAKkkB,oBAAoB/kB,SAC7Ca,KAAKqkB,UAAUU,QAAQD,EAE3B,CACA,OAAA/f,GACE/E,KAAKqkB,UAAUO,aACfjgB,MAAMI,SACR,CAGA,iBAAAf,CAAkBF,GAShB,OAPAA,EAAOvX,OAASmO,GAAWoJ,EAAOvX,SAAWlH,SAAS6G,KAGtD4X,EAAO8f,WAAa9f,EAAO9b,OAAS,GAAG8b,EAAO9b,oBAAsB8b,EAAO8f,WAC3C,iBAArB9f,EAAOggB,YAChBhgB,EAAOggB,UAAYhgB,EAAOggB,UAAU5hC,MAAM,KAAKY,KAAInF,GAAS4f,OAAOC,WAAW7f,MAEzEmmB,CACT,CACA,wBAAA6gB,GACO3kB,KAAK6E,QAAQgf,eAKlBtjB,GAAaC,IAAIR,KAAK6E,QAAQtY,OAAQ82B,IACtC9iB,GAAac,GAAGrB,KAAK6E,QAAQtY,OAAQ82B,GAAaG,IAAuBpkB,IACvE,MAAM4lB,EAAoBhlB,KAAKkkB,oBAAoB/mC,IAAIiiB,EAAM7S,OAAOtB,MACpE,GAAI+5B,EAAmB,CACrB5lB,EAAMkD,iBACN,MAAM3G,EAAOqE,KAAKmkB,cAAgBvkC,OAC5BmE,EAASihC,EAAkB3gC,UAAY2b,KAAK4E,SAASvgB,UAC3D,GAAIsX,EAAKspB,SAKP,YAJAtpB,EAAKspB,SAAS,CACZtjC,IAAKoC,EACLmhC,SAAU,WAMdvpB,EAAKlQ,UAAY1H,CACnB,KAEJ,CACA,eAAA8gC,GACE,MAAMpjC,EAAU,CACdka,KAAMqE,KAAKmkB,aACXL,UAAW9jB,KAAK6E,QAAQif,UACxBF,WAAY5jB,KAAK6E,QAAQ+e,YAE3B,OAAO,IAAIuB,sBAAqBhkB,GAAWnB,KAAKolB,kBAAkBjkB,IAAU1f,EAC9E,CAGA,iBAAA2jC,CAAkBjkB,GAChB,MAAMkkB,EAAgB/H,GAAStd,KAAKikB,aAAa9mC,IAAI,IAAImgC,EAAM/wB,OAAO4N,MAChEob,EAAW+H,IACftd,KAAKskB,oBAAoBC,gBAAkBjH,EAAM/wB,OAAOlI,UACxD2b,KAAKslB,SAASD,EAAc/H,GAAO,EAE/BkH,GAAmBxkB,KAAKmkB,cAAgB9+B,SAASC,iBAAiBmG,UAClE85B,EAAkBf,GAAmBxkB,KAAKskB,oBAAoBE,gBACpExkB,KAAKskB,oBAAoBE,gBAAkBA,EAC3C,IAAK,MAAMlH,KAASnc,EAAS,CAC3B,IAAKmc,EAAMkI,eAAgB,CACzBxlB,KAAKokB,cAAgB,KACrBpkB,KAAKylB,kBAAkBJ,EAAc/H,IACrC,QACF,CACA,MAAMoI,EAA2BpI,EAAM/wB,OAAOlI,WAAa2b,KAAKskB,oBAAoBC,gBAEpF,GAAIgB,GAAmBG,GAGrB,GAFAnQ,EAAS+H,IAEJkH,EACH,YAMCe,GAAoBG,GACvBnQ,EAAS+H,EAEb,CACF,CACA,gCAAAoH,GACE1kB,KAAKikB,aAAe,IAAI/yB,IACxB8O,KAAKkkB,oBAAsB,IAAIhzB,IAC/B,MAAMy0B,EAAc/f,GAAezT,KAAKqxB,GAAuBxjB,KAAK6E,QAAQtY,QAC5E,IAAK,MAAMq5B,KAAUD,EAAa,CAEhC,IAAKC,EAAO36B,MAAQiQ,GAAW0qB,GAC7B,SAEF,MAAMZ,EAAoBpf,GAAeC,QAAQggB,UAAUD,EAAO36B,MAAO+U,KAAK4E,UAG1EjK,GAAUqqB,KACZhlB,KAAKikB,aAAalyB,IAAI8zB,UAAUD,EAAO36B,MAAO26B,GAC9C5lB,KAAKkkB,oBAAoBnyB,IAAI6zB,EAAO36B,KAAM+5B,GAE9C,CACF,CACA,QAAAM,CAAS/4B,GACHyT,KAAKokB,gBAAkB73B,IAG3ByT,KAAKylB,kBAAkBzlB,KAAK6E,QAAQtY,QACpCyT,KAAKokB,cAAgB73B,EACrBA,EAAO8O,UAAU5E,IAAI8sB,IACrBvjB,KAAK8lB,iBAAiBv5B,GACtBgU,GAAaqB,QAAQ5B,KAAK4E,SAAUwe,GAAgB,CAClDtjB,cAAevT,IAEnB,CACA,gBAAAu5B,CAAiBv5B,GAEf,GAAIA,EAAO8O,UAAU7W,SA9LQ,iBA+L3BohB,GAAeC,QArLc,mBAqLsBtZ,EAAOyO,QAtLtC,cAsLkEK,UAAU5E,IAAI8sB,SAGtG,IAAK,MAAMwC,KAAangB,GAAeI,QAAQzZ,EA9LnB,qBAiM1B,IAAK,MAAMxJ,KAAQ6iB,GAAeM,KAAK6f,EAAWrC,IAChD3gC,EAAKsY,UAAU5E,IAAI8sB,GAGzB,CACA,iBAAAkC,CAAkBhhC,GAChBA,EAAO4W,UAAU1B,OAAO4pB,IACxB,MAAMyC,EAAcpgB,GAAezT,KAAK,GAAGqxB,MAAyBD,KAAuB9+B,GAC3F,IAAK,MAAM9E,KAAQqmC,EACjBrmC,EAAK0b,UAAU1B,OAAO4pB,GAE1B,CAGA,sBAAO9mB,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAO25B,GAAU1e,oBAAoBtF,KAAM8D,GACjD,GAAsB,iBAAXA,EAAX,CAGA,QAAqB/K,IAAjB1O,EAAKyZ,IAAyBA,EAAOrC,WAAW,MAAmB,gBAAXqC,EAC1D,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IAJL,CAKF,GACF,EAOFvD,GAAac,GAAGzhB,OAAQ0jC,IAAuB,KAC7C,IAAK,MAAM2C,KAAOrgB,GAAezT,KApOT,0BAqOtB6xB,GAAU1e,oBAAoB2gB,EAChC,IAOF9pB,GAAmB6nB,IAcnB,MAEMkC,GAAc,UACdC,GAAe,OAAOD,KACtBE,GAAiB,SAASF,KAC1BG,GAAe,OAAOH,KACtBI,GAAgB,QAAQJ,KACxBK,GAAuB,QAAQL,KAC/BM,GAAgB,UAAUN,KAC1BO,GAAsB,OAAOP,KAC7BQ,GAAiB,YACjBC,GAAkB,aAClBC,GAAe,UACfC,GAAiB,YACjBC,GAAW,OACXC,GAAU,MACVC,GAAoB,SACpBC,GAAoB,OACpBC,GAAoB,OAEpBC,GAA2B,mBAE3BC,GAA+B,QAAQD,MAIvCE,GAAuB,2EACvBC,GAAsB,YAFOF,uBAAiDA,mBAA6CA,OAE/EC,KAC5CE,GAA8B,IAAIP,8BAA6CA,+BAA8CA,4BAMnI,MAAMQ,WAAY9iB,GAChB,WAAAP,CAAY5kB,GACVolB,MAAMplB,GACNygB,KAAKiS,QAAUjS,KAAK4E,SAAS5J,QAdN,uCAelBgF,KAAKiS,UAOVjS,KAAKynB,sBAAsBznB,KAAKiS,QAASjS,KAAK0nB,gBAC9CnnB,GAAac,GAAGrB,KAAK4E,SAAU4hB,IAAepnB,GAASY,KAAK0M,SAAStN,KACvE,CAGA,eAAW7C,GACT,MAnDW,KAoDb,CAGA,IAAAmT,GAEE,MAAMiY,EAAY3nB,KAAK4E,SACvB,GAAI5E,KAAK4nB,cAAcD,GACrB,OAIF,MAAME,EAAS7nB,KAAK8nB,iBACdC,EAAYF,EAAStnB,GAAaqB,QAAQimB,EAAQ1B,GAAc,CACpErmB,cAAe6nB,IACZ,KACapnB,GAAaqB,QAAQ+lB,EAAWtB,GAAc,CAC9DvmB,cAAe+nB,IAEH7lB,kBAAoB+lB,GAAaA,EAAU/lB,mBAGzDhC,KAAKgoB,YAAYH,EAAQF,GACzB3nB,KAAKioB,UAAUN,EAAWE,GAC5B,CAGA,SAAAI,CAAU1oC,EAAS2oC,GACZ3oC,IAGLA,EAAQ8b,UAAU5E,IAAIuwB,IACtBhnB,KAAKioB,UAAUriB,GAAec,uBAAuBnnB,IAcrDygB,KAAKmF,gBAZY,KACsB,QAAjC5lB,EAAQic,aAAa,SAIzBjc,EAAQ4B,gBAAgB,YACxB5B,EAAQ6B,aAAa,iBAAiB,GACtC4e,KAAKmoB,gBAAgB5oC,GAAS,GAC9BghB,GAAaqB,QAAQriB,EAAS+mC,GAAe,CAC3CxmB,cAAeooB,KAPf3oC,EAAQ8b,UAAU5E,IAAIywB,GAQtB,GAE0B3nC,EAASA,EAAQ8b,UAAU7W,SAASyiC,KACpE,CACA,WAAAe,CAAYzoC,EAAS2oC,GACd3oC,IAGLA,EAAQ8b,UAAU1B,OAAOqtB,IACzBznC,EAAQm7B,OACR1a,KAAKgoB,YAAYpiB,GAAec,uBAAuBnnB,IAcvDygB,KAAKmF,gBAZY,KACsB,QAAjC5lB,EAAQic,aAAa,SAIzBjc,EAAQ6B,aAAa,iBAAiB,GACtC7B,EAAQ6B,aAAa,WAAY,MACjC4e,KAAKmoB,gBAAgB5oC,GAAS,GAC9BghB,GAAaqB,QAAQriB,EAAS6mC,GAAgB,CAC5CtmB,cAAeooB,KAPf3oC,EAAQ8b,UAAU1B,OAAOutB,GAQzB,GAE0B3nC,EAASA,EAAQ8b,UAAU7W,SAASyiC,KACpE,CACA,QAAAva,CAAStN,GACP,IAAK,CAACsnB,GAAgBC,GAAiBC,GAAcC,GAAgBC,GAAUC,IAAS3lB,SAAShC,EAAMtiB,KACrG,OAEFsiB,EAAMuU,kBACNvU,EAAMkD,iBACN,MAAMwD,EAAW9F,KAAK0nB,eAAevhC,QAAO5G,IAAY2b,GAAW3b,KACnE,IAAI6oC,EACJ,GAAI,CAACtB,GAAUC,IAAS3lB,SAAShC,EAAMtiB,KACrCsrC,EAAoBtiB,EAAS1G,EAAMtiB,MAAQgqC,GAAW,EAAIhhB,EAASpV,OAAS,OACvE,CACL,MAAM2c,EAAS,CAACsZ,GAAiBE,IAAgBzlB,SAAShC,EAAMtiB,KAChEsrC,EAAoBtqB,GAAqBgI,EAAU1G,EAAM7S,OAAQ8gB,GAAQ,EAC3E,CACI+a,IACFA,EAAkB9V,MAAM,CACtB+V,eAAe,IAEjBb,GAAIliB,oBAAoB8iB,GAAmB1Y,OAE/C,CACA,YAAAgY,GAEE,OAAO9hB,GAAezT,KAAKm1B,GAAqBtnB,KAAKiS,QACvD,CACA,cAAA6V,GACE,OAAO9nB,KAAK0nB,eAAev1B,MAAKzN,GAASsb,KAAK4nB,cAAcljC,MAAW,IACzE,CACA,qBAAA+iC,CAAsBhjC,EAAQqhB,GAC5B9F,KAAKsoB,yBAAyB7jC,EAAQ,OAAQ,WAC9C,IAAK,MAAMC,KAASohB,EAClB9F,KAAKuoB,6BAA6B7jC,EAEtC,CACA,4BAAA6jC,CAA6B7jC,GAC3BA,EAAQsb,KAAKwoB,iBAAiB9jC,GAC9B,MAAM+jC,EAAWzoB,KAAK4nB,cAAcljC,GAC9BgkC,EAAY1oB,KAAK2oB,iBAAiBjkC,GACxCA,EAAMtD,aAAa,gBAAiBqnC,GAChCC,IAAchkC,GAChBsb,KAAKsoB,yBAAyBI,EAAW,OAAQ,gBAE9CD,GACH/jC,EAAMtD,aAAa,WAAY,MAEjC4e,KAAKsoB,yBAAyB5jC,EAAO,OAAQ,OAG7Csb,KAAK4oB,mCAAmClkC,EAC1C,CACA,kCAAAkkC,CAAmClkC,GACjC,MAAM6H,EAASqZ,GAAec,uBAAuBhiB,GAChD6H,IAGLyT,KAAKsoB,yBAAyB/7B,EAAQ,OAAQ,YAC1C7H,EAAMyV,IACR6F,KAAKsoB,yBAAyB/7B,EAAQ,kBAAmB,GAAG7H,EAAMyV,MAEtE,CACA,eAAAguB,CAAgB5oC,EAASspC,GACvB,MAAMH,EAAY1oB,KAAK2oB,iBAAiBppC,GACxC,IAAKmpC,EAAUrtB,UAAU7W,SApKN,YAqKjB,OAEF,MAAMkjB,EAAS,CAAC3N,EAAUia,KACxB,MAAMz0B,EAAUqmB,GAAeC,QAAQ9L,EAAU2uB,GAC7CnpC,GACFA,EAAQ8b,UAAUqM,OAAOsM,EAAW6U,EACtC,EAEFnhB,EAAOyf,GAA0BH,IACjCtf,EA5K2B,iBA4KIwf,IAC/BwB,EAAUtnC,aAAa,gBAAiBynC,EAC1C,CACA,wBAAAP,CAAyB/oC,EAASwC,EAAWpE,GACtC4B,EAAQgc,aAAaxZ,IACxBxC,EAAQ6B,aAAaW,EAAWpE,EAEpC,CACA,aAAAiqC,CAAczY,GACZ,OAAOA,EAAK9T,UAAU7W,SAASwiC,GACjC,CAGA,gBAAAwB,CAAiBrZ,GACf,OAAOA,EAAKpJ,QAAQuhB,IAAuBnY,EAAOvJ,GAAeC,QAAQyhB,GAAqBnY,EAChG,CAGA,gBAAAwZ,CAAiBxZ,GACf,OAAOA,EAAKnU,QA5LO,gCA4LoBmU,CACzC,CAGA,sBAAO1S,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAOm9B,GAAIliB,oBAAoBtF,MACrC,GAAsB,iBAAX8D,EAAX,CAGA,QAAqB/K,IAAjB1O,EAAKyZ,IAAyBA,EAAOrC,WAAW,MAAmB,gBAAXqC,EAC1D,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,IAJL,CAKF,GACF,EAOFvD,GAAac,GAAGhc,SAAUkhC,GAAsBc,IAAsB,SAAUjoB,GAC1E,CAAC,IAAK,QAAQgC,SAASpB,KAAKgH,UAC9B5H,EAAMkD,iBAEJpH,GAAW8E,OAGfwnB,GAAIliB,oBAAoBtF,MAAM0P,MAChC,IAKAnP,GAAac,GAAGzhB,OAAQ6mC,IAAqB,KAC3C,IAAK,MAAMlnC,KAAWqmB,GAAezT,KAAKo1B,IACxCC,GAAIliB,oBAAoB/lB,EAC1B,IAMF4c,GAAmBqrB,IAcnB,MAEMxiB,GAAY,YACZ8jB,GAAkB,YAAY9jB,KAC9B+jB,GAAiB,WAAW/jB,KAC5BgkB,GAAgB,UAAUhkB,KAC1BikB,GAAiB,WAAWjkB,KAC5BkkB,GAAa,OAAOlkB,KACpBmkB,GAAe,SAASnkB,KACxBokB,GAAa,OAAOpkB,KACpBqkB,GAAc,QAAQrkB,KAEtBskB,GAAkB,OAClBC,GAAkB,OAClBC,GAAqB,UACrB7lB,GAAc,CAClBmc,UAAW,UACX2J,SAAU,UACVxJ,MAAO,UAEHvc,GAAU,CACdoc,WAAW,EACX2J,UAAU,EACVxJ,MAAO,KAOT,MAAMyJ,WAAchlB,GAClB,WAAAP,CAAY5kB,EAASukB,GACnBa,MAAMplB,EAASukB,GACf9D,KAAKsgB,SAAW,KAChBtgB,KAAK2pB,sBAAuB,EAC5B3pB,KAAK4pB,yBAA0B,EAC/B5pB,KAAK4gB,eACP,CAGA,kBAAWld,GACT,OAAOA,EACT,CACA,sBAAWC,GACT,OAAOA,EACT,CACA,eAAWpH,GACT,MA/CS,OAgDX,CAGA,IAAAmT,GACoBnP,GAAaqB,QAAQ5B,KAAK4E,SAAUwkB,IACxCpnB,mBAGdhC,KAAK6pB,gBACD7pB,KAAK6E,QAAQib,WACf9f,KAAK4E,SAASvJ,UAAU5E,IA/CN,QAsDpBuJ,KAAK4E,SAASvJ,UAAU1B,OAAO2vB,IAC/BztB,GAAOmE,KAAK4E,UACZ5E,KAAK4E,SAASvJ,UAAU5E,IAAI8yB,GAAiBC,IAC7CxpB,KAAKmF,gBARY,KACfnF,KAAK4E,SAASvJ,UAAU1B,OAAO6vB,IAC/BjpB,GAAaqB,QAAQ5B,KAAK4E,SAAUykB,IACpCrpB,KAAK8pB,oBAAoB,GAKG9pB,KAAK4E,SAAU5E,KAAK6E,QAAQib,WAC5D,CACA,IAAArQ,GACOzP,KAAK+pB,YAGQxpB,GAAaqB,QAAQ5B,KAAK4E,SAAUskB,IACxClnB,mBAQdhC,KAAK4E,SAASvJ,UAAU5E,IAAI+yB,IAC5BxpB,KAAKmF,gBANY,KACfnF,KAAK4E,SAASvJ,UAAU5E,IAAI6yB,IAC5BtpB,KAAK4E,SAASvJ,UAAU1B,OAAO6vB,GAAoBD,IACnDhpB,GAAaqB,QAAQ5B,KAAK4E,SAAUukB,GAAa,GAGrBnpB,KAAK4E,SAAU5E,KAAK6E,QAAQib,YAC5D,CACA,OAAA/a,GACE/E,KAAK6pB,gBACD7pB,KAAK+pB,WACP/pB,KAAK4E,SAASvJ,UAAU1B,OAAO4vB,IAEjC5kB,MAAMI,SACR,CACA,OAAAglB,GACE,OAAO/pB,KAAK4E,SAASvJ,UAAU7W,SAAS+kC,GAC1C,CAIA,kBAAAO,GACO9pB,KAAK6E,QAAQ4kB,WAGdzpB,KAAK2pB,sBAAwB3pB,KAAK4pB,0BAGtC5pB,KAAKsgB,SAAWziB,YAAW,KACzBmC,KAAKyP,MAAM,GACVzP,KAAK6E,QAAQob,QAClB,CACA,cAAA+J,CAAe5qB,EAAO6qB,GACpB,OAAQ7qB,EAAMqB,MACZ,IAAK,YACL,IAAK,WAEDT,KAAK2pB,qBAAuBM,EAC5B,MAEJ,IAAK,UACL,IAAK,WAEDjqB,KAAK4pB,wBAA0BK,EAIrC,GAAIA,EAEF,YADAjqB,KAAK6pB,gBAGP,MAAMvc,EAAclO,EAAMU,cACtBE,KAAK4E,WAAa0I,GAAetN,KAAK4E,SAASpgB,SAAS8oB,IAG5DtN,KAAK8pB,oBACP,CACA,aAAAlJ,GACErgB,GAAac,GAAGrB,KAAK4E,SAAUkkB,IAAiB1pB,GAASY,KAAKgqB,eAAe5qB,GAAO,KACpFmB,GAAac,GAAGrB,KAAK4E,SAAUmkB,IAAgB3pB,GAASY,KAAKgqB,eAAe5qB,GAAO,KACnFmB,GAAac,GAAGrB,KAAK4E,SAAUokB,IAAe5pB,GAASY,KAAKgqB,eAAe5qB,GAAO,KAClFmB,GAAac,GAAGrB,KAAK4E,SAAUqkB,IAAgB7pB,GAASY,KAAKgqB,eAAe5qB,GAAO,IACrF,CACA,aAAAyqB,GACE9c,aAAa/M,KAAKsgB,UAClBtgB,KAAKsgB,SAAW,IAClB,CAGA,sBAAO7jB,CAAgBqH,GACrB,OAAO9D,KAAKuH,MAAK,WACf,MAAMld,EAAOq/B,GAAMpkB,oBAAoBtF,KAAM8D,GAC7C,GAAsB,iBAAXA,EAAqB,CAC9B,QAA4B,IAAjBzZ,EAAKyZ,GACd,MAAM,IAAIU,UAAU,oBAAoBV,MAE1CzZ,EAAKyZ,GAAQ9D,KACf,CACF,GACF,ECr0IK,SAASkqB,GAAc7tB,GACD,WAAvBhX,SAASuX,WAAyBP,IACjChX,SAASyF,iBAAiB,mBAAoBuR,EACrD,CDy0IAuK,GAAqB8iB,IAMrBvtB,GAAmButB,IEtyInBQ,IAvCA,WAC2B,GAAG93B,MAAM5U,KAChC6H,SAAS+a,iBAAiB,+BAETtd,KAAI,SAAUqnC,GAC/B,OAAO,IAAI/J,GAAQ+J,EAAkB,CAAElK,MAAO,CAAEvQ,KAAM,IAAKD,KAAM,MACnE,GACF,IAiCAya,IA5BA,WACY7kC,SAAS68B,eAAe,mBAC9Bp3B,iBAAiB,SAAS,WAC5BzF,SAAS6G,KAAKT,UAAY,EAC1BpG,SAASC,gBAAgBmG,UAAY,CACvC,GACF,IAuBAy+B,IArBA,WACE,IAAIE,EAAM/kC,SAAS68B,eAAe,mBAC9BmI,EAAShlC,SACVilC,uBAAuB,aAAa,GACpChnC,wBACH1D,OAAOkL,iBAAiB,UAAU,WAC5BkV,KAAKuqB,UAAYvqB,KAAKwqB,SAAWxqB,KAAKwqB,QAAUH,EAAOzsC,OACzDwsC,EAAIrpC,MAAM6wB,QAAU,QAEpBwY,EAAIrpC,MAAM6wB,QAAU,OAEtB5R,KAAKuqB,UAAYvqB,KAAKwqB,OACxB,GACF","sources":["webpack://pydata_sphinx_theme/webpack/bootstrap","webpack://pydata_sphinx_theme/webpack/runtime/define property getters","webpack://pydata_sphinx_theme/webpack/runtime/hasOwnProperty shorthand","webpack://pydata_sphinx_theme/webpack/runtime/make namespace object","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/enums.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/applyStyles.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getBasePlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/math.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/userAgent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/contains.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isTableElement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getParentNode.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/within.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/mergePaddingObject.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getFreshSideObject.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/expandToHashMap.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/arrow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getVariation.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/computeStyles.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/eventListeners.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getOppositePlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/rectToClientRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/computeOffsets.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/detectOverflow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/flip.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/hide.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/offset.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/popperOffsets.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/preventOverflow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getAltAxis.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/orderModifiers.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/createPopper.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/debounce.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/mergeByName.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/popper.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/popper-lite.js","webpack://pydata_sphinx_theme/./node_modules/bootstrap/dist/js/bootstrap.esm.js","webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/mixin.js","webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/bootstrap.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export var top = 'top';\nexport var bottom = 'bottom';\nexport var right = 'right';\nexport var left = 'left';\nexport var auto = 'auto';\nexport var basePlacements = [top, bottom, right, left];\nexport var start = 'start';\nexport var end = 'end';\nexport var clippingParents = 'clippingParents';\nexport var viewport = 'viewport';\nexport var popper = 'popper';\nexport var reference = 'reference';\nexport var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {\n return acc.concat([placement + \"-\" + start, placement + \"-\" + end]);\n}, []);\nexport var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {\n return acc.concat([placement, placement + \"-\" + start, placement + \"-\" + end]);\n}, []); // modifiers that need to read the DOM\n\nexport var beforeRead = 'beforeRead';\nexport var read = 'read';\nexport var afterRead = 'afterRead'; // pure-logic modifiers\n\nexport var beforeMain = 'beforeMain';\nexport var main = 'main';\nexport var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)\n\nexport var beforeWrite = 'beforeWrite';\nexport var write = 'write';\nexport var afterWrite = 'afterWrite';\nexport var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];","export default function getNodeName(element) {\n return element ? (element.nodeName || '').toLowerCase() : null;\n}","export default function getWindow(node) {\n if (node == null) {\n return window;\n }\n\n if (node.toString() !== '[object Window]') {\n var ownerDocument = node.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView || window : window;\n }\n\n return node;\n}","import getWindow from \"./getWindow.js\";\n\nfunction isElement(node) {\n var OwnElement = getWindow(node).Element;\n return node instanceof OwnElement || node instanceof Element;\n}\n\nfunction isHTMLElement(node) {\n var OwnElement = getWindow(node).HTMLElement;\n return node instanceof OwnElement || node instanceof HTMLElement;\n}\n\nfunction isShadowRoot(node) {\n // IE 11 has no ShadowRoot\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n\n var OwnElement = getWindow(node).ShadowRoot;\n return node instanceof OwnElement || node instanceof ShadowRoot;\n}\n\nexport { isElement, isHTMLElement, isShadowRoot };","import getNodeName from \"../dom-utils/getNodeName.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // This modifier takes the styles prepared by the `computeStyles` modifier\n// and applies them to the HTMLElements such as popper and arrow\n\nfunction applyStyles(_ref) {\n var state = _ref.state;\n Object.keys(state.elements).forEach(function (name) {\n var style = state.styles[name] || {};\n var attributes = state.attributes[name] || {};\n var element = state.elements[name]; // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n } // Flow doesn't support to extend this property, but it's the most\n // effective way to apply styles to an HTMLElement\n // $FlowFixMe[cannot-write]\n\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (name) {\n var value = attributes[name];\n\n if (value === false) {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value === true ? '' : value);\n }\n });\n });\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state;\n var initialStyles = {\n popper: {\n position: state.options.strategy,\n left: '0',\n top: '0',\n margin: '0'\n },\n arrow: {\n position: 'absolute'\n },\n reference: {}\n };\n Object.assign(state.elements.popper.style, initialStyles.popper);\n state.styles = initialStyles;\n\n if (state.elements.arrow) {\n Object.assign(state.elements.arrow.style, initialStyles.arrow);\n }\n\n return function () {\n Object.keys(state.elements).forEach(function (name) {\n var element = state.elements[name];\n var attributes = state.attributes[name] || {};\n var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them\n\n var style = styleProperties.reduce(function (style, property) {\n style[property] = '';\n return style;\n }, {}); // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n }\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (attribute) {\n element.removeAttribute(attribute);\n });\n });\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'applyStyles',\n enabled: true,\n phase: 'write',\n fn: applyStyles,\n effect: effect,\n requires: ['computeStyles']\n};","import { auto } from \"../enums.js\";\nexport default function getBasePlacement(placement) {\n return placement.split('-')[0];\n}","export var max = Math.max;\nexport var min = Math.min;\nexport var round = Math.round;","export default function getUAString() {\n var uaData = navigator.userAgentData;\n\n if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {\n return uaData.brands.map(function (item) {\n return item.brand + \"/\" + item.version;\n }).join(' ');\n }\n\n return navigator.userAgent;\n}","import getUAString from \"../utils/userAgent.js\";\nexport default function isLayoutViewport() {\n return !/^((?!chrome|android).)*safari/i.test(getUAString());\n}","import { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport { round } from \"../utils/math.js\";\nimport getWindow from \"./getWindow.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getBoundingClientRect(element, includeScale, isFixedStrategy) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n\n var clientRect = element.getBoundingClientRect();\n var scaleX = 1;\n var scaleY = 1;\n\n if (includeScale && isHTMLElement(element)) {\n scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;\n scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;\n }\n\n var _ref = isElement(element) ? getWindow(element) : window,\n visualViewport = _ref.visualViewport;\n\n var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;\n var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;\n var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;\n var width = clientRect.width / scaleX;\n var height = clientRect.height / scaleY;\n return {\n width: width,\n height: height,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x,\n x: x,\n y: y\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\"; // Returns the layout rect of an element relative to its offsetParent. Layout\n// means it doesn't take into account transforms.\n\nexport default function getLayoutRect(element) {\n var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.\n // Fixes https://github.com/popperjs/popper-core/issues/1223\n\n var width = element.offsetWidth;\n var height = element.offsetHeight;\n\n if (Math.abs(clientRect.width - width) <= 1) {\n width = clientRect.width;\n }\n\n if (Math.abs(clientRect.height - height) <= 1) {\n height = clientRect.height;\n }\n\n return {\n x: element.offsetLeft,\n y: element.offsetTop,\n width: width,\n height: height\n };\n}","import { isShadowRoot } from \"./instanceOf.js\";\nexport default function contains(parent, child) {\n var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method\n\n if (parent.contains(child)) {\n return true;\n } // then fallback to custom implementation with Shadow DOM support\n else if (rootNode && isShadowRoot(rootNode)) {\n var next = child;\n\n do {\n if (next && parent.isSameNode(next)) {\n return true;\n } // $FlowFixMe[prop-missing]: need a better way to handle this...\n\n\n next = next.parentNode || next.host;\n } while (next);\n } // Give up, the result is false\n\n\n return false;\n}","import getWindow from \"./getWindow.js\";\nexport default function getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}","import getNodeName from \"./getNodeName.js\";\nexport default function isTableElement(element) {\n return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;\n}","import { isElement } from \"./instanceOf.js\";\nexport default function getDocumentElement(element) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]\n element.document) || window.document).documentElement;\n}","import getNodeName from \"./getNodeName.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport { isShadowRoot } from \"./instanceOf.js\";\nexport default function getParentNode(element) {\n if (getNodeName(element) === 'html') {\n return element;\n }\n\n return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle\n // $FlowFixMe[incompatible-return]\n // $FlowFixMe[prop-missing]\n element.assignedSlot || // step into the shadow DOM of the parent of a slotted node\n element.parentNode || ( // DOM Element detected\n isShadowRoot(element) ? element.host : null) || // ShadowRoot detected\n // $FlowFixMe[incompatible-call]: HTMLElement is a Node\n getDocumentElement(element) // fallback\n\n );\n}","import getWindow from \"./getWindow.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isHTMLElement, isShadowRoot } from \"./instanceOf.js\";\nimport isTableElement from \"./isTableElement.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getUAString from \"../utils/userAgent.js\";\n\nfunction getTrueOffsetParent(element) {\n if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837\n getComputedStyle(element).position === 'fixed') {\n return null;\n }\n\n return element.offsetParent;\n} // `.offsetParent` reports `null` for fixed elements, while absolute elements\n// return the containing block\n\n\nfunction getContainingBlock(element) {\n var isFirefox = /firefox/i.test(getUAString());\n var isIE = /Trident/i.test(getUAString());\n\n if (isIE && isHTMLElement(element)) {\n // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport\n var elementCss = getComputedStyle(element);\n\n if (elementCss.position === 'fixed') {\n return null;\n }\n }\n\n var currentNode = getParentNode(element);\n\n if (isShadowRoot(currentNode)) {\n currentNode = currentNode.host;\n }\n\n while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {\n var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that\n // create a containing block.\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n\n if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {\n return currentNode;\n } else {\n currentNode = currentNode.parentNode;\n }\n }\n\n return null;\n} // Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\n\n\nexport default function getOffsetParent(element) {\n var window = getWindow(element);\n var offsetParent = getTrueOffsetParent(element);\n\n while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {\n offsetParent = getTrueOffsetParent(offsetParent);\n }\n\n if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {\n return window;\n }\n\n return offsetParent || getContainingBlock(element) || window;\n}","export default function getMainAxisFromPlacement(placement) {\n return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';\n}","import { max as mathMax, min as mathMin } from \"./math.js\";\nexport function within(min, value, max) {\n return mathMax(min, mathMin(value, max));\n}\nexport function withinMaxClamp(min, value, max) {\n var v = within(min, value, max);\n return v > max ? max : v;\n}","import getFreshSideObject from \"./getFreshSideObject.js\";\nexport default function mergePaddingObject(paddingObject) {\n return Object.assign({}, getFreshSideObject(), paddingObject);\n}","export default function getFreshSideObject() {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n}","export default function expandToHashMap(value, keys) {\n return keys.reduce(function (hashMap, key) {\n hashMap[key] = value;\n return hashMap;\n }, {});\n}","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport contains from \"../dom-utils/contains.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport { within } from \"../utils/within.js\";\nimport mergePaddingObject from \"../utils/mergePaddingObject.js\";\nimport expandToHashMap from \"../utils/expandToHashMap.js\";\nimport { left, right, basePlacements, top, bottom } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar toPaddingObject = function toPaddingObject(padding, state) {\n padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {\n placement: state.placement\n })) : padding;\n return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n};\n\nfunction arrow(_ref) {\n var _state$modifiersData$;\n\n var state = _ref.state,\n name = _ref.name,\n options = _ref.options;\n var arrowElement = state.elements.arrow;\n var popperOffsets = state.modifiersData.popperOffsets;\n var basePlacement = getBasePlacement(state.placement);\n var axis = getMainAxisFromPlacement(basePlacement);\n var isVertical = [left, right].indexOf(basePlacement) >= 0;\n var len = isVertical ? 'height' : 'width';\n\n if (!arrowElement || !popperOffsets) {\n return;\n }\n\n var paddingObject = toPaddingObject(options.padding, state);\n var arrowRect = getLayoutRect(arrowElement);\n var minProp = axis === 'y' ? top : left;\n var maxProp = axis === 'y' ? bottom : right;\n var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];\n var startDiff = popperOffsets[axis] - state.rects.reference[axis];\n var arrowOffsetParent = getOffsetParent(arrowElement);\n var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;\n var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is\n // outside of the popper bounds\n\n var min = paddingObject[minProp];\n var max = clientSize - arrowRect[len] - paddingObject[maxProp];\n var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;\n var offset = within(min, center, max); // Prevents breaking syntax highlighting...\n\n var axisProp = axis;\n state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state,\n options = _ref2.options;\n var _options$element = options.element,\n arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;\n\n if (arrowElement == null) {\n return;\n } // CSS selector\n\n\n if (typeof arrowElement === 'string') {\n arrowElement = state.elements.popper.querySelector(arrowElement);\n\n if (!arrowElement) {\n return;\n }\n }\n\n if (!contains(state.elements.popper, arrowElement)) {\n return;\n }\n\n state.elements.arrow = arrowElement;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'arrow',\n enabled: true,\n phase: 'main',\n fn: arrow,\n effect: effect,\n requires: ['popperOffsets'],\n requiresIfExists: ['preventOverflow']\n};","export default function getVariation(placement) {\n return placement.split('-')[1];\n}","import { top, left, right, bottom, end } from \"../enums.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getWindow from \"../dom-utils/getWindow.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getComputedStyle from \"../dom-utils/getComputedStyle.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport { round } from \"../utils/math.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar unsetSides = {\n top: 'auto',\n right: 'auto',\n bottom: 'auto',\n left: 'auto'\n}; // Round the offsets to the nearest suitable subpixel based on the DPR.\n// Zooming can change the DPR, but it seems to report a value that will\n// cleanly divide the values into the appropriate subpixels.\n\nfunction roundOffsetsByDPR(_ref, win) {\n var x = _ref.x,\n y = _ref.y;\n var dpr = win.devicePixelRatio || 1;\n return {\n x: round(x * dpr) / dpr || 0,\n y: round(y * dpr) / dpr || 0\n };\n}\n\nexport function mapToStyles(_ref2) {\n var _Object$assign2;\n\n var popper = _ref2.popper,\n popperRect = _ref2.popperRect,\n placement = _ref2.placement,\n variation = _ref2.variation,\n offsets = _ref2.offsets,\n position = _ref2.position,\n gpuAcceleration = _ref2.gpuAcceleration,\n adaptive = _ref2.adaptive,\n roundOffsets = _ref2.roundOffsets,\n isFixed = _ref2.isFixed;\n var _offsets$x = offsets.x,\n x = _offsets$x === void 0 ? 0 : _offsets$x,\n _offsets$y = offsets.y,\n y = _offsets$y === void 0 ? 0 : _offsets$y;\n\n var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref3.x;\n y = _ref3.y;\n var hasX = offsets.hasOwnProperty('x');\n var hasY = offsets.hasOwnProperty('y');\n var sideX = left;\n var sideY = top;\n var win = window;\n\n if (adaptive) {\n var offsetParent = getOffsetParent(popper);\n var heightProp = 'clientHeight';\n var widthProp = 'clientWidth';\n\n if (offsetParent === getWindow(popper)) {\n offsetParent = getDocumentElement(popper);\n\n if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {\n heightProp = 'scrollHeight';\n widthProp = 'scrollWidth';\n }\n } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it\n\n\n offsetParent = offsetParent;\n\n if (placement === top || (placement === left || placement === right) && variation === end) {\n sideY = bottom;\n var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]\n offsetParent[heightProp];\n y -= offsetY - popperRect.height;\n y *= gpuAcceleration ? 1 : -1;\n }\n\n if (placement === left || (placement === top || placement === bottom) && variation === end) {\n sideX = right;\n var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]\n offsetParent[widthProp];\n x -= offsetX - popperRect.width;\n x *= gpuAcceleration ? 1 : -1;\n }\n }\n\n var commonStyles = Object.assign({\n position: position\n }, adaptive && unsetSides);\n\n var _ref4 = roundOffsets === true ? roundOffsetsByDPR({\n x: x,\n y: y\n }, getWindow(popper)) : {\n x: x,\n y: y\n };\n\n x = _ref4.x;\n y = _ref4.y;\n\n if (gpuAcceleration) {\n var _Object$assign;\n\n return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? \"translate(\" + x + \"px, \" + y + \"px)\" : \"translate3d(\" + x + \"px, \" + y + \"px, 0)\", _Object$assign));\n }\n\n return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + \"px\" : '', _Object$assign2[sideX] = hasX ? x + \"px\" : '', _Object$assign2.transform = '', _Object$assign2));\n}\n\nfunction computeStyles(_ref5) {\n var state = _ref5.state,\n options = _ref5.options;\n var _options$gpuAccelerat = options.gpuAcceleration,\n gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,\n _options$adaptive = options.adaptive,\n adaptive = _options$adaptive === void 0 ? true : _options$adaptive,\n _options$roundOffsets = options.roundOffsets,\n roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;\n var commonStyles = {\n placement: getBasePlacement(state.placement),\n variation: getVariation(state.placement),\n popper: state.elements.popper,\n popperRect: state.rects.popper,\n gpuAcceleration: gpuAcceleration,\n isFixed: state.options.strategy === 'fixed'\n };\n\n if (state.modifiersData.popperOffsets != null) {\n state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.popperOffsets,\n position: state.options.strategy,\n adaptive: adaptive,\n roundOffsets: roundOffsets\n })));\n }\n\n if (state.modifiersData.arrow != null) {\n state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.arrow,\n position: 'absolute',\n adaptive: false,\n roundOffsets: roundOffsets\n })));\n }\n\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-placement': state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'computeStyles',\n enabled: true,\n phase: 'beforeWrite',\n fn: computeStyles,\n data: {}\n};","import getWindow from \"../dom-utils/getWindow.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar passive = {\n passive: true\n};\n\nfunction effect(_ref) {\n var state = _ref.state,\n instance = _ref.instance,\n options = _ref.options;\n var _options$scroll = options.scroll,\n scroll = _options$scroll === void 0 ? true : _options$scroll,\n _options$resize = options.resize,\n resize = _options$resize === void 0 ? true : _options$resize;\n var window = getWindow(state.elements.popper);\n var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);\n\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.addEventListener('resize', instance.update, passive);\n }\n\n return function () {\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.removeEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.removeEventListener('resize', instance.update, passive);\n }\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'eventListeners',\n enabled: true,\n phase: 'write',\n fn: function fn() {},\n effect: effect,\n data: {}\n};","var hash = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nexport default function getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}","var hash = {\n start: 'end',\n end: 'start'\n};\nexport default function getOppositeVariationPlacement(placement) {\n return placement.replace(/start|end/g, function (matched) {\n return hash[matched];\n });\n}","import getWindow from \"./getWindow.js\";\nexport default function getWindowScroll(node) {\n var win = getWindow(node);\n var scrollLeft = win.pageXOffset;\n var scrollTop = win.pageYOffset;\n return {\n scrollLeft: scrollLeft,\n scrollTop: scrollTop\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nexport default function getWindowScrollBarX(element) {\n // If has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n // Popper 1 is broken in this case and never had a bug report so let's assume\n // it's not an issue. I don't think anyone ever specifies width on \n // anyway.\n // Browsers where the left scrollbar doesn't cause an issue report `0` for\n // this (e.g. Edge 2019, IE11, Safari)\n return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;\n}","import getComputedStyle from \"./getComputedStyle.js\";\nexport default function isScrollParent(element) {\n // Firefox wants us to check `-x` and `-y` variations as well\n var _getComputedStyle = getComputedStyle(element),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);\n}","import getParentNode from \"./getParentNode.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nexport default function getScrollParent(node) {\n if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return node.ownerDocument.body;\n }\n\n if (isHTMLElement(node) && isScrollParent(node)) {\n return node;\n }\n\n return getScrollParent(getParentNode(node));\n}","import getScrollParent from \"./getScrollParent.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getWindow from \"./getWindow.js\";\nimport isScrollParent from \"./isScrollParent.js\";\n/*\ngiven a DOM element, return the list of all scroll parents, up the list of ancesors\nuntil we get to the top window object. This list is what we attach scroll listeners\nto, because if any of these parent elements scroll, we'll need to re-calculate the\nreference element's position.\n*/\n\nexport default function listScrollParents(element, list) {\n var _element$ownerDocumen;\n\n if (list === void 0) {\n list = [];\n }\n\n var scrollParent = getScrollParent(element);\n var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);\n var win = getWindow(scrollParent);\n var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;\n var updatedList = list.concat(target);\n return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here\n updatedList.concat(listScrollParents(getParentNode(target)));\n}","export default function rectToClientRect(rect) {\n return Object.assign({}, rect, {\n left: rect.x,\n top: rect.y,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height\n });\n}","import { viewport } from \"../enums.js\";\nimport getViewportRect from \"./getViewportRect.js\";\nimport getDocumentRect from \"./getDocumentRect.js\";\nimport listScrollParents from \"./listScrollParents.js\";\nimport getOffsetParent from \"./getOffsetParent.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport contains from \"./contains.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport rectToClientRect from \"../utils/rectToClientRect.js\";\nimport { max, min } from \"../utils/math.js\";\n\nfunction getInnerBoundingClientRect(element, strategy) {\n var rect = getBoundingClientRect(element, false, strategy === 'fixed');\n rect.top = rect.top + element.clientTop;\n rect.left = rect.left + element.clientLeft;\n rect.bottom = rect.top + element.clientHeight;\n rect.right = rect.left + element.clientWidth;\n rect.width = element.clientWidth;\n rect.height = element.clientHeight;\n rect.x = rect.left;\n rect.y = rect.top;\n return rect;\n}\n\nfunction getClientRectFromMixedType(element, clippingParent, strategy) {\n return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));\n} // A \"clipping parent\" is an overflowable container with the characteristic of\n// clipping (or hiding) overflowing elements with a position different from\n// `initial`\n\n\nfunction getClippingParents(element) {\n var clippingParents = listScrollParents(getParentNode(element));\n var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;\n var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;\n\n if (!isElement(clipperElement)) {\n return [];\n } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414\n\n\n return clippingParents.filter(function (clippingParent) {\n return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';\n });\n} // Gets the maximum area that the element is visible in due to any number of\n// clipping parents\n\n\nexport default function getClippingRect(element, boundary, rootBoundary, strategy) {\n var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);\n var clippingParents = [].concat(mainClippingParents, [rootBoundary]);\n var firstClippingParent = clippingParents[0];\n var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {\n var rect = getClientRectFromMixedType(element, clippingParent, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromMixedType(element, firstClippingParent, strategy));\n clippingRect.width = clippingRect.right - clippingRect.left;\n clippingRect.height = clippingRect.bottom - clippingRect.top;\n clippingRect.x = clippingRect.left;\n clippingRect.y = clippingRect.top;\n return clippingRect;\n}","import getWindow from \"./getWindow.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getViewportRect(element, strategy) {\n var win = getWindow(element);\n var html = getDocumentElement(element);\n var visualViewport = win.visualViewport;\n var width = html.clientWidth;\n var height = html.clientHeight;\n var x = 0;\n var y = 0;\n\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n var layoutViewport = isLayoutViewport();\n\n if (layoutViewport || !layoutViewport && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n\n return {\n width: width,\n height: height,\n x: x + getWindowScrollBarX(element),\n y: y\n };\n}","import getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nimport { max } from \"../utils/math.js\"; // Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable\n\nexport default function getDocumentRect(element) {\n var _element$ownerDocumen;\n\n var html = getDocumentElement(element);\n var winScroll = getWindowScroll(element);\n var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;\n var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);\n var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);\n var x = -winScroll.scrollLeft + getWindowScrollBarX(element);\n var y = -winScroll.scrollTop;\n\n if (getComputedStyle(body || html).direction === 'rtl') {\n x += max(html.clientWidth, body ? body.clientWidth : 0) - width;\n }\n\n return {\n width: width,\n height: height,\n x: x,\n y: y\n };\n}","import getBasePlacement from \"./getBasePlacement.js\";\nimport getVariation from \"./getVariation.js\";\nimport getMainAxisFromPlacement from \"./getMainAxisFromPlacement.js\";\nimport { top, right, bottom, left, start, end } from \"../enums.js\";\nexport default function computeOffsets(_ref) {\n var reference = _ref.reference,\n element = _ref.element,\n placement = _ref.placement;\n var basePlacement = placement ? getBasePlacement(placement) : null;\n var variation = placement ? getVariation(placement) : null;\n var commonX = reference.x + reference.width / 2 - element.width / 2;\n var commonY = reference.y + reference.height / 2 - element.height / 2;\n var offsets;\n\n switch (basePlacement) {\n case top:\n offsets = {\n x: commonX,\n y: reference.y - element.height\n };\n break;\n\n case bottom:\n offsets = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n\n case right:\n offsets = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n\n case left:\n offsets = {\n x: reference.x - element.width,\n y: commonY\n };\n break;\n\n default:\n offsets = {\n x: reference.x,\n y: reference.y\n };\n }\n\n var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;\n\n if (mainAxis != null) {\n var len = mainAxis === 'y' ? 'height' : 'width';\n\n switch (variation) {\n case start:\n offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);\n break;\n\n case end:\n offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);\n break;\n\n default:\n }\n }\n\n return offsets;\n}","import getClippingRect from \"../dom-utils/getClippingRect.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getBoundingClientRect from \"../dom-utils/getBoundingClientRect.js\";\nimport computeOffsets from \"./computeOffsets.js\";\nimport rectToClientRect from \"./rectToClientRect.js\";\nimport { clippingParents, reference, popper, bottom, top, right, basePlacements, viewport } from \"../enums.js\";\nimport { isElement } from \"../dom-utils/instanceOf.js\";\nimport mergePaddingObject from \"./mergePaddingObject.js\";\nimport expandToHashMap from \"./expandToHashMap.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport default function detectOverflow(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$placement = _options.placement,\n placement = _options$placement === void 0 ? state.placement : _options$placement,\n _options$strategy = _options.strategy,\n strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,\n _options$boundary = _options.boundary,\n boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,\n _options$rootBoundary = _options.rootBoundary,\n rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,\n _options$elementConte = _options.elementContext,\n elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,\n _options$altBoundary = _options.altBoundary,\n altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,\n _options$padding = _options.padding,\n padding = _options$padding === void 0 ? 0 : _options$padding;\n var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n var altContext = elementContext === popper ? reference : popper;\n var popperRect = state.rects.popper;\n var element = state.elements[altBoundary ? altContext : elementContext];\n var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);\n var referenceClientRect = getBoundingClientRect(state.elements.reference);\n var popperOffsets = computeOffsets({\n reference: referenceClientRect,\n element: popperRect,\n strategy: 'absolute',\n placement: placement\n });\n var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));\n var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect\n // 0 or negative = within the clipping rect\n\n var overflowOffsets = {\n top: clippingClientRect.top - elementClientRect.top + paddingObject.top,\n bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - elementClientRect.left + paddingObject.left,\n right: elementClientRect.right - clippingClientRect.right + paddingObject.right\n };\n var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element\n\n if (elementContext === popper && offsetData) {\n var offset = offsetData[placement];\n Object.keys(overflowOffsets).forEach(function (key) {\n var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;\n var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key] += offset[axis] * multiply;\n });\n }\n\n return overflowOffsets;\n}","import getOppositePlacement from \"../utils/getOppositePlacement.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getOppositeVariationPlacement from \"../utils/getOppositeVariationPlacement.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport computeAutoPlacement from \"../utils/computeAutoPlacement.js\";\nimport { bottom, top, start, right, left, auto } from \"../enums.js\";\nimport getVariation from \"../utils/getVariation.js\"; // eslint-disable-next-line import/no-unused-modules\n\nfunction getExpandedFallbackPlacements(placement) {\n if (getBasePlacement(placement) === auto) {\n return [];\n }\n\n var oppositePlacement = getOppositePlacement(placement);\n return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];\n}\n\nfunction flip(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n\n if (state.modifiersData[name]._skip) {\n return;\n }\n\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,\n specifiedFallbackPlacements = options.fallbackPlacements,\n padding = options.padding,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n _options$flipVariatio = options.flipVariations,\n flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,\n allowedAutoPlacements = options.allowedAutoPlacements;\n var preferredPlacement = state.options.placement;\n var basePlacement = getBasePlacement(preferredPlacement);\n var isBasePlacement = basePlacement === preferredPlacement;\n var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));\n var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {\n return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n flipVariations: flipVariations,\n allowedAutoPlacements: allowedAutoPlacements\n }) : placement);\n }, []);\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var checksMap = new Map();\n var makeFallbackChecks = true;\n var firstFittingPlacement = placements[0];\n\n for (var i = 0; i < placements.length; i++) {\n var placement = placements[i];\n\n var _basePlacement = getBasePlacement(placement);\n\n var isStartVariation = getVariation(placement) === start;\n var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;\n var len = isVertical ? 'width' : 'height';\n var overflow = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n altBoundary: altBoundary,\n padding: padding\n });\n var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;\n\n if (referenceRect[len] > popperRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide);\n }\n\n var altVariationSide = getOppositePlacement(mainVariationSide);\n var checks = [];\n\n if (checkMainAxis) {\n checks.push(overflow[_basePlacement] <= 0);\n }\n\n if (checkAltAxis) {\n checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);\n }\n\n if (checks.every(function (check) {\n return check;\n })) {\n firstFittingPlacement = placement;\n makeFallbackChecks = false;\n break;\n }\n\n checksMap.set(placement, checks);\n }\n\n if (makeFallbackChecks) {\n // `2` may be desired in some cases – research later\n var numberOfChecks = flipVariations ? 3 : 1;\n\n var _loop = function _loop(_i) {\n var fittingPlacement = placements.find(function (placement) {\n var checks = checksMap.get(placement);\n\n if (checks) {\n return checks.slice(0, _i).every(function (check) {\n return check;\n });\n }\n });\n\n if (fittingPlacement) {\n firstFittingPlacement = fittingPlacement;\n return \"break\";\n }\n };\n\n for (var _i = numberOfChecks; _i > 0; _i--) {\n var _ret = _loop(_i);\n\n if (_ret === \"break\") break;\n }\n }\n\n if (state.placement !== firstFittingPlacement) {\n state.modifiersData[name]._skip = true;\n state.placement = firstFittingPlacement;\n state.reset = true;\n }\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'flip',\n enabled: true,\n phase: 'main',\n fn: flip,\n requiresIfExists: ['offset'],\n data: {\n _skip: false\n }\n};","import getVariation from \"./getVariation.js\";\nimport { variationPlacements, basePlacements, placements as allPlacements } from \"../enums.js\";\nimport detectOverflow from \"./detectOverflow.js\";\nimport getBasePlacement from \"./getBasePlacement.js\";\nexport default function computeAutoPlacement(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n placement = _options.placement,\n boundary = _options.boundary,\n rootBoundary = _options.rootBoundary,\n padding = _options.padding,\n flipVariations = _options.flipVariations,\n _options$allowedAutoP = _options.allowedAutoPlacements,\n allowedAutoPlacements = _options$allowedAutoP === void 0 ? allPlacements : _options$allowedAutoP;\n var variation = getVariation(placement);\n var placements = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {\n return getVariation(placement) === variation;\n }) : basePlacements;\n var allowedPlacements = placements.filter(function (placement) {\n return allowedAutoPlacements.indexOf(placement) >= 0;\n });\n\n if (allowedPlacements.length === 0) {\n allowedPlacements = placements;\n } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...\n\n\n var overflows = allowedPlacements.reduce(function (acc, placement) {\n acc[placement] = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding\n })[getBasePlacement(placement)];\n return acc;\n }, {});\n return Object.keys(overflows).sort(function (a, b) {\n return overflows[a] - overflows[b];\n });\n}","import { top, bottom, left, right } from \"../enums.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\n\nfunction getSideOffsets(overflow, rect, preventedOffsets) {\n if (preventedOffsets === void 0) {\n preventedOffsets = {\n x: 0,\n y: 0\n };\n }\n\n return {\n top: overflow.top - rect.height - preventedOffsets.y,\n right: overflow.right - rect.width + preventedOffsets.x,\n bottom: overflow.bottom - rect.height + preventedOffsets.y,\n left: overflow.left - rect.width - preventedOffsets.x\n };\n}\n\nfunction isAnySideFullyClipped(overflow) {\n return [top, right, bottom, left].some(function (side) {\n return overflow[side] >= 0;\n });\n}\n\nfunction hide(_ref) {\n var state = _ref.state,\n name = _ref.name;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var preventedOffsets = state.modifiersData.preventOverflow;\n var referenceOverflow = detectOverflow(state, {\n elementContext: 'reference'\n });\n var popperAltOverflow = detectOverflow(state, {\n altBoundary: true\n });\n var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);\n var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);\n var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);\n var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);\n state.modifiersData[name] = {\n referenceClippingOffsets: referenceClippingOffsets,\n popperEscapeOffsets: popperEscapeOffsets,\n isReferenceHidden: isReferenceHidden,\n hasPopperEscaped: hasPopperEscaped\n };\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-reference-hidden': isReferenceHidden,\n 'data-popper-escaped': hasPopperEscaped\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'hide',\n enabled: true,\n phase: 'main',\n requiresIfExists: ['preventOverflow'],\n fn: hide\n};","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport { top, left, right, placements } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport function distanceAndSkiddingToXY(placement, rects, offset) {\n var basePlacement = getBasePlacement(placement);\n var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;\n\n var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {\n placement: placement\n })) : offset,\n skidding = _ref[0],\n distance = _ref[1];\n\n skidding = skidding || 0;\n distance = (distance || 0) * invertDistance;\n return [left, right].indexOf(basePlacement) >= 0 ? {\n x: distance,\n y: skidding\n } : {\n x: skidding,\n y: distance\n };\n}\n\nfunction offset(_ref2) {\n var state = _ref2.state,\n options = _ref2.options,\n name = _ref2.name;\n var _options$offset = options.offset,\n offset = _options$offset === void 0 ? [0, 0] : _options$offset;\n var data = placements.reduce(function (acc, placement) {\n acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);\n return acc;\n }, {});\n var _data$state$placement = data[state.placement],\n x = _data$state$placement.x,\n y = _data$state$placement.y;\n\n if (state.modifiersData.popperOffsets != null) {\n state.modifiersData.popperOffsets.x += x;\n state.modifiersData.popperOffsets.y += y;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'offset',\n enabled: true,\n phase: 'main',\n requires: ['popperOffsets'],\n fn: offset\n};","import computeOffsets from \"../utils/computeOffsets.js\";\n\nfunction popperOffsets(_ref) {\n var state = _ref.state,\n name = _ref.name;\n // Offsets are the actual position the popper needs to have to be\n // properly positioned near its reference element\n // This is the most basic placement, and will be adjusted by\n // the modifiers in the next step\n state.modifiersData[name] = computeOffsets({\n reference: state.rects.reference,\n element: state.rects.popper,\n strategy: 'absolute',\n placement: state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'popperOffsets',\n enabled: true,\n phase: 'read',\n fn: popperOffsets,\n data: {}\n};","import { top, left, right, bottom, start } from \"../enums.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport getAltAxis from \"../utils/getAltAxis.js\";\nimport { within, withinMaxClamp } from \"../utils/within.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport getFreshSideObject from \"../utils/getFreshSideObject.js\";\nimport { min as mathMin, max as mathMax } from \"../utils/math.js\";\n\nfunction preventOverflow(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n padding = options.padding,\n _options$tether = options.tether,\n tether = _options$tether === void 0 ? true : _options$tether,\n _options$tetherOffset = options.tetherOffset,\n tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;\n var overflow = detectOverflow(state, {\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n altBoundary: altBoundary\n });\n var basePlacement = getBasePlacement(state.placement);\n var variation = getVariation(state.placement);\n var isBasePlacement = !variation;\n var mainAxis = getMainAxisFromPlacement(basePlacement);\n var altAxis = getAltAxis(mainAxis);\n var popperOffsets = state.modifiersData.popperOffsets;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {\n placement: state.placement\n })) : tetherOffset;\n var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {\n mainAxis: tetherOffsetValue,\n altAxis: tetherOffsetValue\n } : Object.assign({\n mainAxis: 0,\n altAxis: 0\n }, tetherOffsetValue);\n var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;\n var data = {\n x: 0,\n y: 0\n };\n\n if (!popperOffsets) {\n return;\n }\n\n if (checkMainAxis) {\n var _offsetModifierState$;\n\n var mainSide = mainAxis === 'y' ? top : left;\n var altSide = mainAxis === 'y' ? bottom : right;\n var len = mainAxis === 'y' ? 'height' : 'width';\n var offset = popperOffsets[mainAxis];\n var min = offset + overflow[mainSide];\n var max = offset - overflow[altSide];\n var additive = tether ? -popperRect[len] / 2 : 0;\n var minLen = variation === start ? referenceRect[len] : popperRect[len];\n var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go\n // outside the reference bounds\n\n var arrowElement = state.elements.arrow;\n var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {\n width: 0,\n height: 0\n };\n var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();\n var arrowPaddingMin = arrowPaddingObject[mainSide];\n var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want\n // to include its full size in the calculation. If the reference is small\n // and near the edge of a boundary, the popper can overflow even if the\n // reference is not overflowing as well (e.g. virtual elements with no\n // width or height)\n\n var arrowLen = within(0, referenceRect[len], arrowRect[len]);\n var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;\n var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;\n var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);\n var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;\n var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;\n var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;\n var tetherMax = offset + maxOffset - offsetModifierValue;\n var preventedOffset = within(tether ? mathMin(min, tetherMin) : min, offset, tether ? mathMax(max, tetherMax) : max);\n popperOffsets[mainAxis] = preventedOffset;\n data[mainAxis] = preventedOffset - offset;\n }\n\n if (checkAltAxis) {\n var _offsetModifierState$2;\n\n var _mainSide = mainAxis === 'x' ? top : left;\n\n var _altSide = mainAxis === 'x' ? bottom : right;\n\n var _offset = popperOffsets[altAxis];\n\n var _len = altAxis === 'y' ? 'height' : 'width';\n\n var _min = _offset + overflow[_mainSide];\n\n var _max = _offset - overflow[_altSide];\n\n var isOriginSide = [top, left].indexOf(basePlacement) !== -1;\n\n var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;\n\n var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;\n\n var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;\n\n var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);\n\n popperOffsets[altAxis] = _preventedOffset;\n data[altAxis] = _preventedOffset - _offset;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'preventOverflow',\n enabled: true,\n phase: 'main',\n fn: preventOverflow,\n requiresIfExists: ['offset']\n};","export default function getAltAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getNodeScroll from \"./getNodeScroll.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport { round } from \"../utils/math.js\";\n\nfunction isElementScaled(element) {\n var rect = element.getBoundingClientRect();\n var scaleX = round(rect.width) / element.offsetWidth || 1;\n var scaleY = round(rect.height) / element.offsetHeight || 1;\n return scaleX !== 1 || scaleY !== 1;\n} // Returns the composite rect of an element relative to its offsetParent.\n// Composite means it takes into account transforms as well as layout.\n\n\nexport default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n\n var isOffsetParentAnElement = isHTMLElement(offsetParent);\n var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);\n var documentElement = getDocumentElement(offsetParent);\n var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);\n var scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n var offsets = {\n x: 0,\n y: 0\n };\n\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078\n isScrollParent(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n\n if (isHTMLElement(offsetParent)) {\n offsets = getBoundingClientRect(offsetParent, true);\n offsets.x += offsetParent.clientLeft;\n offsets.y += offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n\n return {\n x: rect.left + scroll.scrollLeft - offsets.x,\n y: rect.top + scroll.scrollTop - offsets.y,\n width: rect.width,\n height: rect.height\n };\n}","import getWindowScroll from \"./getWindowScroll.js\";\nimport getWindow from \"./getWindow.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getHTMLElementScroll from \"./getHTMLElementScroll.js\";\nexport default function getNodeScroll(node) {\n if (node === getWindow(node) || !isHTMLElement(node)) {\n return getWindowScroll(node);\n } else {\n return getHTMLElementScroll(node);\n }\n}","export default function getHTMLElementScroll(element) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n}","import { modifierPhases } from \"../enums.js\"; // source: https://stackoverflow.com/questions/49875255\n\nfunction order(modifiers) {\n var map = new Map();\n var visited = new Set();\n var result = [];\n modifiers.forEach(function (modifier) {\n map.set(modifier.name, modifier);\n }); // On visiting object, check for its dependencies and visit them recursively\n\n function sort(modifier) {\n visited.add(modifier.name);\n var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);\n requires.forEach(function (dep) {\n if (!visited.has(dep)) {\n var depModifier = map.get(dep);\n\n if (depModifier) {\n sort(depModifier);\n }\n }\n });\n result.push(modifier);\n }\n\n modifiers.forEach(function (modifier) {\n if (!visited.has(modifier.name)) {\n // check for visited object\n sort(modifier);\n }\n });\n return result;\n}\n\nexport default function orderModifiers(modifiers) {\n // order based on dependencies\n var orderedModifiers = order(modifiers); // order based on phase\n\n return modifierPhases.reduce(function (acc, phase) {\n return acc.concat(orderedModifiers.filter(function (modifier) {\n return modifier.phase === phase;\n }));\n }, []);\n}","import getCompositeRect from \"./dom-utils/getCompositeRect.js\";\nimport getLayoutRect from \"./dom-utils/getLayoutRect.js\";\nimport listScrollParents from \"./dom-utils/listScrollParents.js\";\nimport getOffsetParent from \"./dom-utils/getOffsetParent.js\";\nimport orderModifiers from \"./utils/orderModifiers.js\";\nimport debounce from \"./utils/debounce.js\";\nimport mergeByName from \"./utils/mergeByName.js\";\nimport detectOverflow from \"./utils/detectOverflow.js\";\nimport { isElement } from \"./dom-utils/instanceOf.js\";\nvar DEFAULT_OPTIONS = {\n placement: 'bottom',\n modifiers: [],\n strategy: 'absolute'\n};\n\nfunction areValidElements() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return !args.some(function (element) {\n return !(element && typeof element.getBoundingClientRect === 'function');\n });\n}\n\nexport function popperGenerator(generatorOptions) {\n if (generatorOptions === void 0) {\n generatorOptions = {};\n }\n\n var _generatorOptions = generatorOptions,\n _generatorOptions$def = _generatorOptions.defaultModifiers,\n defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,\n _generatorOptions$def2 = _generatorOptions.defaultOptions,\n defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;\n return function createPopper(reference, popper, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n var state = {\n placement: 'bottom',\n orderedModifiers: [],\n options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),\n modifiersData: {},\n elements: {\n reference: reference,\n popper: popper\n },\n attributes: {},\n styles: {}\n };\n var effectCleanupFns = [];\n var isDestroyed = false;\n var instance = {\n state: state,\n setOptions: function setOptions(setOptionsAction) {\n var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;\n cleanupModifierEffects();\n state.options = Object.assign({}, defaultOptions, state.options, options);\n state.scrollParents = {\n reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],\n popper: listScrollParents(popper)\n }; // Orders the modifiers based on their dependencies and `phase`\n // properties\n\n var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers\n\n state.orderedModifiers = orderedModifiers.filter(function (m) {\n return m.enabled;\n });\n runModifierEffects();\n return instance.update();\n },\n // Sync update – it will always be executed, even if not necessary. This\n // is useful for low frequency updates where sync behavior simplifies the\n // logic.\n // For high frequency updates (e.g. `resize` and `scroll` events), always\n // prefer the async Popper#update method\n forceUpdate: function forceUpdate() {\n if (isDestroyed) {\n return;\n }\n\n var _state$elements = state.elements,\n reference = _state$elements.reference,\n popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements\n // anymore\n\n if (!areValidElements(reference, popper)) {\n return;\n } // Store the reference and popper rects to be read by modifiers\n\n\n state.rects = {\n reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),\n popper: getLayoutRect(popper)\n }; // Modifiers have the ability to reset the current update cycle. The\n // most common use case for this is the `flip` modifier changing the\n // placement, which then needs to re-run all the modifiers, because the\n // logic was previously ran for the previous placement and is therefore\n // stale/incorrect\n\n state.reset = false;\n state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier\n // is filled with the initial data specified by the modifier. This means\n // it doesn't persist and is fresh on each update.\n // To ensure persistent data, use `${name}#persistent`\n\n state.orderedModifiers.forEach(function (modifier) {\n return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);\n });\n\n for (var index = 0; index < state.orderedModifiers.length; index++) {\n if (state.reset === true) {\n state.reset = false;\n index = -1;\n continue;\n }\n\n var _state$orderedModifie = state.orderedModifiers[index],\n fn = _state$orderedModifie.fn,\n _state$orderedModifie2 = _state$orderedModifie.options,\n _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,\n name = _state$orderedModifie.name;\n\n if (typeof fn === 'function') {\n state = fn({\n state: state,\n options: _options,\n name: name,\n instance: instance\n }) || state;\n }\n }\n },\n // Async and optimistically optimized update – it will not be executed if\n // not necessary (debounced to run at most once-per-tick)\n update: debounce(function () {\n return new Promise(function (resolve) {\n instance.forceUpdate();\n resolve(state);\n });\n }),\n destroy: function destroy() {\n cleanupModifierEffects();\n isDestroyed = true;\n }\n };\n\n if (!areValidElements(reference, popper)) {\n return instance;\n }\n\n instance.setOptions(options).then(function (state) {\n if (!isDestroyed && options.onFirstUpdate) {\n options.onFirstUpdate(state);\n }\n }); // Modifiers have the ability to execute arbitrary code before the first\n // update cycle runs. They will be executed in the same order as the update\n // cycle. This is useful when a modifier adds some persistent data that\n // other modifiers need to use, but the modifier is run after the dependent\n // one.\n\n function runModifierEffects() {\n state.orderedModifiers.forEach(function (_ref) {\n var name = _ref.name,\n _ref$options = _ref.options,\n options = _ref$options === void 0 ? {} : _ref$options,\n effect = _ref.effect;\n\n if (typeof effect === 'function') {\n var cleanupFn = effect({\n state: state,\n name: name,\n instance: instance,\n options: options\n });\n\n var noopFn = function noopFn() {};\n\n effectCleanupFns.push(cleanupFn || noopFn);\n }\n });\n }\n\n function cleanupModifierEffects() {\n effectCleanupFns.forEach(function (fn) {\n return fn();\n });\n effectCleanupFns = [];\n }\n\n return instance;\n };\n}\nexport var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules\n\nexport { detectOverflow };","export default function debounce(fn) {\n var pending;\n return function () {\n if (!pending) {\n pending = new Promise(function (resolve) {\n Promise.resolve().then(function () {\n pending = undefined;\n resolve(fn());\n });\n });\n }\n\n return pending;\n };\n}","export default function mergeByName(modifiers) {\n var merged = modifiers.reduce(function (merged, current) {\n var existing = merged[current.name];\n merged[current.name] = existing ? Object.assign({}, existing, current, {\n options: Object.assign({}, existing.options, current.options),\n data: Object.assign({}, existing.data, current.data)\n }) : current;\n return merged;\n }, {}); // IE11 does not support Object.values\n\n return Object.keys(merged).map(function (key) {\n return merged[key];\n });\n}","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nimport offset from \"./modifiers/offset.js\";\nimport flip from \"./modifiers/flip.js\";\nimport preventOverflow from \"./modifiers/preventOverflow.js\";\nimport arrow from \"./modifiers/arrow.js\";\nimport hide from \"./modifiers/hide.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles, offset, flip, preventOverflow, arrow, hide];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow }; // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper as createPopperLite } from \"./popper-lite.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport * from \"./modifiers/index.js\";","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow };","/*!\n * Bootstrap v5.3.2 (https://getbootstrap.com/)\n * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\nimport * as Popper from '@popperjs/core';\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * Constants\n */\n\nconst elementMap = new Map();\nconst Data = {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map());\n }\n const instanceMap = elementMap.get(element);\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`);\n return;\n }\n instanceMap.set(key, instance);\n },\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null;\n }\n return null;\n },\n remove(element, key) {\n if (!elementMap.has(element)) {\n return;\n }\n const instanceMap = elementMap.get(element);\n instanceMap.delete(key);\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element);\n }\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst MAX_UID = 1000000;\nconst MILLISECONDS_MULTIPLIER = 1000;\nconst TRANSITION_END = 'transitionend';\n\n/**\n * Properly escape IDs selectors to handle weird IDs\n * @param {string} selector\n * @returns {string}\n */\nconst parseSelector = selector => {\n if (selector && window.CSS && window.CSS.escape) {\n // document.querySelector needs escaping to handle IDs (html5+) containing for instance /\n selector = selector.replace(/#([^\\s\"#']+)/g, (match, id) => `#${CSS.escape(id)}`);\n }\n return selector;\n};\n\n// Shout-out Angus Croll (https://goo.gl/pxwQGp)\nconst toType = object => {\n if (object === null || object === undefined) {\n return `${object}`;\n }\n return Object.prototype.toString.call(object).match(/\\s([a-z]+)/i)[1].toLowerCase();\n};\n\n/**\n * Public Util API\n */\n\nconst getUID = prefix => {\n do {\n prefix += Math.floor(Math.random() * MAX_UID);\n } while (document.getElementById(prefix));\n return prefix;\n};\nconst getTransitionDurationFromElement = element => {\n if (!element) {\n return 0;\n }\n\n // Get transition-duration of the element\n let {\n transitionDuration,\n transitionDelay\n } = window.getComputedStyle(element);\n const floatTransitionDuration = Number.parseFloat(transitionDuration);\n const floatTransitionDelay = Number.parseFloat(transitionDelay);\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0;\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0];\n transitionDelay = transitionDelay.split(',')[0];\n return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n};\nconst triggerTransitionEnd = element => {\n element.dispatchEvent(new Event(TRANSITION_END));\n};\nconst isElement = object => {\n if (!object || typeof object !== 'object') {\n return false;\n }\n if (typeof object.jquery !== 'undefined') {\n object = object[0];\n }\n return typeof object.nodeType !== 'undefined';\n};\nconst getElement = object => {\n // it's a jQuery object or a node element\n if (isElement(object)) {\n return object.jquery ? object[0] : object;\n }\n if (typeof object === 'string' && object.length > 0) {\n return document.querySelector(parseSelector(object));\n }\n return null;\n};\nconst isVisible = element => {\n if (!isElement(element) || element.getClientRects().length === 0) {\n return false;\n }\n const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';\n // Handle `details` element as its content may falsie appear visible when it is closed\n const closedDetails = element.closest('details:not([open])');\n if (!closedDetails) {\n return elementIsVisible;\n }\n if (closedDetails !== element) {\n const summary = element.closest('summary');\n if (summary && summary.parentNode !== closedDetails) {\n return false;\n }\n if (summary === null) {\n return false;\n }\n }\n return elementIsVisible;\n};\nconst isDisabled = element => {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return true;\n }\n if (element.classList.contains('disabled')) {\n return true;\n }\n if (typeof element.disabled !== 'undefined') {\n return element.disabled;\n }\n return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';\n};\nconst findShadowRoot = element => {\n if (!document.documentElement.attachShadow) {\n return null;\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode();\n return root instanceof ShadowRoot ? root : null;\n }\n if (element instanceof ShadowRoot) {\n return element;\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null;\n }\n return findShadowRoot(element.parentNode);\n};\nconst noop = () => {};\n\n/**\n * Trick to restart an element's animation\n *\n * @param {HTMLElement} element\n * @return void\n *\n * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n */\nconst reflow = element => {\n element.offsetHeight; // eslint-disable-line no-unused-expressions\n};\n\nconst getjQuery = () => {\n if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n return window.jQuery;\n }\n return null;\n};\nconst DOMContentLoadedCallbacks = [];\nconst onDOMContentLoaded = callback => {\n if (document.readyState === 'loading') {\n // add listener on the first call when the document is in loading state\n if (!DOMContentLoadedCallbacks.length) {\n document.addEventListener('DOMContentLoaded', () => {\n for (const callback of DOMContentLoadedCallbacks) {\n callback();\n }\n });\n }\n DOMContentLoadedCallbacks.push(callback);\n } else {\n callback();\n }\n};\nconst isRTL = () => document.documentElement.dir === 'rtl';\nconst defineJQueryPlugin = plugin => {\n onDOMContentLoaded(() => {\n const $ = getjQuery();\n /* istanbul ignore if */\n if ($) {\n const name = plugin.NAME;\n const JQUERY_NO_CONFLICT = $.fn[name];\n $.fn[name] = plugin.jQueryInterface;\n $.fn[name].Constructor = plugin;\n $.fn[name].noConflict = () => {\n $.fn[name] = JQUERY_NO_CONFLICT;\n return plugin.jQueryInterface;\n };\n }\n });\n};\nconst execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {\n return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;\n};\nconst executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n if (!waitForTransition) {\n execute(callback);\n return;\n }\n const durationPadding = 5;\n const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;\n let called = false;\n const handler = ({\n target\n }) => {\n if (target !== transitionElement) {\n return;\n }\n called = true;\n transitionElement.removeEventListener(TRANSITION_END, handler);\n execute(callback);\n };\n transitionElement.addEventListener(TRANSITION_END, handler);\n setTimeout(() => {\n if (!called) {\n triggerTransitionEnd(transitionElement);\n }\n }, emulatedDuration);\n};\n\n/**\n * Return the previous/next element of a list.\n *\n * @param {array} list The list of elements\n * @param activeElement The active element\n * @param shouldGetNext Choose to get next or previous element\n * @param isCycleAllowed\n * @return {Element|elem} The proper element\n */\nconst getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n const listLength = list.length;\n let index = list.indexOf(activeElement);\n\n // if the element does not exist in the list return an element\n // depending on the direction and if cycle is allowed\n if (index === -1) {\n return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];\n }\n index += shouldGetNext ? 1 : -1;\n if (isCycleAllowed) {\n index = (index + listLength) % listLength;\n }\n return list[Math.max(0, Math.min(index, listLength - 1))];\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst namespaceRegex = /[^.]*(?=\\..*)\\.|.*/;\nconst stripNameRegex = /\\..*/;\nconst stripUidRegex = /::\\d+$/;\nconst eventRegistry = {}; // Events storage\nlet uidEvent = 1;\nconst customEvents = {\n mouseenter: 'mouseover',\n mouseleave: 'mouseout'\n};\nconst nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);\n\n/**\n * Private methods\n */\n\nfunction makeEventUid(element, uid) {\n return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;\n}\nfunction getElementEvents(element) {\n const uid = makeEventUid(element);\n element.uidEvent = uid;\n eventRegistry[uid] = eventRegistry[uid] || {};\n return eventRegistry[uid];\n}\nfunction bootstrapHandler(element, fn) {\n return function handler(event) {\n hydrateObj(event, {\n delegateTarget: element\n });\n if (handler.oneOff) {\n EventHandler.off(element, event.type, fn);\n }\n return fn.apply(element, [event]);\n };\n}\nfunction bootstrapDelegationHandler(element, selector, fn) {\n return function handler(event) {\n const domElements = element.querySelectorAll(selector);\n for (let {\n target\n } = event; target && target !== this; target = target.parentNode) {\n for (const domElement of domElements) {\n if (domElement !== target) {\n continue;\n }\n hydrateObj(event, {\n delegateTarget: target\n });\n if (handler.oneOff) {\n EventHandler.off(element, event.type, selector, fn);\n }\n return fn.apply(target, [event]);\n }\n }\n };\n}\nfunction findHandler(events, callable, delegationSelector = null) {\n return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector);\n}\nfunction normalizeParameters(originalTypeEvent, handler, delegationFunction) {\n const isDelegated = typeof handler === 'string';\n // TODO: tooltip passes `false` instead of selector, so we need to check\n const callable = isDelegated ? delegationFunction : handler || delegationFunction;\n let typeEvent = getTypeEvent(originalTypeEvent);\n if (!nativeEvents.has(typeEvent)) {\n typeEvent = originalTypeEvent;\n }\n return [isDelegated, callable, typeEvent];\n}\nfunction addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);\n\n // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n if (originalTypeEvent in customEvents) {\n const wrapFunction = fn => {\n return function (event) {\n if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) {\n return fn.call(this, event);\n }\n };\n };\n callable = wrapFunction(callable);\n }\n const events = getElementEvents(element);\n const handlers = events[typeEvent] || (events[typeEvent] = {});\n const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null);\n if (previousFunction) {\n previousFunction.oneOff = previousFunction.oneOff && oneOff;\n return;\n }\n const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''));\n const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable);\n fn.delegationSelector = isDelegated ? handler : null;\n fn.callable = callable;\n fn.oneOff = oneOff;\n fn.uidEvent = uid;\n handlers[uid] = fn;\n element.addEventListener(typeEvent, fn, isDelegated);\n}\nfunction removeHandler(element, events, typeEvent, handler, delegationSelector) {\n const fn = findHandler(events[typeEvent], handler, delegationSelector);\n if (!fn) {\n return;\n }\n element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));\n delete events[typeEvent][fn.uidEvent];\n}\nfunction removeNamespacedHandlers(element, events, typeEvent, namespace) {\n const storeElementEvent = events[typeEvent] || {};\n for (const [handlerKey, event] of Object.entries(storeElementEvent)) {\n if (handlerKey.includes(namespace)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n}\nfunction getTypeEvent(event) {\n // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n event = event.replace(stripNameRegex, '');\n return customEvents[event] || event;\n}\nconst EventHandler = {\n on(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, false);\n },\n one(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, true);\n },\n off(element, originalTypeEvent, handler, delegationFunction) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);\n const inNamespace = typeEvent !== originalTypeEvent;\n const events = getElementEvents(element);\n const storeElementEvent = events[typeEvent] || {};\n const isNamespace = originalTypeEvent.startsWith('.');\n if (typeof callable !== 'undefined') {\n // Simplest case: handler is passed, remove that listener ONLY.\n if (!Object.keys(storeElementEvent).length) {\n return;\n }\n removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null);\n return;\n }\n if (isNamespace) {\n for (const elementEvent of Object.keys(events)) {\n removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));\n }\n }\n for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {\n const handlerKey = keyHandlers.replace(stripUidRegex, '');\n if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n },\n trigger(element, event, args) {\n if (typeof event !== 'string' || !element) {\n return null;\n }\n const $ = getjQuery();\n const typeEvent = getTypeEvent(event);\n const inNamespace = event !== typeEvent;\n let jQueryEvent = null;\n let bubbles = true;\n let nativeDispatch = true;\n let defaultPrevented = false;\n if (inNamespace && $) {\n jQueryEvent = $.Event(event, args);\n $(element).trigger(jQueryEvent);\n bubbles = !jQueryEvent.isPropagationStopped();\n nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();\n defaultPrevented = jQueryEvent.isDefaultPrevented();\n }\n const evt = hydrateObj(new Event(event, {\n bubbles,\n cancelable: true\n }), args);\n if (defaultPrevented) {\n evt.preventDefault();\n }\n if (nativeDispatch) {\n element.dispatchEvent(evt);\n }\n if (evt.defaultPrevented && jQueryEvent) {\n jQueryEvent.preventDefault();\n }\n return evt;\n }\n};\nfunction hydrateObj(obj, meta = {}) {\n for (const [key, value] of Object.entries(meta)) {\n try {\n obj[key] = value;\n } catch (_unused) {\n Object.defineProperty(obj, key, {\n configurable: true,\n get() {\n return value;\n }\n });\n }\n }\n return obj;\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(value) {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n if (value === Number(value).toString()) {\n return Number(value);\n }\n if (value === '' || value === 'null') {\n return null;\n }\n if (typeof value !== 'string') {\n return value;\n }\n try {\n return JSON.parse(decodeURIComponent(value));\n } catch (_unused) {\n return value;\n }\n}\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);\n}\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value);\n },\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`);\n },\n getDataAttributes(element) {\n if (!element) {\n return {};\n }\n const attributes = {};\n const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));\n for (const key of bsKeys) {\n let pureKey = key.replace(/^bs/, '');\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);\n attributes[pureKey] = normalizeData(element.dataset[key]);\n }\n return attributes;\n },\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`));\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/config.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Class definition\n */\n\nclass Config {\n // Getters\n static get Default() {\n return {};\n }\n static get DefaultType() {\n return {};\n }\n static get NAME() {\n throw new Error('You have to implement the static method \"NAME\", for each component!');\n }\n _getConfig(config) {\n config = this._mergeConfigObj(config);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n _configAfterMerge(config) {\n return config;\n }\n _mergeConfigObj(config, element) {\n const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse\n\n return {\n ...this.constructor.Default,\n ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),\n ...(typeof config === 'object' ? config : {})\n };\n }\n _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n for (const [property, expectedTypes] of Object.entries(configTypes)) {\n const value = config[property];\n const valueType = isElement(value) ? 'element' : toType(value);\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`);\n }\n }\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst VERSION = '5.3.2';\n\n/**\n * Class definition\n */\n\nclass BaseComponent extends Config {\n constructor(element, config) {\n super();\n element = getElement(element);\n if (!element) {\n return;\n }\n this._element = element;\n this._config = this._getConfig(config);\n Data.set(this._element, this.constructor.DATA_KEY, this);\n }\n\n // Public\n dispose() {\n Data.remove(this._element, this.constructor.DATA_KEY);\n EventHandler.off(this._element, this.constructor.EVENT_KEY);\n for (const propertyName of Object.getOwnPropertyNames(this)) {\n this[propertyName] = null;\n }\n }\n _queueCallback(callback, element, isAnimated = true) {\n executeAfterTransition(callback, element, isAnimated);\n }\n _getConfig(config) {\n config = this._mergeConfigObj(config, this._element);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n\n // Static\n static getInstance(element) {\n return Data.get(getElement(element), this.DATA_KEY);\n }\n static getOrCreateInstance(element, config = {}) {\n return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n }\n static get VERSION() {\n return VERSION;\n }\n static get DATA_KEY() {\n return `bs.${this.NAME}`;\n }\n static get EVENT_KEY() {\n return `.${this.DATA_KEY}`;\n }\n static eventName(name) {\n return `${name}${this.EVENT_KEY}`;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst getSelector = element => {\n let selector = element.getAttribute('data-bs-target');\n if (!selector || selector === '#') {\n let hrefAttribute = element.getAttribute('href');\n\n // The only valid content that could double as a selector are IDs or classes,\n // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n // `document.querySelector` will rightfully complain it is invalid.\n // See https://github.com/twbs/bootstrap/issues/32273\n if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) {\n return null;\n }\n\n // Just in case some CMS puts out a full URL with the anchor appended\n if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {\n hrefAttribute = `#${hrefAttribute.split('#')[1]}`;\n }\n selector = hrefAttribute && hrefAttribute !== '#' ? parseSelector(hrefAttribute.trim()) : null;\n }\n return selector;\n};\nconst SelectorEngine = {\n find(selector, element = document.documentElement) {\n return [].concat(...Element.prototype.querySelectorAll.call(element, selector));\n },\n findOne(selector, element = document.documentElement) {\n return Element.prototype.querySelector.call(element, selector);\n },\n children(element, selector) {\n return [].concat(...element.children).filter(child => child.matches(selector));\n },\n parents(element, selector) {\n const parents = [];\n let ancestor = element.parentNode.closest(selector);\n while (ancestor) {\n parents.push(ancestor);\n ancestor = ancestor.parentNode.closest(selector);\n }\n return parents;\n },\n prev(element, selector) {\n let previous = element.previousElementSibling;\n while (previous) {\n if (previous.matches(selector)) {\n return [previous];\n }\n previous = previous.previousElementSibling;\n }\n return [];\n },\n // TODO: this is now unused; remove later along with prev()\n next(element, selector) {\n let next = element.nextElementSibling;\n while (next) {\n if (next.matches(selector)) {\n return [next];\n }\n next = next.nextElementSibling;\n }\n return [];\n },\n focusableChildren(element) {\n const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable=\"true\"]'].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(',');\n return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el));\n },\n getSelectorFromElement(element) {\n const selector = getSelector(element);\n if (selector) {\n return SelectorEngine.findOne(selector) ? selector : null;\n }\n return null;\n },\n getElementFromSelector(element) {\n const selector = getSelector(element);\n return selector ? SelectorEngine.findOne(selector) : null;\n },\n getMultipleElementsFromSelector(element) {\n const selector = getSelector(element);\n return selector ? SelectorEngine.find(selector) : [];\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`;\n const name = component.NAME;\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n if (isDisabled(this)) {\n return;\n }\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`);\n const instance = component.getOrCreateInstance(target);\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]();\n });\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$f = 'alert';\nconst DATA_KEY$a = 'bs.alert';\nconst EVENT_KEY$b = `.${DATA_KEY$a}`;\nconst EVENT_CLOSE = `close${EVENT_KEY$b}`;\nconst EVENT_CLOSED = `closed${EVENT_KEY$b}`;\nconst CLASS_NAME_FADE$5 = 'fade';\nconst CLASS_NAME_SHOW$8 = 'show';\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME$f;\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE);\n if (closeEvent.defaultPrevented) {\n return;\n }\n this._element.classList.remove(CLASS_NAME_SHOW$8);\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5);\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated);\n }\n\n // Private\n _destroyElement() {\n this._element.remove();\n EventHandler.trigger(this._element, EVENT_CLOSED);\n this.dispose();\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this);\n if (typeof config !== 'string') {\n return;\n }\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](this);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close');\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$e = 'button';\nconst DATA_KEY$9 = 'bs.button';\nconst EVENT_KEY$a = `.${DATA_KEY$9}`;\nconst DATA_API_KEY$6 = '.data-api';\nconst CLASS_NAME_ACTIVE$3 = 'active';\nconst SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle=\"button\"]';\nconst EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`;\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME$e;\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this);\n if (config === 'toggle') {\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => {\n event.preventDefault();\n const button = event.target.closest(SELECTOR_DATA_TOGGLE$5);\n const data = Button.getOrCreateInstance(button);\n data.toggle();\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/swipe.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$d = 'swipe';\nconst EVENT_KEY$9 = '.bs.swipe';\nconst EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`;\nconst EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`;\nconst EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`;\nconst EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`;\nconst EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`;\nconst POINTER_TYPE_TOUCH = 'touch';\nconst POINTER_TYPE_PEN = 'pen';\nconst CLASS_NAME_POINTER_EVENT = 'pointer-event';\nconst SWIPE_THRESHOLD = 40;\nconst Default$c = {\n endCallback: null,\n leftCallback: null,\n rightCallback: null\n};\nconst DefaultType$c = {\n endCallback: '(function|null)',\n leftCallback: '(function|null)',\n rightCallback: '(function|null)'\n};\n\n/**\n * Class definition\n */\n\nclass Swipe extends Config {\n constructor(element, config) {\n super();\n this._element = element;\n if (!element || !Swipe.isSupported()) {\n return;\n }\n this._config = this._getConfig(config);\n this._deltaX = 0;\n this._supportPointerEvents = Boolean(window.PointerEvent);\n this._initEvents();\n }\n\n // Getters\n static get Default() {\n return Default$c;\n }\n static get DefaultType() {\n return DefaultType$c;\n }\n static get NAME() {\n return NAME$d;\n }\n\n // Public\n dispose() {\n EventHandler.off(this._element, EVENT_KEY$9);\n }\n\n // Private\n _start(event) {\n if (!this._supportPointerEvents) {\n this._deltaX = event.touches[0].clientX;\n return;\n }\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX;\n }\n }\n _end(event) {\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX - this._deltaX;\n }\n this._handleSwipe();\n execute(this._config.endCallback);\n }\n _move(event) {\n this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX;\n }\n _handleSwipe() {\n const absDeltaX = Math.abs(this._deltaX);\n if (absDeltaX <= SWIPE_THRESHOLD) {\n return;\n }\n const direction = absDeltaX / this._deltaX;\n this._deltaX = 0;\n if (!direction) {\n return;\n }\n execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback);\n }\n _initEvents() {\n if (this._supportPointerEvents) {\n EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event));\n EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event));\n this._element.classList.add(CLASS_NAME_POINTER_EVENT);\n } else {\n EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event));\n EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event));\n EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event));\n }\n }\n _eventIsPointerPenTouch(event) {\n return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);\n }\n\n // Static\n static isSupported() {\n return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$c = 'carousel';\nconst DATA_KEY$8 = 'bs.carousel';\nconst EVENT_KEY$8 = `.${DATA_KEY$8}`;\nconst DATA_API_KEY$5 = '.data-api';\nconst ARROW_LEFT_KEY$1 = 'ArrowLeft';\nconst ARROW_RIGHT_KEY$1 = 'ArrowRight';\nconst TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\nconst ORDER_NEXT = 'next';\nconst ORDER_PREV = 'prev';\nconst DIRECTION_LEFT = 'left';\nconst DIRECTION_RIGHT = 'right';\nconst EVENT_SLIDE = `slide${EVENT_KEY$8}`;\nconst EVENT_SLID = `slid${EVENT_KEY$8}`;\nconst EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`;\nconst EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`;\nconst EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`;\nconst EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`;\nconst EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`;\nconst EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;\nconst CLASS_NAME_CAROUSEL = 'carousel';\nconst CLASS_NAME_ACTIVE$2 = 'active';\nconst CLASS_NAME_SLIDE = 'slide';\nconst CLASS_NAME_END = 'carousel-item-end';\nconst CLASS_NAME_START = 'carousel-item-start';\nconst CLASS_NAME_NEXT = 'carousel-item-next';\nconst CLASS_NAME_PREV = 'carousel-item-prev';\nconst SELECTOR_ACTIVE = '.active';\nconst SELECTOR_ITEM = '.carousel-item';\nconst SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;\nconst SELECTOR_ITEM_IMG = '.carousel-item img';\nconst SELECTOR_INDICATORS = '.carousel-indicators';\nconst SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';\nconst SELECTOR_DATA_RIDE = '[data-bs-ride=\"carousel\"]';\nconst KEY_TO_DIRECTION = {\n [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT,\n [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT\n};\nconst Default$b = {\n interval: 5000,\n keyboard: true,\n pause: 'hover',\n ride: false,\n touch: true,\n wrap: true\n};\nconst DefaultType$b = {\n interval: '(number|boolean)',\n // TODO:v6 remove boolean support\n keyboard: 'boolean',\n pause: '(string|boolean)',\n ride: '(boolean|string)',\n touch: 'boolean',\n wrap: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Carousel extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._interval = null;\n this._activeElement = null;\n this._isSliding = false;\n this.touchTimeout = null;\n this._swipeHelper = null;\n this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element);\n this._addEventListeners();\n if (this._config.ride === CLASS_NAME_CAROUSEL) {\n this.cycle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$b;\n }\n static get DefaultType() {\n return DefaultType$b;\n }\n static get NAME() {\n return NAME$c;\n }\n\n // Public\n next() {\n this._slide(ORDER_NEXT);\n }\n nextWhenVisible() {\n // FIXME TODO use `document.visibilityState`\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden && isVisible(this._element)) {\n this.next();\n }\n }\n prev() {\n this._slide(ORDER_PREV);\n }\n pause() {\n if (this._isSliding) {\n triggerTransitionEnd(this._element);\n }\n this._clearInterval();\n }\n cycle() {\n this._clearInterval();\n this._updateInterval();\n this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval);\n }\n _maybeEnableCycle() {\n if (!this._config.ride) {\n return;\n }\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.cycle());\n return;\n }\n this.cycle();\n }\n to(index) {\n const items = this._getItems();\n if (index > items.length - 1 || index < 0) {\n return;\n }\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.to(index));\n return;\n }\n const activeIndex = this._getItemIndex(this._getActive());\n if (activeIndex === index) {\n return;\n }\n const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;\n this._slide(order, items[index]);\n }\n dispose() {\n if (this._swipeHelper) {\n this._swipeHelper.dispose();\n }\n super.dispose();\n }\n\n // Private\n _configAfterMerge(config) {\n config.defaultInterval = config.interval;\n return config;\n }\n _addEventListeners() {\n if (this._config.keyboard) {\n EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event));\n }\n if (this._config.pause === 'hover') {\n EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause());\n EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle());\n }\n if (this._config.touch && Swipe.isSupported()) {\n this._addTouchEventListeners();\n }\n }\n _addTouchEventListeners() {\n for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {\n EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault());\n }\n const endCallBack = () => {\n if (this._config.pause !== 'hover') {\n return;\n }\n\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause();\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout);\n }\n this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval);\n };\n const swipeConfig = {\n leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),\n rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),\n endCallback: endCallBack\n };\n this._swipeHelper = new Swipe(this._element, swipeConfig);\n }\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return;\n }\n const direction = KEY_TO_DIRECTION[event.key];\n if (direction) {\n event.preventDefault();\n this._slide(this._directionToOrder(direction));\n }\n }\n _getItemIndex(element) {\n return this._getItems().indexOf(element);\n }\n _setActiveIndicatorElement(index) {\n if (!this._indicatorsElement) {\n return;\n }\n const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement);\n activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2);\n activeIndicator.removeAttribute('aria-current');\n const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to=\"${index}\"]`, this._indicatorsElement);\n if (newActiveIndicator) {\n newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2);\n newActiveIndicator.setAttribute('aria-current', 'true');\n }\n }\n _updateInterval() {\n const element = this._activeElement || this._getActive();\n if (!element) {\n return;\n }\n const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);\n this._config.interval = elementInterval || this._config.defaultInterval;\n }\n _slide(order, element = null) {\n if (this._isSliding) {\n return;\n }\n const activeElement = this._getActive();\n const isNext = order === ORDER_NEXT;\n const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap);\n if (nextElement === activeElement) {\n return;\n }\n const nextElementIndex = this._getItemIndex(nextElement);\n const triggerEvent = eventName => {\n return EventHandler.trigger(this._element, eventName, {\n relatedTarget: nextElement,\n direction: this._orderToDirection(order),\n from: this._getItemIndex(activeElement),\n to: nextElementIndex\n });\n };\n const slideEvent = triggerEvent(EVENT_SLIDE);\n if (slideEvent.defaultPrevented) {\n return;\n }\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n // TODO: change tests that use empty divs to avoid this check\n return;\n }\n const isCycling = Boolean(this._interval);\n this.pause();\n this._isSliding = true;\n this._setActiveIndicatorElement(nextElementIndex);\n this._activeElement = nextElement;\n const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;\n const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;\n nextElement.classList.add(orderClassName);\n reflow(nextElement);\n activeElement.classList.add(directionalClassName);\n nextElement.classList.add(directionalClassName);\n const completeCallBack = () => {\n nextElement.classList.remove(directionalClassName, orderClassName);\n nextElement.classList.add(CLASS_NAME_ACTIVE$2);\n activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName);\n this._isSliding = false;\n triggerEvent(EVENT_SLID);\n };\n this._queueCallback(completeCallBack, activeElement, this._isAnimated());\n if (isCycling) {\n this.cycle();\n }\n }\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_SLIDE);\n }\n _getActive() {\n return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);\n }\n _getItems() {\n return SelectorEngine.find(SELECTOR_ITEM, this._element);\n }\n _clearInterval() {\n if (this._interval) {\n clearInterval(this._interval);\n this._interval = null;\n }\n }\n _directionToOrder(direction) {\n if (isRTL()) {\n return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;\n }\n return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;\n }\n _orderToDirection(order) {\n if (isRTL()) {\n return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;\n }\n return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Carousel.getOrCreateInstance(this, config);\n if (typeof config === 'number') {\n data.to(config);\n return;\n }\n if (typeof config === 'string') {\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {\n return;\n }\n event.preventDefault();\n const carousel = Carousel.getOrCreateInstance(target);\n const slideIndex = this.getAttribute('data-bs-slide-to');\n if (slideIndex) {\n carousel.to(slideIndex);\n carousel._maybeEnableCycle();\n return;\n }\n if (Manipulator.getDataAttribute(this, 'slide') === 'next') {\n carousel.next();\n carousel._maybeEnableCycle();\n return;\n }\n carousel.prev();\n carousel._maybeEnableCycle();\n});\nEventHandler.on(window, EVENT_LOAD_DATA_API$3, () => {\n const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);\n for (const carousel of carousels) {\n Carousel.getOrCreateInstance(carousel);\n }\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Carousel);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$b = 'collapse';\nconst DATA_KEY$7 = 'bs.collapse';\nconst EVENT_KEY$7 = `.${DATA_KEY$7}`;\nconst DATA_API_KEY$4 = '.data-api';\nconst EVENT_SHOW$6 = `show${EVENT_KEY$7}`;\nconst EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`;\nconst EVENT_HIDE$6 = `hide${EVENT_KEY$7}`;\nconst EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`;\nconst EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`;\nconst CLASS_NAME_SHOW$7 = 'show';\nconst CLASS_NAME_COLLAPSE = 'collapse';\nconst CLASS_NAME_COLLAPSING = 'collapsing';\nconst CLASS_NAME_COLLAPSED = 'collapsed';\nconst CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;\nconst CLASS_NAME_HORIZONTAL = 'collapse-horizontal';\nconst WIDTH = 'width';\nconst HEIGHT = 'height';\nconst SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';\nconst SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle=\"collapse\"]';\nconst Default$a = {\n parent: null,\n toggle: true\n};\nconst DefaultType$a = {\n parent: '(null|element)',\n toggle: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Collapse extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._isTransitioning = false;\n this._triggerArray = [];\n const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4);\n for (const elem of toggleList) {\n const selector = SelectorEngine.getSelectorFromElement(elem);\n const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element);\n if (selector !== null && filterElement.length) {\n this._triggerArray.push(elem);\n }\n }\n this._initializeChildren();\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());\n }\n if (this._config.toggle) {\n this.toggle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$a;\n }\n static get DefaultType() {\n return DefaultType$a;\n }\n static get NAME() {\n return NAME$b;\n }\n\n // Public\n toggle() {\n if (this._isShown()) {\n this.hide();\n } else {\n this.show();\n }\n }\n show() {\n if (this._isTransitioning || this._isShown()) {\n return;\n }\n let activeChildren = [];\n\n // find active children\n if (this._config.parent) {\n activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, {\n toggle: false\n }));\n }\n if (activeChildren.length && activeChildren[0]._isTransitioning) {\n return;\n }\n const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6);\n if (startEvent.defaultPrevented) {\n return;\n }\n for (const activeInstance of activeChildren) {\n activeInstance.hide();\n }\n const dimension = this._getDimension();\n this._element.classList.remove(CLASS_NAME_COLLAPSE);\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n this._element.style[dimension] = 0;\n this._addAriaAndCollapsedClass(this._triggerArray, true);\n this._isTransitioning = true;\n const complete = () => {\n this._isTransitioning = false;\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);\n this._element.style[dimension] = '';\n EventHandler.trigger(this._element, EVENT_SHOWN$6);\n };\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n const scrollSize = `scroll${capitalizedDimension}`;\n this._queueCallback(complete, this._element, true);\n this._element.style[dimension] = `${this._element[scrollSize]}px`;\n }\n hide() {\n if (this._isTransitioning || !this._isShown()) {\n return;\n }\n const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6);\n if (startEvent.defaultPrevented) {\n return;\n }\n const dimension = this._getDimension();\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;\n reflow(this._element);\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);\n for (const trigger of this._triggerArray) {\n const element = SelectorEngine.getElementFromSelector(trigger);\n if (element && !this._isShown(element)) {\n this._addAriaAndCollapsedClass([trigger], false);\n }\n }\n this._isTransitioning = true;\n const complete = () => {\n this._isTransitioning = false;\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n this._element.classList.add(CLASS_NAME_COLLAPSE);\n EventHandler.trigger(this._element, EVENT_HIDDEN$6);\n };\n this._element.style[dimension] = '';\n this._queueCallback(complete, this._element, true);\n }\n _isShown(element = this._element) {\n return element.classList.contains(CLASS_NAME_SHOW$7);\n }\n\n // Private\n _configAfterMerge(config) {\n config.toggle = Boolean(config.toggle); // Coerce string values\n config.parent = getElement(config.parent);\n return config;\n }\n _getDimension() {\n return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;\n }\n _initializeChildren() {\n if (!this._config.parent) {\n return;\n }\n const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4);\n for (const element of children) {\n const selected = SelectorEngine.getElementFromSelector(element);\n if (selected) {\n this._addAriaAndCollapsedClass([element], this._isShown(selected));\n }\n }\n }\n _getFirstLevelChildren(selector) {\n const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);\n // remove children if greater depth\n return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element));\n }\n _addAriaAndCollapsedClass(triggerArray, isOpen) {\n if (!triggerArray.length) {\n return;\n }\n for (const element of triggerArray) {\n element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen);\n element.setAttribute('aria-expanded', isOpen);\n }\n }\n\n // Static\n static jQueryInterface(config) {\n const _config = {};\n if (typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false;\n }\n return this.each(function () {\n const data = Collapse.getOrCreateInstance(this, _config);\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') {\n event.preventDefault();\n }\n for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {\n Collapse.getOrCreateInstance(element, {\n toggle: false\n }).toggle();\n }\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Collapse);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$a = 'dropdown';\nconst DATA_KEY$6 = 'bs.dropdown';\nconst EVENT_KEY$6 = `.${DATA_KEY$6}`;\nconst DATA_API_KEY$3 = '.data-api';\nconst ESCAPE_KEY$2 = 'Escape';\nconst TAB_KEY$1 = 'Tab';\nconst ARROW_UP_KEY$1 = 'ArrowUp';\nconst ARROW_DOWN_KEY$1 = 'ArrowDown';\nconst RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button\n\nconst EVENT_HIDE$5 = `hide${EVENT_KEY$6}`;\nconst EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`;\nconst EVENT_SHOW$5 = `show${EVENT_KEY$6}`;\nconst EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`;\nconst EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst CLASS_NAME_SHOW$6 = 'show';\nconst CLASS_NAME_DROPUP = 'dropup';\nconst CLASS_NAME_DROPEND = 'dropend';\nconst CLASS_NAME_DROPSTART = 'dropstart';\nconst CLASS_NAME_DROPUP_CENTER = 'dropup-center';\nconst CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';\nconst SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle=\"dropdown\"]:not(.disabled):not(:disabled)';\nconst SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`;\nconst SELECTOR_MENU = '.dropdown-menu';\nconst SELECTOR_NAVBAR = '.navbar';\nconst SELECTOR_NAVBAR_NAV = '.navbar-nav';\nconst SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';\nconst PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';\nconst PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';\nconst PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';\nconst PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';\nconst PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';\nconst PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';\nconst PLACEMENT_TOPCENTER = 'top';\nconst PLACEMENT_BOTTOMCENTER = 'bottom';\nconst Default$9 = {\n autoClose: true,\n boundary: 'clippingParents',\n display: 'dynamic',\n offset: [0, 2],\n popperConfig: null,\n reference: 'toggle'\n};\nconst DefaultType$9 = {\n autoClose: '(boolean|string)',\n boundary: '(string|element)',\n display: 'string',\n offset: '(array|string|function)',\n popperConfig: '(null|object|function)',\n reference: '(string|element|object)'\n};\n\n/**\n * Class definition\n */\n\nclass Dropdown extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._popper = null;\n this._parent = this._element.parentNode; // dropdown wrapper\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent);\n this._inNavbar = this._detectNavbar();\n }\n\n // Getters\n static get Default() {\n return Default$9;\n }\n static get DefaultType() {\n return DefaultType$9;\n }\n static get NAME() {\n return NAME$a;\n }\n\n // Public\n toggle() {\n return this._isShown() ? this.hide() : this.show();\n }\n show() {\n if (isDisabled(this._element) || this._isShown()) {\n return;\n }\n const relatedTarget = {\n relatedTarget: this._element\n };\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget);\n if (showEvent.defaultPrevented) {\n return;\n }\n this._createPopper();\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop);\n }\n }\n this._element.focus();\n this._element.setAttribute('aria-expanded', true);\n this._menu.classList.add(CLASS_NAME_SHOW$6);\n this._element.classList.add(CLASS_NAME_SHOW$6);\n EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget);\n }\n hide() {\n if (isDisabled(this._element) || !this._isShown()) {\n return;\n }\n const relatedTarget = {\n relatedTarget: this._element\n };\n this._completeHide(relatedTarget);\n }\n dispose() {\n if (this._popper) {\n this._popper.destroy();\n }\n super.dispose();\n }\n update() {\n this._inNavbar = this._detectNavbar();\n if (this._popper) {\n this._popper.update();\n }\n }\n\n // Private\n _completeHide(relatedTarget) {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget);\n if (hideEvent.defaultPrevented) {\n return;\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop);\n }\n }\n if (this._popper) {\n this._popper.destroy();\n }\n this._menu.classList.remove(CLASS_NAME_SHOW$6);\n this._element.classList.remove(CLASS_NAME_SHOW$6);\n this._element.setAttribute('aria-expanded', 'false');\n Manipulator.removeDataAttribute(this._menu, 'popper');\n EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget);\n }\n _getConfig(config) {\n config = super._getConfig(config);\n if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {\n // Popper virtual elements require a getBoundingClientRect method\n throw new TypeError(`${NAME$a.toUpperCase()}: Option \"reference\" provided type \"object\" without a required \"getBoundingClientRect\" method.`);\n }\n return config;\n }\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper (https://popper.js.org)');\n }\n let referenceElement = this._element;\n if (this._config.reference === 'parent') {\n referenceElement = this._parent;\n } else if (isElement(this._config.reference)) {\n referenceElement = getElement(this._config.reference);\n } else if (typeof this._config.reference === 'object') {\n referenceElement = this._config.reference;\n }\n const popperConfig = this._getPopperConfig();\n this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);\n }\n _isShown() {\n return this._menu.classList.contains(CLASS_NAME_SHOW$6);\n }\n _getPlacement() {\n const parentDropdown = this._parent;\n if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {\n return PLACEMENT_RIGHT;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {\n return PLACEMENT_LEFT;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {\n return PLACEMENT_TOPCENTER;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {\n return PLACEMENT_BOTTOMCENTER;\n }\n\n // We need to trim the value because custom properties can also include spaces\n const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {\n return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;\n }\n return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;\n }\n _detectNavbar() {\n return this._element.closest(SELECTOR_NAVBAR) !== null;\n }\n _getOffset() {\n const {\n offset\n } = this._config;\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10));\n }\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element);\n }\n return offset;\n }\n _getPopperConfig() {\n const defaultBsPopperConfig = {\n placement: this._getPlacement(),\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n }, {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }]\n };\n\n // Disable Popper if we have a static display or Dropdown is in Navbar\n if (this._inNavbar || this._config.display === 'static') {\n Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove\n defaultBsPopperConfig.modifiers = [{\n name: 'applyStyles',\n enabled: false\n }];\n }\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n };\n }\n _selectMenuItem({\n key,\n target\n }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element));\n if (!items.length) {\n return;\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Dropdown.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n static clearMenus(event) {\n if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {\n return;\n }\n const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN);\n for (const toggle of openToggles) {\n const context = Dropdown.getInstance(toggle);\n if (!context || context._config.autoClose === false) {\n continue;\n }\n const composedPath = event.composedPath();\n const isMenuTarget = composedPath.includes(context._menu);\n if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {\n continue;\n }\n\n // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu\n if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) {\n continue;\n }\n const relatedTarget = {\n relatedTarget: context._element\n };\n if (event.type === 'click') {\n relatedTarget.clickEvent = event;\n }\n context._completeHide(relatedTarget);\n }\n }\n static dataApiKeydownHandler(event) {\n // If not an UP | DOWN | ESCAPE key => not a dropdown command\n // If input/textarea && if key is other than ESCAPE => not a dropdown command\n\n const isInput = /input|textarea/i.test(event.target.tagName);\n const isEscapeEvent = event.key === ESCAPE_KEY$2;\n const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key);\n if (!isUpOrDownEvent && !isEscapeEvent) {\n return;\n }\n if (isInput && !isEscapeEvent) {\n return;\n }\n event.preventDefault();\n\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode);\n const instance = Dropdown.getOrCreateInstance(getToggleButton);\n if (isUpOrDownEvent) {\n event.stopPropagation();\n instance.show();\n instance._selectMenuItem(event);\n return;\n }\n if (instance._isShown()) {\n // else is escape and we check if it is shown\n event.stopPropagation();\n instance.hide();\n getToggleButton.focus();\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);\nEventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);\nEventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);\nEventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) {\n event.preventDefault();\n Dropdown.getOrCreateInstance(this).toggle();\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Dropdown);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/backdrop.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$9 = 'backdrop';\nconst CLASS_NAME_FADE$4 = 'fade';\nconst CLASS_NAME_SHOW$5 = 'show';\nconst EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`;\nconst Default$8 = {\n className: 'modal-backdrop',\n clickCallback: null,\n isAnimated: false,\n isVisible: true,\n // if false, we use the backdrop helper without adding any element to the dom\n rootElement: 'body' // give the choice to place backdrop under different elements\n};\n\nconst DefaultType$8 = {\n className: 'string',\n clickCallback: '(function|null)',\n isAnimated: 'boolean',\n isVisible: 'boolean',\n rootElement: '(element|string)'\n};\n\n/**\n * Class definition\n */\n\nclass Backdrop extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n this._isAppended = false;\n this._element = null;\n }\n\n // Getters\n static get Default() {\n return Default$8;\n }\n static get DefaultType() {\n return DefaultType$8;\n }\n static get NAME() {\n return NAME$9;\n }\n\n // Public\n show(callback) {\n if (!this._config.isVisible) {\n execute(callback);\n return;\n }\n this._append();\n const element = this._getElement();\n if (this._config.isAnimated) {\n reflow(element);\n }\n element.classList.add(CLASS_NAME_SHOW$5);\n this._emulateAnimation(() => {\n execute(callback);\n });\n }\n hide(callback) {\n if (!this._config.isVisible) {\n execute(callback);\n return;\n }\n this._getElement().classList.remove(CLASS_NAME_SHOW$5);\n this._emulateAnimation(() => {\n this.dispose();\n execute(callback);\n });\n }\n dispose() {\n if (!this._isAppended) {\n return;\n }\n EventHandler.off(this._element, EVENT_MOUSEDOWN);\n this._element.remove();\n this._isAppended = false;\n }\n\n // Private\n _getElement() {\n if (!this._element) {\n const backdrop = document.createElement('div');\n backdrop.className = this._config.className;\n if (this._config.isAnimated) {\n backdrop.classList.add(CLASS_NAME_FADE$4);\n }\n this._element = backdrop;\n }\n return this._element;\n }\n _configAfterMerge(config) {\n // use getElement() with the default \"body\" to get a fresh Element on each instantiation\n config.rootElement = getElement(config.rootElement);\n return config;\n }\n _append() {\n if (this._isAppended) {\n return;\n }\n const element = this._getElement();\n this._config.rootElement.append(element);\n EventHandler.on(element, EVENT_MOUSEDOWN, () => {\n execute(this._config.clickCallback);\n });\n this._isAppended = true;\n }\n _emulateAnimation(callback) {\n executeAfterTransition(callback, this._getElement(), this._config.isAnimated);\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/focustrap.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$8 = 'focustrap';\nconst DATA_KEY$5 = 'bs.focustrap';\nconst EVENT_KEY$5 = `.${DATA_KEY$5}`;\nconst EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`;\nconst EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`;\nconst TAB_KEY = 'Tab';\nconst TAB_NAV_FORWARD = 'forward';\nconst TAB_NAV_BACKWARD = 'backward';\nconst Default$7 = {\n autofocus: true,\n trapElement: null // The element to trap focus inside of\n};\n\nconst DefaultType$7 = {\n autofocus: 'boolean',\n trapElement: 'element'\n};\n\n/**\n * Class definition\n */\n\nclass FocusTrap extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n this._isActive = false;\n this._lastTabNavDirection = null;\n }\n\n // Getters\n static get Default() {\n return Default$7;\n }\n static get DefaultType() {\n return DefaultType$7;\n }\n static get NAME() {\n return NAME$8;\n }\n\n // Public\n activate() {\n if (this._isActive) {\n return;\n }\n if (this._config.autofocus) {\n this._config.trapElement.focus();\n }\n EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop\n EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event));\n EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event));\n this._isActive = true;\n }\n deactivate() {\n if (!this._isActive) {\n return;\n }\n this._isActive = false;\n EventHandler.off(document, EVENT_KEY$5);\n }\n\n // Private\n _handleFocusin(event) {\n const {\n trapElement\n } = this._config;\n if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {\n return;\n }\n const elements = SelectorEngine.focusableChildren(trapElement);\n if (elements.length === 0) {\n trapElement.focus();\n } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {\n elements[elements.length - 1].focus();\n } else {\n elements[0].focus();\n }\n }\n _handleKeydown(event) {\n if (event.key !== TAB_KEY) {\n return;\n }\n this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/scrollBar.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';\nconst SELECTOR_STICKY_CONTENT = '.sticky-top';\nconst PROPERTY_PADDING = 'padding-right';\nconst PROPERTY_MARGIN = 'margin-right';\n\n/**\n * Class definition\n */\n\nclass ScrollBarHelper {\n constructor() {\n this._element = document.body;\n }\n\n // Public\n getWidth() {\n // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes\n const documentWidth = document.documentElement.clientWidth;\n return Math.abs(window.innerWidth - documentWidth);\n }\n hide() {\n const width = this.getWidth();\n this._disableOverFlow();\n // give padding to element to balance the hidden scrollbar width\n this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width);\n // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth\n this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width);\n this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width);\n }\n reset() {\n this._resetElementAttributes(this._element, 'overflow');\n this._resetElementAttributes(this._element, PROPERTY_PADDING);\n this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING);\n this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN);\n }\n isOverflowing() {\n return this.getWidth() > 0;\n }\n\n // Private\n _disableOverFlow() {\n this._saveInitialAttribute(this._element, 'overflow');\n this._element.style.overflow = 'hidden';\n }\n _setElementAttributes(selector, styleProperty, callback) {\n const scrollbarWidth = this.getWidth();\n const manipulationCallBack = element => {\n if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {\n return;\n }\n this._saveInitialAttribute(element, styleProperty);\n const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty);\n element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`);\n };\n this._applyManipulationCallback(selector, manipulationCallBack);\n }\n _saveInitialAttribute(element, styleProperty) {\n const actualValue = element.style.getPropertyValue(styleProperty);\n if (actualValue) {\n Manipulator.setDataAttribute(element, styleProperty, actualValue);\n }\n }\n _resetElementAttributes(selector, styleProperty) {\n const manipulationCallBack = element => {\n const value = Manipulator.getDataAttribute(element, styleProperty);\n // We only want to remove the property if the value is `null`; the value can also be zero\n if (value === null) {\n element.style.removeProperty(styleProperty);\n return;\n }\n Manipulator.removeDataAttribute(element, styleProperty);\n element.style.setProperty(styleProperty, value);\n };\n this._applyManipulationCallback(selector, manipulationCallBack);\n }\n _applyManipulationCallback(selector, callBack) {\n if (isElement(selector)) {\n callBack(selector);\n return;\n }\n for (const sel of SelectorEngine.find(selector, this._element)) {\n callBack(sel);\n }\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$7 = 'modal';\nconst DATA_KEY$4 = 'bs.modal';\nconst EVENT_KEY$4 = `.${DATA_KEY$4}`;\nconst DATA_API_KEY$2 = '.data-api';\nconst ESCAPE_KEY$1 = 'Escape';\nconst EVENT_HIDE$4 = `hide${EVENT_KEY$4}`;\nconst EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`;\nconst EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`;\nconst EVENT_SHOW$4 = `show${EVENT_KEY$4}`;\nconst EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`;\nconst EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`;\nconst EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`;\nconst EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`;\nconst EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`;\nconst EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`;\nconst CLASS_NAME_OPEN = 'modal-open';\nconst CLASS_NAME_FADE$3 = 'fade';\nconst CLASS_NAME_SHOW$4 = 'show';\nconst CLASS_NAME_STATIC = 'modal-static';\nconst OPEN_SELECTOR$1 = '.modal.show';\nconst SELECTOR_DIALOG = '.modal-dialog';\nconst SELECTOR_MODAL_BODY = '.modal-body';\nconst SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle=\"modal\"]';\nconst Default$6 = {\n backdrop: true,\n focus: true,\n keyboard: true\n};\nconst DefaultType$6 = {\n backdrop: '(boolean|string)',\n focus: 'boolean',\n keyboard: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Modal extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);\n this._backdrop = this._initializeBackDrop();\n this._focustrap = this._initializeFocusTrap();\n this._isShown = false;\n this._isTransitioning = false;\n this._scrollBar = new ScrollBarHelper();\n this._addEventListeners();\n }\n\n // Getters\n static get Default() {\n return Default$6;\n }\n static get DefaultType() {\n return DefaultType$6;\n }\n static get NAME() {\n return NAME$7;\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget);\n }\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, {\n relatedTarget\n });\n if (showEvent.defaultPrevented) {\n return;\n }\n this._isShown = true;\n this._isTransitioning = true;\n this._scrollBar.hide();\n document.body.classList.add(CLASS_NAME_OPEN);\n this._adjustDialog();\n this._backdrop.show(() => this._showElement(relatedTarget));\n }\n hide() {\n if (!this._isShown || this._isTransitioning) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4);\n if (hideEvent.defaultPrevented) {\n return;\n }\n this._isShown = false;\n this._isTransitioning = true;\n this._focustrap.deactivate();\n this._element.classList.remove(CLASS_NAME_SHOW$4);\n this._queueCallback(() => this._hideModal(), this._element, this._isAnimated());\n }\n dispose() {\n EventHandler.off(window, EVENT_KEY$4);\n EventHandler.off(this._dialog, EVENT_KEY$4);\n this._backdrop.dispose();\n this._focustrap.deactivate();\n super.dispose();\n }\n handleUpdate() {\n this._adjustDialog();\n }\n\n // Private\n _initializeBackDrop() {\n return new Backdrop({\n isVisible: Boolean(this._config.backdrop),\n // 'static' option will be translated to true, and booleans will keep their value,\n isAnimated: this._isAnimated()\n });\n }\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n });\n }\n _showElement(relatedTarget) {\n // try to append dynamic modal\n if (!document.body.contains(this._element)) {\n document.body.append(this._element);\n }\n this._element.style.display = 'block';\n this._element.removeAttribute('aria-hidden');\n this._element.setAttribute('aria-modal', true);\n this._element.setAttribute('role', 'dialog');\n this._element.scrollTop = 0;\n const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog);\n if (modalBody) {\n modalBody.scrollTop = 0;\n }\n reflow(this._element);\n this._element.classList.add(CLASS_NAME_SHOW$4);\n const transitionComplete = () => {\n if (this._config.focus) {\n this._focustrap.activate();\n }\n this._isTransitioning = false;\n EventHandler.trigger(this._element, EVENT_SHOWN$4, {\n relatedTarget\n });\n };\n this._queueCallback(transitionComplete, this._dialog, this._isAnimated());\n }\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => {\n if (event.key !== ESCAPE_KEY$1) {\n return;\n }\n if (this._config.keyboard) {\n this.hide();\n return;\n }\n this._triggerBackdropTransition();\n });\n EventHandler.on(window, EVENT_RESIZE$1, () => {\n if (this._isShown && !this._isTransitioning) {\n this._adjustDialog();\n }\n });\n EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => {\n // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks\n EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => {\n if (this._element !== event.target || this._element !== event2.target) {\n return;\n }\n if (this._config.backdrop === 'static') {\n this._triggerBackdropTransition();\n return;\n }\n if (this._config.backdrop) {\n this.hide();\n }\n });\n });\n }\n _hideModal() {\n this._element.style.display = 'none';\n this._element.setAttribute('aria-hidden', true);\n this._element.removeAttribute('aria-modal');\n this._element.removeAttribute('role');\n this._isTransitioning = false;\n this._backdrop.hide(() => {\n document.body.classList.remove(CLASS_NAME_OPEN);\n this._resetAdjustments();\n this._scrollBar.reset();\n EventHandler.trigger(this._element, EVENT_HIDDEN$4);\n });\n }\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_FADE$3);\n }\n _triggerBackdropTransition() {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1);\n if (hideEvent.defaultPrevented) {\n return;\n }\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n const initialOverflowY = this._element.style.overflowY;\n // return if the following background transition hasn't yet completed\n if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {\n return;\n }\n if (!isModalOverflowing) {\n this._element.style.overflowY = 'hidden';\n }\n this._element.classList.add(CLASS_NAME_STATIC);\n this._queueCallback(() => {\n this._element.classList.remove(CLASS_NAME_STATIC);\n this._queueCallback(() => {\n this._element.style.overflowY = initialOverflowY;\n }, this._dialog);\n }, this._dialog);\n this._element.focus();\n }\n\n /**\n * The following methods are used to handle overflowing modals\n */\n\n _adjustDialog() {\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n const scrollbarWidth = this._scrollBar.getWidth();\n const isBodyOverflowing = scrollbarWidth > 0;\n if (isBodyOverflowing && !isModalOverflowing) {\n const property = isRTL() ? 'paddingLeft' : 'paddingRight';\n this._element.style[property] = `${scrollbarWidth}px`;\n }\n if (!isBodyOverflowing && isModalOverflowing) {\n const property = isRTL() ? 'paddingRight' : 'paddingLeft';\n this._element.style[property] = `${scrollbarWidth}px`;\n }\n }\n _resetAdjustments() {\n this._element.style.paddingLeft = '';\n this._element.style.paddingRight = '';\n }\n\n // Static\n static jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n const data = Modal.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](relatedTarget);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n EventHandler.one(target, EVENT_SHOW$4, showEvent => {\n if (showEvent.defaultPrevented) {\n // only register focus restorer if modal will actually get shown\n return;\n }\n EventHandler.one(target, EVENT_HIDDEN$4, () => {\n if (isVisible(this)) {\n this.focus();\n }\n });\n });\n\n // avoid conflict when clicking modal toggler while another one is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1);\n if (alreadyOpen) {\n Modal.getInstance(alreadyOpen).hide();\n }\n const data = Modal.getOrCreateInstance(target);\n data.toggle(this);\n});\nenableDismissTrigger(Modal);\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Modal);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap offcanvas.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$6 = 'offcanvas';\nconst DATA_KEY$3 = 'bs.offcanvas';\nconst EVENT_KEY$3 = `.${DATA_KEY$3}`;\nconst DATA_API_KEY$1 = '.data-api';\nconst EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`;\nconst ESCAPE_KEY = 'Escape';\nconst CLASS_NAME_SHOW$3 = 'show';\nconst CLASS_NAME_SHOWING$1 = 'showing';\nconst CLASS_NAME_HIDING = 'hiding';\nconst CLASS_NAME_BACKDROP = 'offcanvas-backdrop';\nconst OPEN_SELECTOR = '.offcanvas.show';\nconst EVENT_SHOW$3 = `show${EVENT_KEY$3}`;\nconst EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`;\nconst EVENT_HIDE$3 = `hide${EVENT_KEY$3}`;\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`;\nconst EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`;\nconst EVENT_RESIZE = `resize${EVENT_KEY$3}`;\nconst EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`;\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`;\nconst SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle=\"offcanvas\"]';\nconst Default$5 = {\n backdrop: true,\n keyboard: true,\n scroll: false\n};\nconst DefaultType$5 = {\n backdrop: '(boolean|string)',\n keyboard: 'boolean',\n scroll: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Offcanvas extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._isShown = false;\n this._backdrop = this._initializeBackDrop();\n this._focustrap = this._initializeFocusTrap();\n this._addEventListeners();\n }\n\n // Getters\n static get Default() {\n return Default$5;\n }\n static get DefaultType() {\n return DefaultType$5;\n }\n static get NAME() {\n return NAME$6;\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget);\n }\n show(relatedTarget) {\n if (this._isShown) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, {\n relatedTarget\n });\n if (showEvent.defaultPrevented) {\n return;\n }\n this._isShown = true;\n this._backdrop.show();\n if (!this._config.scroll) {\n new ScrollBarHelper().hide();\n }\n this._element.setAttribute('aria-modal', true);\n this._element.setAttribute('role', 'dialog');\n this._element.classList.add(CLASS_NAME_SHOWING$1);\n const completeCallBack = () => {\n if (!this._config.scroll || this._config.backdrop) {\n this._focustrap.activate();\n }\n this._element.classList.add(CLASS_NAME_SHOW$3);\n this._element.classList.remove(CLASS_NAME_SHOWING$1);\n EventHandler.trigger(this._element, EVENT_SHOWN$3, {\n relatedTarget\n });\n };\n this._queueCallback(completeCallBack, this._element, true);\n }\n hide() {\n if (!this._isShown) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3);\n if (hideEvent.defaultPrevented) {\n return;\n }\n this._focustrap.deactivate();\n this._element.blur();\n this._isShown = false;\n this._element.classList.add(CLASS_NAME_HIDING);\n this._backdrop.hide();\n const completeCallback = () => {\n this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING);\n this._element.removeAttribute('aria-modal');\n this._element.removeAttribute('role');\n if (!this._config.scroll) {\n new ScrollBarHelper().reset();\n }\n EventHandler.trigger(this._element, EVENT_HIDDEN$3);\n };\n this._queueCallback(completeCallback, this._element, true);\n }\n dispose() {\n this._backdrop.dispose();\n this._focustrap.deactivate();\n super.dispose();\n }\n\n // Private\n _initializeBackDrop() {\n const clickCallback = () => {\n if (this._config.backdrop === 'static') {\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);\n return;\n }\n this.hide();\n };\n\n // 'static' option will be translated to true, and booleans will keep their value\n const isVisible = Boolean(this._config.backdrop);\n return new Backdrop({\n className: CLASS_NAME_BACKDROP,\n isVisible,\n isAnimated: true,\n rootElement: this._element.parentNode,\n clickCallback: isVisible ? clickCallback : null\n });\n }\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n });\n }\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return;\n }\n if (this._config.keyboard) {\n this.hide();\n return;\n }\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);\n });\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Offcanvas.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](this);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n if (isDisabled(this)) {\n return;\n }\n EventHandler.one(target, EVENT_HIDDEN$3, () => {\n // focus on trigger when it is closed\n if (isVisible(this)) {\n this.focus();\n }\n });\n\n // avoid conflict when clicking a toggler of an offcanvas, while another is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR);\n if (alreadyOpen && alreadyOpen !== target) {\n Offcanvas.getInstance(alreadyOpen).hide();\n }\n const data = Offcanvas.getOrCreateInstance(target);\n data.toggle(this);\n});\nEventHandler.on(window, EVENT_LOAD_DATA_API$2, () => {\n for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {\n Offcanvas.getOrCreateInstance(selector).show();\n }\n});\nEventHandler.on(window, EVENT_RESIZE, () => {\n for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {\n if (getComputedStyle(element).position !== 'fixed') {\n Offcanvas.getOrCreateInstance(element).hide();\n }\n }\n});\nenableDismissTrigger(Offcanvas);\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Offcanvas);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n// js-docs-start allow-list\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\nconst DefaultAllowlist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n};\n// js-docs-end allow-list\n\nconst uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);\n\n/**\n * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation\n * contexts.\n *\n * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38\n */\n// eslint-disable-next-line unicorn/better-regex\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;\nconst allowedAttribute = (attribute, allowedAttributeList) => {\n const attributeName = attribute.nodeName.toLowerCase();\n if (allowedAttributeList.includes(attributeName)) {\n if (uriAttributes.has(attributeName)) {\n return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue));\n }\n return true;\n }\n\n // Check if a regular expression validates the attribute.\n return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName));\n};\nfunction sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {\n if (!unsafeHtml.length) {\n return unsafeHtml;\n }\n if (sanitizeFunction && typeof sanitizeFunction === 'function') {\n return sanitizeFunction(unsafeHtml);\n }\n const domParser = new window.DOMParser();\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n const elements = [].concat(...createdDocument.body.querySelectorAll('*'));\n for (const element of elements) {\n const elementName = element.nodeName.toLowerCase();\n if (!Object.keys(allowList).includes(elementName)) {\n element.remove();\n continue;\n }\n const attributeList = [].concat(...element.attributes);\n const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);\n for (const attribute of attributeList) {\n if (!allowedAttribute(attribute, allowedAttributes)) {\n element.removeAttribute(attribute.nodeName);\n }\n }\n }\n return createdDocument.body.innerHTML;\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/template-factory.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$5 = 'TemplateFactory';\nconst Default$4 = {\n allowList: DefaultAllowlist,\n content: {},\n // { selector : text , selector2 : text2 , }\n extraClass: '',\n html: false,\n sanitize: true,\n sanitizeFn: null,\n template: '
'\n};\nconst DefaultType$4 = {\n allowList: 'object',\n content: 'object',\n extraClass: '(string|function)',\n html: 'boolean',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n template: 'string'\n};\nconst DefaultContentType = {\n entry: '(string|element|function|null)',\n selector: '(string|element)'\n};\n\n/**\n * Class definition\n */\n\nclass TemplateFactory extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n }\n\n // Getters\n static get Default() {\n return Default$4;\n }\n static get DefaultType() {\n return DefaultType$4;\n }\n static get NAME() {\n return NAME$5;\n }\n\n // Public\n getContent() {\n return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean);\n }\n hasContent() {\n return this.getContent().length > 0;\n }\n changeContent(content) {\n this._checkContent(content);\n this._config.content = {\n ...this._config.content,\n ...content\n };\n return this;\n }\n toHtml() {\n const templateWrapper = document.createElement('div');\n templateWrapper.innerHTML = this._maybeSanitize(this._config.template);\n for (const [selector, text] of Object.entries(this._config.content)) {\n this._setContent(templateWrapper, text, selector);\n }\n const template = templateWrapper.children[0];\n const extraClass = this._resolvePossibleFunction(this._config.extraClass);\n if (extraClass) {\n template.classList.add(...extraClass.split(' '));\n }\n return template;\n }\n\n // Private\n _typeCheckConfig(config) {\n super._typeCheckConfig(config);\n this._checkContent(config.content);\n }\n _checkContent(arg) {\n for (const [selector, content] of Object.entries(arg)) {\n super._typeCheckConfig({\n selector,\n entry: content\n }, DefaultContentType);\n }\n }\n _setContent(template, content, selector) {\n const templateElement = SelectorEngine.findOne(selector, template);\n if (!templateElement) {\n return;\n }\n content = this._resolvePossibleFunction(content);\n if (!content) {\n templateElement.remove();\n return;\n }\n if (isElement(content)) {\n this._putElementInTemplate(getElement(content), templateElement);\n return;\n }\n if (this._config.html) {\n templateElement.innerHTML = this._maybeSanitize(content);\n return;\n }\n templateElement.textContent = content;\n }\n _maybeSanitize(arg) {\n return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;\n }\n _resolvePossibleFunction(arg) {\n return execute(arg, [this]);\n }\n _putElementInTemplate(element, templateElement) {\n if (this._config.html) {\n templateElement.innerHTML = '';\n templateElement.append(element);\n return;\n }\n templateElement.textContent = element.textContent;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$4 = 'tooltip';\nconst DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);\nconst CLASS_NAME_FADE$2 = 'fade';\nconst CLASS_NAME_MODAL = 'modal';\nconst CLASS_NAME_SHOW$2 = 'show';\nconst SELECTOR_TOOLTIP_INNER = '.tooltip-inner';\nconst SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;\nconst EVENT_MODAL_HIDE = 'hide.bs.modal';\nconst TRIGGER_HOVER = 'hover';\nconst TRIGGER_FOCUS = 'focus';\nconst TRIGGER_CLICK = 'click';\nconst TRIGGER_MANUAL = 'manual';\nconst EVENT_HIDE$2 = 'hide';\nconst EVENT_HIDDEN$2 = 'hidden';\nconst EVENT_SHOW$2 = 'show';\nconst EVENT_SHOWN$2 = 'shown';\nconst EVENT_INSERTED = 'inserted';\nconst EVENT_CLICK$1 = 'click';\nconst EVENT_FOCUSIN$1 = 'focusin';\nconst EVENT_FOCUSOUT$1 = 'focusout';\nconst EVENT_MOUSEENTER = 'mouseenter';\nconst EVENT_MOUSELEAVE = 'mouseleave';\nconst AttachmentMap = {\n AUTO: 'auto',\n TOP: 'top',\n RIGHT: isRTL() ? 'left' : 'right',\n BOTTOM: 'bottom',\n LEFT: isRTL() ? 'right' : 'left'\n};\nconst Default$3 = {\n allowList: DefaultAllowlist,\n animation: true,\n boundary: 'clippingParents',\n container: false,\n customClass: '',\n delay: 0,\n fallbackPlacements: ['top', 'right', 'bottom', 'left'],\n html: false,\n offset: [0, 6],\n placement: 'top',\n popperConfig: null,\n sanitize: true,\n sanitizeFn: null,\n selector: false,\n template: '
' + '
' + '
' + '
',\n title: '',\n trigger: 'hover focus'\n};\nconst DefaultType$3 = {\n allowList: 'object',\n animation: 'boolean',\n boundary: '(string|element)',\n container: '(string|element|boolean)',\n customClass: '(string|function)',\n delay: '(number|object)',\n fallbackPlacements: 'array',\n html: 'boolean',\n offset: '(array|string|function)',\n placement: '(string|function)',\n popperConfig: '(null|object|function)',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n selector: '(string|boolean)',\n template: 'string',\n title: '(string|element|function)',\n trigger: 'string'\n};\n\n/**\n * Class definition\n */\n\nclass Tooltip extends BaseComponent {\n constructor(element, config) {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper (https://popper.js.org)');\n }\n super(element, config);\n\n // Private\n this._isEnabled = true;\n this._timeout = 0;\n this._isHovered = null;\n this._activeTrigger = {};\n this._popper = null;\n this._templateFactory = null;\n this._newContent = null;\n\n // Protected\n this.tip = null;\n this._setListeners();\n if (!this._config.selector) {\n this._fixTitle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$3;\n }\n static get DefaultType() {\n return DefaultType$3;\n }\n static get NAME() {\n return NAME$4;\n }\n\n // Public\n enable() {\n this._isEnabled = true;\n }\n disable() {\n this._isEnabled = false;\n }\n toggleEnabled() {\n this._isEnabled = !this._isEnabled;\n }\n toggle() {\n if (!this._isEnabled) {\n return;\n }\n this._activeTrigger.click = !this._activeTrigger.click;\n if (this._isShown()) {\n this._leave();\n return;\n }\n this._enter();\n }\n dispose() {\n clearTimeout(this._timeout);\n EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);\n if (this._element.getAttribute('data-bs-original-title')) {\n this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));\n }\n this._disposePopper();\n super.dispose();\n }\n show() {\n if (this._element.style.display === 'none') {\n throw new Error('Please use show on visible elements');\n }\n if (!(this._isWithContent() && this._isEnabled)) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2));\n const shadowRoot = findShadowRoot(this._element);\n const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);\n if (showEvent.defaultPrevented || !isInTheDom) {\n return;\n }\n\n // TODO: v6 remove this or make it optional\n this._disposePopper();\n const tip = this._getTipElement();\n this._element.setAttribute('aria-describedby', tip.getAttribute('id'));\n const {\n container\n } = this._config;\n if (!this._element.ownerDocument.documentElement.contains(this.tip)) {\n container.append(tip);\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));\n }\n this._popper = this._createPopper(tip);\n tip.classList.add(CLASS_NAME_SHOW$2);\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop);\n }\n }\n const complete = () => {\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2));\n if (this._isHovered === false) {\n this._leave();\n }\n this._isHovered = false;\n };\n this._queueCallback(complete, this.tip, this._isAnimated());\n }\n hide() {\n if (!this._isShown()) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2));\n if (hideEvent.defaultPrevented) {\n return;\n }\n const tip = this._getTipElement();\n tip.classList.remove(CLASS_NAME_SHOW$2);\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop);\n }\n }\n this._activeTrigger[TRIGGER_CLICK] = false;\n this._activeTrigger[TRIGGER_FOCUS] = false;\n this._activeTrigger[TRIGGER_HOVER] = false;\n this._isHovered = null; // it is a trick to support manual triggering\n\n const complete = () => {\n if (this._isWithActiveTrigger()) {\n return;\n }\n if (!this._isHovered) {\n this._disposePopper();\n }\n this._element.removeAttribute('aria-describedby');\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2));\n };\n this._queueCallback(complete, this.tip, this._isAnimated());\n }\n update() {\n if (this._popper) {\n this._popper.update();\n }\n }\n\n // Protected\n _isWithContent() {\n return Boolean(this._getTitle());\n }\n _getTipElement() {\n if (!this.tip) {\n this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());\n }\n return this.tip;\n }\n _createTipElement(content) {\n const tip = this._getTemplateFactory(content).toHtml();\n\n // TODO: remove this check in v6\n if (!tip) {\n return null;\n }\n tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2);\n // TODO: v6 the following can be achieved with CSS only\n tip.classList.add(`bs-${this.constructor.NAME}-auto`);\n const tipId = getUID(this.constructor.NAME).toString();\n tip.setAttribute('id', tipId);\n if (this._isAnimated()) {\n tip.classList.add(CLASS_NAME_FADE$2);\n }\n return tip;\n }\n setContent(content) {\n this._newContent = content;\n if (this._isShown()) {\n this._disposePopper();\n this.show();\n }\n }\n _getTemplateFactory(content) {\n if (this._templateFactory) {\n this._templateFactory.changeContent(content);\n } else {\n this._templateFactory = new TemplateFactory({\n ...this._config,\n // the `content` var has to be after `this._config`\n // to override config.content in case of popover\n content,\n extraClass: this._resolvePossibleFunction(this._config.customClass)\n });\n }\n return this._templateFactory;\n }\n _getContentForTemplate() {\n return {\n [SELECTOR_TOOLTIP_INNER]: this._getTitle()\n };\n }\n _getTitle() {\n return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');\n }\n\n // Private\n _initializeOnDelegatedTarget(event) {\n return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());\n }\n _isAnimated() {\n return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2);\n }\n _isShown() {\n return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2);\n }\n _createPopper(tip) {\n const placement = execute(this._config.placement, [this, tip, this._element]);\n const attachment = AttachmentMap[placement.toUpperCase()];\n return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment));\n }\n _getOffset() {\n const {\n offset\n } = this._config;\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10));\n }\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element);\n }\n return offset;\n }\n _resolvePossibleFunction(arg) {\n return execute(arg, [this._element]);\n }\n _getPopperConfig(attachment) {\n const defaultBsPopperConfig = {\n placement: attachment,\n modifiers: [{\n name: 'flip',\n options: {\n fallbackPlacements: this._config.fallbackPlacements\n }\n }, {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }, {\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n }, {\n name: 'arrow',\n options: {\n element: `.${this.constructor.NAME}-arrow`\n }\n }, {\n name: 'preSetPlacement',\n enabled: true,\n phase: 'beforeMain',\n fn: data => {\n // Pre-set Popper's placement attribute in order to read the arrow sizes properly.\n // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement\n this._getTipElement().setAttribute('data-popper-placement', data.state.placement);\n }\n }]\n };\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n };\n }\n _setListeners() {\n const triggers = this._config.trigger.split(' ');\n for (const trigger of triggers) {\n if (trigger === 'click') {\n EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context.toggle();\n });\n } else if (trigger !== TRIGGER_MANUAL) {\n const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1);\n const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1);\n EventHandler.on(this._element, eventIn, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;\n context._enter();\n });\n EventHandler.on(this._element, eventOut, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);\n context._leave();\n });\n }\n }\n this._hideModalHandler = () => {\n if (this._element) {\n this.hide();\n }\n };\n EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);\n }\n _fixTitle() {\n const title = this._element.getAttribute('title');\n if (!title) {\n return;\n }\n if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {\n this._element.setAttribute('aria-label', title);\n }\n this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility\n this._element.removeAttribute('title');\n }\n _enter() {\n if (this._isShown() || this._isHovered) {\n this._isHovered = true;\n return;\n }\n this._isHovered = true;\n this._setTimeout(() => {\n if (this._isHovered) {\n this.show();\n }\n }, this._config.delay.show);\n }\n _leave() {\n if (this._isWithActiveTrigger()) {\n return;\n }\n this._isHovered = false;\n this._setTimeout(() => {\n if (!this._isHovered) {\n this.hide();\n }\n }, this._config.delay.hide);\n }\n _setTimeout(handler, timeout) {\n clearTimeout(this._timeout);\n this._timeout = setTimeout(handler, timeout);\n }\n _isWithActiveTrigger() {\n return Object.values(this._activeTrigger).includes(true);\n }\n _getConfig(config) {\n const dataAttributes = Manipulator.getDataAttributes(this._element);\n for (const dataAttribute of Object.keys(dataAttributes)) {\n if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {\n delete dataAttributes[dataAttribute];\n }\n }\n config = {\n ...dataAttributes,\n ...(typeof config === 'object' && config ? config : {})\n };\n config = this._mergeConfigObj(config);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n _configAfterMerge(config) {\n config.container = config.container === false ? document.body : getElement(config.container);\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n };\n }\n if (typeof config.title === 'number') {\n config.title = config.title.toString();\n }\n if (typeof config.content === 'number') {\n config.content = config.content.toString();\n }\n return config;\n }\n _getDelegateConfig() {\n const config = {};\n for (const [key, value] of Object.entries(this._config)) {\n if (this.constructor.Default[key] !== value) {\n config[key] = value;\n }\n }\n config.selector = false;\n config.trigger = 'manual';\n\n // In the future can be replaced with:\n // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])\n // `Object.fromEntries(keysWithDifferentValues)`\n return config;\n }\n _disposePopper() {\n if (this._popper) {\n this._popper.destroy();\n this._popper = null;\n }\n if (this.tip) {\n this.tip.remove();\n this.tip = null;\n }\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Tooltip.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Tooltip);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$3 = 'popover';\nconst SELECTOR_TITLE = '.popover-header';\nconst SELECTOR_CONTENT = '.popover-body';\nconst Default$2 = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '
' + '
' + '

' + '
' + '
',\n trigger: 'click'\n};\nconst DefaultType$2 = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n};\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default$2;\n }\n static get DefaultType() {\n return DefaultType$2;\n }\n static get NAME() {\n return NAME$3;\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent();\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n };\n }\n _getContent() {\n return this._resolvePossibleFunction(this._config.content);\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$2 = 'scrollspy';\nconst DATA_KEY$2 = 'bs.scrollspy';\nconst EVENT_KEY$2 = `.${DATA_KEY$2}`;\nconst DATA_API_KEY = '.data-api';\nconst EVENT_ACTIVATE = `activate${EVENT_KEY$2}`;\nconst EVENT_CLICK = `click${EVENT_KEY$2}`;\nconst EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`;\nconst CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';\nconst CLASS_NAME_ACTIVE$1 = 'active';\nconst SELECTOR_DATA_SPY = '[data-bs-spy=\"scroll\"]';\nconst SELECTOR_TARGET_LINKS = '[href]';\nconst SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\nconst SELECTOR_NAV_LINKS = '.nav-link';\nconst SELECTOR_NAV_ITEMS = '.nav-item';\nconst SELECTOR_LIST_ITEMS = '.list-group-item';\nconst SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;\nconst SELECTOR_DROPDOWN = '.dropdown';\nconst SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';\nconst Default$1 = {\n offset: null,\n // TODO: v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: '0px 0px -25%',\n smoothScroll: false,\n target: null,\n threshold: [0.1, 0.5, 1]\n};\nconst DefaultType$1 = {\n offset: '(number|null)',\n // TODO v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: 'string',\n smoothScroll: 'boolean',\n target: 'element',\n threshold: 'array'\n};\n\n/**\n * Class definition\n */\n\nclass ScrollSpy extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n\n // this._element is the observablesContainer and config.target the menu links wrapper\n this._targetLinks = new Map();\n this._observableSections = new Map();\n this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element;\n this._activeTarget = null;\n this._observer = null;\n this._previousScrollData = {\n visibleEntryTop: 0,\n parentScrollTop: 0\n };\n this.refresh(); // initialize\n }\n\n // Getters\n static get Default() {\n return Default$1;\n }\n static get DefaultType() {\n return DefaultType$1;\n }\n static get NAME() {\n return NAME$2;\n }\n\n // Public\n refresh() {\n this._initializeTargetsAndObservables();\n this._maybeEnableSmoothScroll();\n if (this._observer) {\n this._observer.disconnect();\n } else {\n this._observer = this._getNewObserver();\n }\n for (const section of this._observableSections.values()) {\n this._observer.observe(section);\n }\n }\n dispose() {\n this._observer.disconnect();\n super.dispose();\n }\n\n // Private\n _configAfterMerge(config) {\n // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case\n config.target = getElement(config.target) || document.body;\n\n // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only\n config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin;\n if (typeof config.threshold === 'string') {\n config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value));\n }\n return config;\n }\n _maybeEnableSmoothScroll() {\n if (!this._config.smoothScroll) {\n return;\n }\n\n // unregister any previous listeners\n EventHandler.off(this._config.target, EVENT_CLICK);\n EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {\n const observableSection = this._observableSections.get(event.target.hash);\n if (observableSection) {\n event.preventDefault();\n const root = this._rootElement || window;\n const height = observableSection.offsetTop - this._element.offsetTop;\n if (root.scrollTo) {\n root.scrollTo({\n top: height,\n behavior: 'smooth'\n });\n return;\n }\n\n // Chrome 60 doesn't support `scrollTo`\n root.scrollTop = height;\n }\n });\n }\n _getNewObserver() {\n const options = {\n root: this._rootElement,\n threshold: this._config.threshold,\n rootMargin: this._config.rootMargin\n };\n return new IntersectionObserver(entries => this._observerCallback(entries), options);\n }\n\n // The logic of selection\n _observerCallback(entries) {\n const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`);\n const activate = entry => {\n this._previousScrollData.visibleEntryTop = entry.target.offsetTop;\n this._process(targetElement(entry));\n };\n const parentScrollTop = (this._rootElement || document.documentElement).scrollTop;\n const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop;\n this._previousScrollData.parentScrollTop = parentScrollTop;\n for (const entry of entries) {\n if (!entry.isIntersecting) {\n this._activeTarget = null;\n this._clearActiveClass(targetElement(entry));\n continue;\n }\n const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop;\n // if we are scrolling down, pick the bigger offsetTop\n if (userScrollsDown && entryIsLowerThanPrevious) {\n activate(entry);\n // if parent isn't scrolled, let's keep the first visible item, breaking the iteration\n if (!parentScrollTop) {\n return;\n }\n continue;\n }\n\n // if we are scrolling up, pick the smallest offsetTop\n if (!userScrollsDown && !entryIsLowerThanPrevious) {\n activate(entry);\n }\n }\n }\n _initializeTargetsAndObservables() {\n this._targetLinks = new Map();\n this._observableSections = new Map();\n const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target);\n for (const anchor of targetLinks) {\n // ensure that the anchor has an id and is not disabled\n if (!anchor.hash || isDisabled(anchor)) {\n continue;\n }\n const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element);\n\n // ensure that the observableSection exists & is visible\n if (isVisible(observableSection)) {\n this._targetLinks.set(decodeURI(anchor.hash), anchor);\n this._observableSections.set(anchor.hash, observableSection);\n }\n }\n }\n _process(target) {\n if (this._activeTarget === target) {\n return;\n }\n this._clearActiveClass(this._config.target);\n this._activeTarget = target;\n target.classList.add(CLASS_NAME_ACTIVE$1);\n this._activateParents(target);\n EventHandler.trigger(this._element, EVENT_ACTIVATE, {\n relatedTarget: target\n });\n }\n _activateParents(target) {\n // Activate dropdown parents\n if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {\n SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1);\n return;\n }\n for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {\n // Set triggered links parents as active\n // With both
+ + + + + + + + + + + + + + + - - -
+ + + +
+

Литература

+ +
+
+ +
-
-
- -
-

Литература

- -
-
- -
-
-
-
- -
+
+ + + +
+
-

Литература#

+

Литература#

-
-
ADPP92
-

M. J. Assael, J. H. Dymond, M. Papadaki, and P. M. Patterson. Correlation and prediction of dense fluid transport coefficients. I. n-alkanes. International Journal of Thermophysics, 13(2):269–281, 1992. doi:10.1007/bf00504436.

-
-
BPL82
-

L. E. Baker, A. C. Pierce, and K. D. Luks. Gibbs energy analysis of phase equilibria. Society of Petroleum Engineers Journal, 22(5):731–742, 1982. doi:10.2118/9806-PA.

-
-
BEKS17
-

J. Bezanson, A. Edelman, S. Karpinski, and V. B. Shah. Julia: a fresh approach to numerical computing. SIAM Review, 59(1):65–98, 2017. doi:10.1137/141000671.

-
-
DB17
-

T. A. Driscoll and R. J. Braun. Fundamentals of numerical computation. Society for Industrial and Applied Mathematics, 2017. ISBN 978-1-61197-507-9. URL: https://tobydriscoll.net/project/fnc/.

-
-
GS01
-

J. Gross and G. Sadowski. Perturbed-chain SAFT: an equation of state based on a perturbation theory for chain molecules. Industrial & Engineering Chemistry Research, 40(4):1244–1260, 2001. doi:10.1021/ie0003887.

-
-
Joh14
-

David Johnston. Advances in thermodynamics of the van der waals fluid. arXiv, 2014. doi:10.1088/978-1-627-05532-1.

-
-
KM86
-

T.Y. Kwak and G.A. Mansoori. Van der waals mixing rules for cubic equations of state. applications for supercritical fluid extraction modelling. Chemical Engineering Science, 41(5):1303–1309, 1986. doi:10.1016/0009-2509(86)87103-2.

-
-
Kwo20
-

T. Kwong. Hands-on design patterns and best practices with Julia: proven solutions to common problems in software design for Julia 1.x. Packt Publishing, 2020. ISBN 9781838648817.

-
-
Lek82
-

J. Lekner. Parametric solution of the van der waals liquid–vapor coexistence curve. American Journal of Physics, 50(2):161–163, 1982. doi:10.1119/1.12877.

-
-
LeV02
-

R. J. LeVeque. Finite Volume Methods for Hyperbolic Problems. Cambridge University Press, 2002. doi:10.1017/cbo9780511791253.

-
-
Mic82a
-

M. L. Michelsen. The isothermal flash problem. part II. phase-split calculation. Fluid Phase Equilibria, 9(1):21–40, 1982. doi:10.1016/0378-3812(82)85002-4.

-
-
Mic82b
-

M. L. Michelsen. The isothermal flash problem. part I. stability. Fluid Phase Equilibria, 9(1):1–19, 1982. doi:10.1016/0378-3812(82)85001-2.

-
-
OT20
-

I. F. D. Oliveira and R. H. C. Takahashi. An enhancement of the bisection method average performance preserving minmax optimality. ACM Transactions on Mathematical Software, 2020. doi:10.1145/3423597.

-
-
PTVF07
-

W. H. Press, S. A. Teukolsky, W. T. Vetterling, and B. P. Flannery. Numerical Recipes 3rd Edition: The Art of Scientific Computing. Cambridge University Press, USA, 3 edition, 2007. ISBN 0521880688.

-
-
Rid79
-

C. Ridders. A new algorithm for computing a single root of a real continuous function. IEEE Transactions on Circuits and Systems, 26(11):979–980, 1979. doi:10.1109/TCS.1979.1084580.

-
-
02
-

А.И. Брусиловский. Фазовые превращения при разработке месторождений нефти и газа. ВИНИТИ РАН, Грааль, 2002. ISBN 5-94688-031-4.

-
-
16
-

Рябенький В.С. Введение в вычислительную математику. Физматлит, Москва, 3 edition, 2016. ISBN 978-5-9221-0926-0.

-
-
71
-

И. Ф. Голубев and Н. Е. Гнездилов. Вязкость газовых смесей. Издательство государственного комитета стандартов кабинета министров СССР, Москва, 1971.

-
-
89
-

А. А. Самарский and А. В. Гулин. Численные методы: учеб. пособие для вузов. Наука, Москва, 1989. ISBN 978-5020139961.

-
-
+
+[ADPP92] +

M. J. Assael, J. H. Dymond, M. Papadaki, and P. M. Patterson. Correlation and prediction of dense fluid transport coefficients. I. n-alkanes. International Journal of Thermophysics, 13(2):269–281, 1992. doi:10.1007/bf00504436.

+
+
+[BPL82] +

L. E. Baker, A. C. Pierce, and K. D. Luks. Gibbs energy analysis of phase equilibria. Society of Petroleum Engineers Journal, 22(5):731–742, 1982. doi:10.2118/9806-PA.

+
+
+[BPRS18] +

Atilim Gunes Baydin, Barak A. Pearlmutter, Alexey Andreyevich Radul, and Jeffrey Mark Siskind. Automatic differentiation in machine learning: a survey. Journal of Machine Learning Research, 18:1–43, 2018. URL: https://jmlr.org/papers/v18/17-468.html.

+
+
+[BEKS17] +

J. Bezanson, A. Edelman, S. Karpinski, and V. B. Shah. Julia: a fresh approach to numerical computing. SIAM Review, 59(1):65–98, 2017. doi:10.1137/141000671.

+
+
+[DB17] +

T. A. Driscoll and R. J. Braun. Fundamentals of numerical computation. Society for Industrial and Applied Mathematics, 2017. ISBN 978-1-61197-507-9. URL: https://tobydriscoll.net/project/fnc/.

+
+
+[Gri12] +

Andreas Griewank. Who invented the reverse mode of differentiation? In Martin Grötschel, editor, Optimization Stories, pages 389–400. EMS Press, 2012. doi:10.4171/dms/6/38.

+
+
+[GS01] +

J. Gross and G. Sadowski. Perturbed-chain SAFT: an equation of state based on a perturbation theory for chain molecules. Industrial & Engineering Chemistry Research, 40(4):1244–1260, 2001. doi:10.1021/ie0003887.

+
+
+[Inn18] +

Michael Innes. Don't unroll adjoint: differentiating ssa-form programs. CoRR, 2018. doi:https://doi.org/10.48550/arXiv.1810.07951.

+
+
+[Joh14] +

David Johnston. Advances in thermodynamics of the van der waals fluid. arXiv, 2014. doi:10.1088/978-1-627-05532-1.

+
+
+[KW19] +

Mykel J. Kochenderfer and Tim A. Wheeler. Algorithms for optimization. The MIT Press, 2019. ISBN 978-0-262-03942-0.

+
+
+[KM86] +

T.Y. Kwak and G.A. Mansoori. Van der waals mixing rules for cubic equations of state. applications for supercritical fluid extraction modelling. Chemical Engineering Science, 41(5):1303–1309, 1986. doi:10.1016/0009-2509(86)87103-2.

+
+
+[Kwo20] +

T. Kwong. Hands-on design patterns and best practices with Julia: proven solutions to common problems in software design for Julia 1.x. Packt Publishing, 2020. ISBN 9781838648817.

+
+
+[Lek82] +

J. Lekner. Parametric solution of the van der waals liquid–vapor coexistence curve. American Journal of Physics, 50(2):161–163, 1982. doi:10.1119/1.12877.

+
+
+[LeV02] +

R. J. LeVeque. Finite Volume Methods for Hyperbolic Problems. Cambridge University Press, 2002. doi:10.1017/cbo9780511791253.

+
+
+[MSA03] +

Joaquim R. R. A. Martins, Peter Sturdza, and Juan J. Alonso. The complex-step derivative approximation. ACM Transactions on Mathematical Software, 29(3):245–262, 2003. doi:10.1145/838250.838251.

+
+
+[Mic82a] +

M. L. Michelsen. The isothermal flash problem. part II. phase-split calculation. Fluid Phase Equilibria, 9(1):21–40, 1982. doi:10.1016/0378-3812(82)85002-4.

+
+
+[Mic82b] +

M. L. Michelsen. The isothermal flash problem. part I. stability. Fluid Phase Equilibria, 9(1):1–19, 1982. doi:10.1016/0378-3812(82)85001-2.

+
+
+[OT20] +

I. F. D. Oliveira and R. H. C. Takahashi. An enhancement of the bisection method average performance preserving minmax optimality. ACM Transactions on Mathematical Software, 2020. doi:10.1145/3423597.

+
+
+[PTVF07] +

W. H. Press, S. A. Teukolsky, W. T. Vetterling, and B. P. Flannery. Numerical Recipes 3rd Edition: The Art of Scientific Computing. Cambridge University Press, USA, 3 edition, 2007. ISBN 0521880688.

+
+
+[RLP16] +

J. Revels, M. Lubin, and T. Papamarkou. Forward-mode automatic differentiation in Julia. arXiv:1607.07892 [cs.MS], 2016. URL: https://arxiv.org/abs/1607.07892.

+
+
+[Rid79] +

C. Ridders. A new algorithm for computing a single root of a real continuous function. IEEE Transactions on Circuits and Systems, 26(11):979–980, 1979. doi:10.1109/TCS.1979.1084580.

+
+
+[Wen64] +

R. E. Wengert. A simple automatic derivative evaluation program. Communications of the ACM, 7(8):463–464, 1964. doi:10.1145/355586.364791.

+
+
+[02] +

А.И. Брусиловский. Фазовые превращения при разработке месторождений нефти и газа. ВИНИТИ РАН, Грааль, 2002. ISBN 5-94688-031-4.

+
+
+[16] +

Рябенький В.С. Введение в вычислительную математику. Физматлит, Москва, 3 edition, 2016. ISBN 978-5-9221-0926-0.

+
+
+[71] +

И. Ф. Голубев and Н. Е. Гнездилов. Вязкость газовых смесей. Издательство государственного комитета стандартов кабинета министров СССР, Москва, 1971.

+
+
+[89] +

А. А. Самарский and А. В. Гулин. Численные методы: учеб. пособие для вузов. Наука, Москва, 1989. ISBN 978-5020139961.

+
+
@@ -757,7 +611,7 @@

ЛитератураЛитература - - - -

- + + + + +
+
+ +
- + + + + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/appendix/cholesky.html b/appendix/cholesky.html index c61652e..a7c5915 100644 --- a/appendix/cholesky.html +++ b/appendix/cholesky.html @@ -1,54 +1,64 @@ + - + + + - + Разложение Холецкого — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/appendix/genindex.html b/appendix/genindex.html deleted file mode 100644 index cc4df45..0000000 --- a/appendix/genindex.html +++ /dev/null @@ -1,753 +0,0 @@ - - - - - - - - - Указатель — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - -
-
- - -
-
-
-
-
- -
-

Указатель

- -
-
- -
-
-
-
- -
- -
-

Указатель#

-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/appendix/materials.html b/appendix/materials.html index 8065814..b77b308 100644 --- a/appendix/materials.html +++ b/appendix/materials.html @@ -1,54 +1,64 @@ + - + + + - + Дополнительные материалы — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + +
+ + + -
+ + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/appendix/solvecubic.html b/appendix/solvecubic.html index dc842bb..791ccc9 100644 --- a/appendix/solvecubic.html +++ b/appendix/solvecubic.html @@ -1,54 +1,64 @@ + - + + + - + Решение кубического уравнения — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/autodiff/backwardmode.html b/autodiff/backwardmode.html new file mode 100644 index 0000000..33e914f --- /dev/null +++ b/autodiff/backwardmode.html @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + 8.5. Автоматическое дифференцирование назад — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Автоматическое дифференцирование назад

+ +
+ +
+
+ + + + +
+ +
+

8.5. Автоматическое дифференцирование назад#

+

Автоматическое дифференцирование назад (обратное, backward mode, reverse accumulation) это вид автоматического дифференцирования, в котором вычисления производных распространяются от результата функции к её аргументам. +С историей открытия и авторства этого метода дифференцирования можно ознакомиться в работе [Gri12].

+

Мы приведём общий случай позже, а сейчас продемонстрируем алгоритм на примере функции из Раздела 8.3.

+
+\[f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3}\]
+
+../_images/graph-example.svg
+

Fig. 8.8 Граф вычислений функции \(f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3\).#

+
+
+

В отличие от дифференцирования вперёд, поставим задачу вычисления не одной, а сразу всех частных производных функции \(f\) по аргументам (т.е. найдём градиент)

+
+\[\begin{split}\nabla f (x_1, x_2, x_3) = \begin{bmatrix} +\partial f / \partial x_1 +\\ \partial f / \partial x_2 +\\ \partial f / \partial x_3 +\end{bmatrix}.\end{split}\]
+

Будем считать функцию \(f\) сложной (композитной) функцией промежуточных значений \(x_j\) (\(j = 1, \dots, 7\)) и воспользуемся правилом дифференцирования сложной функции. +Чтобы найти градиент \(\nabla f\), нам понадобится найти все частные производные вида

+
+\[\frac{\partial f}{\partial x_j}, \quad j = 1, \dots, 7,\]
+

при \(j = 1, 2, 3\) искомые производные составляют градиент.

+

Шаг 0. +Совершим обход графа вычислений (Рисунок 8.8) для нахождения (только) промежуточных значений

+
+\[x_1, \dots, x_7.\]
+

На Рисунке 8.9 показан результат этого обхода при вычислении \(f(1, 2, 3)\).

+
+../_images/graph-backward-first-traverse.svg
+

Fig. 8.9 Прямой обход графа вычислений \(f(1, 2, 3)\) для нахождения промежуточных значений (подписаны рядом с вершинами).#

+
+
+

Запомним промежуточные значения \(x_j\) и запомним граф вычислений, он понадобится далее. +На этом первый этап вычислений завершается.

+
+

Warning

+

В дальнейшем мы будем “переопределять” функцию \(f\) для упрощения нотации. +Более корректным было бы вводить новую функцию (со своим именем) на каждом шаге. +Например, при вычислении \(\partial f / \partial x_3\) на шаге 5 было бы корректней определить функцию \(g\)

+
+\[g = g(x_5(x_3), x_7(x_3)) = g(x_3),\]
+

производная которой совпадает с производной \(\partial f / \partial x_3\). +Вместо записи выше мы используем запись

+
+\[f = f(x_5(x_3), x_7(x_3)).\]
+
+

Шаг 1. +Мы будем искать производные “справа-налево”. +Произведём инициализацию алгоритма и вычислим одну (тривиальную) производную

+
+\[\frac{\partial f}{\partial x_7} = 1. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_7}(1, 2, 3) = 1.\]
+

Шаг 2. +Найдём производную \(\partial f / \partial x_6\). +Значение \(x_6\) явно влияет только на \(x_7 = x_6 / x_3\), поэтому (для вычисления производной) посчитаем, что \(f\) это сложная функция вида

+
+\[f = f(x_7(x_6)),\]
+

тогда

+
+\[\frac{\partial f}{\partial x_6} += \frac{\partial f}{\partial x_7} \frac{\partial x_7}{\partial x_6} += 1 \times \frac{1}{x_3} += \frac{1}{x_3} +. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_6}(1, 2, 3) = \frac{1}{3}.\]
+

Здесь производная \(\partial f / \partial x_7\) нам известна с шага 1, а производная \(\partial x_7 / \partial x_6\) определяется из явной связи \(x_7 = x_6 / x_3\). +Отметим, что эта явная связь нам известна из графа вычислений, сохранённом на шаге 0.

+

Шаг 3. +Найдём производную \(\partial f / \partial x_5\). +Значение \(x_5\) явно влияет только на \(x_6\), поэтому представим \(f\) в виде

+
+\[f = f(x_6(x_5)),\]
+

тогда

+
+\[\frac{\partial f}{\partial x_5} += \frac{\partial f}{\partial x_6} \frac{\partial x_6}{\partial x_5} += \frac{1}{x_3} \times 1 += \frac{1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_5}(1, 2, 3) = \frac{1}{3}.\]
+

Значение производной \(\partial f / \partial x_6\) нам известно с шага 2. +В свою очередь, связь \(x_6 = x_4 + x_5\) хранится в графе вычислений, что позволяет вычислить производную \(\partial x_6 / \partial x_5 = 1\).

+

Шаг 4. +Найдём производную \(\partial f / \partial x_4\). +Значение \(x_4\) явно влияет только на \(x_6 = x_4 + x_5\), и этот шаг аналогичен шагу 3.

+
+\[\begin{split}\begin{align} +f &= f(x_6(x_4)) +\\ +\frac{\partial f}{\partial x_4} +&= \frac{\partial f}{\partial x_6} \frac{\partial x_6}{\partial x_4} += \frac{1}{x_3} \times 1 += \frac{1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_4}(1, 2, 3) = \frac{1}{3}. +\end{align}\end{split}\]
+

Шаг 5. +Найдём производную \(\partial f / \partial x_3\). +Значение \(x_3\) явно влияет на \(x_5\) и \(x_7\), поэтому для вычисления производной представим \(f\) в виде

+
+\[f = f(x_5(x_3), x_7(x_3)),\]
+

тогда производная имеет вид

+
+\[\begin{split}\frac{\partial f}{\partial x_3} += \frac{\partial f}{\partial x_5} \frac{\partial x_5}{\partial x_3} + + \frac{\partial f}{\partial x_7} \frac{\partial x_7}{\partial x_3} += \frac{1}{x_3} \times \cos{x_3} + 1 \times \bigg[ - \frac{x_6}{x^2_3} \bigg] += \frac{\cos{x_3}}{x_3} - \frac{x_6}{x^2_3}. +\\ +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_3}(1, 2, 3) = \frac{\cos{3}}{3} - \frac{2 + \sin{3}}{9}.\end{split}\]
+

Здесь мы воспользовались правилом дифференцирования сложной функции. +Значения производных \(\partial f / \partial x_5\) и \(\partial f / \partial x_7\) известны с шагов 3 и 1, соответственно. +Для нахождения производных \(\partial x_5 / \partial x_3\) и \(\partial x_7 / \partial x_3\) мы пользуемся графом вычислений, в котором хранятся явные связи \(x_5 = \sin{x_3}\) и \(x_7 = x_6 / x_3\). +Значение \(x_6\) известно с шага 0.

+

Шаг 6. +Найдём производную \(\partial f / \partial x_2\). +Значение \(x_2\) явно влияет только на \(x_4\), поэтому для нахождения производной представим \(f\) в виде

+
+\[f = f(x_4(x_2)),\]
+

тогда производная имеет вид

+
+\[\frac{\partial f}{\partial x_2} += \frac{\partial f}{\partial x_4} \frac{\partial x_4}{\partial x_2} += \frac{1}{x_3} \times x_1 += \frac{x_1}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_2}(1, 2, 3) = \frac{1}{3}\]
+

Значение производной \(\partial f / \partial x_4\) известно с шага 4, а связь \(x_4 = x_1 x_2\) хранится в графе вычислений, что позволяет посчитать \(\partial x_4 / \partial x_2 = x_1\).

+

Шаг 7. +Последний шаг, вычислим производную \(\partial f / \partial x_1\). +Значение \(x_1\) влияет только на \(x_4\) и этот шаг аналогичен шагу 6.

+
+\[\begin{split}\begin{align} +f &= f(x_4(x_1)) +\\ +\frac{\partial f}{\partial x_1} +&= \frac{\partial f}{\partial x_4} \frac{\partial x_4}{\partial x_1} += \frac{1}{x_3} \times x_2 += \frac{x_2}{x_3}. +\quad +\color{gray} +\bigg\rvert +\ \frac{\partial f}{\partial x_1}(1, 2, 3) = \frac{2}{3} +\end{align}\end{split}\]
+

Итак, задача вычисления градиента в некоторой (одной) точке решена. +Отметим, что она решалась в два прохода по графу вычислений: прямому и обратному. +При обратном проходе мы интенсивно пользовались только одним правилом — правилом дифференцирования сложной функции.

+
+

8.5.1. Общий случай#

+

В общем случае для вычисления градиента функции вида \(f: \real^n \to \real\) ставится вычислить производные вида

+
+(8.8)#\[\frac{\partial f}{\partial x_j}, \quad j = 1, \dots, V,\ V \ge n,\]
+

где \(x_j\) это промежуточные значения (вершины графа вычислений). +Первые \(n\) штук \(x_j\) совпадают с аргументами функции \(f\), а последний \(x_V \equiv f\).

+

Для вычисления одной производной \(\partial f / \partial x_j\) функция \(f\) представляется в виде

+
+\[f = f(\{ x_k(x_j) \}_{k \in K}),\]
+

где \(\{ x_k(x_j) \}_{k \in K}\) это вершины, зависящие явно от \(x_j\)\(K\) множество индексов таких вершин). +На графе вычислений \(x_k\) соответствуют тем вершинам, у которых есть сток (ребро) из \(x_j\) в \(x_k\) (см. Рисунок 8.10).

+
+../_images/graph-backward-general.svg
+

Fig. 8.10 Общая схема графа вычислений производной \(\partial f / \partial x_j\) в автоматическом дифференцировании назад. +Явные связи между вершинами (т.е. дуги графа) показаны прямыми стрелками, а неявные — волнистыми.#

+
+
+

В этом представлении производная \(\partial f / \partial x_j\) вычисляется следующим образом

+
+\[\frac{\partial f}{\partial x_j} += \sum_{k \in K} \frac{\partial f}{\partial x_k} \frac{\partial x_k}{\partial x_j}.\]
+

Производные \(\partial f / \partial x_k\) известны с предыдущих шагов обратного прохода по графу. +В свою очередь, производные \(\partial x_k / \partial x_j\) вычисляются на шаге по явным связям \(x_k(x_j)\), хранящимся в графе вычислений.

+
+
+

8.5.2. Быстродействие и применимость#

+

Рассмотрим два крайних случая.

+

В задаче вычисления градиента функции вида \(f: \real^n \to \real\) (8.8) автоматическому дифференцированию назад требуется два прохода. +По этой причине дифференцирование назад предпочтительней дифференцирования вперёд для вычисления градиента.

+

Напротив, в задаче вычисления производных вида \(\partial f_i / \partial x\) (строки матрицы Якоби) для функции \(f: \real \to \real^m\) автоматическому дифференцированию назад требуется уже \(m + 1\) проходов. +Один прямой проход и по проходу на каждую производную.

+

В общем случае функции вида \(f: \real^n \to \real^m\) автоматическое дифференцирование назад эффективно для вычисления матрицы Якоби при \(n \gg m\).

+

Кроме того, дифференцированию назад требуется хранить граф вычислений, поэтому возникает требование к памяти. +Остро это требование проявляется в задачах с большими графами вычислений, например, при минимизации функции ошибки в машинном обучении.

+
+

Note

+

Воспользоваться автоматическим дифференцированием назад в Julia можно, например, с помощью пакетов +Zygote.jl [Inn18] +или ReverseDiff.jl.

+
+
+
+ + + + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/compgraph.html b/autodiff/compgraph.html new file mode 100644 index 0000000..4071413 --- /dev/null +++ b/autodiff/compgraph.html @@ -0,0 +1,694 @@ + + + + + + + + + + + + + + 8.3. Граф вычислений — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Граф вычислений

+ +
+
+ +
+
+
+ + + + +
+ +
+

8.3. Граф вычислений#

+

Для общего представления автоматического дифференцирования нам понадобится граф вычислений. +Это ориентированный граф для представления последовательности вычислений, скажем, функции \(f\).

+

Обычно вершинами графа являются операции или их аргументы, а рёбра связывают операции с аргументами. +Мы же воспользуемся упрощённым описанием, которого хватит для наших целей. +Так, в вершины графа мы будем помещать значения, возникающие в ходе вычислений (включая аргументы \(f\) и итоговое значение), а рёбра (дуги) графа будут соединять аргументы операции с её результатом.

+

Рассмотрим несколько примеров.

+
+../_images/graph-unary.svg
+

Fig. 8.2 Граф вычислений \(f(x) = \sin x\).#

+
+
+

На Рисунке 8.2 показан граф вычисления унарной функции (функции одного аргумента). +В этом случае \(x_1 \equiv x\), а \(x_2 \equiv f(x)\).

+
+../_images/graph-binary.svg
+

Fig. 8.3 Граф вычислений для операции суммы.#

+
+
+

На Рисунке 8.3 показан граф вычисления суммы \(x_1 + x_2\) с хранением результата в \(x_3\). +С формальной точки зрения, операцию сложения можно представить в виде функции двух аргументов (бинарной функции). +В таком случае стоки вершины \(x_3\) соединяют её с аргументами операции, а саму операцию мы будем подписывать рядом с вершиной-результатом.

+
+../_images/graph-example.svg
+

Fig. 8.4 Граф вычислений функции \(f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3\).#

+
+
+

На Рисунке 8.4 показан граф вычисления функции трёх переменных

+
+\[f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3},\]
+

которую мы будем в качестве примера в последующих разделах. +Значения \(x_1\), \(x_2\) и \(x_3\) являются аргументами функции, а \(x_7\) — значением функции в точке \([x_1, x_2, x_3]^\top\). +Промежуточные значения функции приведены ниже.

+
+
+
function f(x₁, x₂, x₃)
+    @show x₁
+    @show x₂
+    @show x₃
+    @show x₄ = x₁ * x₂
+    @show x₅ = sin(x₃)
+    @show x₆ = x₄ + x₅
+    @show x₇ = x₆ / x₃
+    return x₇
+end
+
+f(1, 2, 3)
+
+
+
+
+
x₁ = 1
+x₂ = 2
+x₃ = 3
+x₄ = x₁ * x₂ = 2
+x₅ = sin(x₃) = 0.1411200080598672
+x₆ = x₄ + x₅ = 2.1411200080598674
+x₇ = x₆ / x₃ = 0.7137066693532891
+
+
+
0.7137066693532891
+
+
+
+
+

Те же промежуточные значения \(x_4\), \(x_5\), \(x_6\), \(x_7\) создаёт компилятор языка. +Они обозначаются как %номер в Julia.

+
+
+
f2(x₁, x₂, x₃) = (x₁ * x₂ + sin(x₃)) / x₃
+@code_lowered f2(1, 2, 3)
+
+
+
+
+
CodeInfo(
+1 ─ %1 = x₁ * x₂
+│   %2 = Main.sin(x₃)
+│   %3 = %1 + %2
+│   %4 = %3 / x₃
+└──      return %4
+)
+
+
+
+
+

В нашем случае x₄ = %1, x₅ = %2, x₆ = %3 и x₇ = %4.

+

Для создания машинного (или промежуточного представления) кода из исходного компилятор строит синтаксическое дерево. +Если не вдаваться в технические детали, синтаксическое дерево напоминает граф вычислений, который мы описывали выше. +Однако, в синтаксическом дереве содержатся не только “привычные” математические операции, но и операторы языка, например, операторы ветвления, циклов или вызова функций. +Кроме того, на разных платформах (железе или операционной системе) машинный код может быть разным, но синтаксические деревья (и исходный код) могут совпадать ввиду более высокого уровня абстракции вычисления.

+

В следующих разделах мы воспользуемся графом вычисления, показанном на Рисунке 8.4, для классификации методов автоматического дифференцирования.

+
+ + + + +
+ + + + + + + + +
+ + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/complexstep.html b/autodiff/complexstep.html new file mode 100644 index 0000000..52929bd --- /dev/null +++ b/autodiff/complexstep.html @@ -0,0 +1,800 @@ + + + + + + + + + + + + + + 8.1. Метод комплексного шага — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Метод комплексного шага

+ +
+
+ +
+
+
+ + + + +
+ +
+

8.1. Метод комплексного шага#

+

Метод комплексного шага (complex step method) [KW19, MSA03] относится к численным методам дифференцирования (наряду с методом конечных разностей). +Однако, арифметика, стоящая за методом, роднит его с методом автоматического дифференцирования вперёд.

+

Заключается метод в следующем. +Вычислим функцию \(f\) один раз в точке \(x + i h\) (\(i h\) и есть комплексный шаг). +Разложение Тейлора для \(f(x + ih)\) имеет вид

+
+\[f(x + i h) += f(x) + i h f'(x) - h^2 \frac{f''(x)}{2!} - i h^3 \frac{f'''(x)}{3!} + \dots\]
+

Мнимая часть разложения

+
+\[\operatorname{Im}(f(x + i h)) = h f'(x) - h^3 \frac{f'''(x)}{3!} + \dots += h f'(x) + O(h^3)\]
+

позволяет вычислить производную \(f'(x)\) с точностью \(O(h^2)\)

+
+(8.1)#\[f'(x) = \frac{\operatorname{Im}(f(x + i h))}{h} + O(h^2).\]
+

В свою очередь, действительная часть разложения

+
+\[\operatorname{Re}(f(x + i h)) += f(x) - h^2 \frac{f''(x)}{2!} + \dots += f(x) + O(h^2)\]
+

содержит значение \(f(x)\) с той же точностью, \(O(h^2)\)

+
+\[f(x) = \operatorname{Re}(f(x + i h)) + O(h^2).\]
+

Метод комплексного шага прост в реализации.

+
+ +
+ Функция 8.1 + + (diff_complexstep) + +
+

Метод комплексного шага

+
"""
+    diff_complexstep(f, x; h=1e-16)
+
+Производная скалярной функции `f` в точке `x` методом комплексного шага,
+размер шага `h`.
+"""
+diff_complexstep(f, x; h=1e-16) = imag(f(x + im * h)) / h
+
+
+

Как видно из реализации, метод можно применять к любой функции, вычислимой от комплекcного аргумента. +При этом от программиста требуется определить только дифференцируемую функцию (скажем, уравнение состояния), а её производные можно вычислить, выполнив вычисление от комплексного числа.

+

В демонстрации ниже показан пример вычисления производной функции методом комплексного шага, а также сравнивается точность этого метода с парой методов конечных разностей.

+
+ +
+ Демонстрация 8.2 + +
+

Рассмотрим три численных метода дифференцирования: методы конечных разностей (прямой и центральный вариант) и метод комплексного шага.

+
+
+
diff_complexstep(f, x, h=1e-16) = imag(f(x + im * h)) / h
+diff_forward(f, x, h=1e-8) = (f(x + h) - f(x)) / h
+diff_central(f, x, h=1e-6) = (f(x + h/2) - f(x - h/2)) / h
+
+
+
+
+

Сравним точности методов на примере вычисления производной синуса в точке \(x = 1/3\).

+
+
+
f(x) = sin(x)
+df(x) = cos(x)
+
+x = 1/3
+h = [2.0^i for i in -52:0]
+
+err_complex = @. abs(1 - diff_complexstep(f, x, h)/df(x))
+err_forward = @. abs(1 - diff_forward(f, x, h)/df(x))
+err_central = @. abs(1 - diff_central(f, x, h)/df(x))
+
+
+
+
+

График зависимости невязки от размера шага \(h\) выглядит следующим образом (\(\log-\log\) шкала).

+
+
+
using Plots
+
+plot(;
+    xaxis=:log10,
+    yaxis=:log10,
+    xlabel="Размер шага h",
+    ylabel="Норма относительной невязки",
+    leg_title="Метод", leg=:top
+)
+
+plot!(h[err_complex .> 0], err_complex[err_complex .> 0]; label="комплексный шаг")
+plot!(h, err_forward; label="разность вперёд")
+plot!(h, err_central; label="центральная разность")
+
+xticks!([10.0^i for i in -14:2:0])
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

При этом значения невязки для метода комплексного шага при шагах менее \(1.5 \times 10^{-8}\) получились нулевыми (поэтому они не насенены на график в логарифмической шкале).

+
+
+
[h err_complex][err_complex .== 0, :]
+
+
+
+
+
27×2 Matrix{Float64}:
+ 2.22045e-16  0.0
+ 4.44089e-16  0.0
+ 8.88178e-16  0.0
+ 1.77636e-15  0.0
+ 3.55271e-15  0.0
+ 7.10543e-15  0.0
+ 1.42109e-14  0.0
+ 2.84217e-14  0.0
+ 5.68434e-14  0.0
+ 1.13687e-13  0.0
+ 2.27374e-13  0.0
+ 4.54747e-13  0.0
+ 9.09495e-13  0.0
+ ⋮            
+ 7.27596e-12  0.0
+ 1.45519e-11  0.0
+ 2.91038e-11  0.0
+ 5.82077e-11  0.0
+ 1.16415e-10  0.0
+ 2.32831e-10  0.0
+ 4.65661e-10  0.0
+ 9.31323e-10  0.0
+ 1.86265e-9   0.0
+ 3.72529e-9   0.0
+ 7.45058e-9   0.0
+ 1.49012e-8   0.0
+
+
+
+
+

Так, метод комплексного шага более устойчив, чем методы конечных разностей, к ошибкам округления, возникающих в арифметике с конечной точностью. +Устойчивость кроется в избегании эффекта subtractive cancellation за счёт вычисления функции один раз (вместо двух).

+

Метод комплескного шага гораздо лучше устойчив к численным эффектам, чем методы конечных разностей. +Тем не менее, его точность аналитически ограничена (8.1). +Далее мы увидим, что можно получить точное значение производной, если вычислить функцию не от комплексного, а от дуального числа.

+
+ + + + +
+ + + + + + + + +
+ + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/dualnumbers.html b/autodiff/dualnumbers.html new file mode 100644 index 0000000..760d7f7 --- /dev/null +++ b/autodiff/dualnumbers.html @@ -0,0 +1,1074 @@ + + + + + + + + + + + + + + 8.2. Дуальные числа — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

8.2. Дуальные числа#

+

Дуальные числа тесно связаны с дифференцированием, а на основе арифметики с ними можно создать алгоритм автоматического дифференцирования вперёд.

+
+ +
+ Определение 8.3 + + (Множество дуальных чисел) + +
+

Дуальные числа \(\dualset\) расширяют[1] действительные числа \(\real\) числом \(\dual\), для которого определяются следующие правила

+
+\[\dual{} \neq 0, \quad \dual{} \times 0 = 0, \quad \text{но} \quad \dual{} \times \dual{} = \dual{}^2 = 0.\]
+

Например, в дуальных числах уравнение \(x^2 = 0\) имеет множество корней: \(0, \dual{}^2, \dual{}^3,\dots\)

+

Определим запись дуальных чисел аналогично записи комплексных

+
+\[ a + b \dual, \quad a, b \in \real,\]
+

где \(a\) назовём действительной частью (компонентой) числа, а \(b\) — дуальной.

+

Сложение и вычитание чисел определяется интуитивно, покомпонентно

+
+\[\begin{split}\begin{align} +\begin{split} + (a + b \dual) + (c + d \dual) = (a + c) + (b + d)\dual, + \\ + (a + b \dual) - (c + d \dual) = (a - c) + (b - d)\dual. +\end{split} +\end{align}\end{split}\]
+

При произведении проявляется природа числа \(\dual\)

+
+\[(a + b \dual)(c + d \dual) = ac + a d \dual + b c \dual + \cancel{b d \dual^2} += ac + (a d + b c)\dual.\]
+

Такое поведение может напомнить пренебрежение квадратичными поправками. +Например, можно считать, что \(b\dual\) и \(d\dual\) являются погрешностями значений \(a\) и \(c\). +Тогда \(b d \dual^2\) мало по сравнению с остальными слагаемыми, и пренебрегается.

+

Деление дуальных чисел можно представить домножением числителя и знаменателя на сопряжённое к знаменателю (при этом знаменатель ненулевой, \(c + d\dual \neq 0\))

+
+\[\frac{a + b\dual}{c + d\dual} += \frac{(a + b\dual)(c - d \dual)}{(c + d\dual)(c - d\dual)} += \frac{ac + (-ad + bc)\dual}{c^2} += \frac{a}{c} + \frac{bc - ad}{c^2}\dual.\]
+
+ +
+ Определение 8.4 + + (Арифметика дуальных чисел) + +
+

Сложение, вычитание, произведение и деление дуальных чисел определяются следующим образом.

+
+(8.2)#\[(a + b \dual) \pm (c + d \dual) = (a \pm c) + (b \pm d)\dual.\]
+
+(8.3)#\[(a + b \dual)(c + d \dual) = ac + (a d + b c)\dual.\]
+
+(8.4)#\[\frac{a + b\dual}{c + d\dual} = \frac{a}{c} + \frac{bc - ad}{c^2}\dual.\]
+
+

8.2.1. Связь с дифференцированием#

+

Попробуем вычислить функцию \(f\) от дуального числа \(a + b\dual{}\). +Для этого воспользуемся разложением Тейлора

+
+\[f(x) = \sum_{k=0}^{\infty} \frac{f^{(k)}(x_0)}{k!} (x - x_0)^k\]
+

и применим его к \(f(a + b\dual{})\)

+
+\[\begin{split}\begin{split} +f(a + b\dual) &= \sum_{k=0}^{\infty} \frac{f^{(k)}(a)}{k!} (a + b\dual - a)^k += \sum_{k=0}^{\infty} \frac{f^{(k)}(a) b^k \dual^k}{k!} +\\ &= f(a) + b f'(a) \dual + \sum_{k=2}^\infty \frac{f^{(k)}(a) b^k \dual^k}{k!} +\\ &= f(a) + b f'(a) \dual + \dual^2 \sum_{k=2}^\infty \frac{f^{(k)}(a) b^k \dual^{k-2}}{k!} +\\ &= f(a) + b f'(a) \dual. +\end{split}\end{split}\]
+

Значит, вычислив функцию от дуального числа, получаем дуальное число, в действительной части которого содержится значение функции, а в дуальной содержится её производится. +(Сравните с методом комплексного шага.)

+

Итак, дуальные числа обладают свойством, непосредственно связанным с дифференцированием.

+
+ +
+ Утверждение 8.5 + + (Значение функции от дуального числа) + +
+
+(8.5)#\[f(a + b\dual) = f(a) + b f'(a)\dual, \quad a, b \in \real.\]
+

Отметим, что соотношение (8.5) выполняется аналитически точно.

+
+ +
+ Пример 8.6 + +
+

Ниже показаны примеры вычисления функций от дуального числа \(3 + 2\dual\). +Чтобы показать определение функции и точку вычисления использована запись \([\text{тело функции}](\text{аргумент})\). +Например, \([x^2 + 3](4)\) означает вычисление \(f(x) = x^2 + 3\) в точке 4, т.е. \([x^2 + 3](4) = 4^2 + 3 = 19\).

+
    +
  • Константа

  • +
+
+\[\begin{split}\begin{align*} +f(x) &= 5, +\\ f(3 + 2\dual) &= [5](3) + 2 \times [0](3) \dual = 5. +\end{align*}\end{split}\]
+
    +
  • Полином

  • +
+
+\[\begin{split}\begin{align*} +f(x) &= 4x^3 + x, +\\ f(3 + 2 \dual) &= [4 x^3 + x](3) + 2 \times [12 x^2 + 1](3) \times \dual +\\ &= 111 + 2 \times 109 \times \dual = 111 + 218 \dual. +\end{align*}\end{split}\]
+
    +
  • Логарифм

  • +
+
+(8.6)#\[\begin{split}\begin{split} +f(x) &= \log x, +\\ f(3 + 2 \dual) &= [\log x](3) + 2 \times [1/x](3) \times \dual + = \log 3 + \frac{2}{3} \dual. +\end{split}\end{split}\]
+

Рассмотрим арифметические операции с функциями. +Для этого воспользуемся свойством (8.5) и определениями арифметических операций с дуальными числами (8.2), (8.3) и (8.4). +Начнём рассмотрение со значения суммы функций в точке \(a + b\dual\)

+
+\[\begin{split}\begin{split} +f(a + b \dual) + g(a + b \dual) +&= (f(a) + b f'(a) \dual) + (g(a) + b g'(a) \dual) +\\ &= (f(a) + g(a)) + b (f'(a) + g'(a)) \dual. +\end{split}\end{split}\]
+

В действительной части мы получили сумму функций, а в дуальной присутствует сумма их производных. +Положим \(b = 1\) и получим

+
+\[f(a + \dual) + g(a + \dual) = (f(a) + g(a)) + (f'(a) + g'(a)) \dual.\]
+

Теперь в дуальной части находится сумма производных функций, она же является производной суммы \((f + g)' = f' + g'\). +То есть,

+
+\[[f + g](a + \dual) = [f + g](a) + [f + g]'(a) \times \dual.\]
+

Итак, мы получили согласие с правилом дифференцирования суммы функций от действительного числа \(a\). +Действительная часть соответствует сумме функций в \(a\), а дуальная — производной суммы функций в \(a\). +Естественно, аналогичное верно и для вычитания.

+

Проверим теперь произведение функций

+
+\[\begin{split}\begin{split} +f(a + \dual) \times g(a + \dual) &= (f(a) + f'(a) \dual) \times (g(a) + g'(a) \dual) +\\ &= f(a) g(a) + (f'(a) g(a) + f(a) g'(a)) \dual. +\end{split}\end{split}\]
+

И снова есть соответствие. +В действительной части мы получили произведение функций, а в дуальной — производную произведения функций \((fg)' = f'g + fg'\) в точке \(a\)

+
+\[[f \times g](a + \dual) = [f \times g](a) + [f \times g]'(a) \times \dual.\]
+

Наконец, проверим деление функций

+
+\[\begin{split}\begin{split} +\frac{f(a + \dual)}{g(a + \dual)} &= \frac{f(a) + f'(a) \dual}{g(a) + g'(a) \dual} +\\ &= \frac{f(a)}{g(a)} + \frac{f'(a) g(a) - f(a) g'(a)}{g^2(a)} \dual. +\end{split}\end{split}\]
+

И снова наблюдается соответствие. +Действительная часть является делением функций, а дуальная — производной деления функций \((f/g)' = (f'g - f g')/g^2\) в точке \(a\)

+
+\[[f / g](a + \dual) = [f / g](a) + [f / g]'(a) \dual.\]
+

Последнее, что осталось проверить, это вычисление сложной (составной) функции

+
+\[g(f(a + \dual)) = g(f(a) + f'(a)\dual) = g(f(a)) + g'(f(a)) f'(a)\dual.\]
+

Как видно, наблюдается соответствие с правилом дифференцирования сложной функции \((g(f(x)))' = g'(f(x)) f'(x)\)

+
+\[[g \circ f](a + \dual) = [g \circ f](a) + [g \circ f]'(a) \times \dual.\]
+
+
+

8.2.2. Автоматическое дифференцирование скалярной функции#

+

Теперь у нас есть все инструменты для вычисления производной функции. +Так, чтобы вычислить производную функции в точке \(f'(x)\), необходимо реализовать вычисление функции от дуального числа \(f(x + \dual)\). +В дуальной части \(f(x + \dual)\) будет содержаться значение производной \(f'(x)\), согласно (8.5).

+

Рассмотрим конкретный пример. +Задача: вычислить производную функции \(f(x) = 3 + x \log{x^2}\) в точке \(x = 5\). +Чтобы верифицировать будущие вычисления, приведём выражение для производной \(f'(x)\)

+
+\[f'(x) = \log{x^2} + 2, \quad x \neq 0,\]
+

и зададим функцию и её производную в коде.

+
+
+
f(x) = 3 + x * log(x^2)
+df(x) = log(x^2) + 2
+
+
+
+
+

В точке \(x = 5\) мы ожидаем следующие значения функции и её производной

+
+
+
f(5), df(5)
+
+
+
+
+
(19.094379124341003, 5.218875824868201)
+
+
+
+
+

Теперь перейдём к реализации метода автоматического дифференцирования. +Во-первых, определим новый тип данных Dual для представления дуального числа.

+
+
+
struct Dual{T<:Real}
+    a::T
+    b::T
+end
+
+
+
+
+

В структуре Dual всего два поля: поле a хранит действительную часть числа, а поле b хранит дуальную. +Кроме того, мы потребовали, чтобы типы полей были одинаковыми.

+

Теперь реализуем арифметику дуальных чисел. +Для этого перегрузим операторы сложения и умножения. +(В \(f(x)\) отсутствуют вычитание и деление, их реализовывать не будем.)

+
+
+
Base.:+(x::Dual, y::Dual) = Dual(x.a + y.a, x.b + y.b)
+Base.:*(x::Dual, y::Dual) = Dual(x.a * y.a, x.b * y.a + x.a * y.b)
+
+
+
+
+

В нашем примере есть ещё две операции: возведение числа в целую степень и логарифмирование. +Для этих операций понадобится реализовать свойство (8.5). +Как известно из матанализа

+
+\[\begin{split}\begin{align} +(x^n)' &= n x^{n-1}, \quad x \in \real, n \in \integer, +\\ (\log{x})' &= 1 / x, \quad\quad x \in \real, x \neq 0. +\end{align}\end{split}\]
+

Воспользуемся этими правилами дифференцирования и добавим методы для оператора ^ и функции натурального логарифма log.

+
+
+
Base.:^(x::Dual, n::Int) = Dual(x.a^n, x.b * n * x.a^(n-1))
+Base.log(x::Dual) = Dual(log(x.a), x.b / x.a)
+
+
+
+
+

Все операции определены и можно провести вычисление с дуальными числами. +Константу 3 представляем в виде \(3 \equiv 3 + 0\times\dual\), а вычисление производим в точке \(x = 5 + \dual\).

+
+
+
d = Dual(3, 0) + Dual(5, 1) * log(Dual(5, 1)^2)
+f(5) == d.a, df(5) == d.b
+
+
+
+
+
(true, true)
+
+
+
+
+

Как видно, действительная часть числа d совпадает с f(5), а дуальная часть совпадает с производной в точке 5 df(5). +Отметим, что эти равенства выполняются точно.

+

Проводить вычисления функции f с дуальными числами пока нельзя. +Дело в том, что в f присутствует сложение 3::Int с дуальным числом (x * log(x^2))::Dual{Float64}, это сложение мы ещё не определили.

+
+
+
f(Dual(5, 1))
+
+
+
+
+
MethodError: no method matching +(::Int64, ::Dual{Float64})
+
+Closest candidates are:
+  +(::Any, ::Any, ::Any, ::Any...)
+   @ Base operators.jl:578
+  +(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}
+   @ Base int.jl:87
+  +(::Union{Int16, Int32, Int64, Int8}, ::BigInt)
+   @ Base gmp.jl:545
+  ...
+
+
+Stacktrace:
+ [1] f(x::Dual{Int64})
+   @ Main ./In[1]:1
+ [2] top-level scope
+   @ In[7]:1
+
+
+
+
+

Есть два способа доопредилить сложение. +Первый состоит в добавлении метода +(::Int, ::Dual) и нам бы его хватило для примера. +Мы же поступим более общим для языка Julia способом. +Мы уже знакомы с функцией promote(xs...), которая возвращает значения аргументов, приведённых к “общему” типу.

+
+
+
promote(1, 2.5, 1//3)
+
+
+
+
+
(1.0, 2.5, 0.3333333333333333)
+
+
+
+
+

Воспользуемся ей, чтобы определить сложение Real чисел с дуальными Dual.

+
+
+
Base.:+(x::Dual, y::Real) = +(promote(x, y)...)
+Base.:+(x::Real, y::Dual) = +(promote(x, y)...)
+
+
+
+
+

Однако, мы ещё не определили правила, по которым приводить Real-числа к Dual-числам. +Для этого надо знать, как работает функция promote(x::T, y::S). +В общих чертах, promote выясняет “общий” для T и S тип U с помощью promote_type, а затем конвертирует к типу U свои аргументы.

+
function promote(x::T, y::S) where {T, S}
+    U = promote_type(T, S)
+    return (convert(U, x), convert(U, y))
+end
+
+
+

Начнём с конвертации.

+
+
+
Base.convert(::Type{Dual{T}}, x::Dual) where {T} = Dual{T}(x.a, x.b)
+Base.convert(::Type{Dual{T}}, x::S) where {T, S<:Real} = Dual{T}(x, zero(x))
+
+
+
+
+

В первой строчке мы определили конвертацию Dual-чисел между собой. +Фактически, при конвертации мы создаём новое Dual число, у которого поля имеют желаемый тип T. +Во второй строчке мы определили конвертацию Real-числа к Dual{T}-числу. +Как нам известно, действительное число это дуальное с нулевой дуальной частью.

+

Теперь перейдём к определению promote_type для дуальных чисел. +Саму функцию promote_type переопределять не рекомендуется. +Вместо этого добавляется метод к функции promote_rule(T1, T2), которая для пары типов T1 и T2 (явно) задаёт общий. +В свою очередь, promote_type использует promote_rule, применяя её попарно ко всем своим аргументам. +Кроме того, promote_type заботится о симметрии аргументов, поэтому promote_rule достаточно определить для пары аргументов один раз, т.е. пара неупорядоченная.

+
+
+
Base.promote_rule(::Type{Dual{T}}, ::Type{Dual{S}}) where {T, S} = Dual{promote_type(T, S)}
+Base.promote_rule(::Type{Dual{T}}, ::Type{S}) where {T, S<:Real} = Dual{promote_type(T, S)}
+
+
+
+
+

В первой строчке мы определяем общий тип для двух дуальных. +Поскольку T и S это подтипы Real (см. выше определение struct Dual), то мы можем воспользоваться promote_type для них. +Для Real чисел promote_type уже определён в Julia. +Во второй строчке для Dual и Real числа мы задаём Dual как общий тип.

+

Теперь promote работает с нашим типом Dual.

+
+
+
promote(1, 2.5, 1//3, Dual(1, 2))
+
+
+
+
+
(Dual{Float64}(1.0, 0.0), Dual{Float64}(2.5, 0.0), Dual{Float64}(0.3333333333333333, 0.0), Dual{Float64}(1.0, 2.0))
+
+
+
+
+
+
+
promote(1//3, Dual(1, 2))
+
+
+
+
+
(Dual{Rational{Int64}}(1//3, 0//1), Dual{Rational{Int64}}(1//1, 2//1))
+
+
+
+
+

Наконец, всё готово для вычисления производной 🎉

+
+
+
f(Dual(5, 1))
+
+
+
+
+
Dual{Float64}(19.094379124341003, 5.218875824868201)
+
+
+
+
+
+
+

8.2.3. Заключение#

+

Ниже представлен полный код из примера выше.

+
struct Dual{T<:Real}
+    a::T
+    b::T
+end
+
+Base.convert(::Type{Dual{T}}, x::Dual) where {T} = Dual{T}(x.a, x.b)
+Base.convert(::Type{Dual{T}}, x::S) where {T, S<:Real} = Dual{T}(x, zero(x))
+
+Base.promote_rule(::Type{Dual{T}}, ::Type{Dual{S}}) where {T, S} = Dual{promote_type(T, S)}
+Base.promote_rule(::Type{Dual{T}}, ::Type{S}) where {T, S<:Real} = Dual{promote_type(T, S)}
+
+Base.:+(x::Dual, y::Real) = +(promote(x, y)...)
+Base.:+(x::Real, y::Dual) = +(promote(x, y)...)
+
+Base.:+(x::Dual, y::Dual) = Dual(x.a + y.a, x.b + y.b)
+Base.:*(x::Dual, y::Dual) = Dual(x.a * y.a, x.b * y.a + x.a * y.b)
+Base.:^(x::Dual, n::Int) = Dual(x.a^n, x.b * n * x.a^(n-1))
+
+Base.log(x::Dual) = Dual(log(x.a), x.b / x.a)
+
+
+

Этот код позволяет автоматически дифференцировать не только функцию \(3 + x \log{x^2}\), но и вообще любую скалярную функцию, состоящую из операций сложения, произведения, возведения в целую степень и логарифмирования. +Чтобы распространить метод на больший класс функций, необходимо доопределить оставшиеся операции, например, вычитание, сравнение или \(\sin\). +Кроме того, понадобится доопределить нематематические функции, например, выделение памяти.

+

Дифференцирование с использованием дуальных чисел обощается на случаи частных производных и производных высших порядков. +Такой вид дифференцирования реализован в пакете ForwardDiff.jl. +С помощью ForwardDiff производную для нашего примера можно вычислить так.

+
+
+
using ForwardDiff
+
+f(x) = 3 + x * log(x^2)
+df(x) = ForwardDiff.derivative(f, x)
+df(5)
+
+
+
+
+
5.218875824868201
+
+
+
+
+

Реализованный нами способ дифференцирования называется автоматическим дифференцированием вперёд. +Смысл слова “вперёд” связан с направленностью цепочки вычислений производной и разъясняется в следующих разделах.

+
+ +
+
+ + + + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/ex.html b/autodiff/ex.html new file mode 100644 index 0000000..58ecc04 --- /dev/null +++ b/autodiff/ex.html @@ -0,0 +1,639 @@ + + + + + + + + + + + + + + 8.7. Задания — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Задания

+ +
+ +
+
+ + + + +
+ +
+

8.7. Задания#

+
+

8.7.1. Автоматическое дифференцирование вперёд#

+

Вам необходимо реализовать автоматическое дифференцирование вперёд для функций f(x), используя дуальные числа. +В задании должна присутствовать проверка правильности вычислений производной. +Для этого сравните производную по реализованному алгоритму в трёх разных x с аналитическими значениями, либо используя ForwardDiff.jl или Zygote.jl.

+

Примеры f(x) приведены ниже

+
    +
  1. 2 + exp(x) * sin(x)

  2. +
  3. 4 * cos(x^2) / x

  4. +
  5. log(sqrt(x)) - exp(x)

  6. +
  7. cbrt(cos(x^2)) / x^4

  8. +
  9. log(1 + tan(x)) / 8.5

  10. +
+
+
+ + + + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/forwardmode.html b/autodiff/forwardmode.html new file mode 100644 index 0000000..dc33172 --- /dev/null +++ b/autodiff/forwardmode.html @@ -0,0 +1,774 @@ + + + + + + + + + + + + + + 8.4. Автоматическое дифференцирование вперёд — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Автоматическое дифференцирование вперёд

+ +
+ +
+
+ + + + +
+ +
+

8.4. Автоматическое дифференцирование вперёд#

+

Автоматическое дифференцирование вперёд (прямое, forward mode, forward accumulation) является видом автоматического дифференцирования, в котором вычисления производных распространяются от аргументов функции к её результату. +Впервые этот метод дифференцирования был представлен R.E. Wengert [Wen64].

+

Сначала мы продемонстируем работу алгоритма на частном примере функции из Раздела 8.3, а затем опишем общий случай. +Ниже показана функция из примера и её граф вычисления.

+
+\[f(x_1, x_2, x_3) = \frac{x_1 x_2 + \sin{x_3}}{x_3}\]
+
+../_images/graph-example.svg
+

Fig. 8.5 Граф вычислений функции \(f(x_1, x_2, x_3) = (x_1 x_2 + \sin{x_3})/x_3\).#

+
+
+

Поставим задачу вычисления первой частной производной \(\partial f / \partial x_1\). +Будем считать, что \(f\) это сложная (композитная) функция от промежуточных значений. +Например, можно сказать, что \(f\) явно зависит от \(x_3\) и \(x_6\), которые, в свою очередь, неявно зависят (или не зависят) от \(x_1\). +Это позволит нам воспользоваться правилом дифференцирования сложной функции и, в конечном итоге, получить производную \(\partial f / \partial x_1\).

+

Итак, наша задача найти все частные производные вида

+
+\[\frac{\partial x_j}{\partial x_1}, \quad j = 1, \dots, 7.\]
+

Часть этих производных нулевые, а при \(j = 7\) мы получим \(\partial x_7 / \partial x_1 \equiv \partial f / \partial x_1\), т.е. искомую частную производную.

+

Шаг 1. +Произведём инициализацию алгоритма. +Нам известны значения аргументов \(x_1\), \(x_2\), \(x_3\) и их частные производные по \(x_1\)

+
+\[\frac{\partial x_1}{\partial x_1} = 1, +\quad \frac{\partial x_2}{\partial x_1} += \frac{\partial x_3}{\partial x_1} += 0.\]
+

Запомним их.

+

Шаг 2. +Найдём производную \(\partial x_4 / \partial x_1\). +Для этого считаем \(x_4\) сложной функцией в соответствии с графом вычисления (см. аргументы вычисления \(x_4\) на Рисунке 8.5)

+
+\[x_4 = x_4(x_1, x_2) = x_1 \times x_2(x_1) = x_4(x_1)\]
+

и получим

+
+\[\frac{\partial x_4}{\partial x_1} += \frac{\partial x_1}{\partial x_1} x_2 + x_1 \frac{\partial x_2}{\partial x_1} += 1 \times x_2 + x_1 \times 0 += x_2.\]
+

Здесь мы воспользовались правилом дифференцирования произведения. +Производные \(\partial x_1 / \partial x_1 = 1\) и \(\partial x_2 / \partial x_1 = 0\) нам известны с шага 1. +В конце шага запомним не только производную \(\partial x_4 / \partial x_1\), но и значение \(x_4 = x_1 x_2\).

+

Шаг 3. +Найдём производную \(\partial x_5 / \partial x_1\). +Поступая также, как на шаге 2, посчитаем \(x_5\) сложной функцией от \(x_3\)

+
+\[x_5 = x_5(x_3) = \sin{x_3(x_1)} = x_5(x_1),\]
+

тогда

+
+\[\frac{\partial x_5}{\partial x_1} += \frac{\partial x_5}{\partial x_3} \frac{\partial x_3}{\partial x_1} += \cos{x_3} \times 0 += 0.\]
+

Здесь мы воспользовались правилом дифференцирования сложной функции и производной функции синуса. +Производная \(\partial x_3 / \partial x_1 = 0\) известна с шага 1. +Как и на шаге 2, запомним \(x_5 = \sin{x_3}\) и \(\partial x_5 / \partial x_1\).

+

Шаг 4. +Найдём производную \(\partial x_6 / \partial x_1\). +Значение \(x_6\) явно вычисляется по \(x_4\) и \(x_5\)

+
+\[x_6 = x_6(x_4, x_5) = x_4(x_1) + x_5(x_1) = x_6(x_1),\]
+

тогда

+
+\[\frac{\partial x_6}{\partial x_1} += \frac{\partial x_4}{\partial x_1} + \frac{\partial x_5}{\partial x_1} += x_2 + 0 += x_2\]
+

Здесь мы воспользовались правилом дифференцирования суммы функций и значениями производных, полученных на шагах 2 и 3. +Запомним значение \(x_6 = x_4 + x_5 = x_1 x_2 + \sin{x_3}\) и производную \(\partial x_6 / \partial x_1\).

+

Шаг 5. +Последний шаг, найдём производную \(\partial x_7 / \partial x_1 \equiv \partial f / \partial x_1\). +Значение \(x_7\) явно определяется по значениям \(x_3\) и \(x_6\)

+
+\[x_7 = x_7(x_3, x_6) = \frac{x_6(x_1)}{x_3(x_1)},\]
+

а производная по \(x_1\) имеет вид

+
+\[\frac{\partial x_7}{\partial x_1} += \frac{ (\partial x_6 / \partial x_1 ) \times x_3 - x_6 \times (\partial x_3 / \partial x_1) }{ x^2_3 } += \frac{x_1 \times x_3 - x_6 \times 0}{x^2_3} += \frac{x_1}{x_3} +, \quad x_3 \neq 0.\]
+

Здесь мы воспользовались правилом дифференцирования деления функций и значениями производных с шагов 1 и 4. +Таким образом, мы вычислили значение первой компоненты градиента функции \(\partial f / \partial x_1\).

+

Отметим, что все промежуточные значения и производные выражались на протяжении алгоритма через значения аргументов функции \(x_1\), \(x_2\) и \(x_3\). +При этом промежуточные значения и производные мы получали в направлении “слева-направо” по графу вычислений, т.е. от аргументов к результату \(x_7 \equiv f\). +На Рисунке 8.6 показан граф вычисления значения функции \(f\) и её производной \(\partial f / \partial x_1\) в точке \([1, 2, 3]^\top\).

+
+../_images/graph-forward-auxillary-values.svg
+

Fig. 8.6 Граф вычисления \(f(1, 2, 3)\) и \(\partial f / \partial x_1 (1, 2, 3)\). +Вычисления распространяются “слева-направо”. +У каждой вершины подписаны значение промежуточной величины \(x_i\) и производной \(\partial x_i / \partial x_1\). +Напоминает дуальные числа?#

+
+
+
+

8.4.1. Общий случай#

+

В общем случае задача автоматического дифференцирования сводится к поиску всех производных вида

+
+\[\frac{\partial x_j}{\partial x_i}, \quad j = 1,\dots,V,\ i = 1,\dots,n,\ V \ge n,\]
+

где \(x_1\), …, \(x_n\) это аргументы функции, а \(x_1\), …, \(x_V\) промежуточные значения в графе вычислений. +В примере выше аргументов было \(n = 3\), а промежуточных значений \(V = 7\).

+

Автоматическое дифференцирование по-разному пользуется правилом дифференцирования сложной (композитной) функции. +В случае дифференцирования вперёд промежуточное значение \(x_j\) представляется в виде функции

+
+(8.7)#\[x_j = x_j( \{ x_k(x_i) \}_{k \in K} ) = x_j(x_i),\]
+

где \(\{x_k\}_{k \in K}\) это промежуточные значения, от которых \(x_j\) зависит явно, непосредственно (а \(K\) это множество индексов таких вершин). +Т.е. на графе вычислений \(\{x_k\}_{k \in K}\) это вершины, которые связаны с \(x_j\) стоком.

+
+../_images/graph-forward-general.svg
+

Fig. 8.7 Общая схема графа вычислений \(\partial x_j / \partial x_i\) для автоматического дифференцирования вперёд. +Явные связи (дуги графа) показаны прямыми стрелками, а неявные связи показаны волнистыми стрелками.#

+
+
+

Применяя к представлению функции \(x_j\) в виде (8.7) правило дифференцирования сложной функции, получаем

+
+\[\frac{\partial x_j}{\partial x_i} += \sum_{k \in K} \frac{\partial x_j}{\partial x_k} \frac{\partial x_k}{\partial x_i},\]
+

где производные \(\partial x_k / \partial x_i\) известны с предыдущих шагов обхода графа вычислений. +В свою очередь, производные \(\partial x_j / \partial x_k\) вычисляются на текущем шаге обхода по явной связи \(x_j(\{ x_k \}_{k \in K})\).

+
+
+

8.4.2. Быстродействие и применимость#

+

Пусть стоит задача вычисления градиента функции вида \(f: \real^n \to \real\)

+
+\[\frac{\partial f}{\partial x_i},\ i = 1, \dots, n.\]
+

В этой задаче автоматическому дифференцированию вперёд требуется \(n\) проходов графа вычислений, по одному проходу на каждую производную.

+

Если же стоит задача найти производные функции \(f: \real \to \real^m\), т.е.

+
+\[\frac{\partial f_j}{\partial x},\ j = 1, \dots, m,\]
+

то автоматическому дифференцированию вперёд требуется всего один проход графа вычислений.

+

В общем случае функции вида \(f: \real^n \to \real^m\) автоматическое дифференцирование вперёд эффективно для вычисления матрицы Якоби при \(n \ll m\).

+

Кроме того, автоматическое дифференцирование вперёд не требует хранения графа вычислений в явном виде, поскольку проход(ы) по графу происходит только в одну сторону. +Другими словами, на практике для реализации нужен не сам граф вычислений, а лишь последовательность инструкций, которые строит компилятор. +Особенно удобно реализовывать дифференцирование вперёд на языках программирования, в которых можно перегрузить операторы и функции. +В этом мы убедились в Разделе 8.2 (Дуальные числа).

+

Возможность не хранить граф вычислений актуальна для задач с большим количеством параметров, например, при минимизации функции ошибки. +В этом случае ограничение по памяти проще удовлетворить.

+

Итак, автоматическое дифференцирование вперёд эффективно по памяти, быстро работает для вычисления строк матрицы Якоби, но медленно для вычисления её столбцов или градиента функции. +Однако, строки матрицы Якоби не так часто нужны на практике, как градиенты функций. +Поэтому для автоматического вычисления градиентов чаще используется дифференцирование назад, о котором речь пойдёт в следующем разделе.

+
+

Note

+

Воспользоваться автоматическим дифференцированием вперёд в Julia можно, например, с помощью пакета ForwardDiff.jl, [RLP16].

+
+
+
+ + + + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/index.html b/autodiff/index.html new file mode 100644 index 0000000..99af60a --- /dev/null +++ b/autodiff/index.html @@ -0,0 +1,644 @@ + + + + + + + + + + + + + + 8. Автоматическое дифференцирование — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Автоматическое дифференцирование

+ +
+
+ +
+
+
+ + + + +
+ +
+

8. Автоматическое дифференцирование#

+

Автоматическое дифференцирование является способом вычисления производных функции, заданной программно. +Этот вид дифференцирования опирается на правило дифференцирования сложной функции, представление функции в виде последовательности элементарных операций и перегрузке программных инструкций (функций, операторов).

+

Автоматическое дифференцирование не является численным дифференцированием. +Численное дифференцирование приближает производную на основе её определения \(f'(x) \approx (f(x) + f(x + \delta x)) / \delta x\). +В то время как автоматическое дифференцирование не требует введения шага \(\delta x\), а производная вычисляется точно (в пределах машинной арифметики).

+

Автоматическое дифференцирование не является символьным дифференцированием. +Символьное дифференцирование преобразовывает выражения и применяет правила дифференцирования, чтобы получить выражение производной \(f'(x)\). +Впоследствии полученное выражение можно вычислить (и даже создать исходный код для производной). +В автоматическом дифференцировании отсутствует программное представление функции в виде математического (символьного) выражения.

+

Сравнение способов дифференцирования показано на Рисунке 8.1.

+
+../_images/baydin-2018-diff-approaches-overview.png +
+

Fig. 8.1 Способы дифференцирования. +Символьное вычисление даёт точный результат, но требует преобразования кода f к closed-form; +численное дифференцирование неточно ввиду погрешностей метода и округления; +автоматическое дифференцирование точно и позволяет использовать управляющие конструкции языка. +Источник: [BPRS18].#

+
+
+
+

Note

+

С автоматическим дифференцированием связано понятие “дифференцируемого” программирования (differential programming). +Это подход к написанию кода, который учитывает возможность автоматически дифференцировать запрограммированные функции.

+
+

В данной главе изложены темы дуальных чисел, графа вычислений, а также автоматического дифференцирования вперёд и назад. +Чтение главы вы можете начать с Раздела 8.2 (Дуальные числа), пропустив Раздел 8.1 (Метод комплексного шага).

+
+

Tip

+

Подробнее с автоматическим дифференцированием вы можете ознакомиться в следующих работах.

+
    +
  • Kochenderfer and Wheeler [KW19].

  • +
  • Дмитрий Кропотов. +Автоматическое дифференцирование. +ВМК МГУ, кафедра математических методов прогнозирования. +https://youtu.be/za2LgI8JFCw.

  • +
  • Baydin, Pearlmutter, Radul, and Siskind [BPRS18].

  • +
+
+
+
+
+ + + + +
+ + + + + + + + +
+ + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/autodiff/oja_problem.html b/autodiff/oja_problem.html new file mode 100644 index 0000000..230d1af --- /dev/null +++ b/autodiff/oja_problem.html @@ -0,0 +1,634 @@ + + + + + + + + + + + + + + 8.6. Оптимальное вычисление матрицы Якоби — Практикум по вычислительной теплофизике + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Оптимальное вычисление матрицы Якоби

+ +
+
+ +
+
+
+ + + + +
+ +
+

8.6. Оптимальное вычисление матрицы Якоби#

+

Напоследок, мы без подробностей затронем задачу оптимального вычисления матрицы Якоби (optimal Jacobian accumulation).

+

Пусть дана функция \(f: \real^n \to \real^m\) и стоит задача вычисления её матрицы Якоби

+
+\[J_{i j} = \frac{\partial f_i}{\partial x_j}(x_1, \dots, x_n), \quad i = 1, \dots, m,\ j = 1, \dots, n,\]
+

за минимальное число операций. +Как нам уже известно, при \(n \gg m\) эффективней по быстродействию использовать автоматическое дифференцирование назад, а в обратном случае \(n \ll m\) — дифференцирование вперёд.

+

В общем случае можно учитывать структуру (топологию) графа вычислений и уменьшить количество вычислительной нагрузки. +Например, можно разделить весь граф вычислений на подграфы, каждый из которых определяет “часть” функции \(f\). +Затем на каждом из участков графа использовать тот вид дифференцирования, который на нём эффективен. +В конце же остаётся “сшить” результаты вычислений, используя правило дифференцирования сложной функции.

+

Мы продемонстрируем эту идею на функции с (очень) специфическим графом вычислений, показанном на Рисунке 8.11.

+
+../_images/graph-cross-example.svg
+

Fig. 8.11 Пример графа вычисления, для которого эффективно использовать оба вида дифференцирования. +Промежуточное значение \(g\) является точкой сочленения.#

+
+
+

В этом случае разумно использовать оба вида дифференцирования. +Для этого представим исходную функцию \(\mathbf{f}\) в виде

+
+\[f_i = f_i(g(x_1, \dots, x_n)), \quad i = 1, \dots, m,\]
+

где промежуточное значение \(g\) является функцией \(\real^n \to \real\). +Тогда производные (элементы матрицы Якоби) имеют вид

+
+\[J_{i j} += \frac{\partial f_i}{\partial x_j} += \frac{\partial f_i}{\partial g} \frac{\partial g}{\partial x_j} +.\]
+

Производные \(\partial g / \partial x_j\) эффективно вычисляются дифференцированием назад, поскольку \(n \gg 1\). +В свою очередь, производные \(\partial f_i / \partial g\) эффективно вычисляются дифференцированием вперёд (\(1 \ll m\)).

+

Так, автоматические способы дифференцирования вперёд и назад являются лишь крайними вариантами обхода графа вычислений в соответствии с правилом дифференцирования сложной функции.

+
+ + + + +
+ + + + + + + + +
+ + + + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/bibliography.html b/bibliography.html deleted file mode 100644 index 8b8f828..0000000 --- a/bibliography.html +++ /dev/null @@ -1,712 +0,0 @@ - - - - - - - - - Литература — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - -
-
- - -
-
-
-
-
- -
-

Литература

- -
-
- -
-
-
-
- -
- -
-

Литература#

-
-
-
ADJB17
-

Tobin A. Driscoll and Richard J. Braun. Fundamentals of numerical computation. Society for Industrial and Applied Mathematics, 2017. ISBN 978-1-61197-507-9. URL: https://tobydriscoll.net/project/fnc/.

-
-
ADPP92
-

M. J. Assael, J. H. Dymond, M. Papadaki, and P. M. Patterson. Correlation and prediction of dense fluid transport coefficients. i. n-alkanes. International Journal of Thermophysics, 13(2):269–281, March 1992. URL: https://doi.org/10.1007/bf00504436, doi:10.1007/bf00504436.

-
-
Joh14
-

David Johnston. Advances in thermodynamics of the van der waals fluid. arXiv, 2014. URL: https://arxiv.org/abs/1402.1205v1, doi:10.1088/978-1-627-05532-1.

-
-
Lek82
-

John Lekner. Parametric solution of the van der waals liquid–vapor coexistence curve. American Journal of Physics, 50(2):161–163, 1982. URL: https://doi.org/10.1119/1.12877, doi:10.1119/1.12877.

-
-
LeV02
-

Randall J. LeVeque. Finite Volume Methods for Hyperbolic Problems. Cambridge University Press, August 2002. URL: https://doi.org/10.1017/cbo9780511791253, doi:10.1017/cbo9780511791253.

-
-
OT20
-

I. F. D. Oliveira and R. H. C. Takahashi. An enhancement of the bisection method average performance preserving minmax optimality. ACM Trans. Math. Softw., December 2020. URL: https://doi.org/10.1145/3423597, doi:10.1145/3423597.

-
-
PTVF07
-

William H. Press, Saul A. Teukolsky, William T. Vetterling, and Brian P. Flannery. Numerical Recipes 3rd Edition: The Art of Scientific Computing. Cambridge University Press, USA, 3 edition, 2007. ISBN 0521880688.

-
-
Rid79
-

C. Ridders. A new algorithm for computing a single root of a real continuous function. IEEE Transactions on Circuits and Systems, 26(11):979–980, 1979. URL: https://doi.org/10.1109/TCS.1979.1084580, doi:10.1109/TCS.1979.1084580.

-
-
16
-

Рябенький В.С. Введение в вычислительную математику. Физматлит, Москва, 3 edition, 2016. ISBN 978-5-9221-0926-0.

-
-
71
-

И. Ф. Голубев and Н. Е. Гнездилов. Вязкость газовых смесей. Издательство государственного комитета стандартов кабинета министров СССР, Москва, 1971. URL: https://lib.mipt.ru/book/35000/?q=%D0%98.%D0%A4.+%D0%93%D0%BE%D0%BB%D1%83%D0%B1%D0%B5%D0%B2+and+%D0%9D.%D0%95.+%D0%93%D0%BD%D0%B5%D0%B7%D0%B4%D0%B8%D0%BB%D0%BE%D0%B2.+%D0%92%D1%8F%D0%B7%D0%BA%D0%BE%D1%81%D1%82%D1%8C+%D0%B3%D0%B0%D0%B7%D0%BE%D0%B2%D1%8B%D1%85+%D1%81%D0%BC%D0%B5%D1%81%D0%B5%D0%B9.

-
-
89
-

А. А. Самарский and А. В. Гулин. Численные методы: учеб. пособие для вузов. Наука, Москва, 1989. ISBN 978-5020139961.

-
-
-
-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/genindex.html b/genindex.html index d67e85a..5213a14 100644 --- a/genindex.html +++ b/genindex.html @@ -1,53 +1,63 @@ + - + + + Index — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/index.html b/index.html index 36e20ef..30576de 100644 --- a/index.html +++ b/index.html @@ -1,54 +1,66 @@ + - + + + - + + + - Предмет практикума — Практикум по вычислительной теплофизике - + О практикуме — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/integration/ex.html b/integration/ex.html index 4b516a3..7ad558c 100644 --- a/integration/ex.html +++ b/integration/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + 5.5. Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+
+ + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/integration/gauss.html b/integration/gauss.html index b31f95b..256e496 100644 --- a/integration/gauss.html +++ b/integration/gauss.html @@ -1,54 +1,66 @@ + - + + + - + + + 5.3. Формулы Гаусса — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + + + +
+ + + +
+ - - + + +
+
\ No newline at end of file diff --git a/integration/index.html b/integration/index.html index e9c7921..19f239a 100644 --- a/integration/index.html +++ b/integration/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 5. Численное интегрирование — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/integration/newton_cotes.html b/integration/newton_cotes.html index 7a6d686..becd473 100644 --- a/integration/newton_cotes.html +++ b/integration/newton_cotes.html @@ -1,54 +1,66 @@ + - + + + - + + + 5.1. Формулы Ньютона-Котса — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -
@@ -889,36 +599,176 @@

5.1.1. Формула прямоугол

для разного числа точек.

-
foo(x) = x * exp(sin(2x))
-plt = plot(layout=(3,1), leg=:none, xlabel=L"x")
-for (i, n) in enumerate((1, 4, 8))
-    plot!(foo, 0, 3; subplot=i, linewidth=2, linecolor=:red)
+
foo(x) = x * exp(sin(2x))
+plt = plot(layout=(3,1), leg=:none, xlabel=L"x")
+for (i, n) in enumerate((1, 4, 8))
+    plot!(foo, 0, 3; subplot=i, linewidth=2, linecolor=:red)
     
-    h = 3/n
-    x = [h/2 + i * h for i in 0:n-1]
-    y = foo.(x)
-    for (px, py) in zip(x, y)
-        h = 3 / n
-        plot!([px-h/2, px+h/2], [py, py];
-            subplot=i, fill=(0, 0.1, :blue), linecolor=:blue, linewidth=2
-        )
-    end
-    scatter!(x, y; subplot=i, marker=:o, markercolor=:lightblue)
-end
-plt
+    h = 3/n
+    x = [h/2 + i * h for i in 0:n-1]
+    y = foo.(x)
+    for (px, py) in zip(x, y)
+        h = 3 / n
+        plot!([px-h/2, px+h/2], [py, py];
+            subplot=i, fill=(0, 0.1, :blue), linecolor=:blue, linewidth=2
+        )
+    end
+    scatter!(x, y; subplot=i, marker=:o, markercolor=:lightblue)
+end
+plt
 
-../_images/newton_cotes_2_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-

Можно показать [89], что составная формула прямоугольников имеет второй порядок сходимости

+

Можно показать [89], что составная формула прямоугольников имеет второй порядок сходимости

\[|\tau_f(h)| \le \frac{h^2(b-a)}{24} \max_{x\in [a,b]} |f''(x)| \sim O(h^2).\]

При этом отсюда видно, что ошибка становится нулевой для линейных функций (для них \(f'' \equiv 0\)).

-

5.1.2. Формула трапеций#

+

5.1.2. Формула трапеций#

Если аппроксимировать функцию на отрезке \([x_{i-1}, x_{i}]\) прямой, проходящей через значения на концах отрезка, то получим формулу трапеций (trapezoidal rule)

\[\int_{x_{i-1}}^{x_i} f(x)\diff x \approx \frac{f(x_{i-1}) + f(x_i)}{2} h.\]
@@ -971,17 +821,17 @@

5.1.2. Формула трапецийВычисляет по формуле трапеций интеграл ∫`f`dx на отрезке [`a`, `b`] с равномерной сеткой из `n` интервалов. Возвращает значение интеграла. -""" -function trapezoid(f, a, b, n) - x = range(a, b; length=n+1) - h = step(x) - if isone(n) - int = h * (f(x[1]) + f(x[2])) / 2 - else - @views int = h * (sum(f, x[2:n]) + (f(x[1]) + f(x[n+1])) / 2) - end - return int -end +""" +function trapezoid(f, a, b, n) + x = range(a, b; length=n+1) + h = step(x) + if isone(n) + int = h * (f(x[1]) + f(x[2])) / 2 + else + @views int = h * (sum(f, x[2:n]) + (f(x[1]) + f(x[n+1])) / 2) + end + return int +end

Для составной формулы трапеций можно показать [89], что

\[|I - T_f| \le \frac{h^2(b-a)}{12} \max_{x\in[a,b]} f''(x) \sim O(h^2).\]

Таким образом, она обладает вторым порядком точности, как и формула прямоугольников. И также точно приближает интеграл от линейной функции.

-

5.1.3. Формула Симпсона#

+

5.1.3. Формула Симпсона#

Формулу Симпсона несложно получить, решив (5.4) для \(x_1 = 0, x_2 = 1/2, x_3 = 1\), что соответствует интерполяции \(f(x)\) параболой по трём точкам. Однако можно взглянуть на вывод этой формулы с другой стороны, на основе экстраполяции Ричардсона.

@@ -1050,7 +1023,7 @@

5.1.2. Формула трапеций

Веса в (5.9) в точности совпадают с решением (5.4) для \(x_1 = 0, x_2 = 1/2, x_3 = 1\). Полученное приближение называется квадратурной формулой Симпсона (Simpson’s rule). Из вывода (5.6)(5.8) видно, -что она имеет чётвертый порядок сходимости. Более точная оценка [89]

+что она имеет чётвертый порядок сходимости. Более точная оценка [89]

\[|I - S_f(h)| \le \frac{h^4 (b-a)}{2880} \sup_{x\in [a,b]} f^{IV}(x) \sim O(h^4).\]

Отсюда видно, что формула Симпсона приближает точно интеграл от многочленов степени не выше третьей.

@@ -1078,10 +1051,10 @@

5.1.2. Формула трапецийВычисляет по формуле Симпсона интеграл ∫`f`dx на отрезке [`a`, `b`] с равномерной сеткой из `n` (чётное) интервалов. Возвращает значение интеграла. -""" -function simpson(f, a, b, n) - return (1/3) * (4*trapezoid(f, a, b, n) - trapezoid(f, a, b, n÷2)) -end +""" +function simpson(f, a, b, n) + return (1/3) * (4*trapezoid(f, a, b, n) - trapezoid(f, a, b, n÷2)) +end

-

5.1.4. Упражения#

-
    +

    5.1.4. Упражения#

    +
    1. Ниже приведена заготовка функции, находящей узлы и коэффициенты формулы Ньютона-Котса, точной для многочлена степени \(p\). Заполните пропуски ⟨...⟩

      """
       Находит узлы и веса формулы Ньютона-Котса с числом узлов `nnodes` на отрезке `[0; 1]`.
       Если аргумент `closed=true` (по умолчанию), то расчет делается для 
       закрытых квадратурных формул, иначе - для открытых
      -"""
      -function newton_cotes_nodes_weights(nnodes::Integer; closed::Bool=true)
      -    if closed
      -        nodes = range(...)
      -    else
      -        nodes = range(...)
      -    end
      -    rhp = ...
      -    w = (vandermonde(nodes))' \ rhp
      -    return (nodes=nodes, weights=w)
      -end
      +"""
      +function newton_cotes_nodes_weights(nnodes::Integer; closed::Bool=true)
      +    if closed
      +        nodes = range(...)
      +    else
      +        nodes = range(...)
      +    end
      +    rhp = ...
      +    w = (vandermonde(nodes))' \ rhp
      +    return (nodes=nodes, weights=w)
      +end
       
    2. @@ -1149,61 +1213,116 @@

      5.1.4. Упражения - + - + - - + + + + - - + + +
      +
      \ No newline at end of file diff --git a/integration/romberg.html b/integration/romberg.html index 4f0ff0a..f68b027 100644 --- a/integration/romberg.html +++ b/integration/romberg.html @@ -1,54 +1,66 @@ + - + + + - + + + 5.2. Метод Ромберга — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
      -
      + + + - - + + + + +
      - + + -
      -
      - - -

-

5.2.3. Реализация#

+

5.2.3. Реализация#

Итак, хранить \(I_{h_{k-1}}^{(j)}\) будем в элементе матрицы I[k, j].

Первый элемент I[1, 1] заполним вручную: он соответствует формуле трапеций на сетке из одного интервала (2 узла). Затем, пока не достигнем необходимой точности, будем делать следующее

-
    +
    1. Измельчим сетку вдвое и подсчитаем интеграл по формуле трапеций на ней (5.17), так получим из I[k, 1] элемент I[k+1, 1];

    2. Вычислим по доступной побочной диагонали слева направо все элементы от I[k, 2] вплоть до I[1, k+1] по формуле перехода (5.14);

    3. Будем продолжать 1 и 2 до тех пор, пока приближения I[1, k+1] и I[2, k] станут неотличимы в заданной точности atol, или пока не исчерпаем количество измельчений maxstep.

    4. @@ -891,22 +656,22 @@

      5.2.3. РеализацияВычисляет интеграл ∫`f`dx на отрезке [`a`, `b`] методом Ромберга. Разбивает отрезок пополам не более `maxstep > 0` раз. Возвращает значение интеграла, если приближения отличаются не более чем на `atol`. -""" -function romberg(f, a, b; atol=1e-6, maxstep::Integer=100) - maxstep = max(1, maxstep) # хотя бы одно разбиение - I = Matrix{Float64}(undef, maxstep+1, maxstep+1) - I[1, 1] = (b - a) * (f(a) + f(b)) / 2 - for i in 2:maxstep+1 - let hc = (b - a) / 2^(i-1), np = 2^(i-2) - I[i, 1] = I[i-1, 1] / 2 + hc * sum(f, (a + hc * (2i-1) for i in 1:np)) - end - for k in i-1:-1:1 - I[k, i-k+1] = (2^i*I[k+1, i-k] - I[k, i-k]) / (2^i - 1) - end - abs(I[1, i] - I[2, i-1]) < atol && return I[1, i] - end - error("Точность не удовлетворена.") -end +""" +function romberg(f, a, b; atol=1e-6, maxstep::Integer=100) + maxstep = max(1, maxstep) # хотя бы одно разбиение + I = Matrix{Float64}(undef, maxstep+1, maxstep+1) + I[1, 1] = (b - a) * (f(a) + f(b)) / 2 + for i in 2:maxstep+1 + let hc = (b - a) / 2^(i-1), np = 2^(i-2) + I[i, 1] = I[i-1, 1] / 2 + hc * sum(f, (a + hc * (2i-1) for i in 1:np)) + end + for k in i-1:-1:1 + I[k, i-k+1] = (2^i*I[k+1, i-k] - I[k, i-k]) / (2^i - 1) + end + abs(I[1, i] - I[2, i-1]) < atol && return I[1, i] + end + error("Точность не удовлетворена.") +end

      нашими реализациями trapezoid_tol и romberg.

      -
      julia> using BenchmarkTools
      +
      julia> using BenchmarkTools
       
      -julia> foo(x) = x * exp(sin(2x));
      +julia> foo(x) = x * exp(sin(2x));
       
      -julia> a, b, atol = 0, 3, 1e-6;
      +julia> a, b, atol = 0, 3, 1e-6;
       
      -julia> @benchmark trapezoid_tol($foo, a, b; atol=$atol)
      +julia> @benchmark trapezoid_tol($foo, a, b; atol=$atol)
       BenchmarkTools.Trial: 10000 samples with 1 evaluation.
        Range (min … max):  121.110 μs … 452.256 μs  ┊ GC (min … max): 0.00% … 0.00%
        Time  (median):     121.582 μs               ┊ GC (median):    0.00%
      @@ -937,7 +702,7 @@ 

      5.2.3. Реализация Memory estimate: 272 bytes, allocs estimate: 17. -julia> @benchmark romberg($foo, a, b; atol=$atol) +julia> @benchmark romberg($foo, a, b; atol=$atol) BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 8.434 μs … 3.711 ms ┊ GC (min … max): 0.00% … 99.35% Time (median): 13.210 μs ┊ GC (median): 0.00% @@ -953,9 +718,9 @@

      5.2.3. Реализацияtrapezoid_tol потребовалось 12 разбиений сетки, а romberg всего 8. Это означает, что trapezoid_tol вычисляла функцию примерно на \(2^{12} - 2^8 \approx 3800\) раз больше.

      В свою очередь, одно вычисление функции foo стоит около 14 нс.

      -
      + + + -

      +
      + + + + + +
      + + + +
      + - - + + +
      +
      \ No newline at end of file diff --git a/interpolation/cubic_spline.html b/interpolation/cubic_spline.html index b5bc652..136c75d 100644 --- a/interpolation/cubic_spline.html +++ b/interpolation/cubic_spline.html @@ -1,54 +1,66 @@ + - + + + - + + + 4.3. Кубические сплайны — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
      -
      + + + - - + + + + +
      - + + -
      -
      - - - +
      + +
      -
      + +
      + + + - + + + + + + + + + + + + - - + + +
      +
      \ No newline at end of file diff --git a/interpolation/ex.html b/interpolation/ex.html index cbc6fed..e639e49 100644 --- a/interpolation/ex.html +++ b/interpolation/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + 4.4. Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
      -
      + + + - - + + + + +
      - + + -
      -
      - - -

@@ -948,61 +644,113 @@

4.4.1. Вязкость разрежен }, codeMirrorConfig: { theme: "abcdef", - mode: "julia-1.6" + mode: "julia-1.9" }, kernelOptions: { - kernelName: "julia-1.6", + name: "julia-1.9", path: "./interpolation" }, predefinedOutput: true } - + - + - - + + + + - - + + +
+
\ No newline at end of file diff --git a/interpolation/index.html b/interpolation/index.html index 6d550cf..c798020 100644 --- a/interpolation/index.html +++ b/interpolation/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 4. Интерполяция — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/interpolation/pwlinear.html b/interpolation/pwlinear.html index 27dd0c4..8891b52 100644 --- a/interpolation/pwlinear.html +++ b/interpolation/pwlinear.html @@ -1,54 +1,66 @@ + - + + + - + + + 4.2. Кусочно-линейная интерполяция — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -
@@ -870,24 +589,142 @@

4.2.1. Hat-функции

Допустим, интерполяция производится по четырём точкам \(t_1 = 1.0, t_2 = 1.3, t_3 = 3.1, t_4 = 4.0\) (абсциссы), соответствующий базис имеет вид.

-
ts = [1.0, 1.3, 3.1, 4.0]
-xs = range(first(ts), last(ts); length=200)
-plt = plot(layout=(4,1),xlabel=L"x", ylims=[-0.1,1.1], ytick=[1], leg=:outertopleft)
-for k in 1:size(ts, 1)
-    φ_k = hatfunc(ts, k)
-    plot!(xs, φ_k.(xs); label="φ_$k", subplot=k)
-    scatter!(ts, φ_k.(ts); label="", subplot=k)
-end
-plt
+
ts = [1.0, 1.3, 3.1, 4.0]
+xs = range(first(ts), last(ts); length=200)
+plt = plot(layout=(4,1),xlabel=L"x", ylims=[-0.1,1.1], ytick=[1], leg=:outertopleft)
+for k in 1:size(ts, 1)
+    φ_k = hatfunc(ts, k)
+    plot!(xs, φ_k.(xs); label="φ_$k", subplot=k)
+    scatter!(ts, φ_k.(ts); label="", subplot=k)
+end
+plt
 
-../_images/pwlinear_2_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-

4.2.2. Интерполяция#

+

4.2.2. Интерполяция#

@@ -913,11 +750,11 @@

4.2.2. Интерполяция

Кусочно-линейная интерполяция

-
"Возвращает кусочно-линейный интерполянт для точек (`t[i]`, `y[i]`)."
-function pwlininterp(t, y)
-    basis = [hatfunc(t, k) for k in 1:size(t, 1)]
-    return x -> sum(y[k]*basis[k](x) for k in 1:size(y, 1))
-end
+
"Возвращает кусочно-линейный интерполянт для точек (`t[i]`, `y[i]`)."
+function pwlininterp(t, y)
+    basis = [hatfunc(t, k) for k in 1:size(t, 1)]
+    return x -> sum(y[k]*basis[k](x) for k in 1:size(y, 1))
+end
 

Рассмотрим пример кусочно-линейной интерполяции на функции из раздела Случай равноотстоящих точек.

-
foo(x) = exp(sin(2x)) + 0.05*sin(15x)
-ts = [1.0, 1.5, 3.0, 3.5, 4.1, 4.5, 5.5]
-ys = foo.(ts)
+
foo(x) = exp(sin(2x)) + 0.05*sin(15x)
+ts = [1.0, 1.5, 3.0, 3.5, 4.1, 4.5, 5.5]
+ys = foo.(ts)
 
-interpolant = pwlininterp(ts, ys)
+interpolant = pwlininterp(ts, ys)
 
-scatter(ts, ys; label="узлы интерполяции", legend=:top, xlabel=L"x")
-xs = range(first(ts), last(ts); length=200)
-plot!(xs, foo.(xs); label="exp(sin(2x)) + 0.05*sin(15x)")
-plot!(xs, interpolant.(xs); label="интерполянт")
+scatter(ts, ys; label="узлы интерполяции", legend=:top, xlabel=L"x")
+xs = range(first(ts), last(ts); length=200)
+plot!(xs, foo.(xs); label="exp(sin(2x)) + 0.05*sin(15x)")
+plot!(xs, interpolant.(xs); label="интерполянт")
 
-../_images/pwlinear_4_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Возьмём большее число точек, на этот раз равноотстоящих.

-
foo(x) = exp(sin(2x)) + 0.05*sin(15x)
-ts = range(1.0, 5.5; length=15)
-ys = foo.(ts)
+
foo(x) = exp(sin(2x)) + 0.05*sin(15x)
+ts = range(1.0, 5.5; length=15)
+ys = foo.(ts)
 
-interpolant = pwlininterp(ts, ys)
+interpolant = pwlininterp(ts, ys)
 
-scatter(ts, ys; label="узлы интерполяции", legend=:top, xlabel=L"x")
-xs = range(first(ts), last(ts); length=200)
-plot!(xs, foo.(xs); label="exp(sin(2x)) + 0.05*sin(15x)")
-plot!(xs, interpolant.(xs); label="интерполянт")
+scatter(ts, ys; label="узлы интерполяции", legend=:top, xlabel=L"x")
+xs = range(first(ts), last(ts); length=200)
+plot!(xs, foo.(xs); label="exp(sin(2x)) + 0.05*sin(15x)")
+plot!(xs, interpolant.(xs); label="интерполянт")
 
-../_images/pwlinear_6_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Похоже, интерполянт стремится к некоторому пределу…

-

4.2.3. Сходимость#

+

4.2.3. Сходимость#

Можно рассмотреть, как меняется ошибка приближения функции интерполянтом в зависимости от количества использующихся точек. Нам понадобятся несколько инструментов.

@@ -1086,61 +1094,115 @@

4.2.3. Сходимость - + -

+ - -
- + + + + + + +
+
+ +
-
+ + + + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/intro/cond.html b/intro/cond.html index d3fcf49..06fee01 100644 --- a/intro/cond.html +++ b/intro/cond.html @@ -1,54 +1,66 @@ + - + + + - + + + 2.2. Обусловленность задач — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/intro/ex.html b/intro/ex.html deleted file mode 100644 index 7c9a5ea..0000000 --- a/intro/ex.html +++ /dev/null @@ -1,771 +0,0 @@ - - - - - - - - - 1.4. Задания — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - - -
-
- - -
-
- Contents -
- -
-
-
-
- -
-

Задания

- -
-
- -
-

Contents

-
- -
-
-
-
- -
- -
-

1.4. Задания#

-
-

1.4.1. Точки#

-
    -
  • Задание предназначено для изучения языка Julia.

  • -
  • Задание можно выполнять в парах. В таком случае один человек в команде реализует интерфейс для CartesianPoint, а второй для PolarPoint.

  • -
-

Создайте модуль Points, предназначенный для работы с точками на плоскости. Реализуйте описанные ниже структуры данных и интерфейс к ним.

-

Создайте две структуры данных для точки на плоскости

-
    -
  1. Композитный тип CartesianPoint: хранит декартовы координаты точки;

  2. -
  3. Композитный тип PolarPoint: хранит полярные координаты точки.

  4. -
-

Оба типа должны быть подтипом абстрактного типа AbstractPoint.

-

К каждой структуре данных имплементируйте следующий интерфейс

-
-
Сложение p + q

Вовзращает новую точку как результат векторного сложения точек p::T и q::T.

-
-
Вычитание p - q

Возвращает новую точку как результат векторного вычитания из точки p::T точки q::T.

-
-
Длина norm(p)

Вовзращает длину радиус-вектора точки p.

-
-
Аргумент arg(p)

Возвращает угол (в радианах) между радиус вектором точки и осью абсцисс.

-
-
Угол между радиус-векторами angle(p::AbstractPoint, q::AbstractPoint)

Возвращает угол между радиус-векторами точек p и q.

-
-
Скалярное произведение радиус-векторов dot(p::AbstractPoint, q::AbstractPoint)

Возвращает скалярное произведение радиус-векторов точек p и q.

-
-
Растяжение α * p

Возвращает новую точку, получающуюся в результате центрального растяжения (α > 1) или сжатия (0 < α < 1) радиус вектора точки p в α::Real раз. Например, точка (5, 6) при α = 2.5 переходит в точку (12.5, 15.0).

-
-
Поворот rotate(p, φ)

Возвращает новую точку, получающуюся поворотом точки p на угол φ против часовой стрелки.

-
-
-

Заметьте, в случае функций angle и dot точки могут иметь разный тип.

-

Также имплементируйте интерфейс перевода из точки из одного типа во второй (см. [url])

-
-
CartesianPoint(p::PolarPoint)

Создает соответствующую точку типа CartesianPoint из точки типа PolarPoint.

-
-
PolarPoint(p::CartesianPoint)

Создает соответствующую точку типа PolarPoint из точки типа CartesianPoint.

-
-
-

В качестве ответа требуется:

-
    -
  • исходные файлы модуля Points;

  • -
  • файл, импортирующий модуль Points и демонстрирующий весь рабочий интерфейс.

  • -
-
-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/intro/float.html b/intro/float.html index 7bd6788..56364d6 100644 --- a/intro/float.html +++ b/intro/float.html @@ -1,54 +1,66 @@ + - + + + - + + + 2.1. Числа с плавающей точкой — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/intro/index.html b/intro/index.html index 2978843..e5ee348 100644 --- a/intro/index.html +++ b/intro/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 2. Введение — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/intro/julia.html b/intro/julia.html deleted file mode 100644 index 844b937..0000000 --- a/intro/julia.html +++ /dev/null @@ -1,3093 +0,0 @@ - - - - - - - - - 1.1. Основы языка программирования Julia — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - - -
-
- - - -
-
-
- -
-

Основы языка программирования Julia

- -
- -
-
-
- -
- -
-

1.1. Основы языка программирования Julia#

-
-

Julia: come for the syntax, stay for the speed

-

Nature

-
-

Почему Julia?

-

Язык Julia создавался как решение two-languages problem в научной и вычислительной среде [BEKS17]. На одних языках просто писать программы, но они медленно исполняются (например, на Python), с другой стороны, в языках с быстрым исполнением программ сложный синтаксис (например, C/C++, Fortran).

-

Так, язык Julia созданный в 2012 году, развивается с фокусом на математические вычисления при сохранении удобного синтаксиса. В языке богатая стандартная библиотека, которая легко расширяется под пользовательские структуры данных.

-

Кто уже пользуется?

-

Julia продолжает набирать популярность. Этот язык уже используется в физике, машинном обучении, финансовых моделях, биологии, медицине, геофизике… А в список пользователей входят: MIT, Princeton, NASA, CISCO, IBM, Adobe…1

-

Как изучить?

-

В данном разделе излагаются основные инструменты языка Julia, которые понадобятся в практикуме. Дополнительные материалы по изучению языка находятся в Приложении Язык Julia.

-
-

1.1.1. Инструкция по установке#

-

Ниже расположены краткие инструкции по установке исполнителя языка Julia для Linux-based операционных систем (ОС), MacOS и Windows. При возникновении неясностей, обратитесь к официальной инструкции для вашей ОС.

- - - -
-
-

1.1.2. Интерактивный режим#

- -

Знакомство языка начнём с интерактивного режима. Для этого необходимо запустить Julia REPL (Read-Evaluate-Print-Loop).

- -

В терминале необходимо набрать команду julia

-
% julia
-               _
-   _       _ _(_)_     |  Documentation: https://docs.julialang.org
-  (_)     | (_) (_)    |
-   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
-  | | | | | | |/ _` |  |
-  | | |_| | | | (_| |  |  Version 1.6.2 (2021-07-14)
- _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
-|__/                   |
-
-julia>
-
-
-

Строки до julia> это приветственное сообщение. Здесь есть ссылка на документацию к языку. Команды для получения помощи и версия релиза.

-

Julia REPL обладает четыремя режимами работы

-
    -
  • Интерпретатор;

  • -
  • Помощь;

  • -
  • Менеджер пакетов;

  • -
  • Командная оболочка.

  • -
-

При запуске запускается режим интерпретатора. Из него можно переключиться в другие режимы, а чтобы вернуться в режим интерпретатора из любого другого, нужно очистить строку Ctrl+E, Ctrl+U и нажать Backspace.

-

Чтобы выйти из REPL, очистите строку и нажмите Ctrl+D.

-
- -
-

В нём вы можете исполнять команды языка и переходить в другие режимы. Prompt-сообщение julia>.

-
julia> println("Hello, world")
-Hello, world
-
-julia>
-
-
-
- -
-

Здесь можно получить помощь и документацию к коду. Переход по нажатию ?. Prompt-сообщение help?>.

-
julia> ?
-
-help?> println
-search: println printstyled print sprint isprint
-
-  println([io::IO], xs...)
-
-  Print (using print) xs followed by a newline. If io is not supplied, prints to stdout.
-
-  ...
-
-
-
- -
-

Посвящён работе c окружениями и со сторонними пакетами 2. Команда перехода ]. Prompt-сообщение (@v1.6) pkg>. Этот режим нам пока не понадобится. Для знакомых с Python, этот режим обладает функционалом pip и virtualenv.

-
julia> ]
-
-(v1.6) pkg> help
-  Welcome to the Pkg REPL-mode. To return to the julia> prompt, ...
-
-
-
- -
-

В этом режиме можно работать с командной оболочкой, не выходя из Julia REPL. Команда перехода ;. Prompt-сообщение shell>.

-
julia> ;
-
-shell> echo 'Привет, мир!'
-Привет, мир!
-
-
-
-
-
-
-

1.1.3. Исполнение программ#

-

Исходный код программы в Julia это текстовый файл, стандартное расширение .jl. Сохраняйте исходный код в UTF кодировке.

-

Чтобы опробовать, создайте текстовый файл с названием hello.jl с содержимым

-
using Random
-
-maze_width = 50
-maze_height = 10
-
-for i in 1:maze_height
-    println(join(rand(1:4) > 2 ? "+" : " " for i in 1:maze_width))
-end
-
-
-

Программа запускается командой julia с указанием полного пути до файла с исходным кодом. Перейдите в терминале в директорию, где вы сохранили hello.jl и выполните команду julia hello.jl

-
% julia hello.jl
-  + + ++++ +++ + + ++ +  +++++ + ++ + + +  + ++ ++
-+ ++   + +++      +    + +  ++ +++++ +++ + + +    
- + ++     ++++++ + ++  ++ ++  + +  +++ + ++ + +++ 
- + + + ++++      +++ ++     +  +     + +   ++++ ++
- ++   ++   ++ +   + + + +++   ++   ++    ++ + + ++
- +        ++  +   ++ ++++    ++  + + + ++ ++  +  +
-+     ++ ++ ++  +++   ++++  +   ++ + + +++++++   +
-+  + + +++     + +         ++++++ ++++ +  + + + ++
-+ +    ++  + ++++++    +  + + +  +++ +   +++      
-+ + +  +  + ++++     + +++ ++++ + +  ++ ++ + ++ + 
-
-
-

У интерпретатора много полезных опций. Например, с опцией -i интерпретатор переходит в интерактивный режим после исполения программы.

-
% julia -i hello.jl
- + +++ ++++ +++    +++ +++    + + +++++  +++   ++ 
-+ +   ++ + + ++ +++ +  ++  ++   ++ +++      ++ +++
-++++   +  + +      +   +++++  ++ +++   +++ +++++  
-    +   +  ++ ++  + + + + ++ +   + ++ +    + + +++
-+++ ++ + + + + +   ++++++   ++++ + ++    + +  +  +
-+ ++    ++++ ++  ++++ +   ++     + ++    + +++ +++
-+ +++ ++++ +++  ++ ++++  +    + + ++++++++     +  
- +  + +   +++ +   +   ++++ +++    + +++ +++     + 
-++ +++++ + ++++    ++  ++    + +  ++ ++++++ ++ +++
-    + +++++ + ++ + +++ ++++  +   + +++  +++ + ++++
-               _
-   _       _ _(_)_     |  Documentation: https://docs.julialang.org
-  (_)     | (_) (_)    |
-   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
-  | | | | | | |/ _` |  |
-  | | |_| | | | (_| |  |  Version 1.6.2 (2021-07-14)
- _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
-|__/                   |
-
-julia> maze_height
-10
-
-
-
-
-

1.1.4. Числа и переменные#

-
-

Tip

-

Данный раздел является кратким обзором следующих разделов манула

-
    -
  • Variables [url];

  • -
  • Integers and Floating-Point Numbers [url];

  • -
  • Mathematical Operations and Elementary Functions [url];

  • -
  • Complex and Rational Numbers [url].

  • -
-
-

В Julia богатая система встроенных числовых типов, узнать тип переменной или литерала можно с помощью функции typeof(x).

-
julia> typeof(5)
-Int64
-
-julia> typeof(5.0)
-Float64
-
-julia> typeof(5im)
-Complex{Int64}
-
-julia> typeof(2.3 + 5.0im)
-ComplexF64 (alias for Complex{Float64})
-
-julia> typeof(2//3)
-Rational{Int64}
-
-julia> typeof(1//3 + 2//3im)
-Complex{Rational{Int64}}
-
-
-

Синтаксис присвоения значения переменной стандартный, также поддерживается параллельное присваивание и каскадное.

-
julia> x = 5
-5
-
-julia> x, y = 1, 2
-(1, 2)
-
-julia> x
-1
-
-julia> y
-2
-
-julia> x = y = 1
-1
-
-julia> x, y
-(1, 1)
-
-julia> (x = (y = 2) + (z = 3))
-5
-
-julia> x, y, z
-(5, 2, 3)
-
-
-

В исполнительном режиме REPL печатает возращаемое значение, его можно опустить с помощью ; в конце выражения.

-
julia> x = 10;
-
-julia> x
-10
-
-
- -

В имена переменных могут входить любые Unicode символы. -REPL позволяет набирать часто употребляемые с помощью LaTeX-подобного синтаксиса и Tab , например, так выглядит набор символов α₁:

-
julia> \alpha  # потом нажмите `<Tab>`, и ввод сменится на α
-       α
-       α\_1  # `<Tab>`
-       α₁
-
-
- - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 1.1 Некоторые операторы и функции.#

Описание

Синтаксис

Бинарные операторы +, -, *, /

x + y, x - y, x * y, x / y

Функции +, -, *, /

+(x, y,..), -(x, y), *(x, y,..), /(x, y)

Унарный минус

-x или -(x)

Частное от деления целых

x ÷ y или ÷(x, y) или div(x, y)

Остаток от деления целых

x % y или %(x, y) или rem(x, y)

Возведение в степень \(x^y\)

x ^ y или ^(x, y)

Логарифмы \(\ln(x)\), \(\log_2(x)\), \(\log_{10}(x)\)

log(x), log2(x), log10(x)

Тригонометрия \(\sin(x)\), \(\cos(x)\)

sin(x), cos(x)

Квадратный корень \(\sqrt{x}\)

sqrt(x)

-

Математические константы

-
julia> π                    # \pi<Tab>
-π = 3.1415926535897...
-
-julia>                     # \euler<Tab>
-ℯ = 2.7182818284590...
-
-julia> typeof()
-Irrational{:ℯ}
-
-
-

При применении операций к разным типам аргументов тип результата интуитивен: число из типа, соответствующего, математически “меньшему” множеству конвертируется в тип математически “большего” множества. Затем операция выполняется для одинаковых типов. Система типов в Julia это её позвоночник, см. раздел Система типов.

-

Редко требуется аргумент подать в явном типе, например,

-
julia> sqrt(-1.0)
-ERROR: DomainError with -1.0:
-sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
-...
-
-julia> sqrt(-1.0 + 0im)
-0.0 + 1.0im
-
-
- -
-
-

1.1.5. Логические типы и сравнение величин#

-

В Julia один логический тип Bool, имеющий два значения: true и false. -Операторы сравнения как правило возвращают тип Bool и используются в логических конструкциях.

- - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 1.2 Некоторые логические операторы и операторы сравнения (функциональные форма не приведена).#

Описание

Синтаксис

Логическое отрицание

!a

Логическое И (short-circuit)

a && b

Логическое ИЛИ (short-circuit)

a || b

Равенство по значению

x == y, isequal(x, y) (не взаимозаменяемы)

Identity

x === y, x y

Неточное равенство по значению

x y, isapprox(x, y[; kwargs...])

Меньше, чем

x < y и x <= y, x y

Больше, чем

x > y и x >= y, x y

-

Кроме того, существует тип Missing со единственным значением missing. Он используюется с операторами & и |, реализующую троичную логику на true, false и missing.

-
-
-

1.1.6. Строки#

-
-

Tip

-

Подробнее о строках в мануале [url].

-
-

В Julia богатая поддержка работы с текстом, встроенные текстовые типы работают с Unicode. -Основные типы: Char, String и SubString.

-

Тип Char используется для работы с отдельными символами, его литерал две одинарные кавычки '.

-
julia> 'a'
-'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
-
-julia> 'α'
-'α': Unicode U+03B1 (category Ll: Letter, lowercase)
-
-julia> 'aa'
-ERROR: syntax: character literal contains multiple characters
-Stacktrace:
- [1] top-level scope
-   @ none:1
-
-
-

Тип String предназначен для строк, его литерал двойные кавычки ".

-
julia> "a"
-"a"
-
-julia> "a" == 'a'
-false
-
-julia> "aaaa"
-"aaaa"
-
-julia> typeof("aaaa")
-String
-
-
-

Escape специальных символов производится привычным \, например '\n', '\t'.

- - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 1.3 Часто используемые операции над строками.#

Описание

Cинтаксис

Пример

Результат

Конкатенация

x * y

"ab" * "b"

"abb"

Дублирование

x ^ i

"a" ^ 6

"aaaaaa"

Интерполяция значения переменной

"$x"

y = 1.0; x = "$y"

x будет "1.0"

Интерполяция результата выражения

"$(expr)"

"$(sin(π/2))"

"1.0"

Разбиение строки

split(x)

split("a b\nc\td")

["a", "b", "c", "d"] (массив)

Сбор строки

join(x [, delim])

join([25, "февраля", 1936], " ")

"25 февраля 1936"

Удаление whitespace окружения

strip(x)

strip(" \ta ba\n")

"a ba"

Форматированная строка (using Printf)

@sprintf "fmt" x...

@sprintf %.2f, %.2f" π

3.14, 2.72"

Печать в stdout

println(x,..)

println("A = ", 10)

Печатает в stdout “A = 10”

Чтение из stdin

readline()

readline()

Ожидание ввода

Парсинг строки

parse(T, x)

parse(Float64, "1.564")

1.564

-

Строки в Julia являются неизменяемыми объектами. -Однако, часто требуется поработать с каким-то участком строки. -Для этого, чтобы экономить память и время, в Julia существует тип SubString, который указывает на часть строки, но при этом ведёт себя как String.

-
julia> split(strip("  1.0 2.0 3.0   "))
-3-element Vector{SubString{String}}:
- "1.0"
- "2.0"
- "3.0"
-
-julia> parse.(Float64, ans)  # ans -- внутренняя переменная REPL, хранящая результат последнего вычисления
-3-element Vector{Float64}:
- 1.0
- 2.0
- 3.0
-
-
-
-
-

1.1.7. Управляющие конструкции#

-
-

Tip

-

Подробнее в мануале [url]. -Здесь освещены не все конструкции и не так подробно.

-
-
-

1.1.7.1. Составные выражения#

-

Блок begin-end позволяет объединять несколько выражений в одно, составное выражение (compound expression). Результат выражения это результат последнего вычисления в выражении.

-
julia> z = begin
-           x = 1
-           y = 2
-           x + y
-       end
-3
-
-julia> x, y
-(1, 2)
-
-
-

Как видно из примера, begin-end исполняется во внешнем пространстве имён. Его двойник блок let-end создаёт собственное пространство имён. Внутри let-end можно пользоваться именами извне, но если происходит присвоение, то имя создаётся внутри видимости let-end.

-
julia> x, y = 1, 2
-(1, 2)
-
-julia> let
-           x = 10
-           y = 20
-           x + y
-       end
-30
-
-julia> x, y
-(1, 2)
-
-
-

С помощью ; можно поместить несколько выражений на одной строке, что часто используется для коротких составных выражений или депривации вывода в REPL.

-
julia> z = (x = 1; y = 2; x + y)
-3
-
-julia> z = begin x = 1; y = 2; x + y end
-3
-
-
-

Предназначение ; аналогично его предназначению в C-подобных языках, но в Julia не требуется ставить ; после каждой инструкции.

-
-
-

1.1.7.2. Ветвление#

-

Основная конструкция это if-elseif-else блок.

-
julia> x, y = 10, 20;
-
-julia> if x < y
-           "x is less than y"
-       elseif x > y
-           "x is greater than y"
-       else
-           "x is equal to y"
-       end
-"x is less than y"
-
-
-
    -
  • В if и elseif должно стоять boolean выражение;

  • -
  • Количество elseif не ограничено.

  • -
-

Блок if-elseif-else, как и begin-end является выражением и возвращает значение. В примере выше возвращается результат первой ветви исполнения – строка “x is less than y”.

-

Также в вашем распоряжении тернарный оператор cond ? whentrue : whenfalse.

-
julia> count = 24;
-
-julia> "$count apple$(count > 1 ? "s" : "")"
-"24 apples"
-
-
-

Помимо этого, в Julia есть try/catch для обработки программных исключений.

-
-
-

1.1.7.3. Циклы#

-

Julia предоставляет два цикла: while и for.

-
julia> i = 1;
-
-julia> while i <= 5
-           println(i)
-           i += 1
-       end
-1
-2
-3
-4
-5
-
-
-

Цикл while создаёт собственное пространство имён, что может вызвать фрустрацию. В REPL всё пространство имён глобальное, поэтому пример выше работает. Если же вы используете while-цикл в глобальном пространстве скрипта, то при обращении к переменной i будет ошибка. В этом случае можно внутри цикла указать global i, чтобы внутри while она была видна. Более лучший вариант это обернуть пример выше в функцию, функции создают собственное пространство имён и конфликта со вложенным в неё while не будет.

-

У for-цикла следующий синтаксис.

-
for item in iterator
-    ...
-end
-
-
-

Переменная цикла item создаётся внутри видимости цикла for автоматически. После исполнения цикла она недоступна, если не была объявлена во внешней области видимости.

-
julia> for j in 1:3
-           println(j)
-       end
-1
-2
-3
-
-julia> j
-ERROR: UndefVarError: j not defined
-
-
-

Здесь использован range operator start:stop, создающий генератор арифметической прогрессии.

-
help?> 1:3
-  (:)(start, [step], stop)
-
-  Range operator. a:b constructs a range from a to b with a step size of 1 (a UnitRange),
-  and a:s:b is similar but uses a step size of s(a StepRange).
-
-
-

Итерировать можно и по коллекциям. Ниже пример для кортежа Tuple.

-
julia> for j in (1, 2, "hello")
-           println(j)
-       end
-1
-2
-hello
-
-
-

Доступно множество утилит для итерирования: zip, enumerate, drop, rest

-
julia> for (i, val) in enumerate((1, 2, "hello"))
-           println("$i: $val")
-       end
-1: 1
-2: 2
-3: hello
-
-
-

Для циклов доступны стандартные команды досрочного завершения итерации continue и всего цикла break.

-

Циклы могут быть вложенными. Для вложенного for-цикла существует альтернативный вариант синтаксиса.

-
- -
-
julia> for j in 1:2
-           for i in 3:4
-               println("i = $i, j = $j")
-           end
-       end
-i = 3, j = 1
-i = 4, j = 1
-i = 3, j = 2
-i = 4, j = 2
-
-
-
- -
-
julia> for j in 1:2, i in 3:4
-           println("i = $i, j = $j")
-       end
-i = 3, j = 1
-i = 4, j = 1
-i = 3, j = 2
-i = 4, j = 2
-
-
-
-
-
-
-
-

1.1.8. Функции#

-
-

Tip

-

Больше информации в мануале [url].

-
-

Основной синтаксис для функций в Julia

-
julia> function f(x, y)
-           return sqrt(x^2 + y^2)
-       end
-f (generic function with 1 method)
-
-
-

Строго говоря, команда return необязательна: функция в Julia возвращает результат последнего выражения, однако, мы будем придерживаться Code Style: Blue.

- -

В теле функции может находиться несколько команд return, в этом случае при вызове сработает только одна из них. -Если необходимо, чтобы функция ничего не возвращала, тогда используется return nothing. -Тип Nothing имеет лишь одно значение nothing, представляющее в Julia отутствие значения.

-

Зачастую пригождается более краткий синтаксис создания функции (assignment form)

-
julia> f(x, y) = sqrt(x^2 + y^2)
-f (generic function with 1 method)
-
-
-

В этом случае справа от = может находиться составное выражение (compound expression) begin-end.

-
julia> g(x, y) = begin              # или g(x, y) = begin z = f(x, y); return 2*z end
-           z = f(x, y)
-           return 2*z
-       end
-g (generic function with 1 method)
-
-
-

Синтаксис вызова интуитивен

-
julia> f(3, 4)
-5.0
-
-julia> g(3, 4)
-10.0
-
-
-

В Julia аргументы передаются по принципу pass-by-sharing. Т.е. аргументы функции внутри тела ведут себя как новые переменные. Однако, у изменяемых mutable аргументов (например, массив), можно поменять значения, и они будут видны извне. По соглашению, если функция меняет свой аргумент, то в её имя добавляется ! в конце, например, map!(f, A, B), push!(A, x) (исключение составляют функции, работающие с вводом-выводом print, write,..).

-

Функции являются first-class объектами. Ими можно “распоряжаться”, как переменными: присваивать их другим переменным, передавать как аргумент…

-
julia> φ = f;
-
-julia> φ(3, 4)
-5.0
-
-
-

Важно, что операторы в Julia также являются функциями

-
julia> +(1, 2, 3) == 1 + 2 + 3
-true
-
-
-

Языковые конструкции, вроде доступа к элементу массива (A[i]) или полю структуры (S.x) являются операторами c функциональными аналогами.

-

Можно создавать анонимные функции

-
julia> x -> 2x                        # короткий синтаксис
-#1 (generic function with 1 method)
-
-julia> f4 = x -> 2x                   # анонимная функция x -> 2x присвоена переменной f4
-#3 (generic function with 1 method)
-
-julia> f4(8)
-16
-
-julia> function (x)                   # длинный синтаксис
-           return 3x
-       end
-#5 (generic function with 1 method)
-
-julia> map(x -> 3x, 1:4)              # пример применения
-4-element Vector{Int64}:              # map здесь создает массив
-  3                                   # из утроенных значений
-  6                                   # арифм. прогрессии от 1 до 4
-  9
- 12
-
-
-

В Julia тип, соответствующий аргументам функции, является кортежем Tuple. Кортеж неизменная коллекция.

-
julia> tup = (3, 4)
-(3, 4)
-
-julia> tup[1]
-3
-
-julia> (3,)  # tuple из одного значения
-(3,)
-
-
-

Функция, конечно, может и возращать Tuple, т.е. возвращать несколько значений. Если абстрагироваться, функция в Julia создаёт из одного кортежа значений другой кортеж.

-
julia> function addmul(x, y)
-           return x + y, x * y
-       end
-addmul (generic function with 1 method)
-
-julia> a, b = addmul(3, 4)
-(7, 12)
-
-julia> a
-7
-
-julia> b
-12
-
-
-

Также существует именованный кортеж NamedTuple, хранящий пары ключ-значение. На его основе создаются функции, принимающие аргументы по ключу.

-

И можно присваивать аргументам значения по умолчанию.

-
# x - позиционный, p - именованный со значением по умолчанию
-julia> f(x; p=10) = p * x
-f (generic function with 1 method)
-
-julia> f(1)
-10
-
-julia> f(2; p=20)
-40
-
-
-
-
-

1.1.9. Система типов#

-
-

Tip

-

Подробнее, как всегда, в мануале к языку [url].

-
-

В Julia сильная динамическая система типов. Система типов и методы функций являются фундаментом по повторному использованию кода.

- -

Поскольку в Julia динамическая типизация, то переменная может менять свой тип в процессе работы программы.

-
julia> x = 5
-5
-
-julia> typeof(x)
-Int64
-
-julia> x  = 5.0
-5.0
-
-julia> typeof(x)
-Float64
-
-
-

В Julia нельзя указать, чтобы переменная имела постоянное значение, но можно указать, что переменная не меняет свой тип

-
julia> const y = 10
-10
-
-julia> y = 10.0
-ERROR: invalid redefinition of constant y
-Stacktrace:
- [1] top-level scope
-   @ REPL[6]:1
-
-julia> y = 20
-WARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors.
-20
-
-
-

Julia не допустила присвоение y = 10.0, потому что оно меняет тип переменной y::Int64. Однако, присваивать значения Int64 переменной y всё-таки можно, но не стоит этого делать.

-
-

1.1.9.1. Декларация типов#

-

С помощью оператора :: вы можете декларировать тип объекта. Обычно это делается для

-
    -
  • переменных;

  • -
  • аргументов функции;

  • -
  • возвращаемого функцией значения;

  • -
  • полей композитных типов (структур).

  • -
- -

Например, вы можете декларировать тип переменной внутри функции (или другой локальной области видимости). В таком случае при присвоении значения происходит конвертация.

-
julia> function foo()
-           x::Int8 = 100
-           return x
-       end
-foo (generic function with 1 method)
-
-julia> x = foo()
-100
-
-julia> typeof(x)
-Int8
-
-julia> typeof(100)
-Int64
-
-
-

Также вы можете декларировать тип возвращаемого значения функцией (хотя, делается это редко, поскольку компилятор выводит типы, если возможно).

-
julia> bar()::Int8 = 100
-bar (generic function with 1 method)
-
-julia> bar()
-100
-
-julia> typeof(bar())
-Int8
-
-
-
-
-

1.1.9.2. Какие бывают типы#

-

Типы в Julia классифицируются по следующим признакам (указаны не все)

-
    -
  • абстрактный abstract (AbstractFloat) и конкретный concrete (Float64);

  • -
  • примитивный primitive (Float64) и композитный composite (Complex{Float64});

  • -
  • параметрический parametric (Complex{Float64});

  • -
  • изменяемый (Vector{Float64}) и неизменяемый (Tuple{Float64,Float64});

  • -
  • -
-

В Julia система типов является деревом, корень которого тип Any. Листьями дерева типов являются конкретные типы. У значения такого типа известна структура в памяти. Абстрактные типы нужны в качестве промежуточных узлов дерева типов, выстраивая иерархию.

- -

Например, так выглядит часть дерева с числовыми и строчными типами, при этом

-
    -
  • конкретные типы указаны в округлённых рамках;

  • -
  • абстрактные в прямоугольных.

  • -
-
- flowchart TB - Any --> Number --> Real --> Integer - Any --> AbstractString --> String([String]) - AbstractString --> SubString[/SubString/] - Number --> Complex[/Complex/] - Real --> AbstractFloat - Real --> Rational[/Rational/] - Rational --> RationalInt64(["Rational{Int64}"]) - Rational --> RationalInt32(["Rational{Int32}"]) - Integer --> Int64([Int64]) - Integer --> Int32([Int32]) - Integer --> Int16([Int16]) - Integer --> Int8([Int8]) -

Несколько функций для интроспекции системы типов

-
    -
  • subtypes(T): подтипы типа T;

  • -
  • isabstracttype(T): является ли тип T абстрактным;

  • -
  • isprimitivetype(T): является ли тип T примитивным;

  • -
  • ismutable(x): является ли значение x изменяемым.

  • -
- -

Также с помощью subtype-оператора Tx <: Ty можно проверять “является ли тип Tx подтипом типа Ty”.

-
julia> Int64 <: Number
-true
-
-
-

Примитивные типы представляются в виде набора бит. Примерами являются Int-ы и Float-ы.

-
-

Note

-

Создание собственных абстрактных и примитивных типов здесь не разбирается.

-
-
-
-

1.1.9.3. Композитные типы#

-

Композитный тип имеет более сложную структуру в памяти, чем примитивный тип. Этот тип является набором именованных полей, а экземпляром такого типа можно манипулирвовать как одним значением. В других языках им соответствуют объекты (objects) или структуры (structs). Примерами встроенных композитых типов являются Complex{T}, Rational{T}, Tuple, String, Array, IO

-

Классический пример – структура для точки на плоскости.

-
julia> struct Point
-           x
-           y::Int64       # так указывается тип (можно и абстрактный)
-       end
-
-julia> p1 = Point(1.0, 2)
-Point(1.0, 2)
-
-julia> typeof(p1)
-Point
-
-julia> p1.x
-1.0
-
-julia> p1.x = 9
-ERROR: setfield! immutable struct of type Point cannot be changed
-...
-
-
-

Присвоение можно разрешить, сделав структуру изменяемой (mutable).

-
julia> mutable struct MPoint
-           x
-           y
-       end
-
-julia> mp1 = MPoint(1, 2)
-MPoint(1, 2)
-
-julia> mp1.x = 10
-10
-
-julia> mp1
-MPoint(10, 2)
-
-
-

Иногда это может приводить к замедлению работы, поскольку mutable struct выделяется в куче, а не на стеке.

-

Тем не менее, в поле обычной структуры можно хранить значение изменяемого типа. В таком случае поле хранит ссылку на изменяемый объект. Объект поменять можно, а ссылку – нет. Например, так хранятся массивы внутри структур.

-

Конструктор (constructor) Point(x, y) для композитного типа можно поменять. Более того, можно создать несколько конструкторов.

-
-
-

1.1.9.4. Параметрические композитные типы#

- -

Параметрический тип это тип, который в своём объявлении содержит дополнительную информацию. Например, тип Complex в языке объявлен следующим образом [source].

-
struct Complex{T<:Real} <: Number
-    re::T
-    im::T
-end
-
-
-

Это объявление значит

- -
    -
  • создать UnionAll-тип Complex, который будет вести себя как супертип для Complex{T};

  • -
  • создать параметрический тип Complex{T},

  • -
  • где параметр T является подтипом типа Real,

  • -
  • при этом типы Complex и Complex{T} являются подтипами Number;

  • -
  • у Complex{T} два поля: re и im, каждое из них имеет тип T.

  • -
- -

В качестве параметров могут быть типы и значения примитивных типов. Например, в Julia объявлен тип для массивов AbstractArray{T,N}, где под T подразумевается тип значений, а под N размерность массива (1 для векторов, 2 для матриц…).

-

Параметрические типы порождают целое семейство типов. Член такого семейства – любая комбинация разрешенных значений параметров типа.

-

Таким образом, с помощью параметризации композитного типа мы можем дать подсказки для компилятора, чтобы тот создавал оптимизированный код.

-
-

1.1.9.4.1. Пример#

-

Рассмотрим две версии Point

-
julia> struct APoint
-           x
-           y
-       end
-
-julia> struct TPoint{T}
-           x::T
-           y::T
-       end
-
-
-

Создадим функцию, вычисляющую расстояние от точки до начала координат

-
julia> dist(p) = sqrt(p.x^2 + p.y^2)
-dist (generic function with 1 method)
-
-
-

Заметьте, в этой функции нет никаких ограничений на тип p.

-

Создадим два массива случайных точек

-
julia> AA = [APoint(rand(2)...) for _ in 1:1_000_000];
-
-julia> TA = [TPoint(rand(2)...) for _ in 1:1_000_000];
-
-julia> typeof(AA), typeof(TA)
-(Vector{APoint}, Vector{TPoint{Float64}})
-
-
-

Про массив TA компилятор явно знает больше, судя по typeof.

-

Измерим время работы. Точный бенчмарк показывает разницу времени работы в два порядка.

-
julia> using BenchmarkTools
-
-julia> @btime dist.(AA);
-  117.766 ms (4999502 allocations: 83.92 MiB)
-
-julia> @btime dist.(TA);
-  1.290 ms (5 allocations: 7.63 MiB)
-
-
- -
-
-
-
-

1.1.10. Методы и multiple dispatch#

-

Для каждой функции в Julia можно определить сколько угодно методов (methods). Это способ полиформизма в языке. Вы уже с ним сталкивались, например, 1 + 2 и 1.0 + 2.0 совершенно разные вызовы. В первом случае вызывается метод +(x, y) для Int64, а во втором метод +(x, y) для сложения Float64.

-

У сложения + в Julia 1.6.2 190 методов.

-
julia> methods(+)
-# 190 methods for generic function "+":
-[1] +(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:87
-[2] +(c::Union{UInt16, UInt32, UInt64, UInt8}, x::BigInt) in Base.GMP at gmp.jl:528
-[3] +(c::Union{Int16, Int32, Int64, Int8}, x::BigInt) in Base.GMP at gmp.jl:534
-...
-
-
-

Узнать, какой метод вызвался можно макросом @which.

-
julia> @which 1 + 2
-+(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:87
-
-julia> @which 1.0 + 2.0
-+(x::Float64, y::Float64) in Base at float.jl:326
-
-julia> @which 1.0 + 2
-+(x::Number, y::Number) in Base at promotion.jl:321
-
-
-

Можно сказать, что функция определяет дефолтное действие с аргументами. А методы функции содержат частные реализации этих действий на случаи тех или иных аргументов. Например, метод sum для вектора сложит все элементы и это займёт линейное время, а sum для арифметической прогрессии займёт константное время, используя формулу. При этом с точки зрения пользователя сигнатура вызова одна и та же: sum(A).

-

Процесс выбора нужного метода называется диспетчеризацией (dispatch). В Julia диспетчеризация производится по типам всех позиционных аргументов функции. Этот механизм называется multiple dispatch. Он гибче и продуктивнее, нежели диспетчеризация по одному типу, например, как в Python (type(x).__add__(x, y)). При этом, в отличие от языков со статической типизацией, нет необходимости указывать типы аргументов.

-

Строго говоря, generic function единственна, а методов у неё много. Однако, всё же принято называть методы функциями, если контекст позволяет.

-

Методы создаются как функции, но с указанием типа хотя бы одного аргумента.

-
julia> f(x, y) = 2x + y
-f (generic function with 1 method)
-
-julia> f(x::Float64, y::Float64) = 3x + y
-f (generic function with 2 methods)
-
-julia> methods(f)
-# 2 methods for generic function "f":
-[1] f(x::Float64, y::Float64) in Main at REPL[28]:1
-[2] f(x, y) in Main at REPL[26]:1
-
-
-

Здесь же посмотрим на диспетчеризацию

-
julia> f(1, 1)
-3
-
-julia> f(1.0, 1.0)  # два Float64, подходит f(x::Float64, y::Float64)
-4.0
-
-julia> f(1.0, 1)    # Float64 и Int64, подходит f(x, y)
-3.0
-
-
-

Конечно, использование не конкретных типов разрешено

-
julia> f(x::Complex, y::Complex) = 5x + y*im
-f (generic function with 3 methods)
-
-julia> f(1.5im, 2.5im)
--2.5 + 7.5im
-
-julia> f(1.5im, 2.5)
-2.5 + 3.0im
-
-
-

При диспетчеризации может возникать коллизия: два или более метода подходят для вызова. В этом случае Julia выдаст ошибку MethodError.

-

Как создаётся быстрый код? При запуске функции или метода от данного набора аргументов в первый раз, Julia

-
    -
  • Запоминает типы аргументов при вызове (типы могут быть и абстрактные);

  • -
  • Выводит типы переменных в теле функции (type inference), для которых это возможно;

  • -
  • Компилирует функцию для данного набора типов аргументов и сохраняет машинный код, если все типы переменных стабильны, т.е. не зависят от значений аргументов;

  • -
  • При дальнейших вызовах функции с теми же типами аргументов будет использоваться компилированная (быстрая) версия.

  • -
-

Кроме того, до запуска скрипта (compilation time) Julia просматривает методы и некоторые из них может прекомпилировать.

-

Методы могут быть параметрическими, и в их теле вам будет доступен тип аргумента на этапе компиляции (typeof(x) не нужен).

- -
-
-

1.1.11. Массивы#

-
-

1.1.11.1. Массивы#

-

В Julia для массивов существует абстрактный тип AbstractArray{T,N}, где T тип элемента массива (Int64, String, Complex{Int64}, Number, Any…), а N размерность. При написании собственных типов с поведением массива в объявлении следует указать, что ваш тип является подтипом AbstractArray.

-

Встроенным типом для массивом является Array{T,N}. Это изменяемый массив динамического размера с column-major хранением элементов.

-
-

Note

-

Поскольку в Julia массивы хранятся постолбично, то для быстродействия вложенный цикл должен проходится по строке, а внешний по столбцу. Вообще, если есть массив A[i, j, k], то цикл должен выглядить так:

-
for k in eachindex(A, 3)
-    for j in eachindex(A, 2)
-        for i in eachindex(A, 1)
-            ...
-        end
-    end
-end
-
-
-
-

Существуют два часто используемых синонима

-
    -
  • Vector{T} == Array{T,1} для одномерных вектор-столбцов;

  • -
  • Matrix{T} == Array{T,2} для матриц и вектор-строк.

  • -
-

Литералом Array{T,N} являются квадратные скобки [], при этом можно явно указать тип T[] (Int[1, 2], Float64[1, 2]). Создание массива с помощью литерала осуществляется посредством вертикальной и горизонтальной конкатенации.

-

Для вертикальной конкатенации используется ; или новая строка.

-
- -
-
julia> [1, 2, 3]
-3-element Vector{Int64}:
- 1
- 2
- 3
-
-
-
- -
-
julia> [[1, 2, 3]; [7, 8]]
-5-element Vector{Int64}:
- 1
- 2
- 3
- 7
- 8
-
-
-
-
-

Для горизонтальной конкатенации используется пробел или табуляция. Запятая , означает отсутствие конкатенации.

-
- -
-
julia> [1 2 3 4]
-1×4 Matrix{Int64}:
- 1  2  3  4
-
-
-
- -
-
julia> [[1, 2] [3, 4]]
-2×2 Matrix{Int64}:
- 1  3
- 2  4
-
-
-
-
-

Если конкатенация не нужна, используйтся запятая ,. В примере ниже показано создание вектора векторов.

-
julia> [[1, 2, 3], [7, 8]]
-2-element Vector{Vector{Int64}}:
- [1, 2, 3]
- [7, 8]
-
-
-

На первый взгляд, синтаксис может показаться запутанным. Однако, он позволяет создавать блочные матрицы и тензоры.

-
- -
- Демонстрация 1.1 - - (Создание блочной матрицы) - -
-

Скажем, задана блочная матрица

-
-\[\begin{split}\mathcal{M} = \left[\begin{array}{ccc|ccc} -1 & 2 & 3 & 1 & 0 & 0 \\ -4 & 5 & 6 & 0 & 1 & 0 \\ -7 & 8 & 9 & 0 & 0 & 1 \\ \hline -0 & 0 & 0 & 10 & 11 & 12 \\ -\end{array}\right] -= \left[\begin{array}{c|c} -A & I \\ \hline -0^\top & b^\top -\end{array}\right]\end{split}\]
-

Соответствующий код будет

-
julia> A = [1 2 3; 4 5 6; 7 8 9]
-3×3 Matrix{Int64}:
- 1  2  3
- 4  5  6
- 7  8  9
-
-julia> I = [1 0 0; 0 1 0; 0 0 1]
-3×3 Matrix{Int64}:
- 1  0  0
- 0  1  0
- 0  0  1
-
-julia> zero = [0, 0, 0]
-3-element Vector{Int64}
- 0
- 0
- 0
-
-julia> b = [10, 11, 12]
-3-element Vector{Int64}:
- 10
- 11
- 12
-
-julia> M = [A I; zero' b']
-4×6 Matrix{Int64}:
- 1  2  3   1   0   0
- 4  5  6   0   1   0
- 7  8  9   0   0   1
- 0  0  0  10  11  12
-
-
-

Оператор ' (одинарная кавычка) выполняет транспонирование.

-
-
-

1.1.11.2. Индексирование#

-

В Julia встроено два вида индексов.

-

Синтаксис первого A[i], это линейный индекс LinearIndex. Он позволяет получить i-ый по счёту в памяти элемент массива. Например, для вектора A[4] это \(A_4\), а для матрицы размера \(2 \times 3\) это \(A_{1, 3}\).

-

Синтаксис второго A[i, j, k,..], это декартов индекс CartesianIndex. Данный индекс учитывает размерность массива. Например, для матрицы элемент A[i, j] это элемент \(A_{i,j}\) (\(i\)-ая строка, \(j\)-ый столбец).

-

Индексом может быть и коллекция элементов, что позволяет обращаться к целым строкам, столцам, их пересечению, или просто некоторому набору элементов. Часто для этого используется range operator start:[step:]stop.

-

Ниже показано несколько примеров для матрицы.

-
julia> A = [1 2 3; 4 5 6; 7 8 9]
-3×3 Matrix{Int64}:
- 1  2  3
- 4  5  6
- 7  8  9
-
-
-
- -
-
julia> A[6]     # линейный индекс
-8
-
-julia> A[3, 2]  # декартов индекс
-8
-
-julia> A[end, end]
-9
-
-
-
- -
-

Строка.

-
julia> A[1, :]  # A[строка 1, все столбцы]
-3-element Vector{Int64}:
- 1
- 2
- 3
-
-
-

Столбец.

-
julia> A[:, 2]  # A[все строки, столбец 2]
-3-element Vector{Int64}:
- 2
- 5
- 8
-
-
-
- -
-

“Пересечение” строк 1 и 2 со столбцами 2 и 3.

-
julia> A[1:2, 2:3]
-2×2 Matrix{Int64}:
- 2  3
- 5  6
-
-
-

Угольные элементы.

-
julia> A[[1, end], [1, end]]
-2×2 Matrix{Int64}:
- 1  3
- 7  9
-
-
-
- -
-

Главная диагональ.

-
julia> A[1:4:end]
-3-element Vector{Int64}:
- 1
- 5
- 9
-
-
-

Побочная диагональ.

-
julia> A[3:2:7]
-3-element Vector{Int64}:
- 7
- 5
- 3
-
-
-
-
-
-
-

1.1.11.3. Присваивание значений#

-

Массив Array{T,N} изменяемый тип, можно перезаписывать его элементы. Это делается с помощью оператора присваивания =, при этом по обе стороны должны находиться объекты одинаковых размерностей.

-
julia> A = [1 2 3; 4 5 6; 7 8 9];
-
-julia> A[:, 1] = [7, 4, 1];
-
-julia> A
-3×3 Matrix{Int64}:
- 7  2  3
- 4  5  6
- 1  8  9
-
-julia> A[1, :] = [-1, 0, 1];
-
-julia> A
-3×3 Matrix{Int64}:
- -1  0  1
-  4  5  6
-  1  8  9
-
-julia> A[1, 2] = 10;
-
-julia> A
-3×3 Matrix{Int64}:
- -1  10  1
-  4   5  6
-  1   8  9
-
-
-

При присваивании можно использовать векторизацию.

-
julia> A[1, :] .= 11;
-
-julia> A
-3×3 Matrix{Int64}:
- 11  11  11
-  4   5   6
-  1   8   9
-
-
-
-
-

1.1.11.4. Вспомогательные функции#

-

Интроспекция массива

-
    -
  • length(A): количество элементов;

  • -
  • ndims(A): размерность;

  • -
  • size(A): кортеж из размеров каждой размерности (число_строк, число_столбцов);

  • -
  • size(A, n): размер размерности n;

  • -
  • eachindex(A): итератор из индексов массива.

  • -
-

Создание массивов

-
    -
  • collect(c): создание массива из коллекции;

  • -
  • zeros([T=Float64,] dims...): массив из нулей типа T размерности dims...;

  • -
  • ones([T=Float64,] dims...): аналогично zeros, но массив из единиц;

  • -
  • copy(A): нерекурсивная копия массива;

  • -
  • similar(A): неинициализированный массив той же размерности и типа, что A;

  • -
  • rand([T=Float64,] dims...): массив из равномерно-распределённых случайных чисел;

  • -
  • fill(x, dims...): массив размера dims... из x;

  • -
  • map(f, c): создание массива на основе применения функции f к каждому элементу коллекции c.

  • -
-

Другие операции

-
    -
  • push!(A, x...): добавление в конец A элемента x;

  • -
  • pop!(A): извлечение элемента с конца A.

  • -
-

Для чтения и записи в файл массивов в форматах с сепаратором (.csv, .tsv,..) есть встроенная библиотека DelimitedFiles.

-
-
-

1.1.11.5. Линейная алгебра#

-
-

Tip

-

Больше информации тут [url].

-
-

В Julia богатая стандартная библиотека операций линейной алгебры. Часто используемые инструменты доступны сразу.

-

Ниже представлены примеры операций для этих векторов и матриц.

-
julia> a = [1, 2, 3]; b = [4, 5, 6];
-
-julia> A = [1 2; 3 4]; B = [-1 -2; -3 -4];
-
-
-
- -
-
julia> c = 2*a + b - a / 2
-3-element Vector{Float64}:
-  5.5
-  8.0
- 10.5
-
-julia> A/2 + 2*B
-2×2 Matrix{Float64}:
- -1.5  -3.0
- -4.5  -6.0
-
-
-
- -
-
julia> A * [1, 2]
-2-element Vector{Int64}:
-  5
- 11
-
-julia> A * B
-2×2 Matrix{Int64}:
-  -7  -10
- -15  -22
-
-
-
- -
-
julia> a'
-1×3 adjoint(::Vector{Int64}) with eltype Int64:
- 1  2  3
-
-julia> a' * b
-32
-
-julia> A * A'
-2×2 Matrix{Int64}:
-  5  11
- 11  25
-
-
-

Для комплексных матриц '-оператор выполняет эрмитово сопряжение.

-
- -
-

Решается система \(A x = [1, 2]^\top\), inv(A)\(= A^{-1}\).

-
julia> x = A \ [1, 2]
-2-element Vector{Float64}:
- 0.0
- 0.5
-
-julia> A * x
-2-element Vector{Float64}:
- 1.0
- 2.0
-
-julia> inv(A) * [1, 2] == x
-true
-
-
-
-
-

Дополнительный набор инструментов импортируется из стандартной библиотеки LinearAlgebra.

-
julia> using LinearAlgebra
-
-julia> det(A), tr(A), norm(a)  # детерминант, след, норма
-(-2.0, 5, 3.7416573867739413)
-
-julia> a  b, A  B  # скалярное умножение (dot)
-(32, -30)
-
-julia> a × b  # векторное умножение
-3-element Vector{Int64}:
- -3
-  6
- -3
-
-
-

LinearAlgebra также содержит

-
    -
  • типы для матриц специального вида;

  • -
  • решатели СЛАУ;

  • -
  • разложения матриц;

  • -
  • функции над матрицами;

  • -
  • низкоуровневые операции;

  • -
  • BLAS-функции;

  • -
  • обёртку над LAPACK.

  • -
-
-
-
-

1.1.12. Векторизация функций#

-
-

Tip

-

Соответствующий раздел мануала [url].

-
-

В Julia любая функция может быть векторизована. Т.е. вы можете создать функцию для скаляров и автоматически получаете её векторизованный аналог. Векторизация осуществляется через механизм broadcasting. При этом достаточно в конце имени функции дописать точку . (dot-syntax).

-
julia> x = [0, π/6, π/3];
-
-julia> sin(x)
-ERROR: MethodError: no method matching sin(::Vector{Float64})
-  ...
-
-julia> sin.(x)
-3-element Vector{Float64}:
- 0.0
- 0.49999999999999994
- 0.8660254037844386
-
-
-

Механизм векторизации “насыщен” (fused). Для программиста это означает, что сложный вызов, например, sin.(cos.(x)) не медленнее цикла, в котором к каждому элементу вектора x применили sin(cos(x[i])).

-

Автоматически векторизуются и пользовательские функции над стандартными типами.

-
julia> f(x) = x^2 + 1
-f (generic function with 1 method)
-
-julia> f.([1, 2, 3])
-3-element Vector{Int64}:
-  2
-  5
- 10
-
-julia> g(x, y) = f(x) + f(y)
-g (generic function with 1 method)
-
-julia> g.([1, 2], [3, 4])
-2-element Vector{Int64}:
- 12
- 22
-
-julia> g.([1, 2], 3)
-2-element Vector{Int64}:
- 12
- 15
-
-julia> parse.(Float64, ["1", "2.5", "-1.2e-9"])
-3-element Vector{Float64}:
-  1.0
-  2.5
- -1.2e-9
-
-
-

Для собственных типов нужно объявлять правила векторизации. Однако, если ваш тип должен вести себя как скаляр, можно воспользоваться Ref(x). Ниже определяется модель идеального газа и его давление. Затем, с помощью Ref и векторизации вычисляется давление кислорода при фиксированной плотности для ряда температур.

-
julia> struct IdealGasComponent
-           name::String
-           molarmass::Float64
-       end
-
-julia> pressure(c::IdealGasComponent, ρ, T) = ρ * 8.314 * T / c.molarmass
-pressure (generic function with 1 method)
-
-julia> oxygen = IdealGasComponent("oxygen", 0.016)
-IdealGasComponent("oxygen", 0.016)
-
-julia> pressure(oxygen, 500, 300)
-7.794375e7
-
-julia> pressure.(Ref(oxygen), 500, [300, 350, 400])
-3-element Vector{Float64}:
- 7.794375e7
- 9.0934375e7
- 1.03925e8
-
-
-

Операторы тоже функции. Так, broadcast порождает, например, поэлементные операции над векторами и матрицами (.+, .*, …).

-
julia> 2 * sin.(x) .* cos.(x) == sin.(2 * x)
-true
-
-
-
- -
- Наблюдение - - (Полиморфизм) - -
-

В этом примере несколько поэлементых видов умножений.

-
    -
  • 2 * x: умножение скаляра на вектор, оно и без броадкаста действует поэлементно;

  • -
  • x .* y: поэлементное умножение векторов.

  • -
-

Если вам надоедает ставить точки везде, воспользуйтесь макросом @.

-
julia> x = [0, π/6, π/3];
-
-julia> @. 2 * sin(x) * cos(x)
-3-element Vector{Float64}:
- 0.0
- 0.8660254037844386
- 0.8660254037844388
-
-
-

Ещё одно важное применение броадкаста: in-place присваивание. Оно делает вашу программу менее прожорливой по памяти, а сборщик мусора не будет добавлять времени работы.

-
julia> x = rand(100); y = rand(100);
-
-julia> @allocated z = x + y;    # первый вызов включает компиляцию
-
-julia> @allocated z = x + y
-896
-
-julia> z = similar(x);          # выделили память под `z` один раз
-
-julia> @allocated z .= x .+ y;  # первый вызов включает компиляцию
-
-julia> @allocated z .= x .+ y
-64
-
-
-
- -
- Демонстрация 1.2 - - ((Ещё один) бенчмарк) - -
-

На аллокации требуется время, а ещё время требуется для работы сборщика мусора. На данных небольшого размера время сборщика мусора существенно по сравнению с временем исполнения.

-

Так, сложение двух векторов размера 100 с аллокацией требует в тесте в среднем 85 нс, а с использованием in-place операций 22 нс. Причём разницу, судя по бенчмарку, занимает сборщик мусора (garbage collector, GC).

-
julia> using BenchmarkTools
-
-julia> x = rand(100); y = rand(100); z = similar(x);
-
-julia> @benchmark $z = $x + $y
-BenchmarkTools.Trial: 10000 samples with 973 evaluations.
- Range (min … max):  75.194 ns … 619.990 ns  ┊ GC (min … max): 0.00% … 0.00%
- Time  (median):     78.805 ns               ┊ GC (median):    0.00%
- Time  (mean ± σ):   85.932 ns ±  41.564 ns  ┊ GC (mean ± σ):  5.88% ± 9.87%
-
-  █▄▁                                                          ▁
-  █████▇█▇▅▅▅▅▄█▇▄▃▃▅▄▁▄▃▃▁▁▄▄▁▄▁▁▁▁▁▁▁▁▁▁▁▁▁▄▁▁▃▁▃▃▁▁▄▅▆▅▇▆▇▆ █
-  75.2 ns       Histogram: log(frequency) by time       365 ns <
-
- Memory estimate: 896 bytes, allocs estimate: 1.
-
-julia> @benchmark $z .= $x .+ $y
-BenchmarkTools.Trial: 10000 samples with 997 evaluations.
- Range (min … max):  20.640 ns … 398.402 ns  ┊ GC (min … max): 0.00% … 0.00%
- Time  (median):     20.930 ns               ┊ GC (median):    0.00%
- Time  (mean ± σ):   22.264 ns ±   8.109 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%
-
-  █▃▁▁▁                                                        ▁
-  █████▇▆▆▇▇▆▆▆▆▆▆▆▆▅▅▅▆▆▆▆▆▇▇▇▇▇▇▆▇▇▆▇▇▇▆▅▆▆▆▆▄▄▅▅▄▄▄▄▄▅▃▁▄▁▄ █
-  20.6 ns       Histogram: log(frequency) by time        45 ns <
-
- Memory estimate: 0 bytes, allocs estimate: 0.
-
-
-

Повторим тест для больших векторов, возьмём их размером 1000000.

-
julia> x = rand(1_000_000); y = rand(1_000_000); z = similar(x);
-
-julia> @benchmark $z = $x + $y
-BenchmarkTools.Trial: 2902 samples with 1 evaluation.
- Range (min … max):  901.201 μs …   6.733 ms  ┊ GC (min … max):  0.00% … 46.36%
- Time  (median):       1.275 ms               ┊ GC (median):     0.00%
- Time  (mean ± σ):     1.713 ms ± 976.100 μs  ┊ GC (mean ± σ):  26.05% ± 25.78%
-
-        ██▄▁                                            ▁▄▄▂▁   ▁
-  ▃▁▁▁▁▅████▇▄▇▅▃▃▁▃▁▁▄▃▁▁▁▃▁▃▃▁▃▁▁▁▃▁▁▁▁▁▁▁▁▁▃▃▁▁▁▁▁▁▁▅██████▇ █
-  901 μs        Histogram: log(frequency) by time        470 ms <
-
- Memory estimate: 7.63 MiB, allocs estimate: 2.
-
-julia> @benchmark $z .= $x .+ $y
-BenchmarkTools.Trial: 5360 samples with 1 evaluation.
- Range (min … max):  789.767 μs …   5.811 ms  ┊ GC (min … max): 0.00% … 0.00%
- Time  (median):     832.923 μs               ┊ GC (median):    0.00%
- Time  (mean ± σ):   921.733 μs ± 295.907 μs  ┊ GC (mean ± σ):  0.00% ± 0.00%
-
-  ▅█▆▃▃▂▁▁▁▁▁▁▁▁                                                ▁
-  ██████████████████▇█▇▇▆▆▇▆▅▆▅▆▆▅▆▅▅▅▄▄▄▄▄▄▄▃▄▅▅▄▅▅▁▄▃▄▅▄▄▄▄▄▅ █
-  790 μs        Histogram: log(frequency) by time       2.42 ms <
-
- Memory estimate: 0 bytes, allocs estimate: 0.
-
-
-

На векторах размера 100 разница среднего времени исполнения составляла \(\approx 4\) раза, а на больших векторах уменьшилась до \(\approx 2\) раз.

-
-
-

1.1.13. Модули#

-
-

Tip

-

Подробнее в секции мануала url.

-
-

В Julia можно разбивать исходный код программы на модули (modules). Модуль создаёт собственное пространство имён и может быть прекомпилирован.

-

Основной синтаксис выглядит так.

-
module Points
-
-using LinearAlgebra
-
-export dist, Point
-
-include("types.jl")
-include("functions.jl")
-
-private_foo() = println("Hello!")
-
-end # module
-
-
-

Всё, что между командами module ... end представляет собой модуль. В данном примере создаётся модуль Points.

-

Инструкция using LinearAlgebra импортирует публичные имена из модуля LinearAlgebra. При таком вызове, например, функция LinearAlgebra.norm из модуля доступна просто по имени norm. Фактически, программист так указывает зависимости модуля.

-

Модуль Points также делает имена dist и Point публичными. Т.е., когда кто-нибудь импортирует Points командой using, то ему будут доступны имена dist и Point. Точно также где-то в исходном коде модуля LinearAlgebra происходит экспорт имени norm.

-

Функция include("<path_to_file>") делает подстановку содержимого файла в модуль. В Julia позднее связывание имён, поэтому вы можете спокойно экспортировать что-то, а объявить где-то позднее.

-

Помимо этого, при импортировании есть следующие опции.

- ---- - - - - - - - - - - - - - - - - - - - - - - -

Команда импорта

Какие имена доступны

using Points

Points, dist, Point, остальные через точку: Points.private_foo

using Points: dist

dist

using Points: dist as d

d

import Points

Points, остальные через точку

import Points as Pnts

Pnts, остальные через точку

-
-

1.1.13.1. Пример разработки модуля#

-

Ниже показана разработка модуля в несколько этапов. В нём привычная структура Point{T}, а её интерфейс оборачивается в модуль. Затем, для примера, структура встраивается в существующую экосистему языка: можно скалярно умножать точки, складывать или умножать на скаляр.

-
- -
-

Points.jl

-
module Points
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-
-println(dist(Point(3, 4)))
-println(Points.random_point())
-
-
-
- -
-

Points.jl

-
module Points
-
-import LinearAlgebra  # для добавления метода к скалярному произведению
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-# Добавление метода к скалярному произведению LinearAlgebra.dot
-LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-using LinearAlbgebra  # Для dot(x, y)
-
-println(dot(Point(-1, 2), Point(-2, -3)))
-
-
-
- -
-

Points.jl

-
module Points
-
-import LinearAlgebra
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-# Расширяение стандартной библиотеки языка, модуля Base
-# `+` коммутативно
-Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
-# `*` не коммутативно
-Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y)
-Base.:*(p::Point, α::Number) = α * p
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-
-println(Point(1, 2) + Point(3.0, 4.1))
-println(2 * Point(1, 2))
-println(Point(1, 2) * 2.0)
-
-
-
-
-
-
-

1.1.13.2. Разбиение исходного файла#

-

Функция include("filename.jl") вставляет содержимое filename.jl в исходный код туда, где include был вызван.

- -

Ниже показана типичная структура исходного когда библиотеки.

-
-
-
-
-
-
-Структура библиотеки и Points.jl
-

Структура директории.

-
src/
-  operators.jl
-  interface.jl
-  types.jl
-  Points.jl
-
-
-

Код модуля src/Points.jl.

-
module Points
-
-import LinearAlgebra
-
-export dist
-export Point
-
-include("types.jl")
-include("interface.jl")
-include("operators.jl")
-
-end # module
-
-
-
-
-
-
-
-
-
-Остальной код
-

src/types.jl

-
struct Point{T}
-    x::T
-    y::T
-end
-
-
-

src/interface.jl

-
dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-
-

src/operators.jl

-
LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
-
-Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y)
-Base.:*(p::Point, α::Number) = α * p
-
-
-
-
-
-
-
-
-
-
1
-

https://juliacomputing.com/case-studies/, https://en.wikipedia.org/wiki/Julia_(programming_language)#Notable_uses

-
-
2
-

Программный пакет package это библиотека кода. Окружение environment позволяет исполнить код только с необходимыми пакетами, что уменьшает количество конфликтов версий между ними.

-
-
-
-
-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/julia/arrays.html b/julia/arrays.html index b6d34a9..2c8e9b3 100644 --- a/julia/arrays.html +++ b/julia/arrays.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.8. Массивы и broadcast — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/julia/controlflow.html b/julia/controlflow.html index 4911fbe..35fb378 100644 --- a/julia/controlflow.html +++ b/julia/controlflow.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.5. Управляющие конструкции — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/julia/ex.html b/julia/ex.html index 5c47143..3b993bd 100644 --- a/julia/ex.html +++ b/julia/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.11. Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/julia/functions.html b/julia/functions.html index 79e2712..daaf388 100644 --- a/julia/functions.html +++ b/julia/functions.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.6. Функции — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/julia/index.html b/julia/index.html index 6f6394e..f20d0a6 100644 --- a/julia/index.html +++ b/julia/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 1. Основы языка программирования Julia — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + + + - - - - - - - + + + - - - - - - - - -
-
+ + + - - + + +
+ +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/julia/install.html b/julia/install.html index e001565..9f51cec 100644 --- a/julia/install.html +++ b/julia/install.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.1. Установка — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+
+ + + + + +
+ + + +
+ - - + + +
+
\ No newline at end of file diff --git a/julia/julia.html b/julia/julia.html deleted file mode 100644 index 484bd68..0000000 --- a/julia/julia.html +++ /dev/null @@ -1,1028 +0,0 @@ - - - - - - - - - 1.10. Модули — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - - -
-
- - - -
-
-
- - -
- -
- -
-

1.10. Модули#

-
-

Tip

-

Подробнее в секции мануала url.

-
-

В Julia можно разбивать исходный код программы на модули (modules). Модуль создаёт собственное пространство имён и может быть прекомпилирован.

-

Основной синтаксис выглядит так.

-
module Points
-
-using LinearAlgebra
-
-export dist, Point
-
-include("types.jl")
-include("functions.jl")
-
-private_foo() = println("Hello!")
-
-end # module
-
-
-

Всё, что между командами module ... end представляет собой модуль. В данном примере создаётся модуль Points.

-

Инструкция using LinearAlgebra импортирует публичные имена из модуля LinearAlgebra. При таком вызове, например, функция LinearAlgebra.norm из модуля доступна просто по имени norm. Фактически, программист так указывает зависимости модуля.

-

Модуль Points также делает имена dist и Point публичными. Т.е., когда кто-нибудь импортирует Points командой using, то ему будут доступны имена dist и Point. Точно также где-то в исходном коде модуля LinearAlgebra происходит экспорт имени norm.

-

Функция include("<path_to_file>") делает подстановку содержимого файла в модуль. В Julia позднее связывание имён, поэтому вы можете спокойно экспортировать что-то, а объявить где-то позднее.

-

Помимо этого, при импортировании есть следующие опции.

- ---- - - - - - - - - - - - - - - - - - - - - - - -

Команда импорта

Какие имена доступны

using Points

Points, dist, Point, остальные через точку: Points.private_foo

using Points: dist

dist

using Points: dist as d

d

import Points

Points, остальные через точку

import Points as Pnts

Pnts, остальные через точку

-
-

1.10.1. Пример разработки модуля#

-

Ниже показана разработка модуля в несколько этапов. В нём привычная структура Point{T}, а её интерфейс оборачивается в модуль. Затем, для примера, структура встраивается в существующую экосистему языка: можно скалярно умножать точки, складывать или умножать на скаляр.

-
- -
-

Points.jl

-
module Points
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-
-println(dist(Point(3, 4)))
-println(Points.random_point())
-
-
-
- -
-

Points.jl

-
module Points
-
-import LinearAlgebra  # для добавления метода к скалярному произведению
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-# Добавление метода к скалярному произведению LinearAlgebra.dot
-LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-using LinearAlbgebra  # Для dot(x, y)
-
-println(dot(Point(-1, 2), Point(-2, -3)))
-
-
-
- -
-

Points.jl

-
module Points
-
-import LinearAlgebra
-
-export dist
-export Point
-
-struct Point{T}
-    x::T
-    y::T
-end
-
-dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-# Расширяение стандартной библиотеки языка, модуля Base
-# `+` коммутативно
-Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
-# `*` не коммутативно
-Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y)
-Base.:*(p::Point, α::Number) = α * p
-
-end # module
-
-
-

script.jl

-
include("path/to/Points.jl")
-using .Points
-
-println(Point(1, 2) + Point(3.0, 4.1))
-println(2 * Point(1, 2))
-println(Point(1, 2) * 2.0)
-
-
-
-
-
-
-

1.10.2. Разбиение исходного файла#

-

Функция include("filename.jl") вставляет содержимое filename.jl в исходный код туда, где include был вызван.

- -

Ниже показана типичная структура исходного когда библиотеки.

-
-
-
-
-
-
-Структура библиотеки и Points.jl
-

Структура директории.

-
src/
-  operators.jl
-  interface.jl
-  types.jl
-  Points.jl
-
-
-

Код модуля src/Points.jl.

-
module Points
-
-import LinearAlgebra
-
-export dist
-export Point
-
-include("types.jl")
-include("interface.jl")
-include("operators.jl")
-
-end # module
-
-
-
-
-
-
-
-
-
-Остальной код
-

src/types.jl

-
struct Point{T}
-    x::T
-    y::T
-end
-
-
-

src/interface.jl

-
dist(p::Point) = sqrt(p.x^2 + p.y^2)
-random_point() = Point(rand(2)...)
-
-
-

src/operators.jl

-
LinearAlgebra.dot(p1::Point, p2::Point) = p1.x * p2.x + p1.y * p2.y
-
-Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
-
-Base.:*(α::Number, p::Point) = Point(α * p.x, α * p.y)
-Base.:*(p::Point, α::Number) = α * p
-
-
-
-
-
-
-
-
-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/julia/linearalgebra.html b/julia/linearalgebra.html index 562c632..efc7b5e 100644 --- a/julia/linearalgebra.html +++ b/julia/linearalgebra.html @@ -1,54 +1,66 @@ + - + + + - + + + 1.9. Линейная алгебра — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + + + +
+ + + +
+ - - + + +
+
\ No newline at end of file diff --git a/nlroot/index.html b/nlroot/index.html index 0715326..17a092c 100644 --- a/nlroot/index.html +++ b/nlroot/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 6. Нелинейные уравнения — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/nlroot/itp.html b/nlroot/itp.html index daf7e93..93013ed 100644 --- a/nlroot/itp.html +++ b/nlroot/itp.html @@ -1,54 +1,66 @@ + - + + + - + + + 6.5. ITP метод — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/nlroot/newton_secant.html b/nlroot/newton_secant.html index 3e035c4..006a0e1 100644 --- a/nlroot/newton_secant.html +++ b/nlroot/newton_secant.html @@ -1,54 +1,66 @@ + - + + + - + + + 6.2. Метод Ньютона и секущих — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -
@@ -962,15 +752,69 @@

6.2.1. Метод Ньютона-Раф

-
f = (x) -> x*exp(x) - 2
-root = secant(f, 0, 1)
-plot(f; xlim=(0.6, 1), label=L"xe^x - 2")
-scatter!([root], [f(root)]; label="метод секущих")
+
f = (x) -> x*exp(x) - 2
+root = secant(f, 0, 1)
+plot(f; xlim=(0.6, 1), label=L"xe^x - 2")
+scatter!([root], [f(root)]; label="метод секущих")
 
-../_images/newton_secant_6_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -984,61 +828,114 @@

6.2.1. Метод Ньютона-Раф }, codeMirrorConfig: { theme: "abcdef", - mode: "julia-1.6" + mode: "julia-1.9" }, kernelOptions: { - kernelName: "julia-1.6", + name: "julia-1.9", path: "./nlroot" }, predefinedOutput: true } - + -

+ - -
- + + + + + + + +
+ +
- + + + + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/nlroot/ridders.html b/nlroot/ridders.html index 9cdd043..4d8df4b 100644 --- a/nlroot/ridders.html +++ b/nlroot/ridders.html @@ -1,54 +1,66 @@ + - + + + - + + + 6.4. Метод Риддерса — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -

Рассмотрим работу метода Риддерса на функции \(f(x) = (\tan{x})^{\tan{x}} - 10^3\) из оригинальной работы [Rid79].

В качестве начального интервала возьмём \([0, 1.5]\). Функция принимает в концах отрезка значения, отличающиеся на 13 порядков!

-
f = (x) -> tan(x)^tan(x) - 1e3
-@show f(0) f(1.5);
+
f = (x) -> tan(x)^tan(x) - 1e3
+@show f(0) f(1.5);
 
@@ -883,22 +611,102 @@

6.4.2. Реализацияxtol = 1e-6.

-
root = ridders(f, 0, 1.5; xtol=1e-6, maxiter=8)
-plt = plot(; layout=(2,1), xlabel=L"x", ylabel=L"f(x)")
-plot!(f; xlim=(0, 1.5), subplot=1, label=L"(\tan x)^{\tan x} - 10^3")
+
root = ridders(f, 0, 1.5; xtol=1e-6, maxiter=8)
+plt = plot(; layout=(2,1), xlabel=L"x", ylabel=L"f(x)")
+plot!(f; xlim=(0, 1.5), subplot=1, label=L"(\tan x)^{\tan x} - 10^3")
 
-plot!(f; xlim=(1.25, 1.38), subplot=2, label=L"(\tan x)^{\tan x} - 10^3")
-scatter!([root], [f(root)]; subplot=2, label="Найденный корень", leg=:topleft)
+plot!(f; xlim=(1.25, 1.38), subplot=2, label=L"(\tan x)^{\tan x} - 10^3")
+scatter!([root], [f(root)]; subplot=2, label="Найденный корень", leg=:topleft)
 
-../_images/ridders_4_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Сравним с методом regula falsi. Для этого выставим для методов одинаковые ftol.

+ + + -
+

+ + + + + +
+ + + +
+
- - + + +
+
\ No newline at end of file diff --git a/nlroot/simpleiter.html b/nlroot/simpleiter.html index 2bdfff5..577826f 100644 --- a/nlroot/simpleiter.html +++ b/nlroot/simpleiter.html @@ -1,54 +1,66 @@ + - + + + - + + + 6.1. Метод простой итерации — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+ + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/objects.inv b/objects.inv index 96971f6a565049a249a7040307f16d1171bc6a8c..4103f57b31aeab4e21e53bc83fd2e9cad4d1d6a8 100644 GIT binary patch delta 5281 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 PEGsTX4F>){Q>SA=r1)mF diff --git a/ode/adaptive_rungekutta.html b/ode/adaptive_rungekutta.html index 790aef6..3b74e7a 100644 --- a/ode/adaptive_rungekutta.html +++ b/ode/adaptive_rungekutta.html @@ -1,54 +1,66 @@ + - + + + - + + + - Адаптивные методы — Практикум по вычислительной теплофизике - + 9.3. Адаптивные методы — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -

Ниже представлен пример решения задачи Коши

@@ -940,33 +661,262 @@

Реализация
-
problem = CauchyODEProblem(
-    f=(t, u) -> exp(t - u*sin(u)),
-    tstart=0,
-    tend=5,
-    u₀=0,
-)
-plt = plot(;
-    title=L"u' = e^{t - u \sin{u}},\quad u(0) = 0,\quad t\in [0, 5]",
-    leg=:topleft,
-    layout=(2,1),
-)
-t, u = rk23(problem; tol=1e-5, maxsteps=1000)
-plot!(t, u; label="РК23", marker=:o, subplot=1, ylabel=L"u", xlim=(-0.1, 5.1))
-plot!(t[1:end-1], diff(t);
-    subplot=2,
-    title="",
-    yaxis=(:log10, L"\tau"),
-    label="",
-    xlabel=L"t",
-    xlim=(-0.1, 5.1),
-)
-plt
+
problem = CauchyODEProblem(
+    f=(t, u) -> exp(t - u*sin(u)),
+    tstart=0,
+    tend=5,
+    u₀=0,
+)
+plt = plot(;
+    title=L"u' = e^{t - u \sin{u}},\quad u(0) = 0,\quad t\in [0, 5]",
+    leg=:topleft,
+    layout=(2,1),
+)
+t, u = rk23(problem; tol=1e-5, maxsteps=1000)
+plot!(t, u; label="РК23", marker=:o, subplot=1, ylabel=L"u", xlim=(-0.1, 5.1))
+plot!(t[1:end-1], diff(t);
+    subplot=2,
+    title="",
+    yaxis=(:log10, L"\tau"),
+    label="",
+    xlabel=L"t",
+    xlim=(-0.1, 5.1),
+)
+plt
 
-../_images/adaptive_rungekutta_2_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

@@ -980,47 +930,115 @@

Реализация - + -

+ - - + + + + - - + + +
+
\ No newline at end of file diff --git a/ode/euler.html b/ode/euler.html index c89a3dd..fcc324b 100644 --- a/ode/euler.html +++ b/ode/euler.html @@ -1,54 +1,66 @@ + - + + + - + + + - Метод Эйлера — Практикум по вычислительной теплофизике - + 9.1. Метод Эйлера — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -

На примере метода Эйлера введём несколько понятий, применяющихся к разностным схемам [89].

- Определение + Определение 9.2 (Сходимость разностного метода)
-

Фиксируем точку \(t\) и построим последовательность сеток \(\omega_\tau\) () таких, что \(\tau \to 0\) и \(t_i = i \tau = t\). Говорят, что метод сходится в точке \(t\), если

+

Фиксируем точку \(t\) и построим последовательность сеток \(\omega_\tau\) (9.2) таких, что \(\tau \to 0\) и \(t_i = i \tau = t\). Говорят, что метод сходится в точке \(t\), если

\[|y_i - u(t_i)| \to 0,\quad \tau \to 0,\: t_i = t.\]

Метод называют сходящимся на отрезке \((0, T]\), если он сходится в каждой точке отрезка.

@@ -803,14 +542,14 @@

Метод Эйлера \[|y_i - u(t_i)| = O(\tau^p),\quad p>0,\: \tau \to 0,\]

то говорят, что метод имеет \(p\)-ый порядок точности.

-

Альтернативное определение сходимости [16] заключается в рассмотрении \(y_\tau\) и проекции \(u_\tau\) как сеточных функций (т.е. функций, определённых на \(\omega_\tau\)), тогда требуют \(\|y_\tau - u_\tau\|_{F_\tau} \to 0\), где \(F_\tau\) – пространство сеточных функций.

-

При подстановке решения \(u\) в численный метод получается выражение для погрешности аппроксимации разностного уравнения на решении исходного уравнения, или невязки. Например, для метода Эйлера () получим вид невязки \(\psi_i\)

+

Альтернативное определение сходимости [16] заключается в рассмотрении \(y_\tau\) и проекции \(u_\tau\) как сеточных функций (т.е. функций, определённых на \(\omega_\tau\)), тогда требуют \(\|y_\tau - u_\tau\|_{F_\tau} \to 0\), где \(F_\tau\) – пространство сеточных функций.

+

При подстановке решения \(u\) в численный метод получается выражение для погрешности аппроксимации разностного уравнения на решении исходного уравнения, или невязки. Например, для метода Эйлера (9.3) получим вид невязки \(\psi_i\)

-()#\[\psi_i = - \frac{u_{i+1} - u_i}{\tau} + f(t_i, u_i).\]
+(9.4)#\[\psi_i = - \frac{u_{i+1} - u_i}{\tau} + f(t_i, u_i).\]
- Определение + Определение 9.3 (Аппроксимация) @@ -823,42 +562,42 @@

Метод Эйлера \[\psi_i = O(\tau^p), \tau \to 0,\]

то говорят о \(p\)-ом порядке аппроксимации.

-

Несложно найти порядок аппроксимации метода Эйлера. Сама невязка имеет вид (), для её получения разложим \(u_{i+1}-u_i\) по формуле Тейлора

+

Несложно найти порядок аппроксимации метода Эйлера. Сама невязка имеет вид (9.4), для её получения разложим \(u_{i+1}-u_i\) по формуле Тейлора

\[u_{i+1} - u_i = u(t_i + \tau) - u(t_i) = u(t_i) + \tau u'(t_i) - u(t_i) + O(\tau) = \tau u'(t_i) + O(\tau).\]
-

Подставим полученное соотношение в невязку ()

+

Подставим полученное соотношение в невязку (9.4)

\[\psi_i = - u'(t_i) + f(t_i, u_i) + O(\tau).\]

Таким образом, метод Эйлера имеет первый порядок аппроксимации.

-

Помимо сходимости и аппроксимации, вводят различные понятия устойчивости. Одной из обобщённых является устойчивость по правой части. Данная устойчивость [16] означает, что при малом возмущении правой части уравнения \(f + \epsilon\) разностный метод будет иметь (а) единственное решение \(z_\tau\), (б) решение \(z_\tau\) будет не сильно отличаться от невозмущённого, т.е. \(\|z_\tau - y_\tau\| \le c \|\epsilon_\tau\|\).

+

Помимо сходимости и аппроксимации, вводят различные понятия устойчивости. Одной из обобщённых является устойчивость по правой части. Данная устойчивость [16] означает, что при малом возмущении правой части уравнения \(f + \epsilon\) разностный метод будет иметь (а) единственное решение \(z_\tau\), (б) решение \(z_\tau\) будет не сильно отличаться от невозмущённого, т.е. \(\|z_\tau - y_\tau\| \le c \|\epsilon_\tau\|\).

- Утверждение + Утверждение 9.4
-

Показано [16], что из аппроксимации и устойчивости по правой части следует сходимость метода с порядком точности, совпадающем с порядком аппроксимации.

+

Показано [16], что из аппроксимации и устойчивости по правой части следует сходимость метода с порядком точности, совпадающем с порядком аппроксимации.

-

Реализация#

+

9.1.1. Реализация#

В этой главе для постановки задачи Коши (скалярной) мы будем пользоваться структурой данных CauchyODEProblem.

-
struct CauchyODEProblem{T<:Real,F<:Function}
-    bound::Tuple{T,T}   # отрезок интегрирования
-    u₀::T               # начальное значение интегрируемой функции
-    f::F                # правая часть ОДУ
-    function CauchyODEProblem(; f::Function, tstart::Real, tend::Real, u₀::Real)
-        new{Float64, typeof(f)}(
-            float.(tuple(tstart, tend)),
-            float(u₀),
-            f,
-        )
-    end
-end
+
struct CauchyODEProblem{T<:Real,F<:Function}
+    bound::Tuple{T,T}   # отрезок интегрирования
+    u₀::T               # начальное значение интегрируемой функции
+    f::F                # правая часть ОДУ
+    function CauchyODEProblem(; f::Function, tstart::Real, tend::Real, u₀::Real)
+        new{Float64, typeof(f)}(
+            float.(tuple(tstart, tend)),
+            float(u₀),
+            f,
+        )
+    end
+end
 
- Демонстрация + Демонстрация 9.6
@@ -929,47 +746,113 @@

Реализация - + - + - - + + + + - - + + +
+
\ No newline at end of file diff --git a/ode/ex.html b/ode/ex.html index ccf4dd4..151d9b3 100644 --- a/ode/ex.html +++ b/ode/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + - Задания — Практикум по вычислительной теплофизике - + 9.4. Задания — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + - -
- + + + + + + +
+
+ +
- + + + + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/ode/index.html b/ode/index.html index 6fc4e00..b1ac2c9 100644 --- a/ode/index.html +++ b/ode/index.html @@ -1,54 +1,66 @@ + - + + + - + + + - Обыкновенные дифференциальные уравнения — Практикум по вычислительной теплофизике - + 9. Обыкновенные дифференциальные уравнения — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/ode/rungekutta.html b/ode/rungekutta.html index d419136..1877974 100644 --- a/ode/rungekutta.html +++ b/ode/rungekutta.html @@ -1,54 +1,66 @@ + - + + + - + + + - Методы Рунге-Кутта — Практикум по вычислительной теплофизике - + 9.2. Методы Рунге-Кутты — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -

Рассмотрим решение задачи Коши из Демонстрации 9.6 4-этапным методом Рунге-Кутты.

-
problem = CauchyODEProblem(;
-    f=(t, u) -> -u + 2exp(t),
-    tstart=0,
-    tend=1,
-    u₀=2,
-)
-plt = plot(; xlabel=L"t", leg=:topleft, layout=(2,2))
-for (i, n) in enumerate((1, 2, 3, 4))
-    t, u = rk4(problem; nsteps=n)
-    plot!((t) -> 2cosh(t); label="", line=2, subplot=i)
-    plot!(t, u; label="nsteps = $n", marker=:o, subplot=i)
-end
-plt
+
problem = CauchyODEProblem(;
+    f=(t, u) -> -u + 2exp(t),
+    tstart=0,
+    tend=1,
+    u₀=2,
+)
+plt = plot(; xlabel=L"t", leg=:topleft, layout=(2,2))
+for (i, n) in enumerate((1, 2, 3, 4))
+    t, u = rk4(problem; nsteps=n)
+    plot!((t) -> 2cosh(t); label="", line=2, subplot=i)
+    plot!(t, u; label="nsteps = $n", marker=:o, subplot=i)
+end
+plt
 
-../_images/rungekutta_2_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-

Невооруженным глазом видно, насколько лучше РК4 справляется с этой задачей, чем метод Эйлера (см. Демонстрация %s).

+

Невооруженным глазом видно, насколько лучше РК4 справляется с этой задачей, чем метод Эйлера (см. Демонстрация 9.6).

Проверим также порядок аппроксимации РК4 и явного метода Эйлера на той же задаче.

-
function residual(problem, method::Function, nsteps, exact::Function)
-    err = Float64[]
-    for n in nsteps
-        t, u = method(problem; nsteps=n)
-        push!(err, norm(u .- exact.(t), Inf))
-    end
-    return err
-end
-
-problem = CauchyODEProblem(
-    f=(t, u) -> -u + 2exp(t),
-    tstart=0,
-    tend=1,
-    u₀=2,
-)
-uexact(t) = 2cosh(t)
-
-nsteps = [2, 5, 10, 25, 50, 100, 500, 1000]
-residual_euler = residual(problem, euler, nsteps, uexact)
-residual_rk4 = residual(problem, rk4, nsteps, uexact)
-
-plot(; xaxis=(:log10, L"n"), yaxis=(:log10, "норма невязки"), leg=:bottomleft)
-yticks!([10.0^(-n) for n in 0:2:14])
-plot!(nsteps, residual_euler; marker=(:o, :red), line=:red, label="явный м. Эйлера")
-plot!(nsteps, 5e-2*(nsteps).^(-1); line=(:dash, 2, :red), label=L"O(n^{-1})")
-plot!(nsteps, residual_rk4; marker=(:o, :blue), label="явный м. РК4", line=(:blue))
-plot!(nsteps, 5e-3*(nsteps).^(-4); line=(:dash, 2, :blue), label=L"O(n^{-4})")
+
function residual(problem, method::Function, nsteps, exact::Function)
+    err = Float64[]
+    for n in nsteps
+        t, u = method(problem; nsteps=n)
+        push!(err, norm(u .- exact.(t), Inf))
+    end
+    return err
+end
+
+problem = CauchyODEProblem(
+    f=(t, u) -> -u + 2exp(t),
+    tstart=0,
+    tend=1,
+    u₀=2,
+)
+uexact(t) = 2cosh(t)
+
+nsteps = [2, 5, 10, 25, 50, 100, 500, 1000]
+residual_euler = residual(problem, euler, nsteps, uexact)
+residual_rk4 = residual(problem, rk4, nsteps, uexact)
+
+plot(; xaxis=(:log10, L"n"), yaxis=(:log10, "норма невязки"), leg=:bottomleft)
+yticks!([10.0^(-n) for n in 0:2:14])
+plot!(nsteps, residual_euler; marker=(:o, :red), line=:red, label="явный м. Эйлера")
+plot!(nsteps, 5e-2*(nsteps).^(-1); line=(:dash, 2, :red), label=L"O(n^{-1})")
+plot!(nsteps, residual_rk4; marker=(:o, :blue), label="явный м. РК4", line=(:blue))
+plot!(nsteps, 5e-3*(nsteps).^(-4); line=(:dash, 2, :blue), label=L"O(n^{-4})")
 
-../_images/rungekutta_4_0.svg
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Построение нормы невязки подтверждает, что метод Эйлера обладает первым порядком сходимости, а метод РК4 – четвёртым.

-

Неявные методы Рунге-Кутта#

-

Комментарий. Причиной разработки неявных методов послужило плохое решение (потеря устойчивости) явными методами жёстких систем уравнений. В жёстких системах компоненты решения \(\mathbf{u}\) изменяются со значительно разными скоростями. В случае явных систем шаг интегрирования \(\tau\) лимитируется самой быстро меняющейся компонентой, что приводит к выбору мелкого шага, а в перспективе к накоплению ошибок на больших масштабах \(T\). Для неявных методов, как правило ограничения на шаг более мягкие или почти отсутствуют. В теории решения жёстких систем вводятся специальные определения устойчивости, которые требуют отдельного рассмотрения. Жёсткие системы появляются, например, в задачах прикладной химии по расчёту динамики многостадийных реакций.

+

9.2.4. Неявные методы Рунге-Кутта#

+
+

Note

+

Иногда в системах дифференциальных уравнений компоненты решения \(\mathbf{u}\) изменяются со значительно разными скоростями. +Такие системы называются жёсткими. +Они появляются, например, в задачах прикладной химии при расчётах динамики многостадийных реакций.

+

Явные методы плохо применимы для решения жёстких систем. +Для них шаг интегрирования \(\tau\) лимитируется наиболее быстро меняющимся уравнением системы \(\mathbf{u}' = \mathbf{f}(t, \mathbf{u})\). +Это требует выбора мелкого шага \(\tau\) и приводит к накоплению ошибок на больших масштабах времени решения \(T\). +Иначе говоря, явные методы быстро теряют численную устойчивость при решении жёстких систем.

+

Для жёстких систем используются неявные методы, для которых (как правило) ограничения на шаг интегрирования \(\tau\) более мягкие или почти отсутствуют.

+

В теории решения жёстких систем вводятся специальные определения устойчивости, которые требуют отдельного рассмотрения.

+

Неявными методами Рунге-Кутта называют методы, для которых \(k_j\) зависит не только от предыдущих \(k\), но и от следующих. То есть,

-()#\[k_j = f\bigg(t_i + a_j \tau, y_i + \tau\sum_{s=1}^m b_{j,s}k_s\bigg),\quad j = 1,\ldots,m,\]
+(9.9)#\[k_j = f\bigg(t_i + a_j \tau, y_i + \tau\sum_{s=1}^m b_{j,s}k_s\bigg),\quad j = 1,\ldots,m,\]

но матрица коэффициентов \(b_{j,s}\), в отличие от явных методов, уже не имеет нижнетреугольный вид.

Простейшим среди таких методов является неявный метод Эйлера (implicit/backward Euler method)

\[\frac{y_{i+1} - y_i}{\tau} = f(t_i+\tau, y_{i+1}).\]
-

Неявные методы требуют в общем случае решения нелинейной системы на \(k_j\) (). Однако, в некоторых случаях показано, что достаточно использовать метод простой итерации для решения такой системы, т.е. явным образом итеративно вычислять

+

Неявные методы требуют в общем случае решения нелинейной системы на \(k_j\) (9.9). Однако, в некоторых случаях показано, что достаточно использовать метод простой итерации для решения такой системы, т.е. явным образом итеративно вычислять

\[k^{(n+1)}_j = f\bigg(t_i + a_j \tau, y_i + \tau\sum_{s=1}^m b_{j,s}k^{(n)}_s\bigg),\quad j = 1,\ldots,m,\]

пока два приближения системы \(k^{(n+1)}_j\) и \(k^{(n)}_j\) не станут сильно отличаться.

@@ -1080,47 +1039,116 @@

Неявные методы Рунге-Кутта - + -

+ - -
- + + + + + + +
+
+ +
- + + + + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/optim/bfgs.html b/optim/bfgs.html index 83ccf41..b5d0a8c 100644 --- a/optim/bfgs.html +++ b/optim/bfgs.html @@ -1,54 +1,66 @@ + - + + + - + + + - Квазиньютоновские методы — Практикум по вычислительной теплофизике - + 10.4. Метод BFGS — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
- - + + +
+
\ No newline at end of file diff --git a/optim/ex.html b/optim/ex.html index 6c09917..dcdb169 100644 --- a/optim/ex.html +++ b/optim/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + - Задания — Практикум по вычислительной теплофизике - + 10.5. Задания — Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/ptsplit/index.html b/ptsplit/index.html index 2331db0..bbdce09 100644 --- a/ptsplit/index.html +++ b/ptsplit/index.html @@ -1,54 +1,66 @@ + - + + + - + + + PT расслоение — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/ptsplit/problem_as_min.html b/ptsplit/problem_as_min.html deleted file mode 100644 index 1767d45..0000000 --- a/ptsplit/problem_as_min.html +++ /dev/null @@ -1,893 +0,0 @@ - - - - - - - - - Постановка задачи — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - - -
-
- - - -
-
-
- - -
- -
- -
-

Постановка задачи#

-

Сначала рассмотрим общую постановку задачи двухфазного равновесия пар-жидкость. -Пусть известны количество вещества компонентов в смеси \(\mathbf{N} = [N_1, \dots, N_n]^\top\), приложенное к смеси давление \(P\) и температура \(T\). -Такие условия можно интерпретировать как закрытую систему (нет обмена веществом с окружающей средой), вещество которой помещено в термостат под поршень.

-

Чтобы решить задачу двухфазного равновесия, проверим сначала устойчивость однофазного состояния. -Если проверка показывает устойчивость состояния, то задача решена: в равновесии существует одна фаза, а её состав равен \(\mathbf{N}\). -В противном случае мы предполагаем (в рамках нашей задачи), что в равновесии сосуществуют две фазы: пар и жидкость. -Равновесное состояние определяется минимумом свободной энергии Гиббса, в нашем случае энергия состояния состоит из вкладов энергий паровой и жидкой фаз

-
-\[G^{II} = G_{\vapor} + G_{\liquid} -= G(\mathbf{N}_{\vapor}, P, T) + G(\mathbf{N}_{\liquid}, P, T),\]
-

где энергия каждой фазы задаётся соотношением

-
-(16)#\[G_{\alpha} = \sum_{i} N_{\alpha,i} \times \mu_{i}(\mathbf{N}_{\alpha}, P, T).\]
-

Здесь \(i \in \{1, \dots, n\}\) это индекс компонента, \(\alpha \in \{\vapor, \liquid\}\) это индекс фазы, а \(N_{\alpha,i}\) это количество вещества компонента \(i\) в фазе \(\alpha\).

-

Поскольку мы предполагаем отсутствие химических превращений, то количество вещества каждого компонента \(N_i\) сохраняется, т.е. \(\mathbf{N}_{\vapor} + \mathbf{N}_{\liquid} = \mathbf{N}\). -Воспользуемся этим и получим, что энергия \(G^{II}\) является функцией \(n\) переменных (давление и температура постоянны)

-
-\[G^{II}(\mathbf{N}_{\vapor}, P, T) -= G(\mathbf{N}_{\vapor}, P, T) + G(\mathbf{N} - \mathbf{N}_{\vapor}, P, T).\]
-

Сама задача фазового равновесия сводится к задаче условной минимизации

-
-(17)#\[\mathbf{N}^*_{\vapor} = \argmin\limits_{\mathbf{N}_{\vapor}} G^{II}(\mathbf{N}_{\vapor}, P, T), \quad P = \const, T = \const,\]
-

по составу паровой фазы \(\mathbf{N}_{\vapor}\). -При этом составы должны удовлетворять некоторым условиям, например, положительности количеств вещества каждого компонента, балансу распределения вещества по фазам и, возможно, условиями, накладываемыми уравнением состояния (моделью флюида).

-

Мы не будем решать задачу равновесия в виде минимизации, а воспользуемся необходимым условием минимума — равенство нулю градиента \(\partial G^{II} / \partial N_{\text{пар},i} = \mathbf{0}\). -Это условие приводит к равенству химпотенциалов компонентов в паре и жидкости

-
-\[\begin{split}\begin{split} - \frac{\partial G^{II}}{\partial N_{\vapor,i}} - &= \frac{\partial G_{\vapor}}{\partial N_{\vapor,i}} + \frac{\partial G_{\liquid}}{\partial N_{\vapor,i}} - = \mu_{i}(\mathbf{N}_{\vapor}, P, T) + \frac{\partial G_{\liquid}}{\partial N_{\liquid,i}} \frac{\partial N_{\liquid,i}}{\partial N_{\vapor,i}} - \\ &= \mu_{i}(\mathbf{N}_{\vapor}, P, T) - \mu_{i}(\mathbf{N}_{\liquid}, P, T) = 0. -\end{split}\end{split}\]
-

Так, задача минимизации (17) свелась к решению нелинейной системы

-
-(18)#\[ \mu_{\vapor,i} = \mu_{\liquid,i},\quad i = 1, \dots, n.\]
-

Однако, стоит помнить, что в общем случае решения задач (17) и (18) разные. -Например, решение задачи в виде нелинейной системы может содержать седловые точки.

-
-

Составы и мольные доли#

-

В системе (18) присутствуют только химпотенциалы компонентов в фазах. -Химпотенциал в переменных \(\mathbf{N}\), \(P\) и \(T\) является однородной функцией нулевого порядка по \(\mathbf{N}\), т.е.

-
-\[\mu_i(\mathbf{N}, P, T) = \mu_i(\boldsymbol{\chi}, P, T),\]
-

где \(\boldsymbol{\chi}\) это вектор из мольных долей компонентов (в фазе)

-
-\[\chi_i -= \frac{\text{кол-во вещества компонента $i$ в фазе}}{\text{общее кол-во вещества в фазе}} -= \frac{N_i}{\sum N_i}.\]
-

В задаче парожидкостного равновесия устоялись следующие обозначения составов в мольных долях

-
-\[\mathbf{z} = (\text{состав в мол. долях смеси в целом}) = \frac{\mathbf{N}}{\sum_i N_i},\]
-
-\[\mathbf{x} = (\text{состав в мол. долях жидкой фазы}),\]
-
-\[\mathbf{y} = (\text{состав в мол. долях паровой (газовой) фазы}).\]
-

А для обозначения долей жидкой и паровой фаз используются

-
-\[ L = (\text{мол. доля жидкой фазы}) - = \frac{N_{\liquid}}{\sum_{\alpha} N_{\alpha}} - = \frac{N_{\liquid}}{\sum_{i} N_{i}},\]
-
-\[ V = (\text{мол. доля паровой фазы}) - = \frac{N_{\vapor}}{\sum_{\alpha} N_{\alpha}} - = \frac{N_{\vapor}}{\sum_{i} N_{i}},\]
-

где \(N_{\alpha} = \sum_i N_{\alpha,i}\) это количество вещества, содержащегося в фазе.

-
-
-

Постановка задачи в виде нелинейной системы#

-

С учётом введённых обозначений, задача парожидкостного равновесия ставится следующим образом.

-
- -
- Определение 1 - - (Задача расчёта двухфазного равновесия пар-жидкость) - -
-

Пусть дана смесь из \(n\) компонентов с мольным составом \(\mathbf{z} = [z_1, \ldots, z_n]^\top\) при температуре \(T\) и давлении \(P\). -Необходимо определить, одна или две фазы сосуществуют в термодинамическом равновесии. -Если фазы две, то для каждой из них нужно определить долю (\(L\), \(V\)) и состав (\(\mathbf{x}\), \(\mathbf{y}\)).

-

Как было сказано ранее, число фаз определяется из проверки термодинамической устойчивости. -В случае двухфазного состояния имеет место система

-
-(19)#\[\mu_{\vapor,i} = \mu_{\liquid,i},\quad i = 1,\dots,n, \quad \text{($n$ уравнений)}\]
-
-(20)#\[\sum_{i} x_i = 1, \quad \text{(1 уравнение)}\]
-
-(21)#\[\sum_{i} y_{i} = 1, \quad \text{(1 уравнение)}\]
-
-(22)#\[L + V = 1, \quad \text{(1 уравнение)}\]
-
-(23)#\[x_{i} L + y_{i} V = z_{i}, \quad \text{($n$ уравнений)}\]
-

Эта система содержит \(2n + 2\) неизвестных (\(x_{i}\), \(y_{i}\), \(V\) и \(L\)), а уравнений \(2 n + 3\). -Однако, уравнения баланса вещества (20)-(23) связаны между собой, поэтому можно одно отбросить, например, (20).

-
-
- - - - -
- -
- -
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/ptsplit/solution.html b/ptsplit/solution.html index 747409a..27aa594 100644 --- a/ptsplit/solution.html +++ b/ptsplit/solution.html @@ -1,54 +1,66 @@ + - + + + - + + + Решение задачи — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+
+ + + + + +
+ + + + + - - + + +
+
\ No newline at end of file diff --git a/ptstability/algorithm.html b/ptstability/algorithm.html index 2d03bb6..6e8e982 100644 --- a/ptstability/algorithm.html +++ b/ptstability/algorithm.html @@ -1,54 +1,66 @@ + - + + + - + + + Алгоритм решения — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/ptstability/criterion.html b/ptstability/criterion.html deleted file mode 100644 index c97deab..0000000 --- a/ptstability/criterion.html +++ /dev/null @@ -1,771 +0,0 @@ - - - - - - - - - Постановка задачи — Практикум по вычислительной теплофизике - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- - - - - - - - - - -
- -
- -
- - - - -
-
- - - - -
-
- - - - - - - -
-
- - -
-
- Contents -
- -
-
-
-
- -
-

Постановка задачи

- -
-
- -
-

Contents

-
- -
-
-
-
- -
- -
-

Постановка задачи#

-

Пусть дана смесь из \(n\) компонентов с мольным составом \(\boldsymbol{N} = [N_1, \ldots, N_n]^\top\) при температуре \(T\) и давлении \(P\). Необходимо определить, является ли однофазное состояние смеси термодинамически стабильным.

-
-

Критерий стабильности#

-

Идея решения задачи заключается в сравнении энергий двух систем

-
    -
  • однофазная (исходная) система;

  • -
  • двухфазная система, где вторая фаза представлена в малом количестве.

  • -
-

Также можно сказать, что мы попытаемся найти флуктуацию (состава и плотности), приводящую систему к двухфазному состоянию, имеющему энергию меньше, чем у однофазной системы. В этом случае однофазное состояние нестабильно. Если же такой флуктуации не существует, то однофазное состояние термодинамически стабильно.

-

Рассмотрим собственный потенциал NPT системы – свободную энергию Гиббса1

-
-\[G = G(\boldsymbol{N}, P, T) = \sum_i N_i \mu_i(\boldsymbol{N}, P, T).\]
-

В дальнейшем зависимость от давления \(P\) и температуры \(T\) писать не будем – это параметры задачи.

-

Теперь предположим, что часть вещества \(\boldsymbol{\varepsilon}\) исходной системы образует вторую фазу. Тогда разница энергий двухфазного и однофазного состояний будет

-
-()#\[\Delta G = G(\boldsymbol{N} - \boldsymbol{\varepsilon}) + G(\boldsymbol{\varepsilon}) - G(\boldsymbol{N})\]
-

Если получится найти такое количество вещества \(\boldsymbol{\varepsilon}\), что \(\Delta G < 0\), то двухфазное состояние имеет меньшую энергию, а однофазное состояние – нестабильно. Для этого, можно, например, найти глобальный минимум \(\Delta G\) и посмотреть его знак. Однако, распространён следующий метод.

-

Будем считать, что общее количество вещества во второй фазе \(\|\boldsymbol{\varepsilon}\|\) мало (вторая фаза в зародышевом состоянии, например). Разложим тогда в ряд Тейлора первое слагаемое из уравнения ()

-
-\[G(\boldsymbol{N} - \boldsymbol{\varepsilon}) \approx G(\boldsymbol{N}) - \sum_i \varepsilon_i \frac{\partial G}{\partial N_i} (\boldsymbol{N}) -= G(\boldsymbol{N}) - \sum_i \varepsilon_i \mu_i(\boldsymbol{N}).\]
-

С учётом разложения, получаем2

-
-\[\Delta G = \sum_i \varepsilon_i \mu_i(\boldsymbol{\varepsilon}) - \sum_i \varepsilon_i \mu_i(\boldsymbol{N}) -= \sum_i \varepsilon_i (\mu_i(\boldsymbol{\varepsilon}) - \mu_i(\boldsymbol{N})).\]
-

Избавимся от абсолютных величин, введя общее количество вещества в фазе-зародыше \(\varepsilon = \sum_i \varepsilon_i\)

-
-()#\[\Delta G = \varepsilon \sum_i x_i (\mu_i(\boldsymbol{x}) - \mu^0_i),\]
-

здесь \(\boldsymbol{x} \equiv \boldsymbol{\varepsilon} / \varepsilon\) – мольный состав фазы-зародыша, а \(\mu^0_i\) – химпотенциал компонентна в однофазном состоянии.

-

Поскольку в () \(\varepsilon > 0\), получаем критерий стабильности фазы

-
-()#\[F(\boldsymbol{x}) = \sum_i x_i (\mu_i(\boldsymbol{x}) - \mu^0_i) \ge 0.\]
-
-
-
1
-

Выражение свободной энергии Гиббса для смеси следует из аддитивности внутренней энергии и энтропии. Подробнее об этом в [02] (Раздел 2.9, Химический потенциал).

-
-
2
-

Строго говоря, это равенство выполняется приближённо. Знак точного равенства поставлен с целью упрощения изложения и математической записи.

-
-
-
-
- - - - -
- -
-
- - -
-
-
-
-
- - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/ptstability/exercise.html b/ptstability/exercise.html index 8b76876..57b3814 100644 --- a/ptstability/exercise.html +++ b/ptstability/exercise.html @@ -1,54 +1,66 @@ + - + + + - + + + Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/ptstability/index.html b/ptstability/index.html index d221b19..f5a3fb1 100644 --- a/ptstability/index.html +++ b/ptstability/index.html @@ -1,54 +1,66 @@ + - + + + - + + + PT стабильность — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - - + - - - - - - - + + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - + + + +
+
- - + + +
+
\ No newline at end of file diff --git a/ptstability/vanderwaals.html b/ptstability/vanderwaals.html index d800fb5..3286a9b 100644 --- a/ptstability/vanderwaals.html +++ b/ptstability/vanderwaals.html @@ -1,54 +1,66 @@ + - + + + - + + + Уравнение состояния ван дер Ваальса — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+
+ + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/search.html b/search.html index b7b1a9b..7f3ab7f 100644 --- a/search.html +++ b/search.html @@ -1,54 +1,62 @@ + - + + + - - Search — Практикум по вычислительной теплофизике - + Search - Практикум по вычислительной теплофизике + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + - + - - + - + - + - - + + + + - + + + - - - + + - - + + + + +
- - - - - - - - - -
-
+ + - - + + + + + + + +
+
+
+
+
+ + + +
+
+ +
+ + + + + + + + -
+
+ + + + + +
+ + + + + - - + + +
+
\ No newline at end of file diff --git a/syslinear/decompose_overview.html b/syslinear/decompose_overview.html index 35e6042..1af40de 100644 --- a/syslinear/decompose_overview.html +++ b/syslinear/decompose_overview.html @@ -1,54 +1,66 @@ + - + + + - + + + 3.5. Обзор других разложений и задач — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/syslinear/ex.html b/syslinear/ex.html index bcab23b..4419e05 100644 --- a/syslinear/ex.html +++ b/syslinear/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + 3.6. Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/syslinear/index.html b/syslinear/index.html index c54a69b..3eb202e 100644 --- a/syslinear/index.html +++ b/syslinear/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 3. Линейные системы уравнений — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/syslinear/plu.html b/syslinear/plu.html index c8e5d7d..6c737d8 100644 --- a/syslinear/plu.html +++ b/syslinear/plu.html @@ -1,54 +1,66 @@ + - + + + - + + + 3.3. PLU-разложение — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + -
+
+ + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/syslinear/triangular.html b/syslinear/triangular.html index daf5347..b2294d3 100644 --- a/syslinear/triangular.html +++ b/syslinear/triangular.html @@ -1,54 +1,66 @@ + - + + + - + + + 3.1. Треугольные системы — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/sysnonlinear/ex.html b/sysnonlinear/ex.html index 988f08c..e7b7551 100644 --- a/sysnonlinear/ex.html +++ b/sysnonlinear/ex.html @@ -1,54 +1,66 @@ + - + + + - + + + 7.3. Задания — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - +
+ +
-
+ +
+ + + - + + + + + + + + + + + + - - + + +
+
\ No newline at end of file diff --git a/sysnonlinear/index.html b/sysnonlinear/index.html index e708266..6683d50 100644 --- a/sysnonlinear/index.html +++ b/sysnonlinear/index.html @@ -1,54 +1,66 @@ + - + + + - + + + 7. Нелинейные системы уравнений — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - - - - + + +
+
\ No newline at end of file diff --git a/sysnonlinear/quasinewton.html b/sysnonlinear/quasinewton.html index 85bb2e8..8721f7e 100644 --- a/sysnonlinear/quasinewton.html +++ b/sysnonlinear/quasinewton.html @@ -1,54 +1,66 @@ + - + + + - + + + 7.2. Метод Бройдена — Практикум по вычислительной теплофизике - + + + + + - - + + + - - - - + + + + + - + - + - - - + + - + + + + - - + - + - + - - + - - - - - - + + - - - - - - - - -
-
+ + + - - + + + + +
- + + -
-
- - -
@@ -870,23 +580,23 @@

7.2.1. Приближение якоби \end{bmatrix}.\end{split}\]

-
function f(x)
-    x₁, x₂, x₃ = x
-    return [
-        x₂*exp(x₁) + sin(x₁),
-        cos(x₂) + x₁*x₃,
-        log(x₃) + x₂^2,
-    ]
-end
-
-function J(x)
-    x₁, x₂, x₃ = x
-    return [
-        x₂*exp(x₁)+cos(x₁)   exp(x₁)  0    ;
-        x₃                  -sin(x₂)  x₁   ;
-        0                    2x₂      1/x₃ ;
-    ]
-end
+
function f(x)
+    x₁, x₂, x₃ = x
+    return [
+        x₂*exp(x₁) + sin(x₁),
+        cos(x₂) + x₁*x₃,
+        log(x₃) + x₂^2,
+    ]
+end
+
+function J(x)
+    x₁, x₂, x₃ = x
+    return [
+        x₂*exp(x₁)+cos(x₁)   exp(x₁)  0    ;
+        x₃                  -sin(x₂)  x₁   ;
+        0                    2x₂      1/x₃ ;
+    ]
+end
 
@@ -894,11 +604,11 @@

7.2.1. Приближение якоби

Вычислим якобиан напрямую Jexact, и через конченые раности Jfd

-
x = [2/3, -1.0, sqrt(2)]
-Jexact, Jfd = J(x), jacobianfd(f, x)
-Jexact |> display
-Jfd |> display
-@show norm(Jexact - Jfd);
+
x = [2/3, -1.0, sqrt(2)]
+Jexact, Jfd = J(x), jacobianfd(f, x)
+Jexact |> display
+Jfd |> display
+@show norm(Jexact - Jfd);
 
@@ -923,7 +633,7 @@

7.2.1. Приближение якоби

Отличие в данной точке получилось небольшим. В качестве меры невязки здесь приведена норма Фробениуса для матриц \(\sqrt{\sum A_{ij}^2}\).

-

7.2.2. Метод Бройдена#

+

7.2.2. Метод Бройдена#

Обозначим приближение якобиана в точке \(\mathbf{x}_k\) через \(\mathbf{B}_k\), т.е.

\[\mathbf{J}(\mathbf{x}_k) \approx \mathbf{B}_k.\]
@@ -961,7 +671,7 @@

7.2.2. Метод Бройдена

Пусть дана функция \(\mathbf{f}\), начальная точка \(\mathbf{x}_1\) и приближение якобиана в этой точке \(\mathbf{B}_1\). Последующие приближения \(k = 2, 3, \ldots\) получаются примением действий

-
    +
    1. Решить систему (7.4), найдя таким образом шаг \(\delta \mathbf{x}_k\);

    2. Построить новое приближение корня \(\mathbf{x}_{k+1} = \mathbf{x}_k + \delta \mathbf{x}_k\) и вычислить значение функции в нём \(\mathbf{f}_{k+1} = \mathbf{f}(\mathbf{x}_{k+1})\);

    3. Получить новое приближение для якобиана \(\mathbf{B}_{k+1}\) из формулы (7.7).

    4. @@ -969,7 +679,7 @@

      7.2.2. Метод Бройдена

В качестве начального приближения якобиана можно использовать как его конечную разность, так и настоящий якобиан.

-

7.2.3. Реализация#

+

7.2.3. Реализация#

В данной реализации для простоты изложения явно не использовано QR-разложение, имеющее преимещуство перед LU-разложением при обновлении B.

@@ -1019,21 +729,21 @@

7.2.3. Реализация

Рассмотрим пример использования метода Бройдена. Возьмём функцию и якобиан из Демонстрации 7.3, где использовался метод Ньютона

-
function f(x)
-    x₁, x₂ = x
-    return [
-        x₁^2 - 2x₂^2 - x₁*x₂ + 2x₁ - x₂ + 1,
-        2x₁^2 - x₂^2 + x₁*x₂ + 3x₂ - 5,
-    ]
-end
-
-function J(x)
-    x₁, x₂ = x
-    return [
-        2x₁-x₂+2 -4x₂-x₁-1;
-        4x₁+x₂   -2x₂+x₁+3
-    ]
-end
+
function f(x)
+    x₁, x₂ = x
+    return [
+        x₁^2 - 2x₂^2 - x₁*x₂ + 2x₁ - x₂ + 1,
+        2x₁^2 - x₂^2 + x₁*x₂ + 3x₂ - 5,
+    ]
+end
+
+function J(x)
+    x₁, x₂ = x
+    return [
+        2x₁-x₂+2 -4x₂-x₁-1;
+        4x₁+x₂   -2x₂+x₁+3
+    ]
+end
 
@@ -1041,12 +751,12 @@

7.2.3. Реализация\(\mathbf{B}_1\) сначала используется истинный якобиан, а затем его конечная разность

-
x = [10.0, 10.0]
-rjac = broydensys(f, x, J(x))
-rfdjac = broydensys(f, x, jacobianfd(f, x))
-@show rjac
-@show rfdjac
-@show f(rjac);
+
x = [10.0, 10.0]
+rjac = broydensys(f, x, J(x))
+rfdjac = broydensys(f, x, jacobianfd(f, x))
+@show rjac
+@show rfdjac
+@show f(rjac);
 
@@ -1061,9 +771,9 @@

7.2.3. Реализация
-
x = [-10.0, 10.0]
-root = broydensys(f, x, jacobianfd(f, x))
-root, f(root)
+
x = [-10.0, 10.0]
+root = broydensys(f, x, jacobianfd(f, x))
+root, f(root)
 
@@ -1075,9 +785,9 @@

7.2.3. Реализация
-
x = [10.0, -10.0]
-root = broydensys(f, x, jacobianfd(f, x))
-root, f(root)
+
x = [10.0, -10.0]
+root = broydensys(f, x, jacobianfd(f, x))
+root, f(root)
 
@@ -1089,9 +799,9 @@

7.2.3. Реализация
-
x = [-10.0, -10.0]
-root = broydensys(f, x, jacobianfd(f, x))
-root, f(root)
+
x = [-10.0, -10.0]
+root = broydensys(f, x, jacobianfd(f, x))
+root, f(root)
 
@@ -1103,8 +813,8 @@

7.2.3. Реализация -

7.2.4. Другие версии метода#

-

Изложенная выше версия метода (7.7) требует решения линейной системы (7.4). Однако, она сочетается с линейным поиском, обеспечивающим глобальную сходимость метода, т.е. сходимостью к корню из произвольного начального приближения \(\mathbf{x}_1\), если корень существует. Правда, для этого необходимо переформулировать постановку задачи \(\mathbf{f}(\mathbf{x}) = \mathbf{0}\) под задачу минимизации [PTVF07].

+

7.2.4. Другие версии метода#

+

Изложенная выше версия метода (7.7) требует решения линейной системы (7.4). Однако, она сочетается с линейным поиском, обеспечивающим глобальную сходимость метода, т.е. сходимостью к корню из произвольного начального приближения \(\mathbf{x}_1\), если корень существует. Правда, для этого необходимо переформулировать постановку задачи \(\mathbf{f}(\mathbf{x}) = \mathbf{0}\) под задачу минимизации [PTVF07].

Если же линейный поиск не используется, распространены две версии алгоритма, использующие вместо матрицы \(\mathbf{B}\) обратную к ней \(\mathbf{B}^{-1}\), полученную аналитически. Использование \(\mathbf{B}^{-1}\) позволяет не решать систему (7.4), а сразу вычислять шаг

\[\delta \mathbf{x}_k = - \mathbf{B}^{-1}_k \mathbf{f}_k.\]
@@ -1139,61 +849,116 @@

7.2.4. Другие версии мет }, codeMirrorConfig: { theme: "abcdef", - mode: "julia-1.6" + mode: "julia-1.9" }, kernelOptions: { - kernelName: "julia-1.6", + name: "julia-1.9", path: "./sysnonlinear" }, predefinedOutput: true } - + -

+ - -
- + + + + + + +

+
+ +
-
+ +

+ + + -
+

+ + + + + +
+ + + +
+

- - + + + \ No newline at end of file