diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml new file mode 100644 index 00000000..2d598682 --- /dev/null +++ b/.github/workflows/deploy-docs.yaml @@ -0,0 +1,29 @@ +name: Deploy MkDocs to GitHub Pages + +on: + push: + branches: + - main + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e ".[dev,graph,routing,docs]" + + - name: Deploy MkDocs + run: | + mkdocs gh-deploy --force \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bc821ab2..cdc8734d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: # Apple Silicon runner: https://github.com/actions/runner-images/issues/9254 # Note we disable MPS for training os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] defaults: run: shell: bash @@ -38,7 +38,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -e ".[testing, graph, routing]" + pip install -e ".[dev, graph, routing]" - name: Run pytest run: pytest --cov=rl4co tests/*.py diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 08445568..f3f4df9d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,22 +1,28 @@ -# Read the Docs configuration file for Sphinx projects +# Read the Docs configuration file for MkDocs projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 -# Set the OS, Python version and other tools you might need +# Set the OS, Python version, and other tools you might need build: os: ubuntu-lts-latest tools: python: "3.11" -# Build documentation in the "docs/" directory with Sphinx -sphinx: - configuration: docs/conf.py +# Build documentation with MkDocs +mkdocs: + configuration: mkdocs.yml # Optional but recommended, declare the Python requirements required # to build your documentation # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: - install: - - requirements: docs/requirements.txt \ No newline at end of file + install: + - method: pip + path: . + extra_requirements: + - dev + - graph + - routing + - docs diff --git a/CITATION.cff b/CITATION.cff index 9d896fe3..b944315c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -29,8 +29,8 @@ preferred-citation: given-names: Minsu - family-names: Choi given-names: Sanghyeok - - family-names: Gast - given-names: Zepeda + - family-names: Gast Zepeda + given-names: Nayeli - family-names: Hottung given-names: AndrΓ© - family-names: Zhou diff --git a/README.md b/README.md index 7ecd0d3e..c62e779d 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,38 @@
-
- AI4CO Logo -
+AI4CO Logo

PyTorch Lightning -base: TorchRL -config: Hydra [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Slack](https://img.shields.io/badge/slack-chat-611f69.svg?logo=slack)](https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4-0IkQ8NQH4TRXIX8PrRmDhQ) -[![License: MIT](https://img.shields.io/badge/License-MIT-red.svg)](https://opensource.org/licenses/MIT) Open In Colab [![PyPI](https://img.shields.io/pypi/v/rl4co?logo=pypi)](https://pypi.org/project/rl4co)[![Codecov](https://codecov.io/github/ai4co/rl4co/tree/main/badge.svg)](https://app.codecov.io/github/ai4co/rl4co/tree/main/rl4co)[![Test](https://github.com/ai4co/rl4co/actions/workflows/tests.yml/badge.svg)](https://github.com/ai4co/rl4co/actions/workflows/tests.yml) +base: TorchRL +config: Hydra +Code style: black +Slack +License: MIT +Open In Colab +PyPI +Codecov +Test + +

+ Documentation | + Getting Started | + Usage | + Contributing | + Paper | + Join Us +

+ -[**Documentation**](https://rl4co.readthedocs.io/) | [**Getting Started**](#getting-started) | [**Usage**](#usage) | [**Contributing**](#contributing) | [**Paper**](https://arxiv.org/abs/2306.17100) | [**Join Us**](#join-us)
+ + An extensive Reinforcement Learning (RL) for Combinatorial Optimization (CO) benchmark. Our goal is to provide a unified framework for RL-based CO algorithms, and to facilitate reproducible research in this field, decoupling the science from the engineering. @@ -27,7 +42,9 @@ RL4CO is built upon: - [PyTorch Lightning](https://github.com/Lightning-AI/lightning): a lightweight PyTorch wrapper for high-performance AI research - [Hydra](https://github.com/facebookresearch/hydra): a framework for elegantly configuring complex applications -![RL4CO-Overview](https://github.com/ai4co/rl4co/assets/48984123/0e409784-05a9-4799-b7aa-6c0f76ecf27f) +
+ RL4CO-Overview +
We offer flexible and efficient implementations of the following policies: - **Constructive**: learn to construct a solution from scratch @@ -35,12 +52,16 @@ We offer flexible and efficient implementations of the following policies: - _NonAutoregressive (NAR)_: learn to predict a heuristic, such as a heatmap, to then construct a solution - **Improvement**: learn to improve an pre-existing solution -![RL4CO-Policy-Overview](https://github.com/ai4co/rl4co/assets/48984123/9e1f32f9-9884-49b9-b6cd-364861cc8fe7) +
+ RL4CO-Policy-Overview +
We provide several utilities and modularization. For example, we modularize reusable components such as _environment embeddings_ that can easily be swapped to [solve new problems](https://github.com/ai4co/rl4co/blob/main/examples/3-creating-new-env-model.ipynb). -![RL4CO-Env-Embeddings](https://github.com/ai4co/rl4co/assets/48984123/c47a9301-4c9f-43fd-b21f-761abeae9717) +
+ RL4CO-Env-Embedding +
## Getting started @@ -178,13 +199,11 @@ We are also on [Slack](https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4 If you find RL4CO valuable for your research or applied projects: ```bibtex -@misc{berto2024rl4co, +@article{berto2024rl4co, title={{RL4CO: an Extensive Reinforcement Learning for Combinatorial Optimization Benchmark}}, - author={Federico Berto and Chuanbo Hua and Junyoung Park and Laurin Luttmann and Yining Ma and Fanchen Bu and Jiarui Wang and Haoran Ye and Minsu Kim and Sanghyeok Choi and Zepeda Gast and Andre Hottung and Jianan Zhou and Jieyi Bi and Yu Hu and Fei Liu and Hyeonah Kim and Jiwoo Son and Haeyeon Kim and Davide Angioni and Wouter Kool and Zhiguang Cao and Jie Zhang and Kijung Shin and Cathy Wu and Sungsoo Ahn and Guojie Song and Changhyun Kwon and Lin Xie and Jinkyoo Park}, + author={Federico Berto and Chuanbo Hua and Junyoung Park and Laurin Luttmann and Yining Ma and Fanchen Bu and Jiarui Wang and Haoran Ye and Minsu Kim and Sanghyeok Choi and Nayeli Gast Zepeda and Andr\'e Hottung and Jianan Zhou and Jieyi Bi and Yu Hu and Fei Liu and Hyeonah Kim and Jiwoo Son and Haeyeon Kim and Davide Angioni and Wouter Kool and Zhiguang Cao and Jie Zhang and Kijung Shin and Cathy Wu and Sungsoo Ahn and Guojie Song and Changhyun Kwon and Lin Xie and Jinkyoo Park}, year={2024}, - eprint={2306.17100}, - archivePrefix={arXiv}, - primaryClass={cs.LG}, + journal={arXiv preprint arXiv:2306.17100}, note={\url{https://github.com/ai4co/rl4co}} } ``` @@ -202,6 +221,4 @@ We invite you to join our AI4CO community, an open research group in Artificial
AI4CO Logo -
- - + \ No newline at end of file diff --git a/configs/experiment/routing/mdpomo.yaml b/configs/experiment/routing/mdpomo.yaml new file mode 100644 index 00000000..2de2a532 --- /dev/null +++ b/configs/experiment/routing/mdpomo.yaml @@ -0,0 +1,41 @@ +# @package _global_ + +defaults: + - override /model: pomo.yaml + - override /env: cvrp.yaml + - override /callbacks: default.yaml + - override /trainer: default.yaml + - override /logger: wandb.yaml + +env: + generator_params: + num_loc: 50 + loc_distribution: "mix_distribution" + + +logger: + wandb: + project: "rl4co" + tags: ["mdpomo", "${env.name}"] + group: "${env.name}${env.generator_params.num_loc}" + name: "mdpomo-${env.name}${env.generator_params.num_loc}" + + +model: + batch_size: 512 + train_data_size: 10_000 + val_data_size: 10_000 + test_data_size: 10_000 + optimizer_kwargs: + lr: 1e-4 + weight_decay: 1e-6 + lr_scheduler: + "MultiStepLR" + lr_scheduler_kwargs: + milestones: [9001] + gamma: 0.1 + +trainer: + max_epochs: 10000 + +seed: 1234 diff --git a/configs/experiment/routing/polynet.yaml b/configs/experiment/routing/polynet.yaml new file mode 100644 index 00000000..709a18cf --- /dev/null +++ b/configs/experiment/routing/polynet.yaml @@ -0,0 +1,44 @@ +# @package _global_ + +defaults: + - override /model: polynet.yaml + - override /env: tsp.yaml + - override /callbacks: default.yaml + - override /trainer: default.yaml + - override /logger: wandb.yaml + +env: + generator_params: + num_loc: 50 + check_solution: False # optimization + +logger: + wandb: + project: "rl4co" + tags: ["polynet", "${env.name}"] + group: "${env.name}${env.generator_params.num_loc}" + name: "polynet-${env.name}${env.generator_params.num_loc}-${model.k}" + +model: + k: 100 + val_num_solutions: ${model.k} + batch_size: 512 + val_batch_size: 1024 + test_batch_size: 1024 + train_data_size: 1_280_000 + val_data_size: 10_000 + test_data_size: 10_000 + optimizer_kwargs: + lr: 1e-4 + weight_decay: 1e-6 + lr_scheduler: + "MultiStepLR" + lr_scheduler_kwargs: + milestones: [80, 95] + gamma: 0.1 + +trainer: + max_epochs: 100 + +seed: 1234 + diff --git a/configs/experiment/scheduling/am-pomo.yaml b/configs/experiment/scheduling/am-pomo.yaml index a3d2cde7..eb49e2da 100644 --- a/configs/experiment/scheduling/am-pomo.yaml +++ b/configs/experiment/scheduling/am-pomo.yaml @@ -14,6 +14,7 @@ model: _target_: rl4co.models.L2DAttnPolicy env_name: ${env.name} scaling_factor: ${scaling_factor} + normalization: "batch" batch_size: 64 num_starts: 10 num_augment: 0 diff --git a/configs/experiment/scheduling/am-ppo.yaml b/configs/experiment/scheduling/am-ppo.yaml index c5d38eb1..f9e5d354 100644 --- a/configs/experiment/scheduling/am-ppo.yaml +++ b/configs/experiment/scheduling/am-ppo.yaml @@ -43,14 +43,8 @@ model: batch_size: 128 val_batch_size: 512 test_batch_size: 64 - # Song et al use 1000 iterations over batches of 20 = 20_000 - # We train 10 epochs on a set of 2000 instance = 20_000 train_data_size: 2000 mini_batch_size: 512 - reward_scale: scale - optimizer_kwargs: - lr: 1e-4 env: - stepwise_reward: True - _torchrl_mode: True \ No newline at end of file + stepwise_reward: True \ No newline at end of file diff --git a/configs/experiment/scheduling/base.yaml b/configs/experiment/scheduling/base.yaml index e84f95fd..c15a6c45 100644 --- a/configs/experiment/scheduling/base.yaml +++ b/configs/experiment/scheduling/base.yaml @@ -22,17 +22,19 @@ trainer: seed: 12345678 -scaling_factor: 20 +scaling_factor: ${env.generator_params.max_processing_time} model: _target_: ??? batch_size: ??? train_data_size: 2_000 val_data_size: 1_000 - test_data_size: 1_000 + test_data_size: 100 optimizer_kwargs: - lr: 1e-4 + lr: 2e-4 weight_decay: 1e-6 lr_scheduler: "ExponentialLR" lr_scheduler_kwargs: gamma: 0.95 + reward_scale: scale + max_grad_norm: 1 diff --git a/configs/experiment/scheduling/ffsp-matnet.yaml b/configs/experiment/scheduling/ffsp-matnet.yaml new file mode 100644 index 00000000..7a1f4148 --- /dev/null +++ b/configs/experiment/scheduling/ffsp-matnet.yaml @@ -0,0 +1,46 @@ +# @package _global_ + +defaults: + - override /model: matnet.yaml + - override /callbacks: default.yaml + - override /trainer: default.yaml + - override /logger: wandb.yaml + - override /env: ffsp.yaml + +logger: + wandb: + project: "rl4co" + log_model: "all" + group: "${env.name}-${env.generator_params.num_job}-${env.generator_params.num_machine}" + tags: ["matnet", "${env.name}"] + name: "matnet-${env.name}-${env.generator_params.num_job}j-${env.generator_params.num_machine}m" + +env: + generator_params: + num_stage: 3 + num_machine: 4 + num_job: 20 + flatten_stages: False + +trainer: + max_epochs: 50 + # NOTE for some reason l2d is extremely sensitive to precision + # ONLY USE 32-true for l2d! + precision: 32-true + gradient_clip_val: 10 # orig paper does not use grad clipping + +seed: 12345678 + +model: + batch_size: 50 + train_data_size: 10_000 + val_data_size: 1_000 + test_data_size: 1_000 + optimizer_kwargs: + lr: 1e-4 + weight_decay: 1e-6 + lr_scheduler: + "MultiStepLR" + lr_scheduler_kwargs: + milestones: [35, 45] + gamma: 0.1 diff --git a/configs/experiment/scheduling/gnn-ppo.yaml b/configs/experiment/scheduling/gnn-ppo.yaml index d9c04856..d2139eea 100644 --- a/configs/experiment/scheduling/gnn-ppo.yaml +++ b/configs/experiment/scheduling/gnn-ppo.yaml @@ -12,24 +12,22 @@ logger: model: _target_: rl4co.models.L2DPPOModel policy_kwargs: - embed_dim: 128 + embed_dim: 256 num_encoder_layers: 3 scaling_factor: ${scaling_factor} - max_grad_norm: 1 - ppo_epochs: 3 + ppo_epochs: 2 het_emb: False + normalization: instance + test_decode_type: greedy batch_size: 128 val_batch_size: 512 test_batch_size: 64 mini_batch_size: 512 - reward_scale: scale - optimizer_kwargs: - lr: 1e-4 + trainer: max_epochs: 10 env: - stepwise_reward: True - _torchrl_mode: True \ No newline at end of file + stepwise_reward: True \ No newline at end of file diff --git a/configs/experiment/scheduling/hgnn-pomo.yaml b/configs/experiment/scheduling/hgnn-pomo.yaml index eb688c03..a964143f 100644 --- a/configs/experiment/scheduling/hgnn-pomo.yaml +++ b/configs/experiment/scheduling/hgnn-pomo.yaml @@ -18,6 +18,7 @@ model: stepwise_encoding: False scaling_factor: ${scaling_factor} het_emb: True + normalization: instance num_starts: 10 batch_size: 64 num_augment: 0 diff --git a/configs/experiment/scheduling/hgnn-ppo.yaml b/configs/experiment/scheduling/hgnn-ppo.yaml index 8e3a62d8..7d46f7d7 100644 --- a/configs/experiment/scheduling/hgnn-ppo.yaml +++ b/configs/experiment/scheduling/hgnn-ppo.yaml @@ -12,24 +12,16 @@ logger: model: _target_: rl4co.models.L2DPPOModel policy_kwargs: - embed_dim: 128 + embed_dim: 256 num_encoder_layers: 3 scaling_factor: ${scaling_factor} - max_grad_norm: 1 - ppo_epochs: 3 + ppo_epochs: 2 het_emb: True + normalization: instance batch_size: 128 val_batch_size: 512 test_batch_size: 64 mini_batch_size: 512 - reward_scale: scale - optimizer_kwargs: - lr: 1e-4 - -trainer: - max_epochs: 10 - env: - stepwise_reward: True - _torchrl_mode: True \ No newline at end of file + stepwise_reward: True \ No newline at end of file diff --git a/configs/experiment/scheduling/matnet-ppo.yaml b/configs/experiment/scheduling/matnet-ppo.yaml index f0e30e3b..c88d2c64 100644 --- a/configs/experiment/scheduling/matnet-ppo.yaml +++ b/configs/experiment/scheduling/matnet-ppo.yaml @@ -36,13 +36,7 @@ model: batch_size: 128 val_batch_size: 512 test_batch_size: 64 - # Song et al use 1000 iterations over batches of 20 = 20_000 - # We train 10 epochs on a set of 2000 instance = 20_000 mini_batch_size: 512 - reward_scale: scale - optimizer_kwargs: - lr: 1e-4 env: - stepwise_reward: True - _torchrl_mode: True \ No newline at end of file + stepwise_reward: True \ No newline at end of file diff --git a/configs/model/polynet.yaml b/configs/model/polynet.yaml new file mode 100644 index 00000000..4070d120 --- /dev/null +++ b/configs/model/polynet.yaml @@ -0,0 +1,11 @@ +_target_: rl4co.models.PolyNet + +# During val/test only we apply dihedral transformations +num_augment: 8 + +metrics: + train: ["loss", "reward"] + val: ["reward", "max_reward", "max_aug_reward"] + test: ${model.metrics.val} + log_on_step: True + diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d4bb2cbb..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md index b89e38ec..169ab0e3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,114 +1,26 @@ -# πŸ“‘ RL4CO Docs +# RL4CO Documentation -We are using [Sphinx](https://www.sphinx-doc.org/en/master/) with [Napoleon extension](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) to build the documentation. -Moreover, we set [Google style](https://google.github.io/styleguide/pyguide.html) to follow with type convention. +We use [MkDocs](https://www.mkdocs.org/) to generate the documentation with the [MkDocs Material theme](https://squidfunk.github.io/mkdocs-material/). -- [Napoleon formatting with Google style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) -- [ReStructured Text (reST)](https://docs.pylonsproject.org/projects/docs-style-guide/) -- [Paragraph-level markup](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#paragraphs) +## Development -See following short example of a sample function taking one position string and optional +From the root directory: -```python -from typing import Optional +1. Install RL4CO locally - -def my_func(param_a: int, param_b: Optional[float] = None) -> str: - """Sample function. - - Args: - param_a: first parameter - param_b: second parameter - - Return: - sum of both numbers - - Example:: - - >>> my_func(1, 2) - 3 - - Note: - If you want to add something. - """ - p = param_b if param_b else 0 - return str(param_a + p) +```bash +pip install -e ".[dev,graph,routing,docs]" ``` -## πŸ—‚οΈ File structures - -``` -. -β”œβ”€β”€ _build/ - output website, only for local building -β”œβ”€β”€ _content/ - content for docs pages in Markdown format -β”œβ”€β”€ _theme/ -β”‚ └── rl4co/ - website theme files -β”œβ”€β”€ conf.py - main config file for building -β”œβ”€β”€ index.md - content for index page -β”œβ”€β”€ make.bat - building script for Windows -β”œβ”€β”€ Makefile - building script for Unix -β”œβ”€β”€ README.md -└── requirements.txt - requirement python packages for Read the Docs building -``` - -## βš™οΈ Build docs locally - -**Step 1**. Install requirement packages (from root folder): `pip install -r docs/requirement.txt`; - -**Step 2**. Run the building script: +note that `docs` is the extra requirement for the documentation. -- **Windows**: run `make.bat`; -- **Linux/macOS**: run `make html`; -The generated docs will be under the `_build` folder. You can open `docs/build/html/index.html` in your browser to check the docs. +2. To build the documentation, run: -We need to have LaTeX installed for rendering math equations. You can for example install TeXLive with the necessary extras by doing one of the following: - -- **Windows/macOS**: check the [Tex Live install guide](https://www.tug.org/texlive/windows.html) for Windows/macOS; -- **Ubuntu (Linux)**: run `sudo apt-get update && sudo apt-get install -y texlive-latex-extra dvipng texlive-pictures`; -- Use the [RTD docker image](https://hub.docker.com/r/readthedocs/build); - -## βš™οΈ Build in Read the Docs - -In the root of this repository, there is `.readthedocs.yaml` which will be loaded by the Read the Docs to build the docs. Please refer to the [configuration file v2 guide from Read the Docs](https://docs.readthedocs.io/en/stable/config-file/v2.html) for details information of variables. - -## πŸ’‘ Notes for contents -
-Markdown and RST support -RST is originally supported by the Sphinx. With the extension `myst_parser` it can support Markdown contents. Follow [this guide](https://www.sphinx-doc.org/en/master/usage/markdown.html) to learn more. - -In the meantime, we can still use RST within Markdown files by -```` -```{eval-rst} -RST CONTENTS -``` -```` -
-
-Jupyter notebook support -With the extension `nbsphinx`, Sphinx can support Jupyter notebook. Follow [this guide](https://docs.readthedocs.io/en/stable/guides/jupyter.html) to learn more. - -Indexing a Jupyter notebook is the same with a Markdown file in RST: -``` -.. toctree:: - :maxdepth: 2 - :caption: Getting started: - - _content/start/installation - _content/start/quickstart_notebook -``` -
-
-API docs auto generator -With Sphinx's `automodule` we can easily get the API docs: -``` -.. automodule:: rl4co.data.generate_data - :members: - :undoc-members: +```bash +mkdocs serve ``` -When deploy in Read the Docs, make sure putting the package to `requirement.txt` mentioned before. -
-## πŸ“š References +### Hooks -We base the above guide on the official [PyTorch Lightning Docs](https://github.com/Lightning-AI/lightning/tree/master/docs). \ No newline at end of file +We are using the [hooks.py](hooks.py) for additional modifications. MkDocs for instance cannot detect files that are not in the same directory as an `__init__.py` (as described [here](https://stackoverflow.com/questions/75232397/mkdocs-unable-to-find-modules)) so we are automatically creating and deleting such files with our script diff --git a/docs/_content/api/algos/a2c.md b/docs/_content/api/algos/a2c.md deleted file mode 100644 index 731f48bc..00000000 --- a/docs/_content/api/algos/a2c.md +++ /dev/null @@ -1,9 +0,0 @@ -# A2C - -## A2C (Advantage Actor Critic) - -```{eval-rst} -.. automodule:: rl4co.models.rl.a2c.a2c - :members: - :undoc-members: -``` diff --git a/docs/_content/api/algos/base.md b/docs/_content/api/algos/base.md deleted file mode 100644 index 243c9dab..00000000 --- a/docs/_content/api/algos/base.md +++ /dev/null @@ -1,9 +0,0 @@ -# Base Classes - -## RL4COLitModule - -```{eval-rst} -.. automodule:: rl4co.models.rl.common.base - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/algos/ppo.md b/docs/_content/api/algos/ppo.md deleted file mode 100644 index d99fd1d3..00000000 --- a/docs/_content/api/algos/ppo.md +++ /dev/null @@ -1,11 +0,0 @@ -# PPO - - -## PPO (Proximal Policy Optimization) - - -```{eval-rst} -.. automodule:: rl4co.models.rl.ppo.ppo - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/algos/reinforce.md b/docs/_content/api/algos/reinforce.md deleted file mode 100644 index ea8070b1..00000000 --- a/docs/_content/api/algos/reinforce.md +++ /dev/null @@ -1,17 +0,0 @@ -# Reinforce - -## REINFORCE - -```{eval-rst} -.. automodule:: rl4co.models.rl.reinforce.reinforce - :members: - :undoc-members: -``` - -## Baselines - -```{eval-rst} -.. automodule:: rl4co.models.rl.reinforce.baselines - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/data.md b/docs/_content/api/data.md deleted file mode 100644 index 87690422..00000000 --- a/docs/_content/api/data.md +++ /dev/null @@ -1,33 +0,0 @@ -# Data - -## Datasets - -```{eval-rst} -.. automodule:: rl4co.data.dataset - :members: - :undoc-members: -``` - -## Data Generation - -```{eval-rst} -.. automodule:: rl4co.data.generate_data - :members: - :undoc-members: -``` - -## Transforms - -```{eval-rst} -.. automodule:: rl4co.data.transforms - :members: - :undoc-members: -``` - -## Utils - -```{eval-rst} -.. automodule:: rl4co.data.utils - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/decoding.md b/docs/_content/api/decoding.md deleted file mode 100644 index 1ba9470b..00000000 --- a/docs/_content/api/decoding.md +++ /dev/null @@ -1,7 +0,0 @@ -# Decoding Strategies - -```{eval-rst} -.. automodule:: rl4co.utils.decoding - :members: - :undoc-members: -``` diff --git a/docs/_content/api/envs/eda.md b/docs/_content/api/envs/eda.md deleted file mode 100644 index d89568b1..00000000 --- a/docs/_content/api/envs/eda.md +++ /dev/null @@ -1,30 +0,0 @@ -# EDA Problems -Environment for Electronic Design Automation (EDA) problems - -## Decap Placement Problem (DPP) - -```{eval-rst} -.. automodule:: rl4co.envs.eda.dpp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.eda.dpp.generator - :members: - :undoc-members: -``` - -## Multi-port Decap Placement Problem (mDPP) - -```{eval-rst} -.. automodule:: rl4co.envs.eda.mdpp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.eda.mdpp.generator - :members: - :undoc-members: -``` diff --git a/docs/_content/api/envs/routing.md b/docs/_content/api/envs/routing.md deleted file mode 100644 index 2ee370cb..00000000 --- a/docs/_content/api/envs/routing.md +++ /dev/null @@ -1,139 +0,0 @@ -# Routing Problems - -See also the [Multi-Task VRP](#Multi-Task-Vehicle-Routing-Problem-(MTVRP)) at the bottom of this page, that includes 16 variants! - - - -## Asymmetric Traveling Salesman Problem (ATSP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.atsp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.atsp.generator - :members: - :undoc-members: -``` - -## Capacitated Vehicle Routing Problem (CVRP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.cvrp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.cvrp.generator - :members: - :undoc-members: -``` - -## Multiple Traveling Salesman Problem (mTSP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.mtsp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.mtsp.generator - :members: - :undoc-members: -``` - - -## Orienteering Problem (OP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.op.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.op.generator - :members: - :undoc-members: -``` - -## Pickup and Delivery Problem (PDP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.pdp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.pdp.generator - :members: - :undoc-members: -``` - -## Prize Collecting Traveling Salesman Problem (PCTSP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.pctsp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.pctsp.generator - :members: - :undoc-members: -``` - -## Split Delivery Vehicle Routing Problem (SDVRP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.sdvrp.env - :members: - :undoc-members: -``` -``` - -## Stochastic Prize Collecting Traveling Salesman Problem (SPCTSP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.spctsp.env - :members: - :undoc-members: -``` -``` - -## Traveling Salesman Problem (TSP) - -```{eval-rst} -.. automodule:: rl4co.envs.routing.tsp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.routing.tsp.generator - :members: - :undoc-members: -``` - ---- - - -## Multi-Task Vehicle Routing Problem (MTVRP) - - - -```{eval-rst} -.. automodule:: rl4co.envs.routing.mtvrp.env - :members: - :undoc-members: - -.. automodule:: rl4co.envs.routing.mtvrp.generator - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/envs/scheduling.md b/docs/_content/api/envs/scheduling.md deleted file mode 100644 index 46edb20d..00000000 --- a/docs/_content/api/envs/scheduling.md +++ /dev/null @@ -1,29 +0,0 @@ -# Scheduling Problems - -## Flexible Flow Shop Problem (FFSP) - -```{eval-rst} -.. automodule:: rl4co.envs.scheduling.ffsp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.scheduling.ffsp.generator - :members: - :undoc-members: -``` - -## Single Machine Total Weighted Tardiness Problem (SMTWTP) - -```{eval-rst} -.. automodule:: rl4co.envs.scheduling.smtwtp.env - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.envs.scheduling.smtwtp.generator - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/models/common/__init__.md b/docs/_content/api/models/common/__init__.md deleted file mode 100644 index bba01830..00000000 --- a/docs/_content/api/models/common/__init__.md +++ /dev/null @@ -1,54 +0,0 @@ -# NCO Methods Overview - - -We categorize NCO approaches (which are in fact not necessarily trained with RL!) into the following: 1) constructive, 2) improvement, 3) transductive. - - - -```{eval-rst} -.. tip:: - Note that in RL4CO we distinguish the RL algorithms and the actors via the following naming: - - * **Model:** Refers to the reinforcement learning algorithm encapsulated within a `LightningModule`. This module is responsible for training the policy. - * **Policy:** Implemented as a `nn.Module`, this neural network (often referred to as the *actor*) takes an instance and outputs a sequence of actions, :math:`\pi = \pi_0, \pi_1, \dots, \pi_N`, which constitutes the solution. - - Here, :math:`\pi_i` represents the action taken at step :math:`i`, forming a sequence that leads to the optimal or near-optimal solution for the given instance. -``` - - -The following table contains the categorization that we follow in RL4CO: - - -```{eval-rst} -.. list-table:: Overview of RL Models and Policies - :widths: 5 5 5 5 25 - :header-rows: 1 - :stub-columns: 1 - - * - Category - - Model or Policy? - - Input - - Output - - Description - * - `Constructive `_ - - Policy - - Instance - - Solution - - Policies trained to generate solutions from scratch. Can be categorized into AutoRegressive (AR) and Non-Autoregressive (NAR). - * - `Improvement `_ - - Policy - - Instance, Current Solution - - Improved Solution - - Policies trained to improve existing solutions iteratively, akin to local search algorithms. They focus on refining *existing* solutions rather than generating them from scratch. - * - `Transductive `_ - - Model - - Instance, (Policy) - - Solution, (Updated Policy) - - Updates policy parameters during online testing to improve solutions of a specific instance. -``` - - - - - - diff --git a/docs/_content/api/models/common/constructive.md b/docs/_content/api/models/common/constructive.md deleted file mode 100644 index 4b3d0e82..00000000 --- a/docs/_content/api/models/common/constructive.md +++ /dev/null @@ -1,71 +0,0 @@ -## Constructive Policies - -Constructive NCO policies pre-train a policy to amortize the inference. "Constructive" means that a solution is created from scratch by the model. We can also categorize constructive NCO in two sub-categories depending on the role of encoder and decoder: - -#### Autoregressive (AR) -Autoregressive approaches **use a learned decoder** that outputs log probabilities for the current solution. These approaches generate a solution step by step, similar to e.g. LLMs. They have an encoder-decoder structure. Some models may not have an encoder at all and just re-encode at each step. - -#### NonAutoregressive (NAR) -The difference between AR and NAR approaches is that NAR **only an encoder is learnable** (they just encode in one shot) and generate for example a heatmap, which can then be decoded simply by using it as a probability distribution or by using some search method on top. - -Here is a general structure of a general constructive policy with an encoder-decoder structure: - -policy - - -where _embeddings_ transfer information from feature space to embedding space. - ---- - - - -### Constructive Policy Base Classes - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.base - :members: - :undoc-members: -``` - - - -### Autoregressive Policies Base Classes - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.autoregressive.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.autoregressive.decoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.autoregressive.policy - :members: - :undoc-members: -``` - -### Nonautoregressive Policies Base Classes - - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.nonautoregressive.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.nonautoregressive.decoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.common.constructive.nonautoregressive.policy - :members: - :undoc-members: -``` diff --git a/docs/_content/api/models/common/improvement.md b/docs/_content/api/models/common/improvement.md deleted file mode 100644 index 80543b2a..00000000 --- a/docs/_content/api/models/common/improvement.md +++ /dev/null @@ -1,3 +0,0 @@ -## Improvement Policies - -These methods differ w.r.t. constructive NCO since they can obtain better solutions similarly to how local search algorithms work - they can improve the solutions over time. This is different from decoding strategies or similar in constructive methods since these policies are trained for performing improvement operations. diff --git a/docs/_content/api/models/common/transductive.md b/docs/_content/api/models/common/transductive.md deleted file mode 100644 index 6c14c036..00000000 --- a/docs/_content/api/models/common/transductive.md +++ /dev/null @@ -1,19 +0,0 @@ -# Transductive Models - - -Transductive models are learning algorithms that optimize on a specific instance. They improve solutions by updating policy parameters $\theta$_, which means that we are running optimization (backprop) **at test time**. Transductive learning can be performed with different policies: for example EAS updates (a part of) AR policies parameters to obtain better solutions, but I guess there are ways (or papers out there I don't know of) that optimize at test time. - - -```{eval-rst} -.. tip:: - You may refer to the definition of `inductive vs transductive RL `_. In inductive RL, we train to generalize to new instances. In transductive RL we train (or finetune) to solve only specific ones. -``` - - -## Base Transductive Model - -```{eval-rst} -.. automodule:: rl4co.models.common.transductive.base - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/models/nn.md b/docs/_content/api/models/nn.md deleted file mode 100644 index ba5fa86b..00000000 --- a/docs/_content/api/models/nn.md +++ /dev/null @@ -1,60 +0,0 @@ -# Neural Network Modules - -## Critic Network - -```{eval-rst} -.. automodule:: rl4co.models.rl.common.critic - :members: - :undoc-members: -``` - -## Graph Neural Networks - -### Graph Attention Encoder - -```{eval-rst} -.. automodule:: rl4co.models.nn.graph.attnnet - :members: - :undoc-members: -``` - -### Graph Convolutional Encoder - -```{eval-rst} -.. automodule:: rl4co.models.nn.graph.gcn - :members: - :undoc-members: -``` - -### Message Passing Encoder - -```{eval-rst} -.. automodule:: rl4co.models.nn.graph.mpnn - :members: - :undoc-members: -``` - -## rl4co.models.nn.attention - -```{eval-rst} -.. automodule:: rl4co.models.nn.attention - :members: - :undoc-members: -``` - - -## rl4co.models.nn.mlp - -```{eval-rst} -.. automodule:: rl4co.models.nn.mlp - :members: - :undoc-members: -``` - -## rl4co.models.nn.ops - -```{eval-rst} -.. automodule:: rl4co.models.nn.ops - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/models/zoo/__init__.md b/docs/_content/api/models/zoo/__init__.md deleted file mode 100644 index dee807f8..00000000 --- a/docs/_content/api/models/zoo/__init__.md +++ /dev/null @@ -1,3 +0,0 @@ -# Model Zoo - -Models from the literature and contributions are contained in the Model Zoo. \ No newline at end of file diff --git a/docs/_content/api/models/zoo/constructive.md b/docs/_content/api/models/zoo/constructive.md deleted file mode 100644 index 4a1b1993..00000000 --- a/docs/_content/api/models/zoo/constructive.md +++ /dev/null @@ -1,215 +0,0 @@ -# Constructive Methods - -These can be classified into Auto-Regressive (AR) and Non-Auto-Regressive (NAR) policies. These constructive methods also include ad-hoc RL algorithms for constructive policies. - -# AutoRegressive - -## Attention Model (AM) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.am.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.am.policy - :members: - :undoc-members: -``` - -## Attention Model - PPO (AM-PPO) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.amppo.model - :members: - :undoc-members: -``` - - - -## Heterogeneous Attention Model (HAM) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ham.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ham.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ham.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ham.attention - :members: - :undoc-members: -``` - - -## Matrix Encoding Network (MatNet) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.matnet.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.matnet.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.matnet.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.matnet.decoder - :members: - :undoc-members: -``` - - -## Multi-Decoder Attention Model (MDAM) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.mdam.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.mdam.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.mdam.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.mdam.decoder - :members: - :undoc-members: -``` - -## POMO - -```{eval-rst} -.. automodule:: rl4co.models.zoo.pomo.model - :members: - :undoc-members: -``` - -## Pointer Network (PtrNet) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ptrnet.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ptrnet.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ptrnet.encoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ptrnet.decoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.ptrnet.critic - :members: - :undoc-members: -``` - -## SymNCO - -```{eval-rst} -.. automodule:: rl4co.models.zoo.symnco.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.symnco.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.symnco.losses - :members: - :undoc-members: -``` - ---- - -# NonAutoregressive - - -## DeepACO - -```{eval-rst} -.. automodule:: rl4co.models.zoo.deepaco.antsystem - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.deepaco.model - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.deepaco.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.deepaco.decoder - :members: - :undoc-members: -``` - - -## NAR-GNN - -```{eval-rst} -.. automodule:: rl4co.models.zoo.nargnn.policy - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.nargnn.encoder - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/models/zoo/improvement.md b/docs/_content/api/models/zoo/improvement.md deleted file mode 100644 index eda6ca2c..00000000 --- a/docs/_content/api/models/zoo/improvement.md +++ /dev/null @@ -1,5 +0,0 @@ -# Improvement Methods - -These methods are trained to improve existing solutions iteratively, akin to local search algorithms. They focus on refining existing solutions rather than generating them from scratch. - -_coming soon!_ \ No newline at end of file diff --git a/docs/_content/api/models/zoo/transductive.md b/docs/_content/api/models/zoo/transductive.md deleted file mode 100644 index b4e0bbbb..00000000 --- a/docs/_content/api/models/zoo/transductive.md +++ /dev/null @@ -1,31 +0,0 @@ -# Transductive Methods - -These methods update policy parameters during online testing to improve the solutions of a specific instance. - -## Active Search (AS) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.active_search.search - :members: - :undoc-members: -``` - -## Efficent Active Search (EAS) - -```{eval-rst} -.. automodule:: rl4co.models.zoo.eas.search - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.eas.decoder - :members: - :undoc-members: -``` - -```{eval-rst} -.. automodule:: rl4co.models.zoo.eas.nn - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/api/tasks.md b/docs/_content/api/tasks.md deleted file mode 100644 index 53bb82a0..00000000 --- a/docs/_content/api/tasks.md +++ /dev/null @@ -1,17 +0,0 @@ -# Tasks: Train and Evaluate - -## Train - -```{eval-rst} -.. automodule:: rl4co.tasks.train - :members: - :undoc-members: -``` - -## Evaluate - -```{eval-rst} -.. automodule:: rl4co.tasks.eval - :members: - :undoc-members: -``` \ No newline at end of file diff --git a/docs/_content/general/faq.md b/docs/_content/general/faq.md deleted file mode 100644 index e16ceaca..00000000 --- a/docs/_content/general/faq.md +++ /dev/null @@ -1,4 +0,0 @@ -# FAQ - -You can submit your questions via GitHub Issues. If asked more than a few times, a question will have its answer added here. If you are looking for collaborations, we would be happy to hear from you on [Slack](https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4-0IkQ8NQH4TRXIX8PrRmDhQ) πŸš€ - diff --git a/docs/_theme/rl4co/__init__.py b/docs/_theme/rl4co/__init__.py deleted file mode 100644 index 31492d0e..00000000 --- a/docs/_theme/rl4co/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Pytorch Lightning Sphinx theme. - -From https://github.com/shiftlab/lightning_sphinx_theme. -""" -from os import path - -__version__ = "0.0.31" -__version_full__ = __version__ - - -def get_html_theme_path(): - """Return list of HTML theme paths.""" - cur_dir = path.abspath(path.dirname(path.dirname(__file__))) - return cur_dir - - -# See http://www.sphinx-doc.org/en/stable/theming.html#distribute-your-theme-as-a-python-package -def setup(app): - app.add_html_theme("ncobench_theme", path.abspath(path.dirname(__file__))) diff --git a/docs/_theme/rl4co/breadcrumbs.html b/docs/_theme/rl4co/breadcrumbs.html deleted file mode 100644 index e60a62e1..00000000 --- a/docs/_theme/rl4co/breadcrumbs.html +++ /dev/null @@ -1,90 +0,0 @@ -{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #} - -{% if page_source_suffix %} -{% set suffix = page_source_suffix %} -{% else %} -{% set suffix = source_suffix %} -{% endif %} - -{% if meta is defined and meta is not none %} -{% set check_meta = True %} -{% else %} -{% set check_meta = False %} -{% endif %} - -{% if check_meta and 'github_url' in meta %} -{% set display_github = True %} -{% endif %} - -{% if check_meta and 'bitbucket_url' in meta %} -{% set display_bitbucket = True %} -{% endif %} - -{% if check_meta and 'gitlab_url' in meta %} -{% set display_gitlab = True %} -{% endif %} - -
- - - - {% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %} - - {% endif %} -
diff --git a/docs/_theme/rl4co/cookie_banner.html b/docs/_theme/rl4co/cookie_banner.html deleted file mode 100644 index a2497a02..00000000 --- a/docs/_theme/rl4co/cookie_banner.html +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/docs/_theme/rl4co/extensions/lightning.py b/docs/_theme/rl4co/extensions/lightning.py deleted file mode 100644 index 8cba7fda..00000000 --- a/docs/_theme/rl4co/extensions/lightning.py +++ /dev/null @@ -1,179 +0,0 @@ -# Copyright The PyTorch Lightning team. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from docutils import nodes -from docutils.statemachine import StringList -from pt_lightning_sphinx_theme.extensions.pytorch_tutorials import ( - CustomCalloutItemDirective, - CustomCardItemDirective, - DisplayItemDirective, - LikeButtonWithTitle, - ReactGreeter, - SlackButton, - TwoColumns, - cardnode, -) -from sphinx.util.docutils import SphinxDirective - - -class tutoriallistnode(nodes.General, nodes.Element): - """A placeholder node that we can use during the first parse to later - replace with the card list.""" - - pass - - -def visit_cardnode(self, node): - """Hook to make ``cardnode`` behave the same as a ``paragraph`` node (e.g. - insert ``

`` tags).""" - self.visit_paragraph(node) - - -def depart_cardnode(self, node): - """Hook to make ``cardnode`` behave the same as a ``paragraph`` node (e.g. - insert ``

`` tags).""" - self.depart_paragraph(node) - - -def purge_cards(app, env, docname): - """Hook to purge the cards from the env for the given docname. - - This will be called for each changed doc when rebuilding, so will - reset the card from that doc. - """ - if not hasattr(env, "all_cardnodes"): - return - - env.all_cardnodes = [node for node in env.all_cardnodes if node["docname"] != docname] - - -def merge_cards(app, env, docnames, other): - """Hook to merge cards from multiple environments (e.g. when multi- - threading).""" - if not hasattr(env, "all_cardnodes"): - env.all_cardnodes = [] - if hasattr(other, "all_cardnodes"): - env.all_cardnodes.extend(other.all_cardnodes) - - -TUTORIAL_LIST_START = """ -.. raw:: html - -
- - - -
- -
- -
-
- -.. Tutorial cards below this line - -""" - -TUTORIAL_LIST_END = """ - -.. End of tutorial card section - -.. raw:: html - -
- - - -
- -
-
-
-""" - - -class TutorialListDirective(SphinxDirective): - """Our custom directive which inserts the header and footer markup for the - tutorial block with a placeholder node (``tutoriallistnode``) which can be - modified inplace later with the list of cards.""" - - def run(self): - start_list = StringList(TUTORIAL_LIST_START.split("\n")) - start_node = nodes.paragraph() - self.state.nested_parse(start_list, self.content_offset, start_node) - - end_list = StringList(TUTORIAL_LIST_END.split("\n")) - end_node = nodes.paragraph() - self.state.nested_parse(end_list, self.content_offset, end_node) - - return start_node.children + [tutoriallistnode("")] + end_node.children - - -def process_card_nodes(app, doctree, fromdocname): - """This hook does two things. - - 1. Find any ``cardnode`` nodes in the document and remove them (we don't want them to render on the page). - 2. Find any ``tutoriallistnode`` nodes in the document and inplace edit them to have the list of ``cardnode`` nodes - from the environment. - """ - for card in doctree.traverse(cardnode): - card.parent.remove(card) - - for node in doctree.traverse(tutoriallistnode): - content = [] - - for card in app.builder.env.all_cardnodes: - content.append(card["node"]) - - node.replace_self(content) - - -def setup(app): - """Set-up the extension. - - Add out custom nodes and directives, then attach our hooks to the - required events. - """ - app.add_node(tutoriallistnode) - app.add_node( - cardnode, - html=(visit_cardnode, depart_cardnode), - latex=(visit_cardnode, depart_cardnode), - text=(visit_cardnode, depart_cardnode), - ) - - app.add_directive("customcarditem", CustomCardItemDirective) - app.add_directive("displayitem", DisplayItemDirective) - app.add_directive("join_slack", SlackButton) - app.add_directive("like_button_with_title", LikeButtonWithTitle) - app.add_directive("react_greeter", ReactGreeter) - app.add_directive("twocolumns", TwoColumns) - app.add_directive("customcalloutitem", CustomCalloutItemDirective) - app.add_directive("tutoriallist", TutorialListDirective) - - app.connect("env-purge-doc", purge_cards) - app.connect("env-merge-info", merge_cards) - app.connect("doctree-resolved", process_card_nodes) - - return { - "parallel_read_safe": True, - "parallel_write_safe": True, - } diff --git a/docs/_theme/rl4co/extensions/pytorch_tutorials.py b/docs/_theme/rl4co/extensions/pytorch_tutorials.py deleted file mode 100644 index 12b0e73d..00000000 --- a/docs/_theme/rl4co/extensions/pytorch_tutorials.py +++ /dev/null @@ -1,523 +0,0 @@ -"""Adapted from PyTorch Tutorials: https://github.com/pytorch/tutorials. - -BSD 3-Clause License - -Copyright (c) 2017, Pytorch contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" - -from docutils import nodes -from docutils.parsers.rst import Directive, directives -from docutils.statemachine import StringList -from pt_lightning_sphinx_theme.extensions.react import get_react_component_rst -from sphinx.util.docutils import SphinxDirective - -try: - FileNotFoundError -except NameError: - FileNotFoundError = IOError - - -class cardnode(nodes.General, nodes.TextElement): - pass - - -class CustomCardItemDirective(SphinxDirective): - option_spec = { - "header": directives.unchanged, - "image": directives.unchanged, - "card_description": directives.unchanged, - "tags": directives.unchanged, - "beta": directives.flag, - } - - def run(self): - try: - if "header" in self.options: - header = self.options["header"] - else: - raise ValueError("header not doc found") - - if "image" in self.options: - image = "" - else: - image = "" - - # TODO: This probably only works when the tutorial list directive is in index.html - link = self.env.docname + ".html" - - if "card_description" in self.options: - card_description = self.options["card_description"] - else: - card_description = "" - - if "tags" in self.options: - tags = self.options["tags"] - else: - tags = "" - - if "beta" in self.options: - beta = "Beta" - else: - beta = "" - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - return [] - - card_rst = CARD_TEMPLATE.format( - header=header, - image=image, - link=link, - card_description=card_description, - tags=tags, - beta=beta, - ) - card_list = StringList(card_rst.split("\n")) - node = cardnode() - self.state.nested_parse(card_list, self.content_offset, node) - - if not hasattr(self.env, "all_cardnodes"): - self.env.all_cardnodes = [] - self.env.all_cardnodes.append({"docname": self.env.docname, "node": node}) - return [node] - - -CARD_TEMPLATE = """ -.. raw:: html - - -""" - - -class CustomCalloutItemDirective(Directive): - option_spec = { - "header": directives.unchanged, - "description": directives.unchanged, - "button_link": directives.unchanged, - "button_text": directives.unchanged, - "col_css": directives.unchanged, - "card_style": directives.unchanged, - "image_center": directives.unchanged, - } - - def run(self): - try: - if "description" in self.options: - description = self.options["description"] - else: - description = "" - - if "header" in self.options: - header = self.options["header"] - else: - raise ValueError("header not doc found") - - if "button_link" in self.options: - button_link = self.options["button_link"] - else: - button_link = "" - - if "button_text" in self.options: - button_text = self.options["button_text"] - else: - button_text = "" - - if "col_css" in self.options: - col_css = self.options["col_css"] - else: - col_css = "col-md-6" - - if "card_style" in self.options: - card_style = self.options["card_style"] - else: - card_style = "text-container" - - if "image_center" in self.options: - image_center = "" - else: - image_center = "" - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - return [] - - callout_rst = CALLOUT_TEMPLATE.format( - description=description, - image_center=image_center, - header=header, - button_link=button_link, - button_text=button_text, - col_css=col_css, - card_style=card_style, - ) - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -CALLOUT_TEMPLATE = """ -.. raw:: html - - -""" - - -class DisplayItemDirective(Directive): - option_spec = { - "header": directives.unchanged, - "description": directives.unchanged, - "col_css": directives.unchanged, - "card_style": directives.unchanged, - "image_center": directives.unchanged, - "image_right": directives.unchanged, - "image_height": directives.unchanged, - "button_link": directives.unchanged, - "height": directives.unchanged, - "tag": directives.unchanged, - } - - def run(self): - try: - if "description" in self.options: - description = self.options["description"] - else: - description = "" - - if "tag" in self.options: - tag = "
" + self.options["tag"] + "
" - else: - tag = "" - - if "height" in self.options: - height = self.options["height"] - else: - height = "" - - if "header" in self.options: - header = self.options["header"] - else: - raise ValueError("header not doc found") - - if "col_css" in self.options: - col_css = self.options["col_css"] - else: - col_css = "col-md-6" - - if "card_style" in self.options: - card_style = self.options["card_style"] - else: - card_style = "display-card" - - if "image_height" in self.options: - image_height = self.options["image_height"] - else: - image_height = "125px" - - image_class = "" - if "image_center" in self.options: - image = ( - "" - ) - image_class = "image-center" - - elif "image_right" in self.options: - image = ( - "" - ) - image_class = "image-right" - else: - image = "" - - if "button_link" in self.options: - button_link = self.options["button_link"] - button_open_html = f"" - button_close_html = "" - card_style = f"{card_style} display-card-hover" - else: - button_link = "" - button_open_html = "" - button_close_html = "" - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - return [] - - callout_rst = DISPLAY_ITEM_TEMPLATE.format( - description=description, - image=image, - height=height, - image_class=image_class, - header=header, - col_css=col_css, - card_style=card_style, - button_open_html=button_open_html, - button_close_html=button_close_html, - tag=tag, - ) - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -DISPLAY_ITEM_TEMPLATE = """ -.. raw:: html - -
- {button_open_html} -
-
{image}
-

{header}

-

{description}

-
- {button_close_html} - {tag} -
-""" - - -class LikeButtonWithTitle(Directive): - option_spec = { - "padding": directives.unchanged, - "title": directives.unchanged, - "width": directives.unchanged, - "margin": directives.unchanged, - } - - def run(self): - try: - # button width - width = "155" - if "width" in self.options: - width = self.options["width"] - - # margin - margin = "40" - if "margin" in self.options: - margin = self.options["margin"] - - # title on button - title = "Join our community" - if "title" in self.options: - title = self.options["title"] - - # button on left, center or right of screen - padding = "30" - if "padding" in self.options: - _ = self.options["padding"] - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - # return [] - callout_rst = get_react_component_rst( - "LikeButtonWithTitle", - width=width, - margin=margin, - title=title, - padding=padding, - ) - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -class ReactGreeter(Directive): - def run(self): - callout_rst = get_react_component_rst("ReactGreeter") - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -class SlackButton(Directive): - option_spec = { - "align": directives.unchanged, - "title": directives.unchanged, - "width": directives.unchanged, - "margin": directives.unchanged, - } - - def run(self): - try: - # button width - width = "155" - if "width" in self.options: - width = self.options["width"] - - # margin - margin = "40" - if "margin" in self.options: - margin = self.options["margin"] - - # title on button - title = "Join our community" - if "title" in self.options: - title = self.options["title"] - - # button on left, center or right of screen - align = "left" - if "align" in self.options: - align = self.options["align"] - - align = f"slack-align-{align}" - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - return [] - callout_rst = SLACK_TEMPLATE.format( - align=align, title=title, margin=margin, width=width - ) - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -SLACK_TEMPLATE = """ -.. raw:: html - - -""" # noqa: E501 - - -class TwoColumns(Directive): - has_content = True - option_spec = { - "left": directives.unchanged, - "right": directives.unchanged, - } - - def run(self): - try: - left = "" - if "left" in self.options: - left = self.options["left"] - - right = "" - if "right" in self.options: - right = self.options["right"] - - except FileNotFoundError as e: - print(e) - return [] - except ValueError as e: - print(e) - raise - return [] - callout_rst = TWO_COLUMN_TEMPLATE.format(left=left, right=right) - callout_list = StringList(callout_rst.split("\n")) - callout = nodes.paragraph() - self.state.nested_parse(callout_list, self.content_offset, callout) - return [callout] - - -TWO_COLUMN_TEMPLATE = """ -.. raw:: html - -
-
- -{left} - -.. raw:: html - -
-
- -{right} - -.. raw:: html - -
-
-""" diff --git a/docs/_theme/rl4co/extensions/react.py b/docs/_theme/rl4co/extensions/react.py deleted file mode 100644 index 9e286e12..00000000 --- a/docs/_theme/rl4co/extensions/react.py +++ /dev/null @@ -1,7 +0,0 @@ -def get_react_component_rst(class_name, **props): - data_props = " ".join([f'data-{key}="{value}"' for key, value in props.items()]) - return f""" -.. raw:: html - -
- """ diff --git a/docs/_theme/rl4co/fonts.html b/docs/_theme/rl4co/fonts.html deleted file mode 100644 index f47dff04..00000000 --- a/docs/_theme/rl4co/fonts.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/footer.html b/docs/_theme/rl4co/footer.html deleted file mode 100644 index ee3f0584..00000000 --- a/docs/_theme/rl4co/footer.html +++ /dev/null @@ -1,74 +0,0 @@ -
- {% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %} - - {% endif %} - - {% if theme_pytorch_project == 'tutorials' %} - -
-
-
Rate this Tutorial
-
- - - - - -
-
-
- - {% else %} - -
- - {% endif %} - -
-

- {%- if show_copyright %} - {%- if hasdoc('copyright') %} - {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} - {%- else %} - {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} - {%- endif %} - {%- endif %} - - {%- if build_id and build_url %} - {% trans build_url=build_url, build_id=build_id %} - - Build - {{ build_id }}. - - {% endtrans %} - {%- elif commit %} - {% trans commit=commit %} - - Revision {{ commit }}. - - {% endtrans %} - {%- elif last_updated %} - {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} - {%- endif %} - -

-
- - {%- if show_sphinx %} - {% trans %} -
- Built with Sphinx using a theme provided by Read the Docs. -
- {% endtrans %} - {%- endif %} - - {%- block extrafooter %} {% endblock %} - -
diff --git a/docs/_theme/rl4co/layout.html b/docs/_theme/rl4co/layout.html deleted file mode 100644 index 1ff94343..00000000 --- a/docs/_theme/rl4co/layout.html +++ /dev/null @@ -1,591 +0,0 @@ -{# TEMPLATE VAR SETTINGS #} -{%- set url_root = pathto('', 1) %} -{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} -{%- if not embedded and docstitle %} - {%- set titlesuffix = " — "|safe + docstitle|e %} -{%- else %} - {%- set titlesuffix = "" %} -{%- endif %} -{%- set lang_attr = 'en' if language == None else (language | replace('_', '-')) %} -{% import 'theme_variables.jinja' as theme_variables %} - - - - - - - - - - - {{ metatags }} - - - {% block htmltitle %} - {{ title|striptags|e }}{{ titlesuffix }} - {% endblock %} - - {# FAVICON #} - {% if favicon %} - - {% endif %} - {# CANONICAL URL #} - {% if theme_canonical_url %} - - {% endif %} - - {# CSS #} - - {# OPENSEARCH #} - {% if not embedded %} - {% if use_opensearch %} - - {% endif %} - - {% endif %} - - - - {%- for css in css_files %} - {%- if css|attr("rel") %} - - {%- else %} - - {%- endif %} - {%- endfor %} - {%- for cssfile in extra_css_files %} - - {%- endfor %} - - {%- block linktags %} - {%- if hasdoc('about') %} - - {%- endif %} - {%- if hasdoc('genindex') %} - - {%- endif %} - {%- if hasdoc('search') %} - - {%- endif %} - {%- if hasdoc('copyright') %} - - {%- endif %} - {%- if next %} - - {%- endif %} - {%- if prev %} - - {%- endif %} - {%- endblock %} - - {%- block extrahead %} - - {% if theme_analytics_id %} - - - {% endif %} - - {% endblock %} - - {# Keep modernizr in head - http://modernizr.com/docs/#installing #} - - - {% include "fonts.html" %} - - - - - - - - -
-
-
- - - - - -
-
-
- - - - {% block extrabody %} {% endblock %} - - {# SIDE NAV, TOGGLES ON MOBILE #} - - - - - -
-
-
- {% include "breadcrumbs.html" %} -
- -
- Shortcuts -
-
- -
-
- - {% if theme_pytorch_project == 'tutorials' %} - - - - {% endif %} - - {%- block content %} - {% if theme_style_external_links|tobool %} - - -
-
-
- {{ toc }} -
-
-
-
-
- - {% include "versions.html" %} - - {% if not embedded %} - - {% if sphinx_version >= "1.8.0" %} - - {%- for scriptfile in script_files %} - {{ js_tag(scriptfile) }} - {%- endfor %} - {% else %} - - {%- for scriptfile in script_files %} - - {%- endfor %} - {% endif %} - - {% endif %} - - - - - - - - - {%- block footer %} {% endblock %} - - - - - - - - - - - - - - {% include "cookie_banner.html" %} - - - - - -
-
-
-
- - -
-
-
- - -
- - - - - - - - - - - - diff --git a/docs/_theme/rl4co/search.html b/docs/_theme/rl4co/search.html deleted file mode 100644 index 2a14048d..00000000 --- a/docs/_theme/rl4co/search.html +++ /dev/null @@ -1,46 +0,0 @@ -{# - basic/search.html - ~~~~~~~~~~~~~~~~~ - - Template for the search page. - - :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -#} -{%- extends "layout.html" %} -{% set title = _('Search') %} -{% set script_files = script_files + ['_static/searchtools.js'] %} -{% set script_files = script_files + ['_static/language_data.js'] %} -{% block footer %} - - {{ super() }} -{% endblock %} -{% block body %} - - - {% if search_performed %} -

{{ _('Search Results') }}

- {% if not search_results %} -

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

- {% endif %} - {% endif %} -
- {% if search_results %} -
    - {% for href, caption, context in search_results %} -
  • - {{ caption }} -

    {{ context|e }}

    -
  • - {% endfor %} -
- {% endif %} -
-{% endblock %} diff --git a/docs/_theme/rl4co/searchbox.html b/docs/_theme/rl4co/searchbox.html deleted file mode 100644 index 54c6e5aa..00000000 --- a/docs/_theme/rl4co/searchbox.html +++ /dev/null @@ -1,16 +0,0 @@ -{%- if builder != 'singlehtml' %} - -{% if theme_pytorch_project == 'tutorials' %} - {% set search_project = 'Tutorials' %} -{% else %} - {% set search_project = 'Docs' %} -{% endif %} - -
-
- - - -
-
-{%- endif %} diff --git a/docs/_theme/rl4co/static/css/theme.css b/docs/_theme/rl4co/static/css/theme.css deleted file mode 100644 index 81b3be18..00000000 --- a/docs/_theme/rl4co/static/css/theme.css +++ /dev/null @@ -1,16268 +0,0 @@ -/*! - * Bootstrap v4.6.1 (https://getbootstrap.com/) - * Copyright 2011-2021 The Bootstrap Authors - * Copyright 2011-2021 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/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: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation 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 -} - -*, -*::before, -*::after { - -webkit-box-sizing: border-box; - 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", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - text-align: left; - background-color: #fff -} - -[tabindex="-1"]:focus:not(:focus-visible) { - outline: 0 !important -} - -hr { - -webkit-box-sizing: content-box; - 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[title], -abbr[data-original-title] { - text-decoration: underline; - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - cursor: help; - border-bottom: 0; - -webkit-text-decoration-skip-ink: none; - text-decoration-skip-ink: none -} - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit -} - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem -} - -ol ol, -ul ul, -ol ul, -ul ol { - 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: -0.25em -} - -sup { - top: -0.5em -} - -a { - color: #007bff; - text-decoration: none; - background-color: rgba(0, 0, 0, 0) -} - -a:hover { - color: #0056b3; - text-decoration: underline -} - -a:not([href]):not([class]) { - color: inherit; - text-decoration: none -} - -a:not([href]):not([class]):hover { - color: inherit; - text-decoration: none -} - -pre, -code, -kbd, -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 { - vertical-align: middle; - border-style: none -} - -svg { - overflow: hidden; - vertical-align: middle -} - -table { - border-collapse: collapse -} - -caption { - padding-top: .75rem; - padding-bottom: .75rem; - color: #6c757d; - text-align: left; - caption-side: bottom -} - -th { - text-align: inherit; - text-align: -webkit-match-parent -} - -label { - display: inline-block; - margin-bottom: .5rem -} - -button { - border-radius: 0 -} - -button:focus:not(:focus-visible) { - outline: 0 -} - -input, -button, -select, -optgroup, -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 -} - -button, -[type=button], -[type=reset], -[type=submit] { - -webkit-appearance: button -} - -button:not(:disabled), -[type=button]:not(:disabled), -[type=reset]:not(:disabled), -[type=submit]:not(:disabled) { - cursor: pointer -} - -button::-moz-focus-inner, -[type=button]::-moz-focus-inner, -[type=reset]::-moz-focus-inner, -[type=submit]::-moz-focus-inner { - padding: 0; - border-style: none -} - -input[type=radio], -input[type=checkbox] { - -webkit-box-sizing: border-box; - 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; - font-weight: 300; - line-height: 1.2 -} - -.display-2 { - font-size: 5.5rem; - font-weight: 300; - line-height: 1.2 -} - -.display-3 { - font-size: 4.5rem; - font-weight: 300; - line-height: 1.2 -} - -.display-4 { - font-size: 3.5rem; - font-weight: 300; - line-height: 1.2 -} - -hr { - margin-top: 1rem; - margin-bottom: 1rem; - border: 0; - 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-unstyled { - padding-left: 0; - list-style: none -} - -.list-inline { - 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: "β€”Β " -} - -.img-fluid { - max-width: 100%; - height: auto -} - -.img-thumbnail { - padding: .25rem; - background-color: #fff; - border: 1px solid #dee2e6; - border-radius: .25rem; - max-width: 100%; - height: auto -} - -.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, -.container-fluid, -.container-xl, -.container-lg, -.container-md, -.container-sm { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto -} - -@media(min-width: 576px) { - - .container-sm, - .container { - max-width: 540px - } -} - -@media(min-width: 768px) { - - .container-md, - .container-sm, - .container { - max-width: 720px - } -} - -@media(min-width: 992px) { - - .container-lg, - .container-md, - .container-sm, - .container { - max-width: 960px - } -} - -@media(min-width: 1200px) { - - .container-xl, - .container-lg, - .container-md, - .container-sm, - .container { - max-width: 1140px - } -} - -.row { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - 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-xl, -.col-xl-auto, -.col-xl-12, -.col-xl-11, -.col-xl-10, -.col-xl-9, -.col-xl-8, -.col-xl-7, -.col-xl-6, -.col-xl-5, -.col-xl-4, -.col-xl-3, -.col-xl-2, -.col-xl-1, -.col-lg, -.col-lg-auto, -.col-lg-12, -.col-lg-11, -.col-lg-10, -.col-lg-9, -.col-lg-8, -.col-lg-7, -.col-lg-6, -.col-lg-5, -.col-lg-4, -.col-lg-3, -.col-lg-2, -.col-lg-1, -.col-md, -.col-md-auto, -.col-md-12, -.col-md-11, -.col-md-10, -.col-md-9, -.col-md-8, -.col-md-7, -.col-md-6, -.col-md-5, -.col-md-4, -.col-md-3, -.col-md-2, -.col-md-1, -.col-sm, -.col-sm-auto, -.col-sm-12, -.col-sm-11, -.col-sm-10, -.col-sm-9, -.col-sm-8, -.col-sm-7, -.col-sm-6, -.col-sm-5, -.col-sm-4, -.col-sm-3, -.col-sm-2, -.col-sm-1, -.col, -.col-auto, -.col-12, -.col-11, -.col-10, -.col-9, -.col-8, -.col-7, -.col-6, -.col-5, -.col-4, -.col-3, -.col-2, -.col-1 { - position: relative; - width: 100%; - padding-right: 15px; - padding-left: 15px -} - -.col { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100% -} - -.row-cols-1>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% -} - -.row-cols-2>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% -} - -.row-cols-3>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.3333333333%; - flex: 0 0 33.3333333333%; - max-width: 33.3333333333% -} - -.row-cols-4>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% -} - -.row-cols-5>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20% -} - -.row-cols-6>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.6666666667%; - flex: 0 0 16.6666666667%; - max-width: 16.6666666667% -} - -.col-auto { - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100% -} - -.col-1 { - -webkit-box-flex: 0; - -ms-flex: 0 0 8.33333333%; - flex: 0 0 8.33333333%; - max-width: 8.33333333% -} - -.col-2 { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.66666667%; - flex: 0 0 16.66666667%; - max-width: 16.66666667% -} - -.col-3 { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% -} - -.col-4 { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.33333333%; - flex: 0 0 33.33333333%; - max-width: 33.33333333% -} - -.col-5 { - -webkit-box-flex: 0; - -ms-flex: 0 0 41.66666667%; - flex: 0 0 41.66666667%; - max-width: 41.66666667% -} - -.col-6 { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% -} - -.col-7 { - -webkit-box-flex: 0; - -ms-flex: 0 0 58.33333333%; - flex: 0 0 58.33333333%; - max-width: 58.33333333% -} - -.col-8 { - -webkit-box-flex: 0; - -ms-flex: 0 0 66.66666667%; - flex: 0 0 66.66666667%; - max-width: 66.66666667% -} - -.col-9 { - -webkit-box-flex: 0; - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75% -} - -.col-10 { - -webkit-box-flex: 0; - -ms-flex: 0 0 83.33333333%; - flex: 0 0 83.33333333%; - max-width: 83.33333333% -} - -.col-11 { - -webkit-box-flex: 0; - -ms-flex: 0 0 91.66666667%; - flex: 0 0 91.66666667%; - max-width: 91.66666667% -} - -.col-12 { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% -} - -.order-first { - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1 -} - -.order-last { - -webkit-box-ordinal-group: 14; - -ms-flex-order: 13; - order: 13 -} - -.order-0 { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0 -} - -.order-1 { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1 -} - -.order-2 { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2 -} - -.order-3 { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3 -} - -.order-4 { - -webkit-box-ordinal-group: 5; - -ms-flex-order: 4; - order: 4 -} - -.order-5 { - -webkit-box-ordinal-group: 6; - -ms-flex-order: 5; - order: 5 -} - -.order-6 { - -webkit-box-ordinal-group: 7; - -ms-flex-order: 6; - order: 6 -} - -.order-7 { - -webkit-box-ordinal-group: 8; - -ms-flex-order: 7; - order: 7 -} - -.order-8 { - -webkit-box-ordinal-group: 9; - -ms-flex-order: 8; - order: 8 -} - -.order-9 { - -webkit-box-ordinal-group: 10; - -ms-flex-order: 9; - order: 9 -} - -.order-10 { - -webkit-box-ordinal-group: 11; - -ms-flex-order: 10; - order: 10 -} - -.order-11 { - -webkit-box-ordinal-group: 12; - -ms-flex-order: 11; - order: 11 -} - -.order-12 { - -webkit-box-ordinal-group: 13; - -ms-flex-order: 12; - order: 12 -} - -.offset-1 { - margin-left: 8.33333333% -} - -.offset-2 { - margin-left: 16.66666667% -} - -.offset-3 { - margin-left: 25% -} - -.offset-4 { - margin-left: 33.33333333% -} - -.offset-5 { - margin-left: 41.66666667% -} - -.offset-6 { - margin-left: 50% -} - -.offset-7 { - margin-left: 58.33333333% -} - -.offset-8 { - margin-left: 66.66666667% -} - -.offset-9 { - margin-left: 75% -} - -.offset-10 { - margin-left: 83.33333333% -} - -.offset-11 { - margin-left: 91.66666667% -} - -@media(min-width: 576px) { - .col-sm { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100% - } - - .row-cols-sm-1>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .row-cols-sm-2>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .row-cols-sm-3>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.3333333333%; - flex: 0 0 33.3333333333%; - max-width: 33.3333333333% - } - - .row-cols-sm-4>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .row-cols-sm-5>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20% - } - - .row-cols-sm-6>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.6666666667%; - flex: 0 0 16.6666666667%; - max-width: 16.6666666667% - } - - .col-sm-auto { - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100% - } - - .col-sm-1 { - -webkit-box-flex: 0; - -ms-flex: 0 0 8.33333333%; - flex: 0 0 8.33333333%; - max-width: 8.33333333% - } - - .col-sm-2 { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.66666667%; - flex: 0 0 16.66666667%; - max-width: 16.66666667% - } - - .col-sm-3 { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .col-sm-4 { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.33333333%; - flex: 0 0 33.33333333%; - max-width: 33.33333333% - } - - .col-sm-5 { - -webkit-box-flex: 0; - -ms-flex: 0 0 41.66666667%; - flex: 0 0 41.66666667%; - max-width: 41.66666667% - } - - .col-sm-6 { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .col-sm-7 { - -webkit-box-flex: 0; - -ms-flex: 0 0 58.33333333%; - flex: 0 0 58.33333333%; - max-width: 58.33333333% - } - - .col-sm-8 { - -webkit-box-flex: 0; - -ms-flex: 0 0 66.66666667%; - flex: 0 0 66.66666667%; - max-width: 66.66666667% - } - - .col-sm-9 { - -webkit-box-flex: 0; - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75% - } - - .col-sm-10 { - -webkit-box-flex: 0; - -ms-flex: 0 0 83.33333333%; - flex: 0 0 83.33333333%; - max-width: 83.33333333% - } - - .col-sm-11 { - -webkit-box-flex: 0; - -ms-flex: 0 0 91.66666667%; - flex: 0 0 91.66666667%; - max-width: 91.66666667% - } - - .col-sm-12 { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .order-sm-first { - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1 - } - - .order-sm-last { - -webkit-box-ordinal-group: 14; - -ms-flex-order: 13; - order: 13 - } - - .order-sm-0 { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0 - } - - .order-sm-1 { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1 - } - - .order-sm-2 { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2 - } - - .order-sm-3 { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3 - } - - .order-sm-4 { - -webkit-box-ordinal-group: 5; - -ms-flex-order: 4; - order: 4 - } - - .order-sm-5 { - -webkit-box-ordinal-group: 6; - -ms-flex-order: 5; - order: 5 - } - - .order-sm-6 { - -webkit-box-ordinal-group: 7; - -ms-flex-order: 6; - order: 6 - } - - .order-sm-7 { - -webkit-box-ordinal-group: 8; - -ms-flex-order: 7; - order: 7 - } - - .order-sm-8 { - -webkit-box-ordinal-group: 9; - -ms-flex-order: 8; - order: 8 - } - - .order-sm-9 { - -webkit-box-ordinal-group: 10; - -ms-flex-order: 9; - order: 9 - } - - .order-sm-10 { - -webkit-box-ordinal-group: 11; - -ms-flex-order: 10; - order: 10 - } - - .order-sm-11 { - -webkit-box-ordinal-group: 12; - -ms-flex-order: 11; - order: 11 - } - - .order-sm-12 { - -webkit-box-ordinal-group: 13; - -ms-flex-order: 12; - order: 12 - } - - .offset-sm-0 { - margin-left: 0 - } - - .offset-sm-1 { - margin-left: 8.33333333% - } - - .offset-sm-2 { - margin-left: 16.66666667% - } - - .offset-sm-3 { - margin-left: 25% - } - - .offset-sm-4 { - margin-left: 33.33333333% - } - - .offset-sm-5 { - margin-left: 41.66666667% - } - - .offset-sm-6 { - margin-left: 50% - } - - .offset-sm-7 { - margin-left: 58.33333333% - } - - .offset-sm-8 { - margin-left: 66.66666667% - } - - .offset-sm-9 { - margin-left: 75% - } - - .offset-sm-10 { - margin-left: 83.33333333% - } - - .offset-sm-11 { - margin-left: 91.66666667% - } -} - -@media(min-width: 768px) { - .col-md { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100% - } - - .row-cols-md-1>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .row-cols-md-2>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .row-cols-md-3>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.3333333333%; - flex: 0 0 33.3333333333%; - max-width: 33.3333333333% - } - - .row-cols-md-4>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .row-cols-md-5>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20% - } - - .row-cols-md-6>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.6666666667%; - flex: 0 0 16.6666666667%; - max-width: 16.6666666667% - } - - .col-md-auto { - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100% - } - - .col-md-1 { - -webkit-box-flex: 0; - -ms-flex: 0 0 8.33333333%; - flex: 0 0 8.33333333%; - max-width: 8.33333333% - } - - .col-md-2 { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.66666667%; - flex: 0 0 16.66666667%; - max-width: 16.66666667% - } - - .col-md-3 { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .col-md-4 { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.33333333%; - flex: 0 0 33.33333333%; - max-width: 33.33333333% - } - - .col-md-5 { - -webkit-box-flex: 0; - -ms-flex: 0 0 41.66666667%; - flex: 0 0 41.66666667%; - max-width: 41.66666667% - } - - .col-md-6 { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .col-md-7 { - -webkit-box-flex: 0; - -ms-flex: 0 0 58.33333333%; - flex: 0 0 58.33333333%; - max-width: 58.33333333% - } - - .col-md-8 { - -webkit-box-flex: 0; - -ms-flex: 0 0 66.66666667%; - flex: 0 0 66.66666667%; - max-width: 66.66666667% - } - - .col-md-9 { - -webkit-box-flex: 0; - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75% - } - - .col-md-10 { - -webkit-box-flex: 0; - -ms-flex: 0 0 83.33333333%; - flex: 0 0 83.33333333%; - max-width: 83.33333333% - } - - .col-md-11 { - -webkit-box-flex: 0; - -ms-flex: 0 0 91.66666667%; - flex: 0 0 91.66666667%; - max-width: 91.66666667% - } - - .col-md-12 { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .order-md-first { - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1 - } - - .order-md-last { - -webkit-box-ordinal-group: 14; - -ms-flex-order: 13; - order: 13 - } - - .order-md-0 { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0 - } - - .order-md-1 { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1 - } - - .order-md-2 { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2 - } - - .order-md-3 { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3 - } - - .order-md-4 { - -webkit-box-ordinal-group: 5; - -ms-flex-order: 4; - order: 4 - } - - .order-md-5 { - -webkit-box-ordinal-group: 6; - -ms-flex-order: 5; - order: 5 - } - - .order-md-6 { - -webkit-box-ordinal-group: 7; - -ms-flex-order: 6; - order: 6 - } - - .order-md-7 { - -webkit-box-ordinal-group: 8; - -ms-flex-order: 7; - order: 7 - } - - .order-md-8 { - -webkit-box-ordinal-group: 9; - -ms-flex-order: 8; - order: 8 - } - - .order-md-9 { - -webkit-box-ordinal-group: 10; - -ms-flex-order: 9; - order: 9 - } - - .order-md-10 { - -webkit-box-ordinal-group: 11; - -ms-flex-order: 10; - order: 10 - } - - .order-md-11 { - -webkit-box-ordinal-group: 12; - -ms-flex-order: 11; - order: 11 - } - - .order-md-12 { - -webkit-box-ordinal-group: 13; - -ms-flex-order: 12; - order: 12 - } - - .offset-md-0 { - margin-left: 0 - } - - .offset-md-1 { - margin-left: 8.33333333% - } - - .offset-md-2 { - margin-left: 16.66666667% - } - - .offset-md-3 { - margin-left: 25% - } - - .offset-md-4 { - margin-left: 33.33333333% - } - - .offset-md-5 { - margin-left: 41.66666667% - } - - .offset-md-6 { - margin-left: 50% - } - - .offset-md-7 { - margin-left: 58.33333333% - } - - .offset-md-8 { - margin-left: 66.66666667% - } - - .offset-md-9 { - margin-left: 75% - } - - .offset-md-10 { - margin-left: 83.33333333% - } - - .offset-md-11 { - margin-left: 91.66666667% - } -} - -@media(min-width: 992px) { - .col-lg { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100% - } - - .row-cols-lg-1>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .row-cols-lg-2>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .row-cols-lg-3>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.3333333333%; - flex: 0 0 33.3333333333%; - max-width: 33.3333333333% - } - - .row-cols-lg-4>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .row-cols-lg-5>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20% - } - - .row-cols-lg-6>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.6666666667%; - flex: 0 0 16.6666666667%; - max-width: 16.6666666667% - } - - .col-lg-auto { - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100% - } - - .col-lg-1 { - -webkit-box-flex: 0; - -ms-flex: 0 0 8.33333333%; - flex: 0 0 8.33333333%; - max-width: 8.33333333% - } - - .col-lg-2 { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.66666667%; - flex: 0 0 16.66666667%; - max-width: 16.66666667% - } - - .col-lg-3 { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .col-lg-4 { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.33333333%; - flex: 0 0 33.33333333%; - max-width: 33.33333333% - } - - .col-lg-5 { - -webkit-box-flex: 0; - -ms-flex: 0 0 41.66666667%; - flex: 0 0 41.66666667%; - max-width: 41.66666667% - } - - .col-lg-6 { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .col-lg-7 { - -webkit-box-flex: 0; - -ms-flex: 0 0 58.33333333%; - flex: 0 0 58.33333333%; - max-width: 58.33333333% - } - - .col-lg-8 { - -webkit-box-flex: 0; - -ms-flex: 0 0 66.66666667%; - flex: 0 0 66.66666667%; - max-width: 66.66666667% - } - - .col-lg-9 { - -webkit-box-flex: 0; - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75% - } - - .col-lg-10 { - -webkit-box-flex: 0; - -ms-flex: 0 0 83.33333333%; - flex: 0 0 83.33333333%; - max-width: 83.33333333% - } - - .col-lg-11 { - -webkit-box-flex: 0; - -ms-flex: 0 0 91.66666667%; - flex: 0 0 91.66666667%; - max-width: 91.66666667% - } - - .col-lg-12 { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .order-lg-first { - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1 - } - - .order-lg-last { - -webkit-box-ordinal-group: 14; - -ms-flex-order: 13; - order: 13 - } - - .order-lg-0 { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0 - } - - .order-lg-1 { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1 - } - - .order-lg-2 { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2 - } - - .order-lg-3 { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3 - } - - .order-lg-4 { - -webkit-box-ordinal-group: 5; - -ms-flex-order: 4; - order: 4 - } - - .order-lg-5 { - -webkit-box-ordinal-group: 6; - -ms-flex-order: 5; - order: 5 - } - - .order-lg-6 { - -webkit-box-ordinal-group: 7; - -ms-flex-order: 6; - order: 6 - } - - .order-lg-7 { - -webkit-box-ordinal-group: 8; - -ms-flex-order: 7; - order: 7 - } - - .order-lg-8 { - -webkit-box-ordinal-group: 9; - -ms-flex-order: 8; - order: 8 - } - - .order-lg-9 { - -webkit-box-ordinal-group: 10; - -ms-flex-order: 9; - order: 9 - } - - .order-lg-10 { - -webkit-box-ordinal-group: 11; - -ms-flex-order: 10; - order: 10 - } - - .order-lg-11 { - -webkit-box-ordinal-group: 12; - -ms-flex-order: 11; - order: 11 - } - - .order-lg-12 { - -webkit-box-ordinal-group: 13; - -ms-flex-order: 12; - order: 12 - } - - .offset-lg-0 { - margin-left: 0 - } - - .offset-lg-1 { - margin-left: 8.33333333% - } - - .offset-lg-2 { - margin-left: 16.66666667% - } - - .offset-lg-3 { - margin-left: 25% - } - - .offset-lg-4 { - margin-left: 33.33333333% - } - - .offset-lg-5 { - margin-left: 41.66666667% - } - - .offset-lg-6 { - margin-left: 50% - } - - .offset-lg-7 { - margin-left: 58.33333333% - } - - .offset-lg-8 { - margin-left: 66.66666667% - } - - .offset-lg-9 { - margin-left: 75% - } - - .offset-lg-10 { - margin-left: 83.33333333% - } - - .offset-lg-11 { - margin-left: 91.66666667% - } -} - -@media(min-width: 1200px) { - .col-xl { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100% - } - - .row-cols-xl-1>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .row-cols-xl-2>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .row-cols-xl-3>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.3333333333%; - flex: 0 0 33.3333333333%; - max-width: 33.3333333333% - } - - .row-cols-xl-4>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .row-cols-xl-5>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20% - } - - .row-cols-xl-6>* { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.6666666667%; - flex: 0 0 16.6666666667%; - max-width: 16.6666666667% - } - - .col-xl-auto { - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100% - } - - .col-xl-1 { - -webkit-box-flex: 0; - -ms-flex: 0 0 8.33333333%; - flex: 0 0 8.33333333%; - max-width: 8.33333333% - } - - .col-xl-2 { - -webkit-box-flex: 0; - -ms-flex: 0 0 16.66666667%; - flex: 0 0 16.66666667%; - max-width: 16.66666667% - } - - .col-xl-3 { - -webkit-box-flex: 0; - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25% - } - - .col-xl-4 { - -webkit-box-flex: 0; - -ms-flex: 0 0 33.33333333%; - flex: 0 0 33.33333333%; - max-width: 33.33333333% - } - - .col-xl-5 { - -webkit-box-flex: 0; - -ms-flex: 0 0 41.66666667%; - flex: 0 0 41.66666667%; - max-width: 41.66666667% - } - - .col-xl-6 { - -webkit-box-flex: 0; - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50% - } - - .col-xl-7 { - -webkit-box-flex: 0; - -ms-flex: 0 0 58.33333333%; - flex: 0 0 58.33333333%; - max-width: 58.33333333% - } - - .col-xl-8 { - -webkit-box-flex: 0; - -ms-flex: 0 0 66.66666667%; - flex: 0 0 66.66666667%; - max-width: 66.66666667% - } - - .col-xl-9 { - -webkit-box-flex: 0; - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75% - } - - .col-xl-10 { - -webkit-box-flex: 0; - -ms-flex: 0 0 83.33333333%; - flex: 0 0 83.33333333%; - max-width: 83.33333333% - } - - .col-xl-11 { - -webkit-box-flex: 0; - -ms-flex: 0 0 91.66666667%; - flex: 0 0 91.66666667%; - max-width: 91.66666667% - } - - .col-xl-12 { - -webkit-box-flex: 0; - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100% - } - - .order-xl-first { - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1 - } - - .order-xl-last { - -webkit-box-ordinal-group: 14; - -ms-flex-order: 13; - order: 13 - } - - .order-xl-0 { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0 - } - - .order-xl-1 { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1 - } - - .order-xl-2 { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2 - } - - .order-xl-3 { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3 - } - - .order-xl-4 { - -webkit-box-ordinal-group: 5; - -ms-flex-order: 4; - order: 4 - } - - .order-xl-5 { - -webkit-box-ordinal-group: 6; - -ms-flex-order: 5; - order: 5 - } - - .order-xl-6 { - -webkit-box-ordinal-group: 7; - -ms-flex-order: 6; - order: 6 - } - - .order-xl-7 { - -webkit-box-ordinal-group: 8; - -ms-flex-order: 7; - order: 7 - } - - .order-xl-8 { - -webkit-box-ordinal-group: 9; - -ms-flex-order: 8; - order: 8 - } - - .order-xl-9 { - -webkit-box-ordinal-group: 10; - -ms-flex-order: 9; - order: 9 - } - - .order-xl-10 { - -webkit-box-ordinal-group: 11; - -ms-flex-order: 10; - order: 10 - } - - .order-xl-11 { - -webkit-box-ordinal-group: 12; - -ms-flex-order: 11; - order: 11 - } - - .order-xl-12 { - -webkit-box-ordinal-group: 13; - -ms-flex-order: 12; - order: 12 - } - - .offset-xl-0 { - margin-left: 0 - } - - .offset-xl-1 { - margin-left: 8.33333333% - } - - .offset-xl-2 { - margin-left: 16.66666667% - } - - .offset-xl-3 { - margin-left: 25% - } - - .offset-xl-4 { - margin-left: 33.33333333% - } - - .offset-xl-5 { - margin-left: 41.66666667% - } - - .offset-xl-6 { - margin-left: 50% - } - - .offset-xl-7 { - margin-left: 58.33333333% - } - - .offset-xl-8 { - margin-left: 66.66666667% - } - - .offset-xl-9 { - margin-left: 75% - } - - .offset-xl-10 { - margin-left: 83.33333333% - } - - .offset-xl-11 { - margin-left: 91.66666667% - } -} - -.table { - width: 100%; - margin-bottom: 1rem; - color: #212529 -} - -.table th, -.table td { - 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 th, -.table-sm td { - padding: .3rem -} - -.table-bordered { - border: 1px solid #dee2e6 -} - -.table-bordered th, -.table-bordered td { - border: 1px solid #dee2e6 -} - -.table-bordered thead th, -.table-bordered thead td { - border-bottom-width: 2px -} - -.table-borderless th, -.table-borderless td, -.table-borderless thead th, -.table-borderless tbody+tbody { - 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>th, -.table-primary>td { - background-color: #b8daff -} - -.table-primary th, -.table-primary td, -.table-primary thead th, -.table-primary tbody+tbody { - border-color: #7abaff -} - -.table-hover .table-primary:hover { - background-color: #9fcdff -} - -.table-hover .table-primary:hover>td, -.table-hover .table-primary:hover>th { - background-color: #9fcdff -} - -.table-secondary, -.table-secondary>th, -.table-secondary>td { - background-color: #d6d8db -} - -.table-secondary th, -.table-secondary td, -.table-secondary thead th, -.table-secondary tbody+tbody { - border-color: #b3b7bb -} - -.table-hover .table-secondary:hover { - background-color: #c8cbcf -} - -.table-hover .table-secondary:hover>td, -.table-hover .table-secondary:hover>th { - background-color: #c8cbcf -} - -.table-success, -.table-success>th, -.table-success>td { - background-color: #c3e6cb -} - -.table-success th, -.table-success td, -.table-success thead th, -.table-success tbody+tbody { - border-color: #8fd19e -} - -.table-hover .table-success:hover { - background-color: #b1dfbb -} - -.table-hover .table-success:hover>td, -.table-hover .table-success:hover>th { - background-color: #b1dfbb -} - -.table-info, -.table-info>th, -.table-info>td { - background-color: #bee5eb -} - -.table-info th, -.table-info td, -.table-info thead th, -.table-info tbody+tbody { - border-color: #86cfda -} - -.table-hover .table-info:hover { - background-color: #abdde5 -} - -.table-hover .table-info:hover>td, -.table-hover .table-info:hover>th { - background-color: #abdde5 -} - -.table-warning, -.table-warning>th, -.table-warning>td { - background-color: #ffeeba -} - -.table-warning th, -.table-warning td, -.table-warning thead th, -.table-warning tbody+tbody { - border-color: #ffdf7e -} - -.table-hover .table-warning:hover { - background-color: #ffe8a1 -} - -.table-hover .table-warning:hover>td, -.table-hover .table-warning:hover>th { - background-color: #ffe8a1 -} - -.table-danger, -.table-danger>th, -.table-danger>td { - background-color: #f5c6cb -} - -.table-danger th, -.table-danger td, -.table-danger thead th, -.table-danger tbody+tbody { - border-color: #ed969e -} - -.table-hover .table-danger:hover { - background-color: #f1b0b7 -} - -.table-hover .table-danger:hover>td, -.table-hover .table-danger:hover>th { - background-color: #f1b0b7 -} - -.table-light, -.table-light>th, -.table-light>td { - background-color: #fdfdfe -} - -.table-light th, -.table-light td, -.table-light thead th, -.table-light tbody+tbody { - border-color: #fbfcfc -} - -.table-hover .table-light:hover { - background-color: #ececf6 -} - -.table-hover .table-light:hover>td, -.table-hover .table-light:hover>th { - background-color: #ececf6 -} - -.table-dark, -.table-dark>th, -.table-dark>td { - background-color: #c6c8ca -} - -.table-dark th, -.table-dark td, -.table-dark thead th, -.table-dark tbody+tbody { - border-color: #95999c -} - -.table-hover .table-dark:hover { - background-color: #b9bbbe -} - -.table-hover .table-dark:hover>td, -.table-hover .table-dark:hover>th { - background-color: #b9bbbe -} - -.table-active, -.table-active>th, -.table-active>td { - background-color: rgba(0, 0, 0, .075) -} - -.table-hover .table-active:hover { - background-color: rgba(0, 0, 0, .075) -} - -.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 th, -.table-dark td, -.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: rgba(255, 255, 255, .05) -} - -.table-dark.table-hover tbody tr:hover { - color: #fff; - background-color: rgba(255, 255, 255, .075) -} - -@media(max-width: 575.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: 767.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: 991.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 + 0.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; - -webkit-transition: border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - .form-control { - -webkit-transition: none; - transition: none - } -} - -.form-control::-ms-expand { - background-color: rgba(0, 0, 0, 0); - border: 0 -} - -.form-control:focus { - color: #495057; - background-color: #fff; - border-color: #80bdff; - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25) -} - -.form-control::-webkit-input-placeholder { - color: #6c757d; - opacity: 1 -} - -.form-control::-moz-placeholder { - color: #6c757d; - opacity: 1 -} - -.form-control:-ms-input-placeholder { - color: #6c757d; - opacity: 1 -} - -.form-control::-ms-input-placeholder { - color: #6c757d; - opacity: 1 -} - -.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=time].form-control, -input[type=datetime-local].form-control, -input[type=month].form-control { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none -} - -select.form-control:-moz-focusring { - color: rgba(0, 0, 0, 0); - text-shadow: 0 0 0 #495057 -} - -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(0.375rem + 1px); - padding-bottom: calc(0.375rem + 1px); - margin-bottom: 0; - font-size: inherit; - line-height: 1.5 -} - -.col-form-label-lg { - padding-top: calc(0.5rem + 1px); - padding-bottom: calc(0.5rem + 1px); - font-size: 1.25rem; - line-height: 1.5 -} - -.col-form-label-sm { - padding-top: calc(0.25rem + 1px); - padding-bottom: calc(0.25rem + 1px); - font-size: 0.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: rgba(0, 0, 0, 0); - border: solid rgba(0, 0, 0, 0); - border-width: 1px 0 -} - -.form-control-plaintext.form-control-sm, -.form-control-plaintext.form-control-lg { - padding-right: 0; - padding-left: 0 -} - -.form-control-sm { - height: calc(1.5em + 0.5rem + 2px); - padding: .25rem .5rem; - font-size: 0.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[size], -select.form-control[multiple] { - height: auto -} - -textarea.form-control { - height: auto -} - -.form-group { - margin-bottom: 1rem -} - -.form-text { - display: block; - margin-top: .25rem -} - -.form-row { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - 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: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-box-align: center; - -ms-flex-align: center; - 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%; - left: 0; - z-index: 5; - display: none; - max-width: 100%; - padding: .25rem .5rem; - margin-top: .1rem; - font-size: 0.875rem; - line-height: 1.5; - color: #fff; - background-color: rgba(40, 167, 69, .9); - border-radius: .25rem -} - -.form-row>.col>.valid-tooltip, -.form-row>[class*=col-]>.valid-tooltip { - left: 5px -} - -.was-validated :valid~.valid-feedback, -.was-validated :valid~.valid-tooltip, -.is-valid~.valid-feedback, -.is-valid~.valid-tooltip { - display: block -} - -.was-validated .form-control:valid, -.form-control.is-valid { - border-color: #28a745; - padding-right: calc(1.5em + 0.75rem) !important; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 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(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) -} - -.was-validated .form-control:valid:focus, -.form-control.is-valid:focus { - border-color: #28a745; - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); - box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25) -} - -.was-validated select.form-control:valid, -select.form-control.is-valid { - padding-right: 3rem !important; - background-position: right 1.5rem center -} - -.was-validated textarea.form-control:valid, -textarea.form-control.is-valid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem) -} - -.was-validated .custom-select:valid, -.custom-select.is-valid { - border-color: #28a745; - padding-right: calc(0.75em + 2.3125rem) !important; - background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 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") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat -} - -.was-validated .custom-select:valid:focus, -.custom-select.is-valid:focus { - border-color: #28a745; - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); - box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25) -} - -.was-validated .form-check-input:valid~.form-check-label, -.form-check-input.is-valid~.form-check-label { - color: #28a745 -} - -.was-validated .form-check-input:valid~.valid-feedback, -.was-validated .form-check-input:valid~.valid-tooltip, -.form-check-input.is-valid~.valid-feedback, -.form-check-input.is-valid~.valid-tooltip { - display: block -} - -.was-validated .custom-control-input:valid~.custom-control-label, -.custom-control-input.is-valid~.custom-control-label { - color: #28a745 -} - -.was-validated .custom-control-input:valid~.custom-control-label::before, -.custom-control-input.is-valid~.custom-control-label::before { - border-color: #28a745 -} - -.was-validated .custom-control-input:valid:checked~.custom-control-label::before, -.custom-control-input.is-valid:checked~.custom-control-label::before { - border-color: #34ce57; - background-color: #34ce57 -} - -.was-validated .custom-control-input:valid:focus~.custom-control-label::before, -.custom-control-input.is-valid:focus~.custom-control-label::before { - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); - box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25) -} - -.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before, -.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before { - border-color: #28a745 -} - -.was-validated .custom-file-input:valid~.custom-file-label, -.custom-file-input.is-valid~.custom-file-label { - border-color: #28a745 -} - -.was-validated .custom-file-input:valid:focus~.custom-file-label, -.custom-file-input.is-valid:focus~.custom-file-label { - border-color: #28a745; - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); - 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%; - left: 0; - z-index: 5; - display: none; - max-width: 100%; - padding: .25rem .5rem; - margin-top: .1rem; - font-size: 0.875rem; - line-height: 1.5; - color: #fff; - background-color: rgba(220, 53, 69, .9); - border-radius: .25rem -} - -.form-row>.col>.invalid-tooltip, -.form-row>[class*=col-]>.invalid-tooltip { - left: 5px -} - -.was-validated :invalid~.invalid-feedback, -.was-validated :invalid~.invalid-tooltip, -.is-invalid~.invalid-feedback, -.is-invalid~.invalid-tooltip { - display: block -} - -.was-validated .form-control:invalid, -.form-control.is-invalid { - border-color: #dc3545; - padding-right: calc(1.5em + 0.75rem) !important; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%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(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) -} - -.was-validated .form-control:invalid:focus, -.form-control.is-invalid:focus { - border-color: #dc3545; - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) -} - -.was-validated select.form-control:invalid, -select.form-control.is-invalid { - padding-right: 3rem !important; - background-position: right 1.5rem center -} - -.was-validated textarea.form-control:invalid, -textarea.form-control.is-invalid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem) -} - -.was-validated .custom-select:invalid, -.custom-select.is-invalid { - border-color: #dc3545; - padding-right: calc(0.75em + 2.3125rem) !important; - background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%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") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat -} - -.was-validated .custom-select:invalid:focus, -.custom-select.is-invalid:focus { - border-color: #dc3545; - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) -} - -.was-validated .form-check-input:invalid~.form-check-label, -.form-check-input.is-invalid~.form-check-label { - color: #dc3545 -} - -.was-validated .form-check-input:invalid~.invalid-feedback, -.was-validated .form-check-input:invalid~.invalid-tooltip, -.form-check-input.is-invalid~.invalid-feedback, -.form-check-input.is-invalid~.invalid-tooltip { - display: block -} - -.was-validated .custom-control-input:invalid~.custom-control-label, -.custom-control-input.is-invalid~.custom-control-label { - color: #dc3545 -} - -.was-validated .custom-control-input:invalid~.custom-control-label::before, -.custom-control-input.is-invalid~.custom-control-label::before { - border-color: #dc3545 -} - -.was-validated .custom-control-input:invalid:checked~.custom-control-label::before, -.custom-control-input.is-invalid:checked~.custom-control-label::before { - border-color: #e4606d; - background-color: #e4606d -} - -.was-validated .custom-control-input:invalid:focus~.custom-control-label::before, -.custom-control-input.is-invalid:focus~.custom-control-label::before { - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) -} - -.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before, -.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before { - border-color: #dc3545 -} - -.was-validated .custom-file-input:invalid~.custom-file-label, -.custom-file-input.is-invalid~.custom-file-label { - border-color: #dc3545 -} - -.was-validated .custom-file-input:invalid:focus~.custom-file-label, -.custom-file-input.is-invalid:focus~.custom-file-label { - border-color: #dc3545; - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) -} - -.form-inline { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center -} - -.form-inline .form-check { - width: 100% -} - -@media(min-width: 576px) { - .form-inline label { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin-bottom: 0 - } - - .form-inline .form-group { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 0; - -ms-flex: 0 0 auto; - flex: 0 0 auto; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin-bottom: 0 - } - - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle - } - - .form-inline .form-control-plaintext { - display: inline-block - } - - .form-inline .input-group, - .form-inline .custom-select { - width: auto - } - - .form-inline .form-check { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - width: auto; - padding-left: 0 - } - - .form-inline .form-check-input { - position: relative; - -ms-flex-negative: 0; - flex-shrink: 0; - margin-top: 0; - margin-right: .25rem; - margin-left: 0 - } - - .form-inline .custom-control { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: 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; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(0, 0, 0, 0); - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - border-radius: .25rem; - -webkit-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - .btn { - -webkit-transition: none; - transition: none - } -} - -.btn:hover { - color: #212529; - text-decoration: none -} - -.btn:focus, -.btn.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - 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:hover { - color: #fff; - background-color: #0069d9; - border-color: #0062cc -} - -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #0069d9; - border-color: #0062cc; - -webkit-box-shadow: 0 0 0 .2rem rgba(38, 143, 255, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(38, 143, 255, .5); - box-shadow: 0 0 0 .2rem rgba(38, 143, 255, .5) -} - -.btn-secondary { - color: #fff; - background-color: #6c757d; - border-color: #6c757d -} - -.btn-secondary:hover { - color: #fff; - background-color: #5a6268; - border-color: #545b62 -} - -.btn-secondary:focus, -.btn-secondary.focus { - color: #fff; - background-color: #5a6268; - border-color: #545b62; - -webkit-box-shadow: 0 0 0 .2rem rgba(130, 138, 145, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(130, 138, 145, .5); - box-shadow: 0 0 0 .2rem rgba(130, 138, 145, .5) -} - -.btn-success { - color: #fff; - background-color: #28a745; - border-color: #28a745 -} - -.btn-success:hover { - color: #fff; - background-color: #218838; - border-color: #1e7e34 -} - -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #218838; - border-color: #1e7e34; - -webkit-box-shadow: 0 0 0 .2rem rgba(72, 180, 97, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(72, 180, 97, .5); - box-shadow: 0 0 0 .2rem rgba(72, 180, 97, .5) -} - -.btn-info { - color: #fff; - background-color: #17a2b8; - border-color: #17a2b8 -} - -.btn-info:hover { - color: #fff; - background-color: #138496; - border-color: #117a8b -} - -.btn-info:focus, -.btn-info.focus { - color: #fff; - background-color: #138496; - border-color: #117a8b; - -webkit-box-shadow: 0 0 0 .2rem rgba(58, 176, 195, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(58, 176, 195, .5); - box-shadow: 0 0 0 .2rem rgba(58, 176, 195, .5) -} - -.btn-warning { - color: #212529; - background-color: #ffc107; - border-color: #ffc107 -} - -.btn-warning:hover { - color: #212529; - background-color: #e0a800; - border-color: #d39e00 -} - -.btn-warning:focus, -.btn-warning.focus { - color: #212529; - background-color: #e0a800; - border-color: #d39e00; - -webkit-box-shadow: 0 0 0 .2rem rgba(222, 170, 12, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(222, 170, 12, .5); - box-shadow: 0 0 0 .2rem rgba(222, 170, 12, .5) -} - -.btn-danger { - color: #fff; - background-color: #dc3545; - border-color: #dc3545 -} - -.btn-danger:hover { - color: #fff; - background-color: #c82333; - border-color: #bd2130 -} - -.btn-danger:focus, -.btn-danger.focus { - color: #fff; - background-color: #c82333; - border-color: #bd2130; - -webkit-box-shadow: 0 0 0 .2rem rgba(225, 83, 97, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(225, 83, 97, .5); - box-shadow: 0 0 0 .2rem rgba(225, 83, 97, .5) -} - -.btn-light { - color: #212529; - background-color: #f8f9fa; - border-color: #f8f9fa -} - -.btn-light:hover { - color: #212529; - background-color: #e2e6ea; - border-color: #dae0e5 -} - -.btn-light:focus, -.btn-light.focus { - color: #212529; - background-color: #e2e6ea; - border-color: #dae0e5; - -webkit-box-shadow: 0 0 0 .2rem rgba(216, 217, 219, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(216, 217, 219, .5); - box-shadow: 0 0 0 .2rem rgba(216, 217, 219, .5) -} - -.btn-dark { - color: #fff; - background-color: #343a40; - border-color: #343a40 -} - -.btn-dark:hover { - color: #fff; - background-color: #23272b; - border-color: #1d2124 -} - -.btn-dark:focus, -.btn-dark.focus { - color: #fff; - background-color: #23272b; - border-color: #1d2124; - -webkit-box-shadow: 0 0 0 .2rem rgba(82, 88, 93, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(82, 88, 93, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); - box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) -} - -.btn-outline-primary.disabled, -.btn-outline-primary:disabled { - color: #007bff; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(108, 117, 125, .5); - box-shadow: 0 0 0 .2rem rgba(108, 117, 125, .5) -} - -.btn-outline-secondary.disabled, -.btn-outline-secondary:disabled { - color: #6c757d; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(108, 117, 125, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); - box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) -} - -.btn-outline-success.disabled, -.btn-outline-success:disabled { - color: #28a745; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); - box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) -} - -.btn-outline-info.disabled, -.btn-outline-info:disabled { - color: #17a2b8; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); - box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) -} - -.btn-outline-warning.disabled, -.btn-outline-warning:disabled { - color: #ffc107; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) -} - -.btn-outline-danger.disabled, -.btn-outline-danger:disabled { - color: #dc3545; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); - box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) -} - -.btn-outline-light.disabled, -.btn-outline-light:disabled { - color: #f8f9fa; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); - box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5) -} - -.btn-outline-dark.disabled, -.btn-outline-dark:disabled { - color: #343a40; - background-color: rgba(0, 0, 0, 0) -} - -.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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); - 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; - text-decoration: underline -} - -.btn-link:focus, -.btn-link.focus { - text-decoration: underline -} - -.btn-link:disabled, -.btn-link.disabled { - color: #6c757d; - pointer-events: none -} - -.btn-lg, -.btn-group-lg>.btn { - padding: .5rem 1rem; - font-size: 1.25rem; - line-height: 1.5; - border-radius: .3rem -} - -.btn-sm, -.btn-group-sm>.btn { - padding: .25rem .5rem; - font-size: 0.875rem; - line-height: 1.5; - border-radius: .2rem -} - -.btn-block { - display: block; - width: 100% -} - -.btn-block+.btn-block { - margin-top: .5rem -} - -input[type=submit].btn-block, -input[type=reset].btn-block, -input[type=button].btn-block { - width: 100% -} - -.fade { - -webkit-transition: opacity .15s linear; - transition: opacity .15s linear -} - -@media(prefers-reduced-motion: reduce) { - .fade { - -webkit-transition: none; - transition: none - } -} - -.fade:not(.show) { - opacity: 0 -} - -.collapse:not(.show) { - display: none -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height .35s ease; - transition: height .35s ease -} - -@media(prefers-reduced-motion: reduce) { - .collapsing { - -webkit-transition: none; - transition: none - } -} - -.dropup, -.dropright, -.dropdown, -.dropleft { - 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 rgba(0, 0, 0, 0); - border-bottom: 0; - border-left: .3em solid rgba(0, 0, 0, 0) -} - -.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: 576px) { - .dropdown-menu-sm-left { - right: auto; - left: 0 - } - - .dropdown-menu-sm-right { - right: 0; - left: auto - } -} - -@media(min-width: 768px) { - .dropdown-menu-md-left { - right: auto; - left: 0 - } - - .dropdown-menu-md-right { - right: 0; - left: auto - } -} - -@media(min-width: 992px) { - .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 rgba(0, 0, 0, 0); - border-bottom: .3em solid; - border-left: .3em solid rgba(0, 0, 0, 0) -} - -.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 rgba(0, 0, 0, 0); - border-right: 0; - border-bottom: .3em solid rgba(0, 0, 0, 0); - 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: "" -} - -.dropleft .dropdown-toggle::after { - display: none -} - -.dropleft .dropdown-toggle::before { - display: inline-block; - margin-right: .255em; - vertical-align: .255em; - content: ""; - border-top: .3em solid rgba(0, 0, 0, 0); - border-right: .3em solid; - border-bottom: .3em solid rgba(0, 0, 0, 0) -} - -.dropleft .dropdown-toggle:empty::after { - margin-left: 0 -} - -.dropleft .dropdown-toggle::before { - vertical-align: 0 -} - -.dropdown-menu[x-placement^=top], -.dropdown-menu[x-placement^=right], -.dropdown-menu[x-placement^=bottom], -.dropdown-menu[x-placement^=left] { - 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: rgba(0, 0, 0, 0); - border: 0 -} - -.dropdown-item:hover, -.dropdown-item:focus { - color: #16181b; - text-decoration: none; - background-color: #e9ecef -} - -.dropdown-item.active, -.dropdown-item:active { - color: #fff; - text-decoration: none; - background-color: #007bff -} - -.dropdown-item.disabled, -.dropdown-item:disabled { - color: #adb5bd; - pointer-events: none; - background-color: rgba(0, 0, 0, 0) -} - -.dropdown-menu.show { - display: block -} - -.dropdown-header { - display: block; - padding: .5rem 1.5rem; - margin-bottom: 0; - font-size: 0.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: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - vertical-align: middle -} - -.btn-group>.btn, -.btn-group-vertical>.btn { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto -} - -.btn-group>.btn:hover, -.btn-group-vertical>.btn:hover { - z-index: 1 -} - -.btn-group>.btn:focus, -.btn-group>.btn:active, -.btn-group>.btn.active, -.btn-group-vertical>.btn:focus, -.btn-group-vertical>.btn:active, -.btn-group-vertical>.btn.active { - z-index: 1 -} - -.btn-toolbar { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start -} - -.btn-toolbar .input-group { - width: auto -} - -.btn-group>.btn:not(:first-child), -.btn-group>.btn-group:not(:first-child) { - margin-left: -1px -} - -.btn-group>.btn:not(:last-child):not(.dropdown-toggle), -.btn-group>.btn-group:not(:last-child)>.btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.btn-group>.btn:not(:first-child), -.btn-group>.btn-group:not(:first-child)>.btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.dropdown-toggle-split { - padding-right: .5625rem; - padding-left: .5625rem -} - -.dropdown-toggle-split::after, -.dropup .dropdown-toggle-split::after, -.dropright .dropdown-toggle-split::after { - margin-left: 0 -} - -.dropleft .dropdown-toggle-split::before { - margin-right: 0 -} - -.btn-sm+.dropdown-toggle-split, -.btn-group-sm>.btn+.dropdown-toggle-split { - padding-right: .375rem; - padding-left: .375rem -} - -.btn-lg+.dropdown-toggle-split, -.btn-group-lg>.btn+.dropdown-toggle-split { - padding-right: .75rem; - padding-left: .75rem -} - -.btn-group-vertical { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center -} - -.btn-group-vertical>.btn, -.btn-group-vertical>.btn-group { - width: 100% -} - -.btn-group-vertical>.btn:not(:first-child), -.btn-group-vertical>.btn-group:not(:first-child) { - margin-top: -1px -} - -.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle), -.btn-group-vertical>.btn-group:not(:last-child)>.btn { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group-vertical>.btn:not(:first-child), -.btn-group-vertical>.btn-group:not(:first-child)>.btn { - 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 input[type=radio], -.btn-group-toggle>.btn input[type=checkbox], -.btn-group-toggle>.btn-group>.btn input[type=radio], -.btn-group-toggle>.btn-group>.btn input[type=checkbox] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none -} - -.input-group { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - width: 100% -} - -.input-group>.form-control, -.input-group>.form-control-plaintext, -.input-group>.custom-select, -.input-group>.custom-file { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - width: 1%; - min-width: 0; - margin-bottom: 0 -} - -.input-group>.form-control+.form-control, -.input-group>.form-control+.custom-select, -.input-group>.form-control+.custom-file, -.input-group>.form-control-plaintext+.form-control, -.input-group>.form-control-plaintext+.custom-select, -.input-group>.form-control-plaintext+.custom-file, -.input-group>.custom-select+.form-control, -.input-group>.custom-select+.custom-select, -.input-group>.custom-select+.custom-file, -.input-group>.custom-file+.form-control, -.input-group>.custom-file+.custom-select, -.input-group>.custom-file+.custom-file { - margin-left: -1px -} - -.input-group>.form-control:focus, -.input-group>.custom-select:focus, -.input-group>.custom-file .custom-file-input:focus~.custom-file-label { - z-index: 3 -} - -.input-group>.custom-file .custom-file-input:focus { - z-index: 4 -} - -.input-group>.form-control:not(:first-child), -.input-group>.custom-select:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.input-group>.custom-file { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - 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:not(.has-validation)>.form-control:not(:last-child), -.input-group:not(.has-validation)>.custom-select:not(:last-child), -.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label, -.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after { - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.input-group.has-validation>.form-control:nth-last-child(n+3), -.input-group.has-validation>.custom-select:nth-last-child(n+3), -.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label, -.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after { - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.input-group-prepend, -.input-group-append { - display: -webkit-box; - display: -ms-flexbox; - display: flex -} - -.input-group-prepend .btn, -.input-group-append .btn { - position: relative; - z-index: 2 -} - -.input-group-prepend .btn:focus, -.input-group-append .btn:focus { - z-index: 3 -} - -.input-group-prepend .btn+.btn, -.input-group-prepend .btn+.input-group-text, -.input-group-prepend .input-group-text+.input-group-text, -.input-group-prepend .input-group-text+.btn, -.input-group-append .btn+.btn, -.input-group-append .btn+.input-group-text, -.input-group-append .input-group-text+.input-group-text, -.input-group-append .input-group-text+.btn { - margin-left: -1px -} - -.input-group-prepend { - margin-right: -1px -} - -.input-group-append { - margin-left: -1px -} - -.input-group-text { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - 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=radio], -.input-group-text input[type=checkbox] { - margin-top: 0 -} - -.input-group-lg>.form-control:not(textarea), -.input-group-lg>.custom-select { - height: calc(1.5em + 1rem + 2px) -} - -.input-group-lg>.form-control, -.input-group-lg>.custom-select, -.input-group-lg>.input-group-prepend>.input-group-text, -.input-group-lg>.input-group-append>.input-group-text, -.input-group-lg>.input-group-prepend>.btn, -.input-group-lg>.input-group-append>.btn { - padding: .5rem 1rem; - font-size: 1.25rem; - line-height: 1.5; - border-radius: .3rem -} - -.input-group-sm>.form-control:not(textarea), -.input-group-sm>.custom-select { - height: calc(1.5em + 0.5rem + 2px) -} - -.input-group-sm>.form-control, -.input-group-sm>.custom-select, -.input-group-sm>.input-group-prepend>.input-group-text, -.input-group-sm>.input-group-append>.input-group-text, -.input-group-sm>.input-group-prepend>.btn, -.input-group-sm>.input-group-append>.btn { - padding: .25rem .5rem; - font-size: 0.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-prepend>.btn, -.input-group>.input-group-prepend>.input-group-text, -.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn, -.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text, -.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn, -.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text, -.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) { - 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:not(:first-child)>.btn, -.input-group>.input-group-prepend:not(:first-child)>.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) { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.custom-control { - position: relative; - z-index: 1; - display: block; - min-height: 1.5rem; - padding-left: 1.5rem; - -webkit-print-color-adjust: exact; - color-adjust: exact -} - -.custom-control-inline { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - 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 { - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - 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 { - position: absolute; - top: .25rem; - left: -1.5rem; - display: block; - width: 1rem; - height: 1rem; - pointer-events: none; - content: ""; - background-color: #fff; - border: #adb5bd solid 1px -} - -.custom-control-label::after { - position: absolute; - top: .25rem; - left: -1.5rem; - display: block; - width: 1rem; - height: 1rem; - content: ""; - background: 50%/50% 50% no-repeat -} - -.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,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 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,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 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,%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(0.25rem + 2px); - left: calc(-2.25rem + 2px); - width: calc(1rem - 4px); - height: calc(1rem - 4px); - background-color: #adb5bd; - border-radius: .5rem; - -webkit-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-transform .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-transform .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: transform .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: transform .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-transform .15s ease-in-out, -webkit-box-shadow .15s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - .custom-switch .custom-control-label::after { - -webkit-transition: none; - transition: none - } -} - -.custom-switch .custom-control-input:checked~.custom-control-label::after { - background-color: #fff; - -webkit-transform: translateX(0.75rem); - transform: translateX(0.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 + 0.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,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat; - border: 1px solid #ced4da; - border-radius: .25rem; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none -} - -.custom-select:focus { - border-color: #80bdff; - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - 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: rgba(0, 0, 0, 0); - text-shadow: 0 0 0 #495057 -} - -.custom-select-sm { - height: calc(1.5em + 0.5rem + 2px); - padding-top: .25rem; - padding-bottom: .25rem; - padding-left: .5rem; - font-size: 0.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 { - position: relative; - display: inline-block; - width: 100%; - height: calc(1.5em + 0.75rem + 2px); - margin-bottom: 0 -} - -.custom-file-input { - position: relative; - z-index: 2; - width: 100%; - height: calc(1.5em + 0.75rem + 2px); - margin: 0; - overflow: hidden; - opacity: 0 -} - -.custom-file-input:focus~.custom-file-label { - border-color: #80bdff; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - 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 { - position: absolute; - top: 0; - right: 0; - left: 0; - z-index: 1; - height: calc(1.5em + 0.75rem + 2px); - padding: .375rem .75rem; - overflow: hidden; - font-weight: 400; - line-height: 1.5; - color: #495057; - background-color: #fff; - border: 1px solid #ced4da; - border-radius: .25rem -} - -.custom-file-label::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - z-index: 3; - display: block; - height: calc(1.5em + 0.75rem); - padding: .375rem .75rem; - line-height: 1.5; - color: #495057; - 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: rgba(0, 0, 0, 0); - -webkit-appearance: none; - -moz-appearance: none; - appearance: none -} - -.custom-range:focus { - outline: 0 -} - -.custom-range:focus::-webkit-slider-thumb { - -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 .2rem rgba(0, 123, 255, .25); - 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: -0.25rem; - background-color: #007bff; - border: 0; - border-radius: 1rem; - -webkit-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - -webkit-appearance: none; - appearance: none -} - -@media(prefers-reduced-motion: reduce) { - .custom-range::-webkit-slider-thumb { - -webkit-transition: none; - transition: none - } -} - -.custom-range::-webkit-slider-thumb:active { - background-color: #b3d7ff -} - -.custom-range::-webkit-slider-runnable-track { - width: 100%; - height: .5rem; - color: rgba(0, 0, 0, 0); - cursor: pointer; - background-color: #dee2e6; - border-color: rgba(0, 0, 0, 0); - border-radius: 1rem -} - -.custom-range::-moz-range-thumb { - width: 1rem; - height: 1rem; - background-color: #007bff; - border: 0; - border-radius: 1rem; - -moz-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - -moz-appearance: none; - appearance: none -} - -@media(prefers-reduced-motion: reduce) { - .custom-range::-moz-range-thumb { - -moz-transition: none; - transition: none - } -} - -.custom-range::-moz-range-thumb:active { - background-color: #b3d7ff -} - -.custom-range::-moz-range-track { - width: 100%; - height: .5rem; - color: rgba(0, 0, 0, 0); - cursor: pointer; - background-color: #dee2e6; - border-color: rgba(0, 0, 0, 0); - 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; - -ms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - 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 { - -ms-transition: none; - transition: none - } -} - -.custom-range::-ms-thumb:active { - background-color: #b3d7ff -} - -.custom-range::-ms-track { - width: 100%; - height: .5rem; - color: rgba(0, 0, 0, 0); - cursor: pointer; - background-color: rgba(0, 0, 0, 0); - border-color: rgba(0, 0, 0, 0); - border-width: .5rem -} - -.custom-range::-ms-fill-lower { - background-color: #dee2e6; - border-radius: 1rem -} - -.custom-range::-ms-fill-upper { - margin-right: 15px; - background-color: #dee2e6; - border-radius: 1rem -} - -.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 { - -webkit-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - - .custom-control-label::before, - .custom-file-label, - .custom-select { - -webkit-transition: none; - transition: none - } -} - -.nav { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - padding-left: 0; - margin-bottom: 0; - list-style: none -} - -.nav-link { - display: block; - padding: .5rem 1rem -} - -.nav-link:hover, -.nav-link:focus { - text-decoration: none -} - -.nav-link.disabled { - color: #6c757d; - pointer-events: none; - cursor: default -} - -.nav-tabs { - border-bottom: 1px solid #dee2e6 -} - -.nav-tabs .nav-link { - margin-bottom: -1px; - border: 1px solid rgba(0, 0, 0, 0); - border-top-left-radius: .25rem; - border-top-right-radius: .25rem -} - -.nav-tabs .nav-link:hover, -.nav-tabs .nav-link:focus { - border-color: #e9ecef #e9ecef #dee2e6 -} - -.nav-tabs .nav-link.disabled { - color: #6c757d; - background-color: rgba(0, 0, 0, 0); - border-color: rgba(0, 0, 0, 0) -} - -.nav-tabs .nav-link.active, -.nav-tabs .nav-item.show .nav-link { - 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-link, -.nav-fill .nav-item { - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - text-align: center -} - -.nav-justified>.nav-link, -.nav-justified .nav-item { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - text-align: center -} - -.tab-content>.tab-pane { - display: none -} - -.tab-content>.active { - display: block -} - -.navbar { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - padding: .5rem 1rem -} - -.navbar .container, -.navbar .container-fluid, -.navbar .container-sm, -.navbar .container-md, -.navbar .container-lg, -.navbar .container-xl { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - 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:hover, -.navbar-brand:focus { - text-decoration: none -} - -.navbar-nav { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - 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 { - -ms-flex-preferred-size: 100%; - flex-basis: 100%; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center -} - -.navbar-toggler { - padding: .25rem .75rem; - font-size: 1.25rem; - line-height: 1; - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(0, 0, 0, 0); - border-radius: .25rem -} - -.navbar-toggler:hover, -.navbar-toggler:focus { - text-decoration: none -} - -.navbar-toggler-icon { - display: inline-block; - width: 1.5em; - height: 1.5em; - vertical-align: middle; - content: ""; - background: 50%/100% 100% no-repeat -} - -.navbar-nav-scroll { - max-height: 75vh; - overflow-y: auto -} - -@media(max-width: 575.98px) { - - .navbar-expand-sm>.container, - .navbar-expand-sm>.container-fluid, - .navbar-expand-sm>.container-sm, - .navbar-expand-sm>.container-md, - .navbar-expand-sm>.container-lg, - .navbar-expand-sm>.container-xl { - padding-right: 0; - padding-left: 0 - } -} - -@media(min-width: 576px) { - .navbar-expand-sm { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start - } - - .navbar-expand-sm .navbar-nav { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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-sm, - .navbar-expand-sm>.container-md, - .navbar-expand-sm>.container-lg, - .navbar-expand-sm>.container-xl { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap - } - - .navbar-expand-sm .navbar-nav-scroll { - overflow: visible - } - - .navbar-expand-sm .navbar-collapse { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto - } - - .navbar-expand-sm .navbar-toggler { - display: none - } -} - -@media(max-width: 767.98px) { - - .navbar-expand-md>.container, - .navbar-expand-md>.container-fluid, - .navbar-expand-md>.container-sm, - .navbar-expand-md>.container-md, - .navbar-expand-md>.container-lg, - .navbar-expand-md>.container-xl { - padding-right: 0; - padding-left: 0 - } -} - -@media(min-width: 768px) { - .navbar-expand-md { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start - } - - .navbar-expand-md .navbar-nav { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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-sm, - .navbar-expand-md>.container-md, - .navbar-expand-md>.container-lg, - .navbar-expand-md>.container-xl { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap - } - - .navbar-expand-md .navbar-nav-scroll { - overflow: visible - } - - .navbar-expand-md .navbar-collapse { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto - } - - .navbar-expand-md .navbar-toggler { - display: none - } -} - -@media(max-width: 991.98px) { - - .navbar-expand-lg>.container, - .navbar-expand-lg>.container-fluid, - .navbar-expand-lg>.container-sm, - .navbar-expand-lg>.container-md, - .navbar-expand-lg>.container-lg, - .navbar-expand-lg>.container-xl { - padding-right: 0; - padding-left: 0 - } -} - -@media(min-width: 992px) { - .navbar-expand-lg { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start - } - - .navbar-expand-lg .navbar-nav { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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-sm, - .navbar-expand-lg>.container-md, - .navbar-expand-lg>.container-lg, - .navbar-expand-lg>.container-xl { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap - } - - .navbar-expand-lg .navbar-nav-scroll { - overflow: visible - } - - .navbar-expand-lg .navbar-collapse { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - 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-sm, - .navbar-expand-xl>.container-md, - .navbar-expand-xl>.container-lg, - .navbar-expand-xl>.container-xl { - padding-right: 0; - padding-left: 0 - } -} - -@media(min-width: 1200px) { - .navbar-expand-xl { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start - } - - .navbar-expand-xl .navbar-nav { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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-sm, - .navbar-expand-xl>.container-md, - .navbar-expand-xl>.container-lg, - .navbar-expand-xl>.container-xl { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap - } - - .navbar-expand-xl .navbar-nav-scroll { - overflow: visible - } - - .navbar-expand-xl .navbar-collapse { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto - } - - .navbar-expand-xl .navbar-toggler { - display: none - } -} - -.navbar-expand { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start -} - -.navbar-expand>.container, -.navbar-expand>.container-fluid, -.navbar-expand>.container-sm, -.navbar-expand>.container-md, -.navbar-expand>.container-lg, -.navbar-expand>.container-xl { - padding-right: 0; - padding-left: 0 -} - -.navbar-expand .navbar-nav { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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-sm, -.navbar-expand>.container-md, -.navbar-expand>.container-lg, -.navbar-expand>.container-xl { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap -} - -.navbar-expand .navbar-nav-scroll { - overflow: visible -} - -.navbar-expand .navbar-collapse { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto -} - -.navbar-expand .navbar-toggler { - display: none -} - -.navbar-light .navbar-brand { - color: rgba(0, 0, 0, .9) -} - -.navbar-light .navbar-brand:hover, -.navbar-light .navbar-brand:focus { - color: rgba(0, 0, 0, .9) -} - -.navbar-light .navbar-nav .nav-link { - color: rgba(0, 0, 0, .5) -} - -.navbar-light .navbar-nav .nav-link:hover, -.navbar-light .navbar-nav .nav-link:focus { - color: rgba(0, 0, 0, .7) -} - -.navbar-light .navbar-nav .nav-link.disabled { - color: rgba(0, 0, 0, .3) -} - -.navbar-light .navbar-nav .show>.nav-link, -.navbar-light .navbar-nav .active>.nav-link, -.navbar-light .navbar-nav .nav-link.show, -.navbar-light .navbar-nav .nav-link.active { - 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,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' 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 { - color: rgba(0, 0, 0, .9) -} - -.navbar-light .navbar-text a:hover, -.navbar-light .navbar-text a:focus { - color: rgba(0, 0, 0, .9) -} - -.navbar-dark .navbar-brand { - color: #fff -} - -.navbar-dark .navbar-brand:hover, -.navbar-dark .navbar-brand:focus { - color: #fff -} - -.navbar-dark .navbar-nav .nav-link { - color: rgba(255, 255, 255, .5) -} - -.navbar-dark .navbar-nav .nav-link:hover, -.navbar-dark .navbar-nav .nav-link:focus { - color: rgba(255, 255, 255, .75) -} - -.navbar-dark .navbar-nav .nav-link.disabled { - color: rgba(255, 255, 255, .25) -} - -.navbar-dark .navbar-nav .show>.nav-link, -.navbar-dark .navbar-nav .active>.nav-link, -.navbar-dark .navbar-nav .nav-link.show, -.navbar-dark .navbar-nav .nav-link.active { - color: #fff -} - -.navbar-dark .navbar-toggler { - color: rgba(255, 255, 255, .5); - border-color: rgba(255, 255, 255, .1) -} - -.navbar-dark .navbar-toggler-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") -} - -.navbar-dark .navbar-text { - color: rgba(255, 255, 255, .5) -} - -.navbar-dark .navbar-text a { - color: #fff -} - -.navbar-dark .navbar-text a:hover, -.navbar-dark .navbar-text a:focus { - color: #fff -} - -.card { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - 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(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px) -} - -.card>.list-group:last-child { - border-bottom-width: 0; - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px) -} - -.card>.card-header+.list-group, -.card>.list-group+.card-footer { - border-top: 0 -} - -.card-body { - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - min-height: 1px; - padding: 1.25rem -} - -.card-title { - margin-bottom: .75rem -} - -.card-subtitle { - margin-top: -0.375rem; - margin-bottom: 0 -} - -.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(0.25rem - 1px) calc(0.25rem - 1px) 0 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(0.25rem - 1px) calc(0.25rem - 1px) -} - -.card-header-tabs { - margin-right: -0.625rem; - margin-bottom: -0.75rem; - margin-left: -0.625rem; - border-bottom: 0 -} - -.card-header-pills { - margin-right: -0.625rem; - margin-left: -0.625rem -} - -.card-img-overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: 1.25rem; - border-radius: calc(0.25rem - 1px) -} - -.card-img, -.card-img-top, -.card-img-bottom { - -ms-flex-negative: 0; - flex-shrink: 0; - width: 100% -} - -.card-img, -.card-img-top { - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px) -} - -.card-img, -.card-img-bottom { - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px) -} - -.card-deck .card { - margin-bottom: 15px -} - -@media(min-width: 576px) { - .card-deck { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - margin-right: -15px; - margin-left: -15px - } - - .card-deck .card { - -webkit-box-flex: 1; - -ms-flex: 1 0 0%; - flex: 1 0 0%; - margin-right: 15px; - margin-bottom: 0; - margin-left: 15px - } -} - -.card-group>.card { - margin-bottom: 15px -} - -@media(min-width: 576px) { - .card-group { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap - } - - .card-group>.card { - -webkit-box-flex: 1; - -ms-flex: 1 0 0%; - 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-img-top, - .card-group>.card:not(:last-child) .card-header { - border-top-right-radius: 0 - } - - .card-group>.card:not(:last-child) .card-img-bottom, - .card-group>.card:not(:last-child) .card-footer { - 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-img-top, - .card-group>.card:not(:first-child) .card-header { - border-top-left-radius: 0 - } - - .card-group>.card:not(:first-child) .card-img-bottom, - .card-group>.card:not(:first-child) .card-footer { - border-bottom-left-radius: 0 - } -} - -.card-columns .card { - margin-bottom: .75rem -} - -@media(min-width: 576px) { - .card-columns { - -webkit-column-count: 3; - -moz-column-count: 3; - column-count: 3; - -webkit-column-gap: 1.25rem; - -moz-column-gap: 1.25rem; - column-gap: 1.25rem; - orphans: 1; - widows: 1 - } - - .card-columns .card { - display: inline-block; - width: 100% - } -} - -.accordion { - overflow-anchor: none -} - -.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 { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - padding: .75rem 1rem; - margin-bottom: 1rem; - list-style: none; - background-color: #e9ecef; - border-radius: .25rem -} - -.breadcrumb-item+.breadcrumb-item { - padding-left: .5rem -} - -.breadcrumb-item+.breadcrumb-item::before { - float: left; - padding-right: .5rem; - color: #6c757d; - content: "/" -} - -.breadcrumb-item+.breadcrumb-item:hover::before { - text-decoration: underline -} - -.breadcrumb-item+.breadcrumb-item:hover::before { - text-decoration: none -} - -.breadcrumb-item.active { - color: #6c757d -} - -.pagination { - display: -webkit-box; - display: -ms-flexbox; - 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; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); - 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: 0.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; - -webkit-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - .badge { - -webkit-transition: none; - transition: none - } -} - -a.badge:hover, -a.badge:focus { - 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:hover, -a.badge-primary:focus { - color: #fff; - background-color: #0062cc -} - -a.badge-primary:focus, -a.badge-primary.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); - box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) -} - -.badge-secondary { - color: #fff; - background-color: #6c757d -} - -a.badge-secondary:hover, -a.badge-secondary:focus { - color: #fff; - background-color: #545b62 -} - -a.badge-secondary:focus, -a.badge-secondary.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(108, 117, 125, .5); - box-shadow: 0 0 0 .2rem rgba(108, 117, 125, .5) -} - -.badge-success { - color: #fff; - background-color: #28a745 -} - -a.badge-success:hover, -a.badge-success:focus { - color: #fff; - background-color: #1e7e34 -} - -a.badge-success:focus, -a.badge-success.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); - box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) -} - -.badge-info { - color: #fff; - background-color: #17a2b8 -} - -a.badge-info:hover, -a.badge-info:focus { - color: #fff; - background-color: #117a8b -} - -a.badge-info:focus, -a.badge-info.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); - box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) -} - -.badge-warning { - color: #212529; - background-color: #ffc107 -} - -a.badge-warning:hover, -a.badge-warning:focus { - color: #212529; - background-color: #d39e00 -} - -a.badge-warning:focus, -a.badge-warning.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); - box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) -} - -.badge-danger { - color: #fff; - background-color: #dc3545 -} - -a.badge-danger:hover, -a.badge-danger:focus { - color: #fff; - background-color: #bd2130 -} - -a.badge-danger:focus, -a.badge-danger.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); - box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) -} - -.badge-light { - color: #212529; - background-color: #f8f9fa -} - -a.badge-light:hover, -a.badge-light:focus { - color: #212529; - background-color: #dae0e5 -} - -a.badge-light:focus, -a.badge-light.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); - box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) -} - -.badge-dark { - color: #fff; - background-color: #343a40 -} - -a.badge-dark:hover, -a.badge-dark:focus { - color: #fff; - background-color: #1d2124 -} - -a.badge-dark:focus, -a.badge-dark.focus { - outline: 0; - -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); - 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: 576px) { - .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 rgba(0, 0, 0, 0); - 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; - z-index: 2; - 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 -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 1rem 0 - } - - to { - background-position: 0 0 - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 1rem 0 - } - - to { - background-position: 0 0 - } -} - -.progress { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - height: 1rem; - overflow: hidden; - line-height: 0; - font-size: 0.75rem; - background-color: #e9ecef; - border-radius: .25rem -} - -.progress-bar { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - overflow: hidden; - color: #fff; - text-align: center; - white-space: nowrap; - background-color: #007bff; - -webkit-transition: width .6s ease; - transition: width .6s ease -} - -@media(prefers-reduced-motion: reduce) { - .progress-bar { - -webkit-transition: none; - transition: none - } -} - -.progress-bar-striped { - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 1rem 1rem -} - -.progress-bar-animated { - -webkit-animation: 1s linear infinite progress-bar-stripes; - animation: 1s linear infinite progress-bar-stripes -} - -@media(prefers-reduced-motion: reduce) { - .progress-bar-animated { - -webkit-animation: none; - animation: none - } -} - -.media { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start -} - -.media-body { - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1 -} - -.list-group { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - 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:hover, -.list-group-item-action:focus { - 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 { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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: 576px) { - .list-group-horizontal-sm { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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: 768px) { - .list-group-horizontal-md { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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: 992px) { - .list-group-horizontal-lg { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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 { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - 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:hover, -.list-group-item-primary.list-group-item-action:focus { - 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:hover, -.list-group-item-secondary.list-group-item-action:focus { - 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:hover, -.list-group-item-success.list-group-item-action:focus { - 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:hover, -.list-group-item-info.list-group-item-action:focus { - 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:hover, -.list-group-item-warning.list-group-item-action:focus { - 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:hover, -.list-group-item-danger.list-group-item-action:focus { - 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:hover, -.list-group-item-light.list-group-item-action:focus { - 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:hover, -.list-group-item-dark.list-group-item-action:focus { - 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):hover, -.close:not(:disabled):not(.disabled):focus { - opacity: .75 -} - -button.close { - padding: 0; - background-color: rgba(0, 0, 0, 0); - border: 0 -} - -a.close.disabled { - pointer-events: none -} - -.toast { - -ms-flex-preferred-size: 350px; - flex-basis: 350px; - max-width: 350px; - font-size: 0.875rem; - background-color: rgba(255, 255, 255, .85); - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, .1); - -webkit-box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .1); - box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .1); - 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: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: .25rem .75rem; - color: #6c757d; - background-color: rgba(255, 255, 255, .85); - background-clip: padding-box; - border-bottom: 1px solid rgba(0, 0, 0, .05); - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px) -} - -.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 { - -webkit-transition: -webkit-transform .3s ease-out; - transition: -webkit-transform .3s ease-out; - transition: transform .3s ease-out; - transition: transform .3s ease-out, -webkit-transform .3s ease-out; - -webkit-transform: translate(0, -50px); - transform: translate(0, -50px) -} - -@media(prefers-reduced-motion: reduce) { - .modal.fade .modal-dialog { - -webkit-transition: none; - transition: none - } -} - -.modal.show .modal-dialog { - -webkit-transform: none; - transform: none -} - -.modal.modal-static .modal-dialog { - -webkit-transform: scale(1.02); - transform: scale(1.02) -} - -.modal-dialog-scrollable { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - max-height: calc(100% - 1rem) -} - -.modal-dialog-scrollable .modal-content { - max-height: calc(100vh - 1rem); - overflow: hidden -} - -.modal-dialog-scrollable .modal-header, -.modal-dialog-scrollable .modal-footer { - -ms-flex-negative: 0; - flex-shrink: 0 -} - -.modal-dialog-scrollable .modal-body { - overflow-y: auto -} - -.modal-dialog-centered { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - min-height: calc(100% - 1rem) -} - -.modal-dialog-centered::before { - display: block; - height: calc(100vh - 1rem); - height: -webkit-min-content; - height: -moz-min-content; - height: min-content; - content: "" -} - -.modal-dialog-centered.modal-dialog-scrollable { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -ms-flex-pack: center; - 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: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - 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: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - padding: 1rem 1rem; - border-bottom: 1px solid #dee2e6; - border-top-left-radius: calc(0.3rem - 1px); - border-top-right-radius: calc(0.3rem - 1px) -} - -.modal-header .close { - padding: 1rem 1rem; - margin: -1rem -1rem -1rem auto -} - -.modal-title { - margin-bottom: 0; - line-height: 1.5 -} - -.modal-body { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - padding: 1rem -} - -.modal-footer { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - padding: .75rem; - border-top: 1px solid #dee2e6; - border-bottom-right-radius: calc(0.3rem - 1px); - border-bottom-left-radius: calc(0.3rem - 1px) -} - -.modal-footer>* { - margin: .25rem -} - -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll -} - -@media(min-width: 576px) { - .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: -webkit-min-content; - height: -moz-min-content; - height: min-content - } - - .modal-sm { - max-width: 300px - } -} - -@media(min-width: 992px) { - - .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", "Liberation 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: 0.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: rgba(0, 0, 0, 0); - border-style: solid -} - -.bs-tooltip-top, -.bs-tooltip-auto[x-placement^=top] { - padding: .4rem 0 -} - -.bs-tooltip-top .arrow, -.bs-tooltip-auto[x-placement^=top] .arrow { - bottom: 0 -} - -.bs-tooltip-top .arrow::before, -.bs-tooltip-auto[x-placement^=top] .arrow::before { - top: 0; - border-width: .4rem .4rem 0; - border-top-color: #000 -} - -.bs-tooltip-right, -.bs-tooltip-auto[x-placement^=right] { - padding: 0 .4rem -} - -.bs-tooltip-right .arrow, -.bs-tooltip-auto[x-placement^=right] .arrow { - left: 0; - width: .4rem; - height: .8rem -} - -.bs-tooltip-right .arrow::before, -.bs-tooltip-auto[x-placement^=right] .arrow::before { - right: 0; - border-width: .4rem .4rem .4rem 0; - border-right-color: #000 -} - -.bs-tooltip-bottom, -.bs-tooltip-auto[x-placement^=bottom] { - padding: .4rem 0 -} - -.bs-tooltip-bottom .arrow, -.bs-tooltip-auto[x-placement^=bottom] .arrow { - top: 0 -} - -.bs-tooltip-bottom .arrow::before, -.bs-tooltip-auto[x-placement^=bottom] .arrow::before { - bottom: 0; - border-width: 0 .4rem .4rem; - border-bottom-color: #000 -} - -.bs-tooltip-left, -.bs-tooltip-auto[x-placement^=left] { - padding: 0 .4rem -} - -.bs-tooltip-left .arrow, -.bs-tooltip-auto[x-placement^=left] .arrow { - right: 0; - width: .4rem; - height: .8rem -} - -.bs-tooltip-left .arrow::before, -.bs-tooltip-auto[x-placement^=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 { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: block; - max-width: 276px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation 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: 0.875rem; - word-wrap: break-word; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: .3rem -} - -.popover .arrow { - position: absolute; - display: block; - width: 1rem; - height: .5rem; - margin: 0 .3rem -} - -.popover .arrow::before, -.popover .arrow::after { - position: absolute; - display: block; - content: ""; - border-color: rgba(0, 0, 0, 0); - border-style: solid -} - -.bs-popover-top, -.bs-popover-auto[x-placement^=top] { - margin-bottom: .5rem -} - -.bs-popover-top>.arrow, -.bs-popover-auto[x-placement^=top]>.arrow { - bottom: calc(-0.5rem - 1px) -} - -.bs-popover-top>.arrow::before, -.bs-popover-auto[x-placement^=top]>.arrow::before { - bottom: 0; - border-width: .5rem .5rem 0; - border-top-color: rgba(0, 0, 0, .25) -} - -.bs-popover-top>.arrow::after, -.bs-popover-auto[x-placement^=top]>.arrow::after { - bottom: 1px; - border-width: .5rem .5rem 0; - border-top-color: #fff -} - -.bs-popover-right, -.bs-popover-auto[x-placement^=right] { - margin-left: .5rem -} - -.bs-popover-right>.arrow, -.bs-popover-auto[x-placement^=right]>.arrow { - left: calc(-0.5rem - 1px); - width: .5rem; - height: 1rem; - margin: .3rem 0 -} - -.bs-popover-right>.arrow::before, -.bs-popover-auto[x-placement^=right]>.arrow::before { - left: 0; - border-width: .5rem .5rem .5rem 0; - border-right-color: rgba(0, 0, 0, .25) -} - -.bs-popover-right>.arrow::after, -.bs-popover-auto[x-placement^=right]>.arrow::after { - left: 1px; - border-width: .5rem .5rem .5rem 0; - border-right-color: #fff -} - -.bs-popover-bottom, -.bs-popover-auto[x-placement^=bottom] { - margin-top: .5rem -} - -.bs-popover-bottom>.arrow, -.bs-popover-auto[x-placement^=bottom]>.arrow { - top: calc(-0.5rem - 1px) -} - -.bs-popover-bottom>.arrow::before, -.bs-popover-auto[x-placement^=bottom]>.arrow::before { - top: 0; - border-width: 0 .5rem .5rem .5rem; - border-bottom-color: rgba(0, 0, 0, .25) -} - -.bs-popover-bottom>.arrow::after, -.bs-popover-auto[x-placement^=bottom]>.arrow::after { - top: 1px; - border-width: 0 .5rem .5rem .5rem; - border-bottom-color: #fff -} - -.bs-popover-bottom .popover-header::before, -.bs-popover-auto[x-placement^=bottom] .popover-header::before { - position: absolute; - top: 0; - left: 50%; - display: block; - width: 1rem; - margin-left: -0.5rem; - content: ""; - border-bottom: 1px solid #f7f7f7 -} - -.bs-popover-left, -.bs-popover-auto[x-placement^=left] { - margin-right: .5rem -} - -.bs-popover-left>.arrow, -.bs-popover-auto[x-placement^=left]>.arrow { - right: calc(-0.5rem - 1px); - width: .5rem; - height: 1rem; - margin: .3rem 0 -} - -.bs-popover-left>.arrow::before, -.bs-popover-auto[x-placement^=left]>.arrow::before { - right: 0; - border-width: .5rem 0 .5rem .5rem; - border-left-color: rgba(0, 0, 0, .25) -} - -.bs-popover-left>.arrow::after, -.bs-popover-auto[x-placement^=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(0.3rem - 1px); - border-top-right-radius: calc(0.3rem - 1px) -} - -.popover-header:empty { - display: none -} - -.popover-body { - padding: .5rem .75rem; - color: #212529 -} - -.carousel { - position: relative -} - -.carousel.pointer-event { - -ms-touch-action: pan-y; - 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%; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-transition: -webkit-transform .6s ease-in-out; - transition: -webkit-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out -} - -@media(prefers-reduced-motion: reduce) { - .carousel-item { - -webkit-transition: none; - transition: none - } -} - -.carousel-item.active, -.carousel-item-next, -.carousel-item-prev { - display: block -} - -.carousel-item-next:not(.carousel-item-left), -.active.carousel-item-right { - -webkit-transform: translateX(100%); - transform: translateX(100%) -} - -.carousel-item-prev:not(.carousel-item-right), -.active.carousel-item-left { - -webkit-transform: translateX(-100%); - transform: translateX(-100%) -} - -.carousel-fade .carousel-item { - opacity: 0; - -webkit-transition-property: opacity; - transition-property: opacity; - -webkit-transform: none; - transform: none -} - -.carousel-fade .carousel-item.active, -.carousel-fade .carousel-item-next.carousel-item-left, -.carousel-fade .carousel-item-prev.carousel-item-right { - z-index: 1; - opacity: 1 -} - -.carousel-fade .active.carousel-item-left, -.carousel-fade .active.carousel-item-right { - z-index: 0; - opacity: 0; - -webkit-transition: opacity 0s .6s; - transition: opacity 0s .6s -} - -@media(prefers-reduced-motion: reduce) { - - .carousel-fade .active.carousel-item-left, - .carousel-fade .active.carousel-item-right { - -webkit-transition: none; - transition: none - } -} - -.carousel-control-prev, -.carousel-control-next { - position: absolute; - top: 0; - bottom: 0; - z-index: 1; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - width: 15%; - padding: 0; - color: #fff; - text-align: center; - background: none; - border: 0; - opacity: .5; - -webkit-transition: opacity .15s ease; - transition: opacity .15s ease -} - -@media(prefers-reduced-motion: reduce) { - - .carousel-control-prev, - .carousel-control-next { - -webkit-transition: none; - transition: none - } -} - -.carousel-control-prev:hover, -.carousel-control-prev:focus, -.carousel-control-next:hover, -.carousel-control-next:focus { - color: #fff; - text-decoration: none; - outline: 0; - opacity: .9 -} - -.carousel-control-prev { - left: 0 -} - -.carousel-control-next { - right: 0 -} - -.carousel-control-prev-icon, -.carousel-control-next-icon { - display: inline-block; - width: 20px; - height: 20px; - background: 50%/100% 100% no-repeat -} - -.carousel-control-prev-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 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,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 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: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding-left: 0; - margin-right: 15%; - margin-left: 15%; - list-style: none -} - -.carousel-indicators li { - -webkit-box-sizing: content-box; - box-sizing: content-box; - -webkit-box-flex: 0; - -ms-flex: 0 1 auto; - 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 rgba(0, 0, 0, 0); - border-bottom: 10px solid rgba(0, 0, 0, 0); - opacity: .5; - -webkit-transition: opacity .6s ease; - transition: opacity .6s ease -} - -@media(prefers-reduced-motion: reduce) { - .carousel-indicators li { - -webkit-transition: none; - 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 -} - -@-webkit-keyframes spinner-border { - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg) - } -} - -@keyframes spinner-border { - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg) - } -} - -.spinner-border { - display: inline-block; - width: 2rem; - height: 2rem; - vertical-align: -0.125em; - border: .25em solid currentColor; - border-right-color: rgba(0, 0, 0, 0); - border-radius: 50%; - -webkit-animation: .75s linear infinite spinner-border; - animation: .75s linear infinite spinner-border -} - -.spinner-border-sm { - width: 1rem; - height: 1rem; - border-width: .2em -} - -@-webkit-keyframes spinner-grow { - 0% { - -webkit-transform: scale(0); - transform: scale(0) - } - - 50% { - opacity: 1; - -webkit-transform: none; - transform: none - } -} - -@keyframes spinner-grow { - 0% { - -webkit-transform: scale(0); - transform: scale(0) - } - - 50% { - opacity: 1; - -webkit-transform: none; - transform: none - } -} - -.spinner-grow { - display: inline-block; - width: 2rem; - height: 2rem; - vertical-align: -0.125em; - background-color: currentColor; - border-radius: 50%; - opacity: 0; - -webkit-animation: .75s linear infinite spinner-grow; - animation: .75s linear infinite spinner-grow -} - -.spinner-grow-sm { - width: 1rem; - height: 1rem -} - -@media(prefers-reduced-motion: reduce) { - - .spinner-border, - .spinner-grow { - -webkit-animation-duration: 1.5s; - animation-duration: 1.5s - } -} - -.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:hover, -a.bg-primary:focus, -button.bg-primary:hover, -button.bg-primary:focus { - background-color: #0062cc !important -} - -.bg-secondary { - background-color: #6c757d !important -} - -a.bg-secondary:hover, -a.bg-secondary:focus, -button.bg-secondary:hover, -button.bg-secondary:focus { - background-color: #545b62 !important -} - -.bg-success { - background-color: #28a745 !important -} - -a.bg-success:hover, -a.bg-success:focus, -button.bg-success:hover, -button.bg-success:focus { - background-color: #1e7e34 !important -} - -.bg-info { - background-color: #17a2b8 !important -} - -a.bg-info:hover, -a.bg-info:focus, -button.bg-info:hover, -button.bg-info:focus { - background-color: #117a8b !important -} - -.bg-warning { - background-color: #ffc107 !important -} - -a.bg-warning:hover, -a.bg-warning:focus, -button.bg-warning:hover, -button.bg-warning:focus { - background-color: #d39e00 !important -} - -.bg-danger { - background-color: #dc3545 !important -} - -a.bg-danger:hover, -a.bg-danger:focus, -button.bg-danger:hover, -button.bg-danger:focus { - background-color: #bd2130 !important -} - -.bg-light { - background-color: #f8f9fa !important -} - -a.bg-light:hover, -a.bg-light:focus, -button.bg-light:hover, -button.bg-light:focus { - background-color: #dae0e5 !important -} - -.bg-dark { - background-color: #343a40 !important -} - -a.bg-dark:hover, -a.bg-dark:focus, -button.bg-dark:hover, -button.bg-dark:focus { - background-color: #1d2124 !important -} - -.bg-white { - background-color: #fff !important -} - -.bg-transparent { - background-color: rgba(0, 0, 0, 0) !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; - border-top-right-radius: .25rem !important -} - -.rounded-right { - border-top-right-radius: .25rem !important; - border-bottom-right-radius: .25rem !important -} - -.rounded-bottom { - border-bottom-right-radius: .25rem !important; - border-bottom-left-radius: .25rem !important -} - -.rounded-left { - border-top-left-radius: .25rem !important; - border-bottom-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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important -} - -.d-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important -} - -@media(min-width: 576px) { - .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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important - } - - .d-sm-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important - } -} - -@media(min-width: 768px) { - .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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important - } - - .d-md-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important - } -} - -@media(min-width: 992px) { - .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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important - } - - .d-lg-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - 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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important - } - - .d-xl-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - 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: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important - } - - .d-print-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - 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 iframe, -.embed-responsive embed, -.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.85714286% -} - -.embed-responsive-16by9::before { - padding-top: 56.25% -} - -.embed-responsive-4by3::before { - padding-top: 75% -} - -.embed-responsive-1by1::before { - padding-top: 100% -} - -.flex-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important -} - -.flex-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important -} - -.flex-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important -} - -.flex-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important -} - -.flex-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important -} - -.flex-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important -} - -.flex-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important -} - -.flex-fill { - -webkit-box-flex: 1 !important; - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important -} - -.flex-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important -} - -.flex-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important -} - -.flex-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important -} - -.flex-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important -} - -.justify-content-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important -} - -.justify-content-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important -} - -.justify-content-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important -} - -.justify-content-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important -} - -.justify-content-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important -} - -.align-items-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important -} - -.align-items-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important -} - -.align-items-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important -} - -.align-items-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important -} - -.align-items-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important -} - -.align-content-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important -} - -.align-content-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important -} - -.align-content-center { - -ms-flex-line-pack: center !important; - align-content: center !important -} - -.align-content-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important -} - -.align-content-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important -} - -.align-content-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important -} - -.align-self-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important -} - -.align-self-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important -} - -.align-self-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important -} - -.align-self-center { - -ms-flex-item-align: center !important; - align-self: center !important -} - -.align-self-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important -} - -.align-self-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important -} - -@media(min-width: 576px) { - .flex-sm-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important - } - - .flex-sm-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important - } - - .flex-sm-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important - } - - .flex-sm-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important - } - - .flex-sm-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important - } - - .flex-sm-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important - } - - .flex-sm-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important - } - - .flex-sm-fill { - -webkit-box-flex: 1 !important; - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important - } - - .flex-sm-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important - } - - .flex-sm-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important - } - - .flex-sm-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important - } - - .flex-sm-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important - } - - .justify-content-sm-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important - } - - .justify-content-sm-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important - } - - .justify-content-sm-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important - } - - .justify-content-sm-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important - } - - .justify-content-sm-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important - } - - .align-items-sm-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important - } - - .align-items-sm-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important - } - - .align-items-sm-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important - } - - .align-items-sm-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important - } - - .align-items-sm-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important - } - - .align-content-sm-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important - } - - .align-content-sm-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important - } - - .align-content-sm-center { - -ms-flex-line-pack: center !important; - align-content: center !important - } - - .align-content-sm-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important - } - - .align-content-sm-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important - } - - .align-content-sm-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important - } - - .align-self-sm-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important - } - - .align-self-sm-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important - } - - .align-self-sm-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important - } - - .align-self-sm-center { - -ms-flex-item-align: center !important; - align-self: center !important - } - - .align-self-sm-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important - } - - .align-self-sm-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important - } -} - -@media(min-width: 768px) { - .flex-md-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important - } - - .flex-md-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important - } - - .flex-md-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important - } - - .flex-md-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important - } - - .flex-md-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important - } - - .flex-md-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important - } - - .flex-md-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important - } - - .flex-md-fill { - -webkit-box-flex: 1 !important; - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important - } - - .flex-md-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important - } - - .flex-md-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important - } - - .flex-md-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important - } - - .flex-md-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important - } - - .justify-content-md-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important - } - - .justify-content-md-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important - } - - .justify-content-md-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important - } - - .justify-content-md-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important - } - - .justify-content-md-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important - } - - .align-items-md-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important - } - - .align-items-md-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important - } - - .align-items-md-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important - } - - .align-items-md-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important - } - - .align-items-md-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important - } - - .align-content-md-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important - } - - .align-content-md-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important - } - - .align-content-md-center { - -ms-flex-line-pack: center !important; - align-content: center !important - } - - .align-content-md-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important - } - - .align-content-md-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important - } - - .align-content-md-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important - } - - .align-self-md-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important - } - - .align-self-md-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important - } - - .align-self-md-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important - } - - .align-self-md-center { - -ms-flex-item-align: center !important; - align-self: center !important - } - - .align-self-md-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important - } - - .align-self-md-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important - } -} - -@media(min-width: 992px) { - .flex-lg-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important - } - - .flex-lg-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important - } - - .flex-lg-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important - } - - .flex-lg-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important - } - - .flex-lg-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important - } - - .flex-lg-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important - } - - .flex-lg-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important - } - - .flex-lg-fill { - -webkit-box-flex: 1 !important; - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important - } - - .flex-lg-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important - } - - .flex-lg-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important - } - - .flex-lg-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important - } - - .flex-lg-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important - } - - .justify-content-lg-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important - } - - .justify-content-lg-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important - } - - .justify-content-lg-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important - } - - .justify-content-lg-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important - } - - .justify-content-lg-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important - } - - .align-items-lg-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important - } - - .align-items-lg-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important - } - - .align-items-lg-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important - } - - .align-items-lg-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important - } - - .align-items-lg-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important - } - - .align-content-lg-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important - } - - .align-content-lg-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important - } - - .align-content-lg-center { - -ms-flex-line-pack: center !important; - align-content: center !important - } - - .align-content-lg-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important - } - - .align-content-lg-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important - } - - .align-content-lg-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important - } - - .align-self-lg-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important - } - - .align-self-lg-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important - } - - .align-self-lg-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important - } - - .align-self-lg-center { - -ms-flex-item-align: center !important; - align-self: center !important - } - - .align-self-lg-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important - } - - .align-self-lg-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important - } -} - -@media(min-width: 1200px) { - .flex-xl-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important - } - - .flex-xl-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important - } - - .flex-xl-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important - } - - .flex-xl-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important - } - - .flex-xl-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important - } - - .flex-xl-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important - } - - .flex-xl-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important - } - - .flex-xl-fill { - -webkit-box-flex: 1 !important; - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important - } - - .flex-xl-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important - } - - .flex-xl-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important - } - - .flex-xl-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important - } - - .flex-xl-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important - } - - .justify-content-xl-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important - } - - .justify-content-xl-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important - } - - .justify-content-xl-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important - } - - .justify-content-xl-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important - } - - .justify-content-xl-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important - } - - .align-items-xl-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important - } - - .align-items-xl-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important - } - - .align-items-xl-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important - } - - .align-items-xl-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important - } - - .align-items-xl-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important - } - - .align-content-xl-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important - } - - .align-content-xl-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important - } - - .align-content-xl-center { - -ms-flex-line-pack: center !important; - align-content: center !important - } - - .align-content-xl-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important - } - - .align-content-xl-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important - } - - .align-content-xl-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important - } - - .align-self-xl-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important - } - - .align-self-xl-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important - } - - .align-self-xl-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important - } - - .align-self-xl-center { - -ms-flex-item-align: center !important; - align-self: center !important - } - - .align-self-xl-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important - } - - .align-self-xl-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important - } -} - -.float-left { - float: left !important -} - -.float-right { - float: right !important -} - -.float-none { - float: none !important -} - -@media(min-width: 576px) { - .float-sm-left { - float: left !important - } - - .float-sm-right { - float: right !important - } - - .float-sm-none { - float: none !important - } -} - -@media(min-width: 768px) { - .float-md-left { - float: left !important - } - - .float-md-right { - float: right !important - } - - .float-md-none { - float: none !important - } -} - -@media(min-width: 992px) { - .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 { - -webkit-user-select: all !important; - -moz-user-select: all !important; - -ms-user-select: all !important; - user-select: all !important -} - -.user-select-auto { - -webkit-user-select: auto !important; - -moz-user-select: auto !important; - -ms-user-select: auto !important; - user-select: auto !important -} - -.user-select-none { - -webkit-user-select: none !important; - -moz-user-select: none !important; - -ms-user-select: none !important; - 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 { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1030 -} - -.fixed-bottom { - position: fixed; - right: 0; - bottom: 0; - left: 0; - z-index: 1030 -} - -@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 { - -webkit-box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important; - box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important -} - -.shadow { - -webkit-box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15) !important; - box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15) !important -} - -.shadow-lg { - -webkit-box-shadow: 0 1rem 3rem rgba(0, 0, 0, .175) !important; - box-shadow: 0 1rem 3rem rgba(0, 0, 0, .175) !important -} - -.shadow-none { - -webkit-box-shadow: none !important; - 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: -0.25rem !important -} - -.mt-n1, -.my-n1 { - margin-top: -0.25rem !important -} - -.mr-n1, -.mx-n1 { - margin-right: -0.25rem !important -} - -.mb-n1, -.my-n1 { - margin-bottom: -0.25rem !important -} - -.ml-n1, -.mx-n1 { - margin-left: -0.25rem !important -} - -.m-n2 { - margin: -0.5rem !important -} - -.mt-n2, -.my-n2 { - margin-top: -0.5rem !important -} - -.mr-n2, -.mx-n2 { - margin-right: -0.5rem !important -} - -.mb-n2, -.my-n2 { - margin-bottom: -0.5rem !important -} - -.ml-n2, -.mx-n2 { - margin-left: -0.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: 576px) { - .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: -0.25rem !important - } - - .mt-sm-n1, - .my-sm-n1 { - margin-top: -0.25rem !important - } - - .mr-sm-n1, - .mx-sm-n1 { - margin-right: -0.25rem !important - } - - .mb-sm-n1, - .my-sm-n1 { - margin-bottom: -0.25rem !important - } - - .ml-sm-n1, - .mx-sm-n1 { - margin-left: -0.25rem !important - } - - .m-sm-n2 { - margin: -0.5rem !important - } - - .mt-sm-n2, - .my-sm-n2 { - margin-top: -0.5rem !important - } - - .mr-sm-n2, - .mx-sm-n2 { - margin-right: -0.5rem !important - } - - .mb-sm-n2, - .my-sm-n2 { - margin-bottom: -0.5rem !important - } - - .ml-sm-n2, - .mx-sm-n2 { - margin-left: -0.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: 768px) { - .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: -0.25rem !important - } - - .mt-md-n1, - .my-md-n1 { - margin-top: -0.25rem !important - } - - .mr-md-n1, - .mx-md-n1 { - margin-right: -0.25rem !important - } - - .mb-md-n1, - .my-md-n1 { - margin-bottom: -0.25rem !important - } - - .ml-md-n1, - .mx-md-n1 { - margin-left: -0.25rem !important - } - - .m-md-n2 { - margin: -0.5rem !important - } - - .mt-md-n2, - .my-md-n2 { - margin-top: -0.5rem !important - } - - .mr-md-n2, - .mx-md-n2 { - margin-right: -0.5rem !important - } - - .mb-md-n2, - .my-md-n2 { - margin-bottom: -0.5rem !important - } - - .ml-md-n2, - .mx-md-n2 { - margin-left: -0.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: 992px) { - .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: -0.25rem !important - } - - .mt-lg-n1, - .my-lg-n1 { - margin-top: -0.25rem !important - } - - .mr-lg-n1, - .mx-lg-n1 { - margin-right: -0.25rem !important - } - - .mb-lg-n1, - .my-lg-n1 { - margin-bottom: -0.25rem !important - } - - .ml-lg-n1, - .mx-lg-n1 { - margin-left: -0.25rem !important - } - - .m-lg-n2 { - margin: -0.5rem !important - } - - .mt-lg-n2, - .my-lg-n2 { - margin-top: -0.5rem !important - } - - .mr-lg-n2, - .mx-lg-n2 { - margin-right: -0.5rem !important - } - - .mb-lg-n2, - .my-lg-n2 { - margin-bottom: -0.5rem !important - } - - .ml-lg-n2, - .mx-lg-n2 { - margin-left: -0.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: -0.25rem !important - } - - .mt-xl-n1, - .my-xl-n1 { - margin-top: -0.25rem !important - } - - .mr-xl-n1, - .mx-xl-n1 { - margin-right: -0.25rem !important - } - - .mb-xl-n1, - .my-xl-n1 { - margin-bottom: -0.25rem !important - } - - .ml-xl-n1, - .mx-xl-n1 { - margin-left: -0.25rem !important - } - - .m-xl-n2 { - margin: -0.5rem !important - } - - .mt-xl-n2, - .my-xl-n2 { - margin-top: -0.5rem !important - } - - .mr-xl-n2, - .mx-xl-n2 { - margin-right: -0.5rem !important - } - - .mb-xl-n2, - .my-xl-n2 { - margin-bottom: -0.5rem !important - } - - .ml-xl-n2, - .mx-xl-n2 { - margin-left: -0.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: rgba(0, 0, 0, 0) -} - -.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: 576px) { - .text-sm-left { - text-align: left !important - } - - .text-sm-right { - text-align: right !important - } - - .text-sm-center { - text-align: center !important - } -} - -@media(min-width: 768px) { - .text-md-left { - text-align: left !important - } - - .text-md-right { - text-align: right !important - } - - .text-md-center { - text-align: center !important - } -} - -@media(min-width: 992px) { - .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:hover, -a.text-primary:focus { - color: #0056b3 !important -} - -.text-secondary { - color: #6c757d !important -} - -a.text-secondary:hover, -a.text-secondary:focus { - color: #494f54 !important -} - -.text-success { - color: #28a745 !important -} - -a.text-success:hover, -a.text-success:focus { - color: #19692c !important -} - -.text-info { - color: #17a2b8 !important -} - -a.text-info:hover, -a.text-info:focus { - color: #0f6674 !important -} - -.text-warning { - color: #ffc107 !important -} - -a.text-warning:hover, -a.text-warning:focus { - color: #ba8b00 !important -} - -.text-danger { - color: #dc3545 !important -} - -a.text-danger:hover, -a.text-danger:focus { - color: #a71d2a !important -} - -.text-light { - color: #f8f9fa !important -} - -a.text-light:hover, -a.text-light:focus { - color: #cbd3da !important -} - -.text-dark { - color: #343a40 !important -} - -a.text-dark:hover, -a.text-dark:focus { - 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: rgba(255, 255, 255, .5) !important -} - -.text-hide { - font: 0/0 a; - color: rgba(0, 0, 0, 0); - text-shadow: none; - background-color: rgba(0, 0, 0, 0); - border: 0 -} - -.text-decoration-none { - text-decoration: none !important -} - -.text-break { - word-break: break-word !important; - word-wrap: break-word !important -} - -.text-reset { - color: inherit !important -} - -.visible { - visibility: visible !important -} - -.invisible { - visibility: hidden !important -} - -@media print { - - *, - *::before, - *::after { - text-shadow: none !important; - -webkit-box-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 - } - - pre, - blockquote { - border: 1px solid #adb5bd; - page-break-inside: avoid - } - - tr, - img { - page-break-inside: avoid - } - - p, - h2, - h3 { - orphans: 3; - widows: 3 - } - - h2, - h3 { - page-break-after: avoid - } - - @page { - size: a3 - } - - body { - min-width: 992px !important - } - - .container { - min-width: 992px !important - } - - .navbar { - display: none - } - - .badge { - border: 1px solid #000 - } - - .table { - border-collapse: collapse !important - } - - .table td, - .table th { - background-color: #fff !important - } - - .table-bordered th, - .table-bordered td { - border: 1px solid #dee2e6 !important - } - - .table-dark { - color: inherit - } - - .table-dark th, - .table-dark td, - .table-dark thead th, - .table-dark tbody+tbody { - border-color: #dee2e6 - } - - .table .thead-dark th { - color: inherit; - border-color: #dee2e6 - } -} - -.highlight table td { - padding: 5px -} - -.highlight table pre { - margin: 0 -} - -.highlight .cm { - color: #998; - font-style: italic -} - -.highlight .cp { - color: #999; - font-weight: bold -} - -.highlight .c1 { - color: #998; - font-style: italic -} - -.highlight .cs { - color: #999; - font-weight: bold; - font-style: italic -} - -.highlight .c, -.highlight .cd { - color: #998; - font-style: italic -} - -.highlight .err { - color: #a61717; - background-color: #e3d2d2 -} - -.highlight .gd { - color: #000; - background-color: #fdd -} - -.highlight .ge { - color: #000; - font-style: italic -} - -.highlight .gr { - color: #a00 -} - -.highlight .gh { - color: #999 -} - -.highlight .gi { - color: #000; - background-color: #dfd -} - -.highlight .go { - color: #888 -} - -.highlight .gp { - color: #555 -} - -.highlight .gs { - font-weight: bold -} - -.highlight .gu { - color: #aaa -} - -.highlight .gt { - color: #a00 -} - -.highlight .kc { - color: #000; - font-weight: bold -} - -.highlight .kd { - color: #000; - font-weight: bold -} - -.highlight .kn { - color: #000; - font-weight: bold -} - -.highlight .kp { - color: #000; - font-weight: bold -} - -.highlight .kr { - color: #000; - font-weight: bold -} - -.highlight .kt { - color: #458; - font-weight: bold -} - -.highlight .k, -.highlight .kv { - color: #000; - font-weight: bold -} - -.highlight .mf { - color: #099 -} - -.highlight .mh { - color: #099 -} - -.highlight .il { - color: #099 -} - -.highlight .mi { - color: #099 -} - -.highlight .mo { - color: #099 -} - -.highlight .m, -.highlight .mb, -.highlight .mx { - color: #099 -} - -.highlight .sb { - color: #d14 -} - -.highlight .sc { - color: #d14 -} - -.highlight .sd { - color: #d14 -} - -.highlight .s2 { - color: #d14 -} - -.highlight .se { - color: #d14 -} - -.highlight .sh { - color: #d14 -} - -.highlight .si { - color: #d14 -} - -.highlight .sx { - color: #d14 -} - -.highlight .sr { - color: #009926 -} - -.highlight .s1 { - color: #d14 -} - -.highlight .ss { - color: #990073 -} - -.highlight .s { - color: #d14 -} - -.highlight .na { - color: teal -} - -.highlight .bp { - color: #525252 -} - -.highlight .nb { - color: #0086b3 -} - -.highlight .nc { - color: #458; - font-weight: bold -} - -.highlight .no { - color: teal -} - -.highlight .nd { - color: #3c5d5d; - font-weight: bold -} - -.highlight .ni { - color: purple -} - -.highlight .ne { - color: #900; - font-weight: bold -} - -.highlight .nf { - color: #900; - font-weight: bold -} - -.highlight .nl { - color: #900; - font-weight: bold -} - -.highlight .nn { - color: #555 -} - -.highlight .nt { - color: navy -} - -.highlight .vc { - color: teal -} - -.highlight .vg { - color: teal -} - -.highlight .vi { - color: teal -} - -.highlight .nv { - color: teal -} - -.highlight .ow { - color: #000; - font-weight: bold -} - -.highlight .o { - color: #000; - font-weight: bold -} - -.highlight .n { - color: #000; - font-weight: bold -} - -.highlight .p { - color: #000; - font-weight: bold -} - -.highlight .w { - color: #bbb -} - -.highlight { - background-color: #f8f8f8 -} - -@font-face { - font-family: FreightSans; - font-weight: 700; - font-style: normal; - src: url("../fonts/FreightSans/freight-sans-bold.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-bold.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 700; - font-style: italic; - src: url("../fonts/FreightSans/freight-sans-bold-italic.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-bold-italic.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 500; - font-style: normal; - src: url("../fonts/FreightSans/freight-sans-medium.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-medium.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 500; - font-style: italic; - src: url("../fonts/FreightSans/freight-sans-medium-italic.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-medium-italic.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 100; - font-style: normal; - src: url("../fonts/FreightSans/freight-sans-light.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-light.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 100; - font-style: italic; - src: url("../fonts/FreightSans/freight-sans-light-italic.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-light-italic.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 400; - font-style: italic; - src: url("../fonts/FreightSans/freight-sans-book-italic.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-book-italic.woff") format("woff") -} - -@font-face { - font-family: FreightSans; - font-weight: 400; - font-style: normal; - src: url("../fonts/FreightSans/freight-sans-book.woff2") format("woff2"), url("../fonts/FreightSans/freight-sans-book.woff") format("woff") -} - -@font-face { - font-family: IBMPlexMono; - font-weight: 600; - font-style: normal; - src: url("../fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff") format("woff") -} - -/* @font-face { - font-family: IBMPlexMono; - font-weight: 600; - font-style: normal; - unicode-range: u+0020-007f; - src: local("IBMPlexMono"), url("../fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff") format("woff") -} */ - -@font-face { - font-family: IBMPlexMono; - font-weight: 500; - font-style: normal; - unicode-range: u+0020-007f; - src: local("IBMPlexMono"), url("../fonts/IBMPlexMono/IBMPlexMono-Medium.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-Medium.woff") format("woff") -} - -@font-face { - font-family: IBMPlexMono; - font-weight: 400; - font-style: normal; - unicode-range: u+0020-007f; - src: local("IBMPlexMono"), url("../fonts/IBMPlexMono/IBMPlexMono-Regular.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-Regular.woff") format("woff") -} - -@font-face { - font-family: IBMPlexMono; - font-weight: 300; - font-style: normal; - unicode-range: u+0020-007f; - src: local("IBMPlexMono"), url("../fonts/IBMPlexMono/IBMPlexMono-Light.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-Light.woff") format("woff") -} - -@font-face { - font-family: UCity; - font-weight: 600; - font-style: normal; - src: local("UCity"), url("../fonts/UCity/UCity-Semibold.woff2") format("woff2") -} - -@font-face { - font-family: UCity; - font-weight: 400; - font-style: normal; - src: local("UCity"), url("../fonts/UCity/UCity-Regular.woff2") format("woff2") -} - -@font-face { - font-family: UCity; - font-weight: 300; - font-style: normal; - src: local("UCity"), url("../fonts/UCity/UCity-Light.woff2") format("woff2") -} - -html { - position: relative; - min-height: 100%; - font-size: 12px -} - -@media screen and (min-width: 768px) { - html { - font-size: 16px - } -} - -* { - -webkit-box-sizing: border-box; - box-sizing: border-box -} - -body { - font-family: FreightSans, Helvetica Neue, Helvetica, Arial, sans-serif -} - -a:link, -a:visited, -a:hover { - text-decoration: none; - color: #de3412 -} - -a.with-right-arrow, -.btn.with-right-arrow { - padding-right: 1.375rem; - position: relative; - background-image: url("../images/chevron-right-orange.svg"); - background-size: 6px 13px; - background-position: center right 5px; - background-repeat: no-repeat -} - -@media screen and (min-width: 768px) { - - a.with-right-arrow, - .btn.with-right-arrow { - background-size: 8px 14px; - background-position: center right 12px; - padding-right: 2rem - } -} - -::-webkit-input-placeholder { - color: #de3412 -} - -::-moz-placeholder { - color: #de3412 -} - -:-ms-input-placeholder { - color: #de3412 -} - -:-moz-placeholder { - color: #de3412 -} - -.email-subscribe-form input.email { - color: #de3412; - border: none; - border-bottom: 1px solid #939393; - width: 100%; - background-color: rgba(0, 0, 0, 0); - outline: none; - font-size: 1.125rem; - letter-spacing: .25px; - line-height: 2.25rem -} - -.email-subscribe-form input[type=submit] { - position: absolute; - right: 0; - top: 10px; - height: 15px; - width: 15px; - background-image: url("../images/arrow-right-with-tail.svg"); - background-color: rgba(0, 0, 0, 0); - background-repeat: no-repeat; - background-size: 15px 15px; - background-position: center center; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - border: 0 -} - -.email-subscribe-form-fields-wrapper { - position: relative -} - -.anchorjs-link { - color: #6c6c6d !important -} - -@media screen and (min-width: 768px) { - .anchorjs-link:hover { - color: inherit; - text-decoration: none !important - } -} - -.pytorch-article #table-of-contents { - display: none -} - -.badge { - font-weight: inherit; - border-radius: 3px -} - -.badge-primary { - background-color: #de3412 -} - -.badge-secondary { - background-color: #979797 -} - -code, -kbd, -pre, -samp { - font-family: "Inconsolata", "IBMPlexMono", "SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", "monospace" -} - -code span, -kbd span, -pre span, -samp span { - font-family: "Inconsolata", "IBMPlexMono", "SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", "monospace" -} - -pre { - padding: 1.125rem; - background-color: #f3f4f7 -} - -pre code { - font-size: .875rem -} - -pre.highlight { - background-color: #f3f4f7; - line-height: 1.3125rem -} - -code.highlighter-rouge { - color: #6c6c6d; - background-color: #f3f4f7; - padding: 2px 6px -} - -a:link code.highlighter-rouge, -a:visited code.highlighter-rouge, -a:hover code.highlighter-rouge { - color: #fe6162 -} - -a:link.has-code, -a:visited.has-code, -a:hover.has-code { - color: #fe6162 -} - -p code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code { - font-size: 78.5% -} - -pre { - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word -} - -.header-holder { - height: 68px; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - left: 0; - margin-left: auto; - margin-right: auto; - position: fixed; - right: 0; - top: 0; - width: 100%; - z-index: 9999; - background-color: #fff; - border-bottom: 1px solid #e2e2e2 -} - -@media screen and (min-width: 1100px) { - .header-holder { - height: 90px - } -} - -.header-container { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center -} - -.header-container:before, -.header-container:after { - content: ""; - display: table -} - -.header-container:after { - clear: both -} - -.header-container { - *zoom: 1 -} - -@media screen and (min-width: 1100px) { - .header-container { - display: block - } -} - -.header-logo { - height: 32px; - width: calc(100% - 25px); - background-image: url("../images/logo_light.svg"), url("../images/logo.png"); - background-repeat: no-repeat; - background-size: contain; - display: block; - float: left; - z-index: 10 -} - -@media screen and (min-width: 1100px) { - .header-logo { - background-size: contain; - position: absolute; - height: 43px; - width: 25%; - top: 4px; - float: none - } -} - -@media screen and (min-width: 1600px) { - .header-logo { - width: 350px - } -} - -.main-menu-open-button { - background-image: url("../images/icon-menu-dots.svg"); - background-position: center center; - background-size: 25px 7px; - background-repeat: no-repeat; - width: 25px; - height: 17px; - position: absolute; - right: 0; - top: 8px -} - -@media screen and (min-width: 1100px) { - .main-menu-open-button { - display: none - } -} - -.header-holder .main-menu { - display: none -} - -@media screen and (min-width: 1100px) { - .header-holder .main-menu { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end - } -} - -.header-holder .main-menu ul { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0 -} - -.header-holder .main-menu ul li { - display: inline-block; - margin-right: 40px; - position: relative -} - -.header-holder .main-menu ul li.active:after { - content: "β€’"; - bottom: -24px; - color: #de3412; - font-size: 1.375rem; - left: 0; - position: absolute; - right: 0; - text-align: center -} - -.header-holder .main-menu ul li.active a { - color: #de3412 -} - -.header-holder .main-menu ul li.docs-active:after { - content: "β€’"; - bottom: -24px; - color: #de3412; - font-size: 1.375rem; - left: -24px; - position: absolute; - right: 0; - text-align: center -} - -.header-holder .main-menu ul li:last-of-type { - margin-right: 0 -} - -.header-holder .main-menu ul li a { - color: #1c1c1c; - font-family: UCity; - font-size: 14px; - font-weight: 600; - line-height: 1.25rem; - letter-spacing: 0px; - text-align: left; - text-decoration: none -} - -@media screen and (min-width: 1100px) { - .header-holder .main-menu ul li a:hover { - color: #de3412 - } -} - -.mobile-main-menu { - display: none -} - -.mobile-main-menu.open { - background-color: #262626; - display: block; - height: 100%; - left: 0; - margin-left: auto; - margin-right: auto; - min-height: 100%; - position: fixed; - right: 0; - top: 0; - width: 100%; - z-index: 99999 -} - -.mobile-main-menu .container-fluid, -.mobile-main-menu .container-sm, -.mobile-main-menu .container-md, -.mobile-main-menu .container-lg, -.mobile-main-menu .container-xl { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - height: 68px; - position: relative -} - -.mobile-main-menu .container-fluid:before, -.mobile-main-menu .container-sm:before, -.mobile-main-menu .container-md:before, -.mobile-main-menu .container-lg:before, -.mobile-main-menu .container-xl:before, -.mobile-main-menu .container-fluid:after, -.mobile-main-menu .container-sm:after, -.mobile-main-menu .container-md:after, -.mobile-main-menu .container-lg:after, -.mobile-main-menu .container-xl:after { - content: ""; - display: table -} - -.mobile-main-menu .container-fluid:after, -.mobile-main-menu .container-sm:after, -.mobile-main-menu .container-md:after, -.mobile-main-menu .container-lg:after, -.mobile-main-menu .container-xl:after { - clear: both -} - -.mobile-main-menu .container-fluid, -.mobile-main-menu .container-sm, -.mobile-main-menu .container-md, -.mobile-main-menu .container-lg, -.mobile-main-menu .container-xl { - *zoom: 1 -} - -.mobile-main-menu.open ul { - list-style-type: none; - padding: 0 -} - -.mobile-main-menu.open ul li a, -.mobile-main-menu.open .resources-mobile-menu-title { - font-size: 2rem; - color: #fff; - letter-spacing: 0; - line-height: 4rem; - text-decoration: none -} - -.mobile-main-menu.open ul li.active a { - color: #de3412 -} - -.main-menu-close-button { - background-image: url("../images/icon-close.svg"); - background-position: center center; - background-repeat: no-repeat; - background-size: 24px 24px; - height: 24px; - position: absolute; - right: 0; - width: 24px; - top: 1px -} - -.mobile-main-menu-header-container { - position: relative -} - -.mobile-main-menu-links-container { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding-left: 2.8125rem; - height: calc(100% - 68px); - overflow-y: scroll -} - -.mobile-main-menu-links-container .main-menu { - height: 100% -} - -.mobile-main-menu-links-container ul.resources-mobile-menu-items li { - padding-left: 15px -} - -.site-footer { - padding: 2.5rem 0; - width: 100%; - background: #000; - background-size: 100%; - margin-left: 0; - margin-right: 0; - position: relative; - z-index: 201 -} - -@media screen and (min-width: 768px) { - .site-footer { - padding: 5rem 0 - } -} - -.site-footer p { - color: #fff -} - -.site-footer ul { - list-style-type: none; - padding-left: 0; - margin-bottom: 0 -} - -.site-footer ul li { - font-size: 1.125rem; - line-height: 2rem; - color: #a0a0a1; - padding-bottom: .375rem -} - -.site-footer ul li.list-title { - padding-bottom: .75rem; - color: #fff -} - -.site-footer a:link, -.site-footer a:visited { - color: inherit -} - -@media screen and (min-width: 768px) { - .site-footer a:hover { - color: #de3412 - } -} - -.docs-tutorials-resources { - background-color: #262626; - color: #fff; - padding-top: 2.5rem; - padding-bottom: 2.5rem; - position: relative; - z-index: 201 -} - -@media screen and (min-width: 768px) { - .docs-tutorials-resources { - padding-top: 5rem; - padding-bottom: 5rem - } -} - -.docs-tutorials-resources p { - color: #929292; - font-size: 1.125rem -} - -.docs-tutorials-resources h2 { - font-size: 1.5rem; - letter-spacing: -0.25px; - text-transform: none; - margin-bottom: .25rem -} - -@media screen and (min-width: 768px) { - .docs-tutorials-resources h2 { - margin-bottom: 1.25rem - } -} - -.docs-tutorials-resources .col-md-4 { - margin-bottom: 2rem; - text-align: center -} - -@media screen and (min-width: 768px) { - .docs-tutorials-resources .col-md-4 { - margin-bottom: 0 - } -} - -.docs-tutorials-resources .with-right-arrow { - margin-left: 12px -} - -.docs-tutorials-resources .with-right-arrow:hover { - background-image: url("../images/chevron-right-white.svg") -} - -.docs-tutorials-resources p { - font-size: 1rem; - line-height: 1.5rem; - letter-spacing: .22px; - color: #939393; - margin-bottom: 0 -} - -@media screen and (min-width: 768px) { - .docs-tutorials-resources p { - margin-bottom: 1.25rem - } -} - -.docs-tutorials-resources a { - font-size: 1.125rem; - color: #de3412 -} - -.docs-tutorials-resources a:hover { - color: #fff -} - -.footer-container { - position: relative -} - -@media screen and (min-width: 768px) { - .footer-logo-wrapper { - position: absolute; - top: 0; - left: 30px - } -} - -.footer-logo { - background-image: url("../images/logo-icon.svg"); - background-position: center; - background-repeat: no-repeat; - background-size: 20px 24px; - display: block; - height: 24px; - margin-bottom: 2.8125rem; - width: 20px -} - -@media screen and (min-width: 768px) { - .footer-logo { - background-size: 29px 36px; - height: 36px; - margin-bottom: 0; - margin-bottom: 0; - width: 29px - } -} - -.footer-links-wrapper { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap -} - -@media screen and (min-width: 768px) { - .footer-links-wrapper { - -ms-flex-wrap: initial; - flex-wrap: initial; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end - } -} - -.footer-links-col { - margin-bottom: 3.75rem; - width: 50% -} - -@media screen and (min-width: 768px) { - .footer-links-col { - margin-bottom: 0; - width: 14%; - margin-right: 23px - } - - .footer-links-col.follow-us-col { - width: 18%; - margin-right: 0 - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - .footer-links-col { - width: 18%; - margin-right: 30px - } -} - -.footer-social-icons { - margin: 8.5625rem 0 2.5rem 0 -} - -.footer-social-icons a { - height: 32px; - width: 32px; - display: inline-block; - background-color: #cccdd1; - border-radius: 50%; - margin-right: 5px -} - -.footer-social-icons a.facebook { - background-image: url("../images/logo-facebook-dark.svg"); - background-position: center center; - background-size: 9px 18px; - background-repeat: no-repeat -} - -.footer-social-icons a.twitter { - background-image: url("../images/logo-twitter-dark.svg"); - background-position: center center; - background-size: 17px 17px; - background-repeat: no-repeat -} - -.footer-social-icons a.youtube { - background-image: url("../images/logo-youtube-dark.svg"); - background-position: center center; - background-repeat: no-repeat -} - -.site-footer .mc-field-group { - margin-top: -2px -} - -article.pytorch-article { - max-width: 920px; - margin: 0 auto -} - -article.pytorch-article h2, -article.pytorch-article h3, -article.pytorch-article h4, -article.pytorch-article h5, -article.pytorch-article h6 { - margin: 1.375rem 0; - color: #262626 -} - -article.pytorch-article h2 { - font-size: 1.625rem; - letter-spacing: 1.33px; - line-height: 2rem; - text-transform: none -} - -article.pytorch-article h3 { - font-weight: 600; - font-size: 1.25rem; - line-height: 1.5rem; - text-transform: none -} - -article.pytorch-article h4, -article.pytorch-article h5, -article.pytorch-article h6 { - font-size: 1.125rem; - letter-spacing: -0.19px; - line-height: 1.875rem -} - -article.pytorch-article p { - margin-bottom: 1.125rem -} - -article.pytorch-article p, -article.pytorch-article ul li, -article.pytorch-article ol li, -article.pytorch-article dl dt, -article.pytorch-article dl dd, -article.pytorch-article blockquote { - font-size: 1rem; - line-height: 1.375rem; - color: #262626; - letter-spacing: .01px; - font-weight: 500 -} - -article.pytorch-article table { - margin-bottom: 2.5rem; - width: 100% -} - -article.pytorch-article table thead { - border-bottom: 1px solid #cacaca -} - -article.pytorch-article table th { - padding: .625rem; - color: #262626 -} - -article.pytorch-article table td { - padding: .3125rem -} - -article.pytorch-article table tr th:first-of-type, -article.pytorch-article table tr td:first-of-type { - padding-left: 0 -} - -article.pytorch-article table.docutils.field-list th.field-name { - padding: .3125rem; - padding-left: 0 -} - -article.pytorch-article table.docutils.field-list td.field-body { - padding: .3125rem -} - -article.pytorch-article table.docutils.field-list td.field-body p:last-of-type { - margin-bottom: 0 -} - -article.pytorch-article ul, -article.pytorch-article ol { - margin: 1.5rem 0 3.125rem 0 -} - -@media screen and (min-width: 768px) { - - article.pytorch-article ul, - article.pytorch-article ol { - padding-left: 6.25rem - } -} - -article.pytorch-article ul li, -article.pytorch-article ol li { - margin-bottom: .625rem -} - -article.pytorch-article dl { - margin-bottom: 1.5rem -} - -article.pytorch-article dl dt { - margin-bottom: .75rem -} - -article.pytorch-article pre { - margin-bottom: 2.5rem -} - -article.pytorch-article hr { - margin-top: 4.6875rem; - margin-bottom: 4.6875rem -} - -article.pytorch-article blockquote { - margin: 0 auto; - margin-bottom: 2.5rem; - width: 65% -} - -article.pytorch-article .hidden { - display: none -} - -article.pytorch-article img { - width: auto -} - -article.pytorch-article .full-img { - width: 100% -} - -article.pytorch-article a>img { - width: auto -} - -html { - height: 100% -} - -@media screen and (min-width: 768px) { - html { - font-size: 16px - } -} - -body { - background: #fff; - height: 100%; - margin: 0 -} - -body.no-scroll { - height: 100%; - overflow: hidden -} - -p { - margin-top: 0; - margin-bottom: 1.125rem -} - -p a:link, -p a:visited, -p a:hover { - color: #de3412; - text-decoration: none -} - -@media screen and (min-width: 768px) { - p a:hover { - text-decoration: underline - } -} - -p a:link, -p a:visited, -p a:hover { - color: #de3412 -} - -.wy-breadcrumbs li a { - color: #de3412 -} - -ul.pytorch-breadcrumbs { - padding-left: 0; - list-style-type: none -} - -ul.pytorch-breadcrumbs li { - display: inline-block; - font-size: .875rem -} - -ul.pytorch-breadcrumbs a { - color: #de3412; - text-decoration: none -} - -.table-of-contents-link-wrapper { - display: block; - margin-top: 0; - padding: 1.25rem 1.875rem; - background-color: #f3f4f7; - position: relative; - color: #262626; - font-size: 1.25rem -} - -.table-of-contents-link-wrapper.is-open .toggle-table-of-contents { - -webkit-transform: rotate(180deg); - transform: rotate(180deg) -} - -@media screen and (min-width: 1100px) { - .table-of-contents-link-wrapper { - display: none - } -} - -.toggle-table-of-contents { - background-image: url("../images/chevron-down-grey.svg"); - background-position: center center; - background-repeat: no-repeat; - background-size: 18px 18px; - height: 100%; - position: absolute; - right: 21px; - width: 30px; - top: 0 -} - -.tutorials-header .header-logo { - background-image: url("../images/logo.png"); - height: 38px; - top: -10px -} - -.tutorials-header .main-menu ul li a { - color: #262626 -} - -.tutorials-header .main-menu-open-button { - background-image: url("../images/icon-menu-dots-dark.svg") -} - -.rst-content footer .rating-hr.hr-top { - margin-bottom: -0.0625rem -} - -.rst-content footer .rating-hr.hr-bottom { - margin-top: -0.0625rem -} - -.rst-content footer .rating-container { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - font-size: 1.125rem -} - -.rst-content footer .rating-container .rating-prompt, -.rst-content footer .rating-container .was-helpful-thank-you { - padding: .625rem 1.25rem .625rem 1.25rem -} - -.rst-content footer .rating-container .was-helpful-thank-you { - display: none -} - -.rst-content footer .rating-container .rating-prompt.yes-link, -.rst-content footer .rating-container .rating-prompt.no-link { - color: #de3412; - cursor: pointer -} - -.rst-content footer .rating-container .rating-prompt.yes-link:hover, -.rst-content footer .rating-container .rating-prompt.no-link:hover { - background-color: #de3412; - color: #fff -} - -.rst-content footer .rating-container .stars-outer { - display: inline-block; - position: relative; - font-family: FontAwesome; - padding: .625rem 1.25rem .625rem 1.25rem -} - -.rst-content footer .rating-container .stars-outer i { - cursor: pointer -} - -.rst-content footer .rating-container .stars-outer .star-fill { - color: #de3412 -} - -.rst-content footer div[role=contentinfo] { - padding-top: 2.5rem -} - -.rst-content footer div[role=contentinfo] p { - margin-bottom: 0 -} - -h1 { - font-size: 2rem; - letter-spacing: 1.78px; - line-height: 2.5rem; - text-transform: uppercase; - margin: 1.375rem 0 -} - -span.pre { - color: #6c6c6d; - background-color: #f3f4f7; - padding: 2px 6px -} - -pre { - background-color: #f3f4f7; - padding: 1.375rem -} - -.highlight .c1 { - color: #6c6c6d -} - -.headerlink { - display: none !important -} - -a:link.has-code, -a:hover.has-code, -a:visited.has-code { - color: #fe6162 -} - -a:link.has-code span, -a:hover.has-code span, -a:visited.has-code span { - color: #fe6162 -} - -article.pytorch-article ul, -article.pytorch-article ol { - padding-left: 1.875rem; - margin: 0 -} - -article.pytorch-article ul li, -article.pytorch-article ol li { - margin: 0; - line-height: 1.75rem -} - -article.pytorch-article ul p, -article.pytorch-article ol p { - line-height: 1.75rem; - margin-bottom: 0 -} - -article.pytorch-article ul ul, -article.pytorch-article ul ol, -article.pytorch-article ol ul, -article.pytorch-article ol ol { - margin: 0 -} - -article.pytorch-article h1, -article.pytorch-article h2, -article.pytorch-article h3, -article.pytorch-article h4, -article.pytorch-article h5, -article.pytorch-article h6 { - font-weight: normal -} - -article.pytorch-article h1 a, -article.pytorch-article h2 a, -article.pytorch-article h3 a, -article.pytorch-article h4 a, -article.pytorch-article h5 a, -article.pytorch-article h6 a { - color: #262626 -} - -article.pytorch-article p.caption { - margin-top: 1.25rem -} - -article.pytorch-article .section:first-of-type h1:first-of-type { - margin-top: 0 -} - -.left-menu-link { - background-color: green -} - -.left-menu-link:hover { - background-color: #de3412 -} - -article.pytorch-article .sphx-glr-thumbcontainer { - margin: 0; - border: 1px solid #d6d7d8; - border-radius: 0; - width: 45%; - text-align: center; - margin-bottom: 5% -} - -@media screen and (max-width: 1100px) { - article.pytorch-article .sphx-glr-thumbcontainer:nth-child(odd) { - margin-left: 0; - margin-right: 2.5% - } - - article.pytorch-article .sphx-glr-thumbcontainer:nth-child(even) { - margin-right: 0; - margin-left: 2.5% - } - - article.pytorch-article .sphx-glr-thumbcontainer .figure { - width: 40% - } -} - -@media screen and (min-width: 1101px) { - article.pytorch-article .sphx-glr-thumbcontainer { - margin-right: 3%; - margin-bottom: 3%; - width: 30% - } -} - -article.pytorch-article .sphx-glr-thumbcontainer .caption-text a { - color: #1c1c1c; - text-decoration: none; - font-family: UCity; - font-size: .875rem; - font-style: normal; - font-weight: 600; - line-height: 1.25rem; - letter-spacing: 0px; - text-align: left -} - -article.pytorch-article .sphx-glr-thumbcontainer:hover { - -webkit-box-shadow: none; - box-shadow: none; - border-bottom-color: #fff -} - -article.pytorch-article .sphx-glr-thumbcontainer:hover .figure:before { - bottom: 100% -} - -article.pytorch-article .sphx-glr-thumbcontainer .figure { - width: 80% -} - -article.pytorch-article .sphx-glr-thumbcontainer .figure:before { - content: ""; - display: block; - position: absolute; - top: 0; - bottom: 35%; - left: 0; - right: 0; - background: #8a94b3; - opacity: .1 -} - -article.pytorch-article .sphx-glr-thumbcontainer .figure a.reference.internal { - text-align: left -} - -@media screen and (min-width: 768px) { - article.pytorch-article .sphx-glr-thumbcontainer:after { - content: ""; - display: block; - width: 0; - height: 1px; - position: absolute; - bottom: -1px; - left: 5px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - article.pytorch-article .sphx-glr-thumbcontainer:hover:after { - width: calc(100% - 5px) - } -} - -@media screen and (min-width: 768px) { - article.pytorch-article .sphx-glr-thumbcontainer:after { - background-color: #de3412 - } -} - -article.pytorch-article .section :not(dt)>code { - color: #262626; - border-top: solid 2px #fff; - background-color: #fff; - border-bottom: solid 2px #fff; - padding: 0px 3px; - -webkit-box-decoration-break: clone; - box-decoration-break: clone -} - -article.pytorch-article .section :not(dt)>code .pre { - outline: 0px; - padding: 0px -} - -article.pytorch-article .function dt, -article.pytorch-article .class dt, -article.pytorch-article .attribute dt, -article.pytorch-article .class .attribute dt, -article.pytorch-article .method dt { - position: relative; - background: #f3f4f7; - padding: .5rem; - border-left: 3px solid #de3412; - word-wrap: break-word; - padding-right: 100px -} - -article.pytorch-article .function dt em.property, -article.pytorch-article .class dt em.property, -article.pytorch-article .attribute dt em.property, -article.pytorch-article .method dt em.property { - font-family: inherit -} - -article.pytorch-article .function dt em, -article.pytorch-article .class dt em, -article.pytorch-article .attribute dt em, -article.pytorch-article .class .attribute dt em, -article.pytorch-article .method dt em, -article.pytorch-article .function dt .sig-paren, -article.pytorch-article .class dt .sig-paren, -article.pytorch-article .attribute dt .sig-paren, -article.pytorch-article .method dt .sig-paren { - font-family: "Inconsolata", "IBMPlexMono", "SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", "monospace"; - font-size: 87.5% -} - -article.pytorch-article .function dt a, -article.pytorch-article .class dt a, -article.pytorch-article .attribute dt a, -article.pytorch-article .class .attribute dt a, -article.pytorch-article .method dt a { - position: absolute; - right: 30px; - padding-right: 0; - top: 50%; - -webkit-transform: perspective(1px) translateY(-50%); - transform: perspective(1px) translateY(-50%) -} - -article.pytorch-article .function dt:hover .viewcode-link, -article.pytorch-article .class dt:hover .viewcode-link, -article.pytorch-article .attribute dt:hover .viewcode-link, -article.pytorch-article .method dt:hover .viewcode-link { - color: #de3412 -} - -article.pytorch-article .function .anchorjs-link, -article.pytorch-article .class .anchorjs-link, -article.pytorch-article .attribute .anchorjs-link, -article.pytorch-article .method .anchorjs-link { - display: inline; - position: absolute; - right: 8px; - font-size: 1.5625rem !important; - padding-left: 0 -} - -article.pytorch-article .function dt>code, -article.pytorch-article .class dt>code, -article.pytorch-article .attribute dt>code, -article.pytorch-article .class .attribute dt>code, -article.pytorch-article .method dt>code { - color: #262626; - border-top: solid 2px #f3f4f7; - background-color: #f3f4f7; - border-bottom: solid 2px #f3f4f7; - -webkit-box-decoration-break: clone; - box-decoration-break: clone -} - -article.pytorch-article .function .viewcode-link, -article.pytorch-article .class .viewcode-link, -article.pytorch-article .attribute .viewcode-link, -article.pytorch-article .method .viewcode-link { - font-size: .875rem; - color: #979797; - letter-spacing: 0; - line-height: 1.5rem; - text-transform: uppercase -} - -article.pytorch-article .function dd, -article.pytorch-article .class dd, -article.pytorch-article .attribute dd, -article.pytorch-article .class .attribute dd, -article.pytorch-article .method dd { - padding-left: 3.75rem -} - -article.pytorch-article .function dd p, -article.pytorch-article .class dd p, -article.pytorch-article .attribute dd p, -article.pytorch-article .class .attribute dd p, -article.pytorch-article .method dd p { - color: #262626 -} - -article.pytorch-article .function table tbody tr th.field-name, -article.pytorch-article .class table tbody tr th.field-name, -article.pytorch-article .attribute table tbody tr th.field-name, -article.pytorch-article .method table tbody tr th.field-name { - white-space: nowrap; - color: #262626; - width: 20% -} - -@media screen and (min-width: 768px) { - - article.pytorch-article .function table tbody tr th.field-name, - article.pytorch-article .class table tbody tr th.field-name, - article.pytorch-article .attribute table tbody tr th.field-name, - article.pytorch-article .method table tbody tr th.field-name { - width: 15% - } -} - -article.pytorch-article .function table tbody tr td.field-body, -article.pytorch-article .class table tbody tr td.field-body, -article.pytorch-article .attribute table tbody tr td.field-body, -article.pytorch-article .method table tbody tr td.field-body { - padding: .625rem; - width: 80%; - color: #262626 -} - -@media screen and (min-width: 768px) { - - article.pytorch-article .function table tbody tr td.field-body, - article.pytorch-article .class table tbody tr td.field-body, - article.pytorch-article .attribute table tbody tr td.field-body, - article.pytorch-article .method table tbody tr td.field-body { - width: 85% - } -} - -@media screen and (min-width: 1600px) { - - article.pytorch-article .function table tbody tr td.field-body, - article.pytorch-article .class table tbody tr td.field-body, - article.pytorch-article .attribute table tbody tr td.field-body, - article.pytorch-article .method table tbody tr td.field-body { - padding-left: 1.25rem - } -} - -article.pytorch-article .function table tbody tr td.field-body p, -article.pytorch-article .class table tbody tr td.field-body p, -article.pytorch-article .attribute table tbody tr td.field-body p, -article.pytorch-article .method table tbody tr td.field-body p { - padding-left: 0px -} - -article.pytorch-article .function table tbody tr td.field-body p:last-of-type, -article.pytorch-article .class table tbody tr td.field-body p:last-of-type, -article.pytorch-article .attribute table tbody tr td.field-body p:last-of-type, -article.pytorch-article .method table tbody tr td.field-body p:last-of-type { - margin-bottom: 0 -} - -article.pytorch-article .function table tbody tr td.field-body ol, -article.pytorch-article .class table tbody tr td.field-body ol, -article.pytorch-article .attribute table tbody tr td.field-body ol, -article.pytorch-article .method table tbody tr td.field-body ol, -article.pytorch-article .function table tbody tr td.field-body ul, -article.pytorch-article .class table tbody tr td.field-body ul, -article.pytorch-article .attribute table tbody tr td.field-body ul, -article.pytorch-article .method table tbody tr td.field-body ul { - padding-left: 1rem; - padding-bottom: 0 -} - -article.pytorch-article .function table.docutils.field-list, -article.pytorch-article .class table.docutils.field-list, -article.pytorch-article .attribute table.docutils.field-list, -article.pytorch-article .method table.docutils.field-list { - margin-bottom: .75rem -} - -article.pytorch-article .attribute .has-code { - float: none -} - -article.pytorch-article .class dt { - border-left: none; - border-top: 3px solid #de3412; - padding-left: 4em -} - -article.pytorch-article .class dt em.property { - position: absolute; - left: .5rem -} - -article.pytorch-article .class dd .docutils dt { - padding-left: .5rem -} - -article.pytorch-article .class em.property { - text-transform: uppercase; - font-style: normal; - color: #de3412; - font-size: 1rem; - letter-spacing: 0; - padding-right: .75rem -} - -article.pytorch-article .class dl dt em.property { - position: static; - left: 0; - padding-right: 0 -} - -article.pytorch-article .class .method dt, -article.pytorch-article .class .staticmethod dt { - border-left: 3px solid #de3412; - border-top: none -} - -article.pytorch-article .class .method dt, -article.pytorch-article .class .staticmethod dt { - padding-left: .5rem -} - -article.pytorch-article .class .attribute dt { - border-top: none -} - -article.pytorch-article .class .attribute dt em.property { - position: relative; - left: 0 -} - -article.pytorch-article table { - table-layout: fixed -} - -article.pytorch-article .note, -article.pytorch-article .warning, -article.pytorch-article .tip, -article.pytorch-article .seealso, -article.pytorch-article .hint, -article.pytorch-article .important, -article.pytorch-article .caution, -article.pytorch-article .danger, -article.pytorch-article .attention, -article.pytorch-article .error { - background: #f3f4f7; - margin-top: 1.875rem; - margin-bottom: 1.125rem -} - -article.pytorch-article .note .admonition-title, -article.pytorch-article .warning .admonition-title, -article.pytorch-article .tip .admonition-title, -article.pytorch-article .seealso .admonition-title, -article.pytorch-article .hint .admonition-title, -article.pytorch-article .important .admonition-title, -article.pytorch-article .caution .admonition-title, -article.pytorch-article .danger .admonition-title, -article.pytorch-article .attention .admonition-title, -article.pytorch-article .error .admonition-title { - color: #fff; - letter-spacing: 1px; - text-transform: uppercase; - margin-bottom: 1.125rem; - padding: 3px 0 3px 1.375rem; - position: relative; - font-size: .875rem -} - -article.pytorch-article .note .admonition-title:before, -article.pytorch-article .warning .admonition-title:before, -article.pytorch-article .tip .admonition-title:before, -article.pytorch-article .seealso .admonition-title:before, -article.pytorch-article .hint .admonition-title:before, -article.pytorch-article .important .admonition-title:before, -article.pytorch-article .caution .admonition-title:before, -article.pytorch-article .danger .admonition-title:before, -article.pytorch-article .attention .admonition-title:before, -article.pytorch-article .error .admonition-title:before { - content: "β€’"; - position: absolute; - left: 9px; - color: #fff; - top: 2px -} - -article.pytorch-article .note p:nth-child(n+2), -article.pytorch-article .warning p:nth-child(n+2), -article.pytorch-article .tip p:nth-child(n+2), -article.pytorch-article .seealso p:nth-child(n+2), -article.pytorch-article .hint p:nth-child(n+2), -article.pytorch-article .important p:nth-child(n+2), -article.pytorch-article .caution p:nth-child(n+2), -article.pytorch-article .danger p:nth-child(n+2), -article.pytorch-article .attention p:nth-child(n+2), -article.pytorch-article .error p:nth-child(n+2) { - padding: 0 1.375rem -} - -article.pytorch-article .note table, -article.pytorch-article .warning table, -article.pytorch-article .tip table, -article.pytorch-article .seealso table, -article.pytorch-article .hint table, -article.pytorch-article .important table, -article.pytorch-article .caution table, -article.pytorch-article .danger table, -article.pytorch-article .attention table, -article.pytorch-article .error table { - margin: 0 2rem; - width: auto -} - -article.pytorch-article .note .pre, -article.pytorch-article .note pre, -article.pytorch-article .warning .pre, -article.pytorch-article .warning pre, -article.pytorch-article .tip .pre, -article.pytorch-article .tip pre, -article.pytorch-article .seealso .pre, -article.pytorch-article .seealso pre, -article.pytorch-article .hint .pre, -article.pytorch-article .hint pre, -article.pytorch-article .important .pre, -article.pytorch-article .important pre, -article.pytorch-article .caution .pre, -article.pytorch-article .caution pre, -article.pytorch-article .danger .pre, -article.pytorch-article .danger pre, -article.pytorch-article .attention .pre, -article.pytorch-article .attention pre, -article.pytorch-article .error .pre, -article.pytorch-article .error pre { - background: #fff; - outline: 1px solid #e9e9e9 -} - -article.pytorch-article .note :not(dt)>code, -article.pytorch-article .warning :not(dt)>code, -article.pytorch-article .tip :not(dt)>code, -article.pytorch-article .seealso :not(dt)>code, -article.pytorch-article .hint :not(dt)>code, -article.pytorch-article .important :not(dt)>code, -article.pytorch-article .caution :not(dt)>code, -article.pytorch-article .danger :not(dt)>code, -article.pytorch-article .attention :not(dt)>code, -article.pytorch-article .error :not(dt)>code { - border-top: solid 2px #fff; - background-color: #fff; - border-bottom: solid 2px #fff; - padding: 0px 3px; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; - outline: 1px solid #e9e9e9 -} - -article.pytorch-article .note :not(dt)>code .pre, -article.pytorch-article .warning :not(dt)>code .pre, -article.pytorch-article .tip :not(dt)>code .pre, -article.pytorch-article .seealso :not(dt)>code .pre, -article.pytorch-article .hint :not(dt)>code .pre, -article.pytorch-article .important :not(dt)>code .pre, -article.pytorch-article .caution :not(dt)>code .pre, -article.pytorch-article .danger :not(dt)>code .pre, -article.pytorch-article .attention :not(dt)>code .pre, -article.pytorch-article .error :not(dt)>code .pre { - outline: 0px; - padding: 0px -} - -article.pytorch-article .note pre, -article.pytorch-article .warning pre, -article.pytorch-article .tip pre, -article.pytorch-article .seealso pre, -article.pytorch-article .hint pre, -article.pytorch-article .important pre, -article.pytorch-article .caution pre, -article.pytorch-article .danger pre, -article.pytorch-article .attention pre, -article.pytorch-article .error pre { - margin-bottom: 0 -} - -article.pytorch-article .note .highlight, -article.pytorch-article .warning .highlight, -article.pytorch-article .tip .highlight, -article.pytorch-article .seealso .highlight, -article.pytorch-article .hint .highlight, -article.pytorch-article .important .highlight, -article.pytorch-article .caution .highlight, -article.pytorch-article .danger .highlight, -article.pytorch-article .attention .highlight, -article.pytorch-article .error .highlight { - margin: 0 2rem 1.125rem 2rem -} - -article.pytorch-article .note ul, -article.pytorch-article .note ol, -article.pytorch-article .warning ul, -article.pytorch-article .warning ol, -article.pytorch-article .tip ul, -article.pytorch-article .tip ol, -article.pytorch-article .seealso ul, -article.pytorch-article .seealso ol, -article.pytorch-article .hint ul, -article.pytorch-article .hint ol, -article.pytorch-article .important ul, -article.pytorch-article .important ol, -article.pytorch-article .caution ul, -article.pytorch-article .caution ol, -article.pytorch-article .danger ul, -article.pytorch-article .danger ol, -article.pytorch-article .attention ul, -article.pytorch-article .attention ol, -article.pytorch-article .error ul, -article.pytorch-article .error ol { - padding-left: 3.25rem -} - -article.pytorch-article .note ul li, -article.pytorch-article .note ol li, -article.pytorch-article .warning ul li, -article.pytorch-article .warning ol li, -article.pytorch-article .tip ul li, -article.pytorch-article .tip ol li, -article.pytorch-article .seealso ul li, -article.pytorch-article .seealso ol li, -article.pytorch-article .hint ul li, -article.pytorch-article .hint ol li, -article.pytorch-article .important ul li, -article.pytorch-article .important ol li, -article.pytorch-article .caution ul li, -article.pytorch-article .caution ol li, -article.pytorch-article .danger ul li, -article.pytorch-article .danger ol li, -article.pytorch-article .attention ul li, -article.pytorch-article .attention ol li, -article.pytorch-article .error ul li, -article.pytorch-article .error ol li { - color: #262626 -} - -article.pytorch-article .note p, -article.pytorch-article .warning p, -article.pytorch-article .tip p, -article.pytorch-article .seealso p, -article.pytorch-article .hint p, -article.pytorch-article .important p, -article.pytorch-article .caution p, -article.pytorch-article .danger p, -article.pytorch-article .attention p, -article.pytorch-article .error p { - margin-top: 1.125rem -} - -article.pytorch-article .note .admonition-title { - background: #54c7ec -} - -article.pytorch-article .warning .admonition-title { - background: #e94f3b -} - -article.pytorch-article .tip .admonition-title { - background: #6bcebb -} - -article.pytorch-article .seealso .admonition-title { - background: #6bcebb -} - -article.pytorch-article .hint .admonition-title { - background: #a2cdde -} - -article.pytorch-article .important .admonition-title { - background: #5890ff -} - -article.pytorch-article .caution .admonition-title { - background: #f7923a -} - -article.pytorch-article .danger .admonition-title { - background: #db2c49 -} - -article.pytorch-article .attention .admonition-title { - background: #f5a623 -} - -article.pytorch-article .error .admonition-title { - background: #cc2f90 -} - -article.pytorch-article .sphx-glr-download-link-note.admonition.note, -article.pytorch-article .reference.download.internal, -article.pytorch-article .sphx-glr-signature { - display: none -} - -article.pytorch-article .admonition>p:last-of-type { - margin-bottom: 0; - padding-bottom: 1.125rem !important -} - -.pytorch-article div.sphx-glr-download a { - background-color: #f3f4f7; - background-image: url("../images/arrow-down-orange.svg"); - background-repeat: no-repeat; - background-position: left 10px center; - background-size: 15px 15px; - border-radius: 0; - border: none; - display: block; - text-align: left; - padding: .9375rem 3.125rem; - position: relative; - margin: 1.25rem auto -} - -@media screen and (min-width: 768px) { - .pytorch-article div.sphx-glr-download a:after { - content: ""; - display: block; - width: 0; - height: 1px; - position: absolute; - bottom: -1px; - left: 5px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - .pytorch-article div.sphx-glr-download a:hover:after { - width: calc(100% - 5px) - } -} - -@media screen and (min-width: 768px) { - .pytorch-article div.sphx-glr-download a:after { - background-color: #de3412 - } -} - -@media screen and (min-width: 768px) { - .pytorch-article div.sphx-glr-download a { - background-position: left 20px center - } -} - -.pytorch-article div.sphx-glr-download a:hover { - -webkit-box-shadow: none; - box-shadow: none; - text-decoration: none; - background-image: url("../images/arrow-down-orange.svg"); - background-color: #f3f4f7 -} - -.pytorch-article div.sphx-glr-download a span.pre { - background-color: rgba(0, 0, 0, 0); - font-size: 1.125rem; - padding: 0; - color: #262626 -} - -.pytorch-article div.sphx-glr-download a code, -.pytorch-article div.sphx-glr-download a kbd, -.pytorch-article div.sphx-glr-download a pre, -.pytorch-article div.sphx-glr-download a samp, -.pytorch-article div.sphx-glr-download a span.pre { - font-family: FreightSans, Helvetica Neue, Helvetica, Arial, sans-serif -} - -.pytorch-article p.sphx-glr-script-out { - margin-bottom: 1.125rem -} - -.pytorch-article div.sphx-glr-script-out { - margin-bottom: 2.5rem -} - -.pytorch-article div.sphx-glr-script-out .highlight { - margin-left: 0; - margin-top: 0 -} - -.pytorch-article div.sphx-glr-script-out .highlight pre { - background-color: #fdede9; - padding: 1.5625rem; - color: #837b79 -} - -.pytorch-article div.sphx-glr-script-out+p { - margin-top: unset -} - -article.pytorch-article .wy-table-responsive table { - border: none; - border-color: #fff !important; - table-layout: fixed -} - -article.pytorch-article .wy-table-responsive table thead tr { - border-bottom: 2px solid #6c6c6d -} - -article.pytorch-article .wy-table-responsive table thead th { - line-height: 1.75rem; - padding-left: .9375rem; - padding-right: .9375rem -} - -article.pytorch-article .wy-table-responsive table tbody .row-odd { - background-color: #f3f4f7 -} - -article.pytorch-article .wy-table-responsive table tbody td { - color: #6c6c6d; - white-space: normal; - padding: .9375rem; - font-size: 1rem; - line-height: 1.375rem -} - -article.pytorch-article .wy-table-responsive table tbody td .pre { - background: #fff; - color: #de3412; - font-size: 87.5% -} - -article.pytorch-article .wy-table-responsive table tbody td code { - font-size: 87.5% -} - -a[rel~=prev], -a[rel~=next] { - padding: .375rem 0 0 0 -} - -img.next-page, -img.previous-page { - width: 8px; - height: 10px; - position: relative; - top: -1px -} - -img.previous-page { - -webkit-transform: scaleX(-1); - transform: scaleX(-1) -} - -.rst-footer-buttons { - margin-top: 1.875rem; - margin-bottom: 1.875rem -} - -.rst-footer-buttons .btn:focus, -.rst-footer-buttons .btn.focus { - -webkit-box-shadow: none; - box-shadow: none -} - -article.pytorch-article blockquote { - margin-left: 3.75rem; - color: #6c6c6d -} - -article.pytorch-article .caption { - color: #6c6c6d; - letter-spacing: .25px; - line-height: 2.125rem -} - -article.pytorch-article .math { - color: #262626; - width: auto; - text-align: center -} - -article.pytorch-article .math img { - width: auto -} - -.pytorch-breadcrumbs-wrapper { - width: 100% -} - -@media screen and (min-width: 1101px) { - .pytorch-breadcrumbs-wrapper { - float: left; - margin-left: 3%; - width: 73% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-breadcrumbs-wrapper { - width: 850px; - margin-left: 1.875rem - } -} - -.pytorch-breadcrumbs-wrapper .pytorch-breadcrumbs-aside { - float: right -} - -.pytorch-breadcrumbs-wrapper .pytorch-breadcrumbs-aside .fa.fa-github { - margin-top: 5px; - display: block -} - -.pytorch-article .container { - padding-left: 0; - padding-right: 0; - max-width: none -} - -a:link, -a:visited, -a:hover { - color: #de3412 -} - -::-webkit-input-placeholder { - color: #de3412 -} - -::-moz-placeholder { - color: #de3412 -} - -:-ms-input-placeholder { - color: #de3412 -} - -:-moz-placeholder { - color: #de3412 -} - -@media screen and (min-width: 768px) { - .site-footer a:hover { - color: #de3412 - } -} - -.docs-tutorials-resources a { - color: #de3412 -} - -.header-holder { - position: relative; - z-index: 201 -} - -.header-holder .main-menu ul li.active:after { - color: #de3412 -} - -.header-holder .main-menu ul li.active a { - color: #de3412 -} - -@media screen and (min-width: 1100px) { - .header-holder .main-menu ul li a:hover { - color: #de3412 - } -} - -.mobile-main-menu.open ul li.active a { - color: #de3412 -} - -.version { - padding-bottom: 1rem -} - -.pytorch-call-to-action-links { - padding-top: 0; - display: -webkit-box; - display: -ms-flexbox; - display: flex -} - -@media screen and (min-width: 768px) { - .pytorch-call-to-action-links { - padding-top: 2.5rem - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - .pytorch-call-to-action-links { - padding-top: 0 - } -} - -@media(min-width: 1100px)and (max-width: 1239px) { - .pytorch-call-to-action-links { - padding-top: 2.5rem - } -} - -.pytorch-call-to-action-links #tutorial-type { - display: none -} - -.pytorch-call-to-action-links .call-to-action-img, -.pytorch-call-to-action-links .call-to-action-notebook-img { - height: 1.375rem; - width: 1.375rem; - margin-right: 10px -} - -.pytorch-call-to-action-links .call-to-action-notebook-img { - height: 1rem -} - -.pytorch-call-to-action-links a { - padding-right: 1.25rem; - color: #000; - cursor: pointer -} - -.pytorch-call-to-action-links a:hover { - color: #de3412 -} - -.pytorch-call-to-action-links a .call-to-action-desktop-view { - display: none -} - -@media screen and (min-width: 768px) { - .pytorch-call-to-action-links a .call-to-action-desktop-view { - display: block - } -} - -.pytorch-call-to-action-links a .call-to-action-mobile-view { - display: block -} - -@media screen and (min-width: 768px) { - .pytorch-call-to-action-links a .call-to-action-mobile-view { - display: none - } -} - -.pytorch-call-to-action-links a #google-colab-link, -.pytorch-call-to-action-links a #download-notebook-link, -.pytorch-call-to-action-links a #github-view-link { - padding-bottom: .625rem; - border-bottom: 1px solid #f3f4f7; - padding-right: 2.5rem; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center -} - -.pytorch-call-to-action-links a #google-colab-link:hover, -.pytorch-call-to-action-links a #download-notebook-link:hover, -.pytorch-call-to-action-links a #github-view-link:hover { - border-bottom-color: #de3412; - color: #de3412 -} - -.slack-container { - display: -webkit-box; - display: -ms-flexbox; - display: flex -} - -.slack-container .slack-button { - border: 1px solid rgba(0, 0, 0, 0); - background: linear-gradient(206.91deg, #de3412 16.83%, #3EABB3 144.59%); - border-radius: 6px; - height: 30px; - width: 210px; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - font-size: 14px -} - -.slack-container a { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - height: 100%; - text-decoration: none -} - -.slack-container .icon { - height: 100%; - color: #fff; - margin-left: 10px; - padding-top: 2px -} - -.slack-container .button-title { - margin: auto; - margin-left: 5px; - margin-right: 5px; - color: #fff -} - -.slack-align-left { - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start -} - -.slack-align-center { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center -} - -.slack-align-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end -} - -#tutorial-cards-container #tutorial-cards { - width: 100% -} - -#tutorial-cards-container .tutorials-nav { - padding-left: 0; - padding-right: 0; - padding-bottom: 0 -} - -#tutorial-cards-container .tutorials-hr { - margin-top: 1rem; - margin-bottom: 1rem -} - -#tutorial-cards-container .card.tutorials-card { - border: 1px solid #cfcfcf; - border-radius: 5px; - height: 98px; - margin-bottom: 1.25rem; - margin-bottom: 1.875rem; - cursor: pointer -} - -@media screen and (min-width: 1240px) { - #tutorial-cards-container .card.tutorials-card { - height: 200px - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - #tutorial-cards-container .card.tutorials-card { - height: 200px - } -} - -#tutorial-cards-container .card.tutorials-card .tutorials-image { - position: absolute; - top: 0px; - right: 0px; - height: 96px; - width: 96px; - opacity: .7 -} - -#tutorial-cards-container .card.tutorials-card .tutorials-image img { - height: 100%; - width: 100% -} - -@media screen and (min-width: 768px) { - #tutorial-cards-container .card.tutorials-card .tutorials-image { - height: 198px; - width: 198px - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - #tutorial-cards-container .card.tutorials-card .tutorials-image { - height: 198px; - width: 198px - } -} - -#tutorial-cards-container .card.tutorials-card .tutorials-image:before { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 1; - opacity: .075 -} - -#tutorial-cards-container .card.tutorials-card .card-title-container { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex -} - -#tutorial-cards-container .card.tutorials-card .card-title-container h4 { - margin-bottom: 1.125rem; - margin-top: 0; - font-size: 1.5rem -} - -#tutorial-cards-container .card.tutorials-card p.card-summary, -#tutorial-cards-container .card.tutorials-card .card-title-container, -#tutorial-cards-container .card.tutorials-card p.tags { - white-space: nowrap; - overflow-y: hidden; - overflow-x: scroll -} - -@media screen and (min-width: 768px) { - - #tutorial-cards-container .card.tutorials-card p.card-summary, - #tutorial-cards-container .card.tutorials-card .card-title-container, - #tutorial-cards-container .card.tutorials-card p.tags { - overflow: hidden - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - - #tutorial-cards-container .card.tutorials-card p.card-summary, - #tutorial-cards-container .card.tutorials-card .card-title-container, - #tutorial-cards-container .card.tutorials-card p.tags { - overflow: hidden - } -} - -#tutorial-cards-container .card.tutorials-card p.card-summary, -#tutorial-cards-container .card.tutorials-card p.tags { - color: #6c6c6d; - font-weight: 400; - margin-bottom: 0; - line-height: 1.5rem; - font-size: .9375rem -} - -#tutorial-cards-container .card.tutorials-card p.card-summary { - height: 1.5rem -} - -@media screen and (min-width: 768px) { - #tutorial-cards-container .card.tutorials-card p.card-summary { - white-space: normal; - height: 4.5rem - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - #tutorial-cards-container .card.tutorials-card p.card-summary { - white-space: normal; - height: 4.5rem - } -} - -#tutorial-cards-container .card.tutorials-card p.card-summary, -#tutorial-cards-container .card.tutorials-card .card-title-container { - width: calc(100% - 96px) -} - -@media screen and (min-width: 768px) { - - #tutorial-cards-container .card.tutorials-card p.card-summary, - #tutorial-cards-container .card.tutorials-card .card-title-container { - width: calc(100% - 200px) - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - - #tutorial-cards-container .card.tutorials-card p.card-summary, - #tutorial-cards-container .card.tutorials-card .card-title-container { - width: calc(100% - 200px) - } -} - -#tutorial-cards-container .card.tutorials-card p.tags { - position: absolute; - bottom: .75rem; - width: calc(100% - 96px - 1.25rem - 1.25rem) -} - -@media screen and (min-width: 768px) { - #tutorial-cards-container .card.tutorials-card p.tags { - width: calc(100% - 200px - 1.25rem - 1.25rem) - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - #tutorial-cards-container .card.tutorials-card p.tags { - width: calc(100% - 200px - 1.25rem - 1.25rem) - } -} - -#tutorial-cards-container .card.tutorials-card h4 { - color: #262626; - margin-bottom: 1.125rem -} - -#tutorial-cards-container .card.tutorials-card a { - height: 100% -} - -@media screen and (min-width: 768px) { - #tutorial-cards-container .card.tutorials-card a { - min-height: 190px - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - #tutorial-cards-container .card.tutorials-card a { - min-height: 234px - } -} - -@media screen and (min-width: 768px) { - #tutorial-cards-container .card.tutorials-card:after { - content: ""; - display: block; - width: 0; - height: 1px; - position: absolute; - bottom: -1px; - left: 5px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - #tutorial-cards-container .card.tutorials-card:hover:after { - width: calc(100% - 5px) - } -} - -#tutorial-cards-container .card.tutorials-card:hover { - background-color: #fff; - border: 1px solid #e2e2e2 -} - -#tutorial-cards-container .card.tutorials-card:hover p.card-summary { - color: #262626 -} - -#tutorial-cards-container .card.tutorials-card:hover .tutorials-image { - opacity: unset -} - -#tutorial-cards-container .tutorial-tags-container { - width: 100% -} - -#tutorial-cards-container .tutorial-tags-container.active { - width: 0 -} - -#tutorial-cards-container .tutorial-filter-menu ul { - list-style-type: none; - padding-left: 1.25rem -} - -#tutorial-cards-container .tutorial-filter-menu ul li { - padding-right: 1.25rem; - word-break: break-all -} - -#tutorial-cards-container .tutorial-filter-menu ul li a { - color: #979797 -} - -#tutorial-cards-container .tutorial-filter-menu ul li a:hover { - color: #de3412 -} - -#tutorial-cards-container .tutorial-filter { - cursor: pointer -} - -#tutorial-cards-container .filter-btn { - color: #979797; - border: 1px solid #979797; - border-radius: 3px; - display: inline-block; - text-align: center; - white-space: nowrap; - vertical-align: middle; - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - margin-bottom: 5px -} - -#tutorial-cards-container .filter-btn:hover { - border: 1px solid #de3412; - color: #de3412 -} - -#tutorial-cards-container .filter-btn.selected { - background-color: #de3412; - border: 1px solid #de3412; - color: #fff -} - -#tutorial-cards-container .all-tag-selected { - background-color: #979797; - color: #fff -} - -#tutorial-cards-container .all-tag-selected:hover { - border-color: #979797; - color: #fff -} - -#tutorial-cards-container .pagination .page { - border: 1px solid #dee2e6; - padding: .5rem .75rem -} - -#tutorial-cards-container .pagination .active .page { - background-color: #dee2e6 -} - -article.pytorch-article .display-card-container .col-md-2 { - padding: 5px -} - -article.pytorch-article .display-card-container .col-md-3 { - padding: 5px -} - -article.pytorch-article .display-card-container .col-md-4 { - padding: 5px -} - -article.pytorch-article .display-card-container .col-md-6 { - padding: 5px -} - -article.pytorch-article .display-card-container .col-md-12 { - padding: 5px -} - -article.pytorch-article .display-card-container h3 { - margin: 5px 0 10px 0 -} - -@media screen and (min-width: 768px) { - article.pytorch-article .display-card-container .display-card-hover:after { - content: ""; - display: block; - width: 0; - height: 2px; - position: absolute; - top: calc(100% - 12px); - left: 15px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - article.pytorch-article .display-card-container .display-card-hover:hover:after { - width: calc(100% - 30px) - } -} - -article.pytorch-article .display-card-container .card-tag { - position: absolute; - bottom: 17px; - left: 15px; - padding: 2px 3px 2px 3px; - border: 1px solid #de3412; - color: #de3412; - border-radius: 4px; - font-size: 10px; - font-weight: 500; - text-transform: uppercase -} - -article.pytorch-article .display-card-container .display-card { - padding-bottom: 10px; - border: 1px solid #cfcfcf; - border-radius: 5px; - padding: 10px -} - -article.pytorch-article .display-card-container .display-card .body-paragraph { - color: #666; - font-weight: 400; - font-size: .875rem; - line-height: 1.25rem -} - -article.pytorch-article .display-card-container .display-card .image-center { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - margin: auto -} - -article.pytorch-article .display-card-container .display-card .image-center img { - height: 125px; - margin: auto; - width: 100%; - -o-object-fit: contain; - object-fit: contain -} - -article.pytorch-article .display-card-container .display-card .image-right { - float: right; - height: 100% -} - -article.pytorch-article .display-card-container .display-card .image-right img { - height: 100%; - width: auto; - -o-object-fit: contain; - object-fit: contain -} - -article.pytorch-article .tutorials-callout-container { - padding-bottom: 50px -} - -article.pytorch-article .tutorials-callout-container .col-md-6 { - padding: 5px -} - -article.pytorch-article .tutorials-callout-container .text-container { - padding-bottom: 10px; - border: 1px solid #cfcfcf; - border-radius: 5px; - padding: 10px -} - -@media screen and (min-width: 768px) { - article.pytorch-article .tutorials-callout-container .text-container:after { - content: ""; - display: block; - width: 0; - height: 2px; - position: absolute; - top: calc(100% - 12px); - left: 15px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - article.pytorch-article .tutorials-callout-container .text-container:hover:after { - width: calc(100% - 30px) - } -} - -@media screen and (min-width: 768px) { - article.pytorch-article .tutorials-callout-container .text-container { - height: 160px - } -} - -article.pytorch-article .tutorials-callout-container .text-container .body-paragraph { - color: #666; - font-weight: 400; - font-size: .875rem; - line-height: 1.25rem -} - -article.pytorch-article .tutorials-callout-container .text-container-small { - padding-bottom: 10px; - border: 1px solid #cfcfcf; - border-radius: 5px; - padding: 10px; - margin-bottom: 10px -} - -@media screen and (min-width: 768px) { - article.pytorch-article .tutorials-callout-container .text-container-small:after { - content: ""; - display: block; - width: 0; - height: 2px; - position: absolute; - top: calc(100% - 22px); - left: 15px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - article.pytorch-article .tutorials-callout-container .text-container-small:hover:after { - width: calc(100% - 30px) - } -} - -@media screen and (min-width: 768px) { - article.pytorch-article .tutorials-callout-container .text-container-small { - height: 130px - } -} - -article.pytorch-article .tutorials-callout-container .text-container-small .body-paragraph { - color: #666; - font-weight: 400; - font-size: .875rem; - line-height: 1.25rem -} - -article.pytorch-article .tutorials-callout-container .btn.callout-button { - font-size: 1.125rem; - border-radius: 0; - border: none; - background-color: #f3f4f7; - color: #6c6c6d; - font-weight: 400; - position: relative; - letter-spacing: .25px -} - -@media screen and (min-width: 768px) { - article.pytorch-article .tutorials-callout-container .btn.callout-button:after { - content: ""; - display: block; - width: 0; - height: 1px; - position: absolute; - bottom: -1px; - left: 5px; - background-color: #de3412; - -webkit-transition: width .25s ease-in-out; - transition: width .25s ease-in-out - } - - article.pytorch-article .tutorials-callout-container .btn.callout-button:hover:after { - width: calc(100% - 5px) - } -} - -article.pytorch-article .tutorials-callout-container .btn.callout-button a { - color: inherit -} - -.center-wrapper { - max-width: 560px; - height: auto; - margin: 1.5rem auto -} - -.video-wrapper { - position: relative; - padding-bottom: 56.25% -} - -.video-wrapper iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100% -} - -.sbs-code { - display: grid; - grid-template-columns: repeat(2, 1fr); - grid-column-gap: 10px; - grid-template-rows: auto; - grid-template-areas: "sbs-hdr1 sbs-hdr2" "sbs-blk1 sbs-blk2"; - margin-bottom: 1.5rem -} - -.sbs-code.container p { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: left; - -ms-flex-pack: left; - justify-content: left; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-style: italic; - color: navy; - margin-bottom: 0rem -} - -.sbs-hdr1 { - grid-area: sbs-hdr1 -} - -.sbs-hdr2 { - grid-area: sbs-hdr2 -} - -.sbs-blk1 { - grid-area: sbs-blk1 -} - -.sbs-blk2 { - grid-area: sbs-blk2 -} - -div.sbs-code :is(.highlight, pre) { - height: 100%; - margin-bottom: 0rem -} - -dl.footnote.brackets { - display: grid; - grid-template-columns: -webkit-max-content auto; - grid-template-columns: max-content auto -} - -.footnote.brackets dt { - grid-column-start: 1; - margin-right: 1rem -} - -.footnote.brackets dd { - grid-column-start: 2 -} - -a.footnote-reference { - vertical-align: super; - font-size: 80%; - line-height: 0rem -} - -.pytorch-container { - margin: 0 auto; - padding: 0 1.875rem; - width: auto; - position: relative -} - -@media screen and (min-width: 1100px) { - .pytorch-container { - padding: 0 - } -} - -@media screen and (min-width: 1101px) { - .pytorch-container { - margin-left: 25% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-container { - margin-left: 350px - } -} - -.pytorch-container:before, -.pytorch-container:after { - content: ""; - display: table -} - -.pytorch-container:after { - clear: both -} - -.pytorch-container { - *zoom: 1 -} - -.pytorch-content-wrap { - background-color: #fff; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - position: relative; - padding-top: 0 -} - -.pytorch-content-wrap:before, -.pytorch-content-wrap:after { - content: ""; - display: table -} - -.pytorch-content-wrap:after { - clear: both -} - -.pytorch-content-wrap { - *zoom: 1 -} - -@media screen and (min-width: 1101px) { - .pytorch-content-wrap { - padding-top: 45px; - float: left; - width: 100%; - display: block - } -} - -@media screen and (min-width: 1600px) { - .pytorch-content-wrap { - width: 100% - } -} - -.pytorch-content { - background: #fff; - width: 100%; - max-width: 700px; - position: relative -} - -.pytorch-content-left { - min-height: 100vh; - margin-top: 2.5rem; - width: 100% -} - -@media screen and (min-width: 1101px) { - .pytorch-content-left { - margin-top: 0; - margin-left: 20px; - width: 73%; - float: left - } -} - -@media screen and (min-width: 1600px) { - .pytorch-content-left { - width: 73%; - margin-left: 30px - } -} - -.pytorch-content-left .main-content { - padding-top: .9375rem -} - -.pytorch-content-left .main-content ul.simple { - padding-bottom: 1.25rem -} - -.pytorch-content-left .main-content .note:nth-child(1), -.pytorch-content-left .main-content .warning:nth-child(1) { - margin-top: 0 -} - -.pytorch-content-right { - display: none; - position: relative; - overflow-x: hidden; - overflow-y: hidden -} - -@media screen and (min-width: 1101px) { - .pytorch-content-right { - display: block; - margin-left: 0; - width: 25%; - float: left; - height: 100%; - padding-right: 5px - } -} - -@media screen and (min-width: 1600px) { - .pytorch-content-right { - width: 24%; - padding-right: 5px - } -} - -@media screen and (min-width: 1101px) { - .pytorch-side-scroll { - position: relative; - overflow-x: hidden; - overflow-y: scroll; - height: 100% - } -} - -.pytorch-menu-vertical { - padding: 1.25rem 1.875rem 2.5rem 1.875rem -} - -@media screen and (min-width: 1101px) { - .pytorch-menu-vertical { - display: block; - padding-top: 0; - padding-right: 13.5%; - padding-bottom: 5.625rem - } -} - -@media screen and (min-width: 1600px) { - .pytorch-menu-vertical { - padding-left: 0; - padding-right: 1.5625rem - } -} - -.pytorch-left-menu { - display: none; - background-color: #fff; - color: #262626; - overflow: scroll; - border-right: 1px solid #e2e2e2; - height: 100% -} - -@media screen and (min-width: 1101px) { - .pytorch-left-menu { - display: block; - overflow-x: hidden; - overflow-y: hidden; - padding-bottom: 110px; - padding: 0 1.875rem 0 0; - width: 22%; - z-index: 200; - float: left - } - - .pytorch-left-menu.make-fixed { - position: fixed; - top: 0; - bottom: 0; - left: 0; - float: none - } -} - -@media screen and (min-width: 1600px) { - .pytorch-left-menu { - padding: 0 0 0 1.875rem; - width: 350px - } -} - -.expand-menu, -.hide-menu { - color: #6c6c6d; - padding-left: 10px; - cursor: none; - float: right; - pointer-events: none -} - -.menu-item-decorator { - color: #848484 -} - -.collapse { - display: none -} - -.left-nav-top-caption { - padding-top: 1rem -} - -.pytorch-left-menu p.caption { - display: block; - margin-bottom: 0px; - text-transform: none; - white-space: normal; - border-radius: 6px; - padding: .5rem; - color: #1c1c1c; - font-family: UCity; - font-size: .875rem; - font-style: normal; - font-weight: 600; - line-height: 1.25rem; - letter-spacing: 0px; - text-align: left -} - -.pytorch-left-menu p.caption:hover { - background-color: #efeeff; - color: #f05f42 -} - -.pytorch-left-menu-search { - margin-bottom: 2.5rem -} - -@media screen and (min-width: 1101px) { - .pytorch-left-menu-search { - margin: 1.25rem .625rem 1.875rem 0 - } -} - -.pytorch-left-menu-search ::-webkit-input-placeholder { - color: #262626 -} - -.pytorch-left-menu-search ::-moz-placeholder { - color: #262626 -} - -.pytorch-left-menu-search :-ms-input-placeholder { - color: #262626 -} - -.pytorch-left-menu-search ::-ms-input-placeholder { - color: #262626 -} - -.pytorch-left-menu-search ::placeholder { - color: #262626 -} - -.pytorch-left-menu-search input[type=text] { - border-radius: 0; - padding: .5rem .75rem; - border-color: #fff; - color: #262626; - border-style: solid; - font-size: 1rem; - width: 100%; - background-color: #f3f4f7; - background-image: url("../images/search-icon.svg"); - background-repeat: no-repeat; - background-size: 18px 18px; - background-position: 12px 10px; - padding-left: 40px; - background-color: #f6f8fb -} - -.pytorch-left-menu-search input[type=text]:focus { - outline: 0 -} - -@media screen and (min-width: 1101px) { - .pytorch-left-menu .pytorch-side-scroll { - width: 120% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-left-menu .pytorch-side-scroll { - width: 340px - } -} - -.pytorch-right-menu { - min-height: 100px; - overflow-x: hidden; - overflow-y: hidden; - left: 0; - z-index: 200; - padding-top: 0; - position: relative -} - -@media screen and (min-width: 1101px) { - .pytorch-right-menu { - width: 100% - } - - .pytorch-right-menu.scrolling-fixed { - position: fixed; - top: 45px; - left: 81.1%; - width: 19%; - padding-right: 10px - } - - .pytorch-right-menu.scrolling-absolute { - position: absolute; - left: 0 - } -} - -@media screen and (min-width: 1600px) { - .pytorch-right-menu { - left: 0; - width: 100% - } - - .pytorch-right-menu.scrolling-fixed { - position: fixed; - top: 45px; - left: 80% - } - - .pytorch-right-menu.scrolling-absolute { - position: absolute; - left: 0 - } -} - -.pytorch-left-menu ul, -.pytorch-right-menu ul { - list-style-type: none; - padding-left: 0; - margin-bottom: 2.5rem -} - -.pytorch-left-menu>ul, -.pytorch-right-menu>ul { - margin-bottom: 2.5rem -} - -.pytorch-left-menu a:link, -.pytorch-left-menu a:visited, -.pytorch-left-menu a:hover, -.pytorch-right-menu a:link, -.pytorch-right-menu a:visited, -.pytorch-right-menu a:hover { - color: #6c6c6d; - font-size: .875rem; - line-height: 1rem; - padding: 0; - text-decoration: none -} - -.pytorch-left-menu a:link.reference.internal, -.pytorch-left-menu a:visited.reference.internal, -.pytorch-left-menu a:hover.reference.internal, -.pytorch-right-menu a:link.reference.internal, -.pytorch-right-menu a:visited.reference.internal, -.pytorch-right-menu a:hover.reference.internal { - min-height: 25px; - height: auto; - padding: 5px; - border-radius: 6px; - position: relative; - width: 100% -} - -.pytorch-left-menu a:link.reference.internal:hover, -.pytorch-left-menu a:visited.reference.internal:hover, -.pytorch-left-menu a:hover.reference.internal:hover, -.pytorch-right-menu a:link.reference.internal:hover, -.pytorch-right-menu a:visited.reference.internal:hover, -.pytorch-right-menu a:hover.reference.internal:hover { - background-color: #efeeff; - color: #f05f42 -} - -.pytorch-left-menu a:link.reference.external, -.pytorch-left-menu a:visited.reference.external, -.pytorch-left-menu a:hover.reference.external, -.pytorch-right-menu a:link.reference.external, -.pytorch-right-menu a:visited.reference.external, -.pytorch-right-menu a:hover.reference.external { - min-height: 25px; - height: auto; - padding: 5px; - border-radius: 6px; - position: relative; - width: 100% -} - -.pytorch-left-menu a:link.reference.external:hover, -.pytorch-left-menu a:visited.reference.external:hover, -.pytorch-left-menu a:hover.reference.external:hover, -.pytorch-right-menu a:link.reference.external:hover, -.pytorch-right-menu a:visited.reference.external:hover, -.pytorch-right-menu a:hover.reference.external:hover { - background-color: #efeeff; - color: #f05f42 -} - -.pytorch-left-menu li code, -.pytorch-right-menu li code { - border: none; - background: inherit; - color: inherit; - padding-left: 0; - padding-right: 0 -} - -.pytorch-left-menu li span.toctree-expand, -.pytorch-right-menu li span.toctree-expand { - display: block; - float: left; - margin-left: -1.2em; - font-size: .8em; - line-height: 1.6em -} - -.pytorch-left-menu li.on a, -.pytorch-left-menu li.current>a, -.pytorch-right-menu li.on a, -.pytorch-right-menu li.current>a { - position: relative; - border: none -} - -.pytorch-left-menu li.on a span.toctree-expand, -.pytorch-left-menu li.current>a span.toctree-expand, -.pytorch-right-menu li.on a span.toctree-expand, -.pytorch-right-menu li.current>a span.toctree-expand { - display: block; - font-size: .8em; - line-height: 1.6em -} - -.pytorch-left-menu li.toctree-l1.current>a, -.pytorch-right-menu li.toctree-l1.current>a { - color: #de3412 -} - -.pytorch-left-menu li.toctree-l1.current>a:before, -.pytorch-right-menu li.toctree-l1.current>a:before { - content: ""; - display: block; - width: 2px; - height: 100%; - background: #de3412; - left: -5px; - top: 0; - position: absolute -} - -.pytorch-left-menu li.toctree-l1.current li.toctree-l2>ul, -.pytorch-left-menu li.toctree-l2.current li.toctree-l3>ul, -.pytorch-right-menu li.toctree-l1.current li.toctree-l2>ul, -.pytorch-right-menu li.toctree-l2.current li.toctree-l3>ul { - display: none -} - -.pytorch-left-menu li.toctree-l1.current li.toctree-l2.current>ul, -.pytorch-left-menu li.toctree-l2.current li.toctree-l3.current>ul, -.pytorch-right-menu li.toctree-l1.current li.toctree-l2.current>ul, -.pytorch-right-menu li.toctree-l2.current li.toctree-l3.current>ul { - display: block -} - -.pytorch-left-menu li.toctree-l2.current li.toctree-l3>a, -.pytorch-right-menu li.toctree-l2.current li.toctree-l3>a { - display: block -} - -.pytorch-left-menu li.toctree-l3, -.pytorch-right-menu li.toctree-l3 { - font-size: .9em -} - -.pytorch-left-menu li.toctree-l3.current li.toctree-l4>a, -.pytorch-right-menu li.toctree-l3.current li.toctree-l4>a { - display: block -} - -.pytorch-left-menu li.toctree-l4, -.pytorch-right-menu li.toctree-l4 { - font-size: .9em -} - -.pytorch-left-menu li.current ul, -.pytorch-right-menu li.current ul { - display: block -} - -.pytorch-left-menu li ul, -.pytorch-right-menu li ul { - margin-bottom: 0; - display: none -} - -.pytorch-left-menu li ul li a, -.pytorch-right-menu li ul li a { - margin-bottom: 0 -} - -.pytorch-left-menu a, -.pytorch-right-menu a { - display: inline-block; - position: relative -} - -.pytorch-left-menu a:hover, -.pytorch-right-menu a:hover { - cursor: pointer -} - -.pytorch-left-menu a:active, -.pytorch-right-menu a:active { - cursor: pointer -} - -.pytorch-left-menu ul { - padding-left: 0; - margin-left: 5px -} - -.pytorch-right-menu a:link, -.pytorch-right-menu a:visited, -.pytorch-right-menu a:hover { - color: #6c6c6d -} - -.pytorch-right-menu a:link span.pre, -.pytorch-right-menu a:visited span.pre, -.pytorch-right-menu a:hover span.pre { - color: #6c6c6d -} - -.pytorch-right-menu a.reference.internal.expanded:before { - content: "-"; - font-family: monospace; - position: absolute; - left: -12px -} - -.pytorch-right-menu a.reference.internal.not-expanded:before { - content: "+"; - font-family: monospace; - position: absolute; - left: -12px -} - -.pytorch-right-menu li.active>a { - color: #de3412 -} - -.pytorch-right-menu li.active>a span.pre, -.pytorch-right-menu li.active>a:before { - color: #de3412 -} - -.pytorch-right-menu li.active>a:after { - content: "β€’"; - color: #de3412; - display: inline-block; - font-size: 1.375rem; - left: -17px; - position: absolute; - top: 1px -} - -.pytorch-right-menu .pytorch-side-scroll>ul>li>ul>li { - margin-bottom: 0 -} - -.pytorch-right-menu ul ul { - padding-left: 0 -} - -.pytorch-right-menu ul ul li { - padding-left: 0px -} - -.pytorch-right-menu ul ul li a.reference.internal { - padding-left: 0 -} - -.pytorch-right-menu ul ul li ul { - display: none; - padding-left: 10px -} - -.pytorch-right-menu ul ul li li a.reference.internal { - padding-left: 0 -} - -.pytorch-right-menu li ul { - display: block -} - -.pytorch-right-menu .pytorch-side-scroll { - padding-top: 20px; -} - -@media screen and (min-width: 1101px) { - .pytorch-right-menu .pytorch-side-scroll { - width: 100% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-right-menu .pytorch-side-scroll { - width: 100% - } -} - -.pytorch-right-menu .pytorch-side-scroll>ul { - padding-left: 20px; - padding-right: 0; - margin-bottom: 0 -} - -@media screen and (min-width: 1600px) { - .pytorch-right-menu .pytorch-side-scroll>ul { - padding-left: 25px - } -} - -.pytorch-right-menu .pytorch-side-scroll>ul>li>a.reference.internal { - color: #262626; - font-weight: 500 -} - -.pytorch-right-menu .pytorch-side-scroll ul li { - position: relative -} - -#pytorch-right-menu .side-scroll-highlight { - color: #de3412 -} - -.header-container { - max-width: none; - margin-top: 4px -} - -@media screen and (min-width: 1101px) { - .header-container { - margin-top: 0 - } -} - -@media screen and (min-width: 1600px) { - .header-container { - margin-top: 0 - } -} - -.container-fluid.header-holder, -.header-holder.container-sm, -.header-holder.container-md, -.header-holder.container-lg, -.header-holder.container-xl { - padding-right: 0; - padding-left: 0 -} - -.header-holder .container { - max-width: none; - padding-right: 1.875rem; - padding-left: 1.875rem -} - -@media screen and (min-width: 1101px) { - .header-holder .container { - padding-right: 1.875rem; - padding-left: 1.875rem - } -} - -.header-holder .main-menu { - -webkit-box-pack: unset; - -ms-flex-pack: unset; - justify-content: unset; - position: relative -} - -@media screen and (min-width: 1101px) { - .header-holder .main-menu ul { - padding-left: 0; - margin-left: 26% - } -} - -@media screen and (min-width: 1600px) { - .header-holder .main-menu ul { - padding-left: 38px; - margin-left: 310px - } -} - -.pytorch-page-level-bar { - display: none; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - background-color: #fff; - border-bottom: 1px solid #e2e2e2; - width: 100%; - z-index: 201 -} - -@media screen and (min-width: 1101px) { - .pytorch-page-level-bar { - left: 0; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - height: 45px; - padding-left: 0; - width: 100%; - position: absolute; - z-index: 1 - } - - .pytorch-page-level-bar.left-menu-is-fixed { - position: fixed; - top: 0; - left: 25%; - padding-left: 0; - right: 0; - width: 75% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-page-level-bar { - left: 0; - right: 0; - width: auto; - z-index: 1 - } - - .pytorch-page-level-bar.left-menu-is-fixed { - left: 350px; - right: 0; - width: auto - } -} - -.pytorch-page-level-bar ul, -.pytorch-page-level-bar li { - margin: 0 -} - -.pytorch-shortcuts-wrapper { - display: none -} - -@media screen and (min-width: 1101px) { - .pytorch-shortcuts-wrapper { - font-size: .875rem; - float: left; - margin-left: 2% - } -} - -@media screen and (min-width: 1600px) { - .pytorch-shortcuts-wrapper { - margin-left: 1.875rem - } -} - -.cookie-banner-wrapper { - display: none -} - -.cookie-banner-wrapper .container { - padding-left: 1.875rem; - padding-right: 1.875rem; - max-width: 1240px -} - -.cookie-banner-wrapper.is-visible { - display: block; - position: fixed; - bottom: 0; - background-color: #f3f4f7; - min-height: 100px; - width: 100%; - z-index: 401; - border-top: 3px solid #ededee -} - -.cookie-banner-wrapper .gdpr-notice { - color: #6c6c6d; - margin-top: 1.5625rem; - text-align: left; - max-width: 1440px -} - -@media screen and (min-width: 768px) { - .cookie-banner-wrapper .gdpr-notice { - width: 77% - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - .cookie-banner-wrapper .gdpr-notice { - width: inherit - } -} - -.cookie-banner-wrapper .gdpr-notice .cookie-policy-link { - color: #343434 -} - -.cookie-banner-wrapper .close-button { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background: rgba(0, 0, 0, 0); - border: 1px solid #f3f4f7; - height: 1.3125rem; - position: absolute; - bottom: 42px; - right: 0; - top: 0; - cursor: pointer; - outline: none -} - -@media screen and (min-width: 768px) { - .cookie-banner-wrapper .close-button { - right: 20%; - top: inherit - } -} - -@media(min-width: 768px)and (max-width: 1239px) { - .cookie-banner-wrapper .close-button { - right: 0; - top: 0 - } -} - -.main-menu ul li .resources-dropdown a { - cursor: pointer -} - -.main-menu ul li .dropdown-menu { - border-radius: 0; - padding: 0 -} - -.main-menu ul li .dropdown-menu .dropdown-item { - color: #6c6c6d; - border-bottom: 1px solid #e2e2e2 -} - -.main-menu ul li .dropdown-menu .dropdown-item:last-of-type { - border-bottom-color: rgba(0, 0, 0, 0) -} - -.main-menu ul li .dropdown-menu .dropdown-item:hover { - background-color: #de3412 -} - -.main-menu ul li .dropdown-menu .dropdown-item p { - font-size: 1rem; - color: #979797 -} - -.main-menu ul li .dropdown-menu a.dropdown-item:hover { - color: #fff -} - -.main-menu ul li .dropdown-menu a.dropdown-item:hover p { - color: #fff -} - -.resources-dropdown-menu { - display: none; - position: absolute; - z-index: 1000; - display: none; - float: left; - min-width: 10rem; - padding: .5rem 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 -} - -.resources-dropdown:hover .resources-dropdown-menu { - display: block -} - -.main-menu ul li .resources-dropdown-menu { - border-radius: 0; - padding: 0 -} - -.main-menu ul li.active:hover .resources-dropdown-menu { - display: block -} - -.main-menu ul li .resources-dropdown-menu .dropdown-item { - color: #6c6c6d; - border-bottom: 1px solid #e2e2e2 -} - -.resources-dropdown .with-down-orange-arrow { - padding-right: 2rem; - position: relative; - background: url("../images/chevron-down-orange.svg"); - background-size: 10px 15px; - background-position: top 0px right 12px; - background-repeat: no-repeat -} - -.with-down-arrow { - padding-right: 2rem; - position: relative; - background-image: url("../images/chevron-down-black.svg"); - background-size: 14px 18px; - background-position: top 7px right 10px; - background-repeat: no-repeat -} - -.with-down-arrow:hover { - background-image: url("../images/chevron-down-orange.svg"); - background-repeat: no-repeat -} - -.header-holder .main-menu ul li a.nav-dropdown-item { - display: block; - width: 100%; - clear: both; - font-weight: 400; - color: #979797; - text-align: left; - padding: 5px; - background-color: rgba(0, 0, 0, 0); - border-bottom: 1px solid #e2e2e2 -} - -.header-holder .main-menu ul li a.nav-dropdown-item:last-of-type { - border-bottom-color: rgba(0, 0, 0, 0) -} - -.header-holder .main-menu ul li a.nav-dropdown-item:hover { - background-color: #efeeff; - color: #de3412 -} - -.header-holder .main-menu ul li a.nav-dropdown-item .dropdown-title { - font-family: UCity; - font-size: .75rem; - font-weight: 400; - line-height: 1.375rem; - color: #6c6c6d -} - -.header-holder .main-menu ul li a.nav-dropdown-item:hover .dropdown-title { - background-color: hover_background; - color: #de3412 -} - -/*# sourceMappingURL=theme.css.map */ - -/* Customize CSS */ -#mainpage-title { - font-size: 2rem; - letter-spacing: 1.78px; - line-height: 2.5rem; - text-transform: uppercase; - margin: 1.375rem 0; -} - -#rl4co h1 { - font-size: 0; - line-height: 0; -} \ No newline at end of file diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff deleted file mode 100644 index e3172484..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff2 deleted file mode 100644 index cec2dc94..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold-italic.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff deleted file mode 100644 index de46625e..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff2 deleted file mode 100644 index dc05cd82..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-bold.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff deleted file mode 100644 index a50e5038..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff2 deleted file mode 100644 index fe284db6..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book-italic.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff deleted file mode 100644 index 6ab8775f..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff2 deleted file mode 100644 index 2688739f..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-book.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff deleted file mode 100644 index beda58d4..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff2 deleted file mode 100644 index e2fa0134..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light-italic.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff deleted file mode 100644 index 226a0bf8..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff2 deleted file mode 100644 index 6d8ff2c0..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-light.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff deleted file mode 100644 index a42115d6..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff2 deleted file mode 100644 index 16a7713a..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium-italic.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff deleted file mode 100644 index 5ea34539..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff2 b/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff2 deleted file mode 100644 index c58b6a52..00000000 Binary files a/docs/_theme/rl4co/static/fonts/FreightSans/freight-sans-medium.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff deleted file mode 100644 index cf37a5c5..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff2 b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff2 deleted file mode 100644 index 955a6eab..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Light.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff deleted file mode 100644 index fc65a679..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff2 b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff2 deleted file mode 100644 index c352e40e..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff deleted file mode 100644 index 7d63d89f..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff2 b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff2 deleted file mode 100644 index d0d7ded9..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-Regular.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff deleted file mode 100644 index 1da7753c..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2 b/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2 deleted file mode 100644 index 79dffdb8..00000000 Binary files a/docs/_theme/rl4co/static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/Inconsolata/Inconsolata.woff2 b/docs/_theme/rl4co/static/fonts/Inconsolata/Inconsolata.woff2 deleted file mode 100644 index 5d7a78e0..00000000 Binary files a/docs/_theme/rl4co/static/fonts/Inconsolata/Inconsolata.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/UCity/UCity-Light.woff2 b/docs/_theme/rl4co/static/fonts/UCity/UCity-Light.woff2 deleted file mode 100644 index 27ba1055..00000000 Binary files a/docs/_theme/rl4co/static/fonts/UCity/UCity-Light.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/UCity/UCity-Regular.woff2 b/docs/_theme/rl4co/static/fonts/UCity/UCity-Regular.woff2 deleted file mode 100644 index 86aafa85..00000000 Binary files a/docs/_theme/rl4co/static/fonts/UCity/UCity-Regular.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/fonts/UCity/UCity-Semibold.woff2 b/docs/_theme/rl4co/static/fonts/UCity/UCity-Semibold.woff2 deleted file mode 100644 index 50be9a4c..00000000 Binary files a/docs/_theme/rl4co/static/fonts/UCity/UCity-Semibold.woff2 and /dev/null differ diff --git a/docs/_theme/rl4co/static/images/arrow-down-orange.svg b/docs/_theme/rl4co/static/images/arrow-down-orange.svg deleted file mode 100644 index 33a0996d..00000000 --- a/docs/_theme/rl4co/static/images/arrow-down-orange.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - Group 5 - Created with Sketch. - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/arrow-right-with-tail.svg b/docs/_theme/rl4co/static/images/arrow-right-with-tail.svg deleted file mode 100644 index 4d72c1d4..00000000 --- a/docs/_theme/rl4co/static/images/arrow-right-with-tail.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - Page 1 - Created with Sketch. - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-down-black.svg b/docs/_theme/rl4co/static/images/chevron-down-black.svg deleted file mode 100644 index 097bc076..00000000 --- a/docs/_theme/rl4co/static/images/chevron-down-black.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - Created with Sketch. - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-down-grey.svg b/docs/_theme/rl4co/static/images/chevron-down-grey.svg deleted file mode 100644 index 82d6514f..00000000 --- a/docs/_theme/rl4co/static/images/chevron-down-grey.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - -Created with Sketch. - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-down-orange.svg b/docs/_theme/rl4co/static/images/chevron-down-orange.svg deleted file mode 100644 index 08d612d7..00000000 --- a/docs/_theme/rl4co/static/images/chevron-down-orange.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - Created with Sketch. - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-down-white.svg b/docs/_theme/rl4co/static/images/chevron-down-white.svg deleted file mode 100644 index e6c94e27..00000000 --- a/docs/_theme/rl4co/static/images/chevron-down-white.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - Created with Sketch. - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-right-orange.svg b/docs/_theme/rl4co/static/images/chevron-right-orange.svg deleted file mode 100644 index 39b7ac28..00000000 --- a/docs/_theme/rl4co/static/images/chevron-right-orange.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - -Page 1 -Created with Sketch. - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/chevron-right-white.svg b/docs/_theme/rl4co/static/images/chevron-right-white.svg deleted file mode 100644 index f4832286..00000000 --- a/docs/_theme/rl4co/static/images/chevron-right-white.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - -Page 1 -Created with Sketch. - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/home-footer-background.jpg b/docs/_theme/rl4co/static/images/home-footer-background.jpg deleted file mode 100644 index b307bb57..00000000 Binary files a/docs/_theme/rl4co/static/images/home-footer-background.jpg and /dev/null differ diff --git a/docs/_theme/rl4co/static/images/icon-close.svg b/docs/_theme/rl4co/static/images/icon-close.svg deleted file mode 100644 index db35a031..00000000 --- a/docs/_theme/rl4co/static/images/icon-close.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - Page 1 - Created with Sketch. - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/icon-menu-dots-dark.svg b/docs/_theme/rl4co/static/images/icon-menu-dots-dark.svg deleted file mode 100644 index bbf461a0..00000000 --- a/docs/_theme/rl4co/static/images/icon-menu-dots-dark.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - Page 1 - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/icon.svg b/docs/_theme/rl4co/static/images/icon.svg deleted file mode 100644 index a3ff2eec..00000000 --- a/docs/_theme/rl4co/static/images/icon.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-facebook-dark.svg b/docs/_theme/rl4co/static/images/logo-facebook-dark.svg deleted file mode 100644 index cff17915..00000000 --- a/docs/_theme/rl4co/static/images/logo-facebook-dark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-icon.svg b/docs/_theme/rl4co/static/images/logo-icon.svg deleted file mode 100644 index a3ff2eec..00000000 --- a/docs/_theme/rl4co/static/images/logo-icon.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-large.svg b/docs/_theme/rl4co/static/images/logo-large.svg deleted file mode 100644 index 4a6cd73f..00000000 --- a/docs/_theme/rl4co/static/images/logo-large.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-lightning-large.svg b/docs/_theme/rl4co/static/images/logo-lightning-large.svg deleted file mode 100644 index 4a6cd73f..00000000 --- a/docs/_theme/rl4co/static/images/logo-lightning-large.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-lightning.svg b/docs/_theme/rl4co/static/images/logo-lightning.svg deleted file mode 100644 index 07c3e5c7..00000000 --- a/docs/_theme/rl4co/static/images/logo-lightning.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-pytorch-dark.svg b/docs/_theme/rl4co/static/images/logo-pytorch-dark.svg deleted file mode 100644 index 9b4c1a56..00000000 --- a/docs/_theme/rl4co/static/images/logo-pytorch-dark.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-pytorch-icon.svg b/docs/_theme/rl4co/static/images/logo-pytorch-icon.svg deleted file mode 100644 index 575f6823..00000000 --- a/docs/_theme/rl4co/static/images/logo-pytorch-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-pytorch.svg b/docs/_theme/rl4co/static/images/logo-pytorch.svg deleted file mode 100644 index f8d44b98..00000000 --- a/docs/_theme/rl4co/static/images/logo-pytorch.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-twitter-dark.svg b/docs/_theme/rl4co/static/images/logo-twitter-dark.svg deleted file mode 100644 index 1572570f..00000000 --- a/docs/_theme/rl4co/static/images/logo-twitter-dark.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo-youtube-dark.svg b/docs/_theme/rl4co/static/images/logo-youtube-dark.svg deleted file mode 100644 index e3cfedd7..00000000 --- a/docs/_theme/rl4co/static/images/logo-youtube-dark.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/logo.png b/docs/_theme/rl4co/static/images/logo.png deleted file mode 100644 index 39b45bef..00000000 Binary files a/docs/_theme/rl4co/static/images/logo.png and /dev/null differ diff --git a/docs/_theme/rl4co/static/images/logo.svg b/docs/_theme/rl4co/static/images/logo.svg deleted file mode 100644 index 07c3e5c7..00000000 --- a/docs/_theme/rl4co/static/images/logo.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/pytorch-colab.svg b/docs/_theme/rl4co/static/images/pytorch-colab.svg deleted file mode 100644 index 2ab15e2f..00000000 --- a/docs/_theme/rl4co/static/images/pytorch-colab.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/pytorch-download.svg b/docs/_theme/rl4co/static/images/pytorch-download.svg deleted file mode 100644 index cc37d638..00000000 --- a/docs/_theme/rl4co/static/images/pytorch-download.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/docs/_theme/rl4co/static/images/pytorch-github.svg b/docs/_theme/rl4co/static/images/pytorch-github.svg deleted file mode 100644 index 2c2570da..00000000 --- a/docs/_theme/rl4co/static/images/pytorch-github.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/docs/_theme/rl4co/static/images/pytorch-x.svg b/docs/_theme/rl4co/static/images/pytorch-x.svg deleted file mode 100644 index cdb3a7ac..00000000 --- a/docs/_theme/rl4co/static/images/pytorch-x.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/docs/_theme/rl4co/static/images/search-icon.svg b/docs/_theme/rl4co/static/images/search-icon.svg deleted file mode 100644 index 68a193ff..00000000 --- a/docs/_theme/rl4co/static/images/search-icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - Created with Sketch. - - - - - - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/images/view-page-source-icon.svg b/docs/_theme/rl4co/static/images/view-page-source-icon.svg deleted file mode 100644 index 4b9ef649..00000000 --- a/docs/_theme/rl4co/static/images/view-page-source-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - diff --git a/docs/_theme/rl4co/static/js/modernizr.min.js b/docs/_theme/rl4co/static/js/modernizr.min.js deleted file mode 100644 index f65d4797..00000000 --- a/docs/_theme/rl4co/static/js/modernizr.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/* Modernizr 2.6.2 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load - */ -;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f); - } -} - -// LikeButtonWithTitle Component - -function LikeButtonWithTitle({ title, margin, padding }) { - const [likeCount, setLikeCount] = useState(100500); - return ( - - ); -} - -mountComponent(".LikeButtonWithTitle", LikeButtonWithTitle); - - -// ReactGreeter component - -function ReactGreeter() { - const [name, setName] = useState(""); - const onSubmit = (event) => { - event.preventDefault(); - alert(`Hello, ${name}!`); - }; - return ( -
- setName(event.target.value)} - /> - -
- ); -} - -mountComponent(".ReactGreeter", ReactGreeter); diff --git a/docs/_theme/rl4co/static/js/theme.js b/docs/_theme/rl4co/static/js/theme.js deleted file mode 100644 index d75a28fe..00000000 --- a/docs/_theme/rl4co/static/js/theme.js +++ /dev/null @@ -1 +0,0 @@ -require=function s(l,a,r){function c(t,e){if(!a[t]){if(!l[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(d)return d(t,!0);var i=new Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}var o=a[t]={exports:{}};l[t][0].call(o.exports,function(e){return c(l[t][1][e]||e)},o,o.exports,s,l,a,r)}return a[t].exports}for(var d="function"==typeof require&&require,e=0;e ul > li > a.reference.internal");for(n=0;n=e?(document.getElementById("pytorch-left-menu").classList.add("make-fixed"),document.getElementById("pytorch-page-level-bar").classList.add("left-menu-is-fixed")):(document.getElementById("pytorch-left-menu").classList.remove("make-fixed"),document.getElementById("pytorch-page-level-bar").classList.remove("left-menu-is-fixed"))},expandClosestUnexpandedParentList:function(e){var t=utilities.closest(e,"ul");if(t){var n=t.previousElementSibling;if(n&&"A"===n.tagName&&n.classList.contains("reference")){if(n.classList.contains("title-link"))return;t.style.display="block",n.classList.remove("not-expanded"),n.classList.add("expanded"),sideMenus.expandClosestUnexpandedParentList(n)}}},handleRightMenu:function(){var e=document.getElementById("pytorch-content-right"),t=document.getElementById("pytorch-right-menu"),n=t.getElementsByTagName("ul")[0],i=document.getElementById("pytorch-article"),o=i.offsetHeight,s=utilities.offset(i).top+o,l=document.getElementById("header-holder").offsetHeight;if(utilities.scrollTop()
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".pytorch-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=n(this);expand=n(''),expand.on("click",function(e){return i.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".pytorch-menu-vertical"),n=t.find('[href="'+e+'"]');if(0===n.length){var i=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(n=t.find('[href="#'+i.attr("id")+'"]')).length&&(n=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(n),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var s=0,e=["ms","moz","webkit","o"],t=0;t"),$("#download-notebook-link").wrap(""),$("#github-view-link").wrap("")}else $(".pytorch-call-to-action-links").hide();$(document).ready(function(){var t=$(this).not("checked"),n="",i="";function o(e){$(e).toggle()}$("#pytorch-left-menu p.caption").each(function(){var e=this.innerText.replace(/[^\w\s]/gi,"").trim();$(this).find("span").addClass("checked"),1==collapsedSections.includes(e)&&t&&"expand"!==sessionStorage.getItem(e)||"collapse"==sessionStorage.getItem(e)?($(this.firstChild).after(""+n+" "),$(this.firstChild).after(""+i+""),$(this).next("ul").hide()):(0==collapsedSections.includes(e)&&t||"expand"==sessionStorage.getItem(e))&&($(this.firstChild).after(""+n+""),$(this.firstChild).after(""+i+""))}),$(".expand-menu").on("click",function(){$(this).prev(".hide-menu").toggle(),$(this).parent().next("ul").toggle();var e=$(this).parent().text().replace(/[^\w\s]/gi,"").trim();"collapse"==sessionStorage.getItem(e)&&sessionStorage.removeItem(e),sessionStorage.setItem(e,"expand"),o(this)}),$(".hide-menu").on("click",function(){$(this).next(".expand-menu").toggle(),$(this).parent().next("ul").toggle();var e=$(this).parent().text().replace(/[^\w\s]/gi,"").trim();"expand"==sessionStorage.getItem(e)&&sessionStorage.removeItem(e),sessionStorage.setItem(e,"collapse"),o(this)}),$("#pytorch-left-menu p.caption").on("click",function(){var e=$(this).text().replace(/[^\w\s]/gi,"").trim(),t=sessionStorage.getItem(e);null==t&&(sessionStorage.setItem(e,"expand"),t="expand"),"expand"==t?($(this).children(".hide-menu").toggle(),$(this).children(".expand-menu").toggle(),$(this).next("ul").toggle(),sessionStorage.setItem(e,"collapse")):($(this).children(".hide-menu").toggle(),$(this).children(".expand-menu").toggle(),$(this).next("ul").toggle(),sessionStorage.setItem(e,"expand"))})}),$(".tutorials-card-container").map(function(){return $(this).data("tags").split(",").map(function(e){return e.trim()})}).get().sort().filter(function(e,t,n){return n.indexOf(e)==t&&""!=e}).forEach(function(e){$(".tutorial-filter-menu").append("
"+e+"
")}),$(".tags").each(function(){var n=$(this).text().split(",");n.forEach(function(e,t){n[t]=n[t].replaceAll("-"," ")}),$(this).html(n.join(", "))}),$(".tutorial-filter").each(function(){var e=$(this).text();$(this).html(e.replaceAll("-"," "))}),$("#tutorial-cards p").each(function(e,t){$(t).text().trim()||$(t).remove()}),$(document).on("click",".page",function(){$("html, body").animate({scrollTop:$("#dropdown-filter-tags").position().top},"slow")});var a=$("a[href='intermediate/speech_command_recognition_with_torchaudio.html']");"SyntaxError"==a.text()&&(console.log("There is an issue with the intermediate/speech_command_recognition_with_torchaudio.html menu item."),a.text("Speech Command Recognition with torchaudio")),$(".stars-outer > i").hover(function(){$(this).prevAll().addBack().toggleClass("fas star-fill")}),$(".stars-outer > i").on("click",function(){$(this).prevAll().each(function(){$(this).addBack().addClass("fas star-fill")}),$(".stars-outer > i").each(function(){$(this).unbind("mouseenter mouseleave").css({"pointer-events":"none"})})}),$("#pytorch-side-scroll-right li a").on("click",function(e){var t=$(this).attr("href");$("html, body").stop().animate({scrollTop:$(t).offset().top-100},850),e.preventDefault});var r=$("#pytorch-side-scroll-right"),c=r.outerHeight()+1,d=r.find("a"),h=d.map(function(){var e=$(this).attr("href");if(e.length)return e});$(window).scroll(function(){$(this).scrollTop();$(".section").each(function(e){var t=$(this).offset().top-$(window).scrollTop();t<=c+200&&c-200<=t&&h[e]=="#"+$(this).attr("id")&&$(".hidden:visible")&&($(d).removeClass("side-scroll-highlight"),$(d[e]).addClass("side-scroll-highlight"))})})},{jquery:"jquery"}]},{},[1,2,3,4,5,6,7,8,9,10,"pt-lightning-sphinx-theme"]); diff --git a/docs/_theme/rl4co/static/js/vendor/anchor.min.js b/docs/_theme/rl4co/static/js/vendor/anchor.min.js deleted file mode 100644 index b2f50a9f..00000000 --- a/docs/_theme/rl4co/static/js/vendor/anchor.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat -// -// AnchorJS - v4.3.0 - 2020-10-21 -// https://www.bryanbraun.com/anchorjs/ -// Copyright (c) 2020 Bryan Braun; Licensed MIT -// -// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat -!function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";return function(A){function d(A){A.icon=Object.prototype.hasOwnProperty.call(A,"icon")?A.icon:"",A.visible=Object.prototype.hasOwnProperty.call(A,"visible")?A.visible:"hover",A.placement=Object.prototype.hasOwnProperty.call(A,"placement")?A.placement:"right",A.ariaLabel=Object.prototype.hasOwnProperty.call(A,"ariaLabel")?A.ariaLabel:"Anchor",A.class=Object.prototype.hasOwnProperty.call(A,"class")?A.class:"",A.base=Object.prototype.hasOwnProperty.call(A,"base")?A.base:"",A.truncate=Object.prototype.hasOwnProperty.call(A,"truncate")?Math.floor(A.truncate):64,A.titleText=Object.prototype.hasOwnProperty.call(A,"titleText")?A.titleText:""}function f(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new TypeError("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}this.options=A||{},this.elements=[],d(this.options),this.isTouchDevice=function(){return Boolean("ontouchstart"in window||window.TouchEvent||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var e,t,o,n,i,s,a,r,c,l,h,u,p=[];if(d(this.options),"touch"===(h=this.options.visible)&&(h=this.isTouchDevice()?"always":"hover"),0===(e=f(A=A||"h2, h3, h4, h5, h6")).length)return this;for(!function(){if(null!==document.head.querySelector("style.anchorjs"))return;var A,e=document.createElement("style");e.className="anchorjs",e.appendChild(document.createTextNode("")),void 0===(A=document.head.querySelector('[rel="stylesheet"],style'))?document.head.appendChild(e):document.head.insertBefore(e,A);e.sheet.insertRule(".anchorjs-link{opacity:0;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}",e.sheet.cssRules.length),e.sheet.insertRule(":hover>.anchorjs-link,.anchorjs-link:focus{opacity:1}",e.sheet.cssRules.length),e.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",e.sheet.cssRules.length),e.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',e.sheet.cssRules.length)}(),t=document.querySelectorAll("[id]"),o=[].map.call(t,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),t=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||t||!1}}}); -// @license-end diff --git a/docs/_theme/rl4co/static/js/vendor/bootstrap.min.js b/docs/_theme/rl4co/static/js/vendor/bootstrap.min.js deleted file mode 100644 index b4dda1d9..00000000 --- a/docs/_theme/rl4co/static/js/vendor/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.6.1 (https://getbootstrap.com/) - * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),a=i(n);function s(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")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=function(t){var e=this,n=!1;return o.default(this).one(d.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||d.triggerTransitionEnd(e)}),t),this},o.default.event.special[d.TRANSITION_END]={bindType:f,delegateType:f,handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c="bs.alert",h=o.default.fn.alert,g=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,c),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(c);i||(i=new t(this),n.data(c,i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',g._handleDismiss(new g)),o.default.fn.alert=g._jQueryInterface,o.default.fn.alert.Constructor=g,o.default.fn.alert.noConflict=function(){return o.default.fn.alert=h,g._jQueryInterface};var m="bs.button",p=o.default.fn.button,_="active",v='[data-toggle^="button"]',y='input:not([type="hidden"])',b=".btn",E=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector(y);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(_))t=!1;else{var a=n.querySelector(".active");a&&o.default(a).removeClass(_)}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains(_)),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(_)),t&&o.default(this._element).toggleClass(_))},e.dispose=function(){o.default.removeData(this._element,m),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),a=i.data(m);a||(a=new t(this),i.data(m,a)),a.shouldAvoidTriggerChange=n,"toggle"===e&&a[e]()}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.button.data-api",v,(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(b)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector(y);if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||E._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",v,(function(t){var e=o.default(t.target).closest(b)[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(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 e=t.prototype;return e.next=function(){this._isSliding||this._slide(N)},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(D)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(I);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one(A,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?N:D;this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(".bs.carousel"),o.default.removeData(this._element,w),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},k,t),d.typeCheckConfig(T,t,O),t},e._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()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(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()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&j[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))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._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()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===N,i=t===D,o=this._getItemIndex(e),a=this._items.length-1;if((i&&0===o||n&&o===a)&&!this._config.wrap)return e;var s=(o+(t===D?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(I)),a=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(a),a},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass(S);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass(S)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(I);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,i,a,s=this,l=this._element.querySelector(I),r=this._getItemIndex(l),u=e||l&&this._getItemByDirection(t,l),f=this._getItemIndex(u),c=Boolean(this._interval);if(t===N?(n="carousel-item-left",i="carousel-item-next",a="left"):(n="carousel-item-right",i="carousel-item-prev",a="right"),u&&o.default(u).hasClass(S))this._isSliding=!1;else if(!this._triggerSlideEvent(u,a).isDefaultPrevented()&&l&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u),this._activeElement=u;var h=o.default.Event(A,{relatedTarget:u,direction:a,from:r,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(l).addClass(n),o.default(u).addClass(n);var g=d.getTransitionDurationFromElement(l);o.default(l).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass(S),o.default(l).removeClass("active "+i+" "+n),s._isSliding=!1,setTimeout((function(){return o.default(s._element).trigger(h)}),0)})).emulateTransitionEnd(g)}else o.default(l).removeClass(S),o.default(u).addClass(S),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(w),i=r({},k,o.default(this).data());"object"==typeof e&&(i=r({},i,e));var a="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data(w,n)),"number"==typeof e)n.to(e);else if("string"==typeof a){if("undefined"==typeof n[a])throw new TypeError('No method named "'+a+'"');n[a]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var a=r({},o.default(i).data(),o.default(this).data()),s=this.getAttribute("data-slide-to");s&&(a.interval=!1),t._jQueryInterface.call(o.default(i),a),s&&o.default(i).data(w).to(s),e.preventDefault()}}},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return k}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",P._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=s,this._triggerArray.push(a))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass(q)?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!(this._isTransitioning||o.default(this._element).hasClass(q)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains(F)}))).length&&(e=null),e&&(n=o.default(e).not(this._selector).data(R))&&n._isTransitioning))){var a=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(a),!a.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data(R,null));var s=this._getDimension();o.default(this._element).removeClass(F).addClass(Q),this._element.style[s]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass(B).attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(s[0].toUpperCase()+s.slice(1)),r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass(Q).addClass("collapse show"),i._element.style[s]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(r),this._element.style[s]=this._element[l]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass(q)){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass(Q).removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var a=0;a0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._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}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(K);if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data(K,n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll(it)),i=0,a=n.length;i0&&s--,40===e.which&&sdocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(ht);var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove(ht),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass(dt),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass(ct),this._config.focus&&this._enforceFocus();var a=o.default.Event("shown.bs.modal",{relatedTarget:t}),s=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(a)};if(n){var l=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._enforceFocus=function(){var t=this;o.default(document).off(pt).on(pt,(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on(yt,(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off(yt)},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on(_t,(function(e){return t.handleUpdate(e)})):o.default(window).off(_t)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass(ft),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger(gt)}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass(dt)?dt:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on(vt,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass(ct),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass(ct);var a=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass(dt)){var s=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._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",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:{"*":["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:[]},popperConfig:null},Ut={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Mt={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"},Wt=function(){function t(t,e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's tooltips require Popper (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 e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass(Rt))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(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},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var s=this.getTipElement(),l=d.getUID(this.constructor.NAME);s.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&o.default(s).addClass(Lt);var r="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(r);this.addAttachmentClass(u);var f=this._getContainer();o.default(s).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(s).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new a.default(this.element,s,this._getPopperConfig(u)),o.default(s).addClass(Rt),o.default(s).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),e===qt&&t._leave(null,t)};if(o.default(this.tip).hasClass(Lt)){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),a=function(){e._hoverState!==xt&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass(Rt),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass(Lt)){var s=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=At(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.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},e._getPopperConfig=function(t){var e=this;return r({},{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)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return Bt[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n=e===Ft?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i=e===Ft?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._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",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Qt:Ft]=!0),o.default(e.getTipElement()).hasClass(Rt)||e._hoverState===xt?e._hoverState=xt:(clearTimeout(e._timeout),e._hoverState=xt,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===xt&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Qt:Ft]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=qt,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===qt&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Pt.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"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()),d.typeCheckConfig(It,t,this.constructor.DefaultType),t.sanitize&&(t.template=At(t.template,t.whiteList,t.sanitizeFn)),t},e._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},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(jt);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass(Lt),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(kt),a="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,a),n.data(kt,i)),"string"==typeof e)){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return Ht}},{key:"NAME",get:function(){return It}},{key:"DATA_KEY",get:function(){return kt}},{key:"Event",get:function(){return Mt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Ut}}]),t}();o.default.fn.tooltip=Wt._jQueryInterface,o.default.fn.tooltip.Constructor=Wt,o.default.fn.tooltip.noConflict=function(){return o.default.fn.tooltip=Ot,Wt._jQueryInterface};var Vt="bs.popover",zt=o.default.fn.popover,Kt=new RegExp("(^|\\s)bs-popover\\S+","g"),Xt=r({},Wt.Default,{placement:"right",trigger:"click",content:"",template:''}),Yt=r({},Wt.DefaultType,{content:"(string|element|function)"}),$t={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"},Jt=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,u(e,n);var a=i.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},a.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(Kt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data(Vt),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data(Vt,e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},l(i,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"Default",get:function(){return Xt}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return Vt}},{key:"Event",get:function(){return $t}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Yt}}]),i}(Wt);o.default.fn.popover=Jt._jQueryInterface,o.default.fn.popover.Constructor=Jt,o.default.fn.popover.noConflict=function(){return o.default.fn.popover=zt,Jt._jQueryInterface};var Gt="scrollspy",Zt="bs.scrollspy",te=o.default.fn[Gt],ee="active",ne="position",ie=".nav, .list-group",oe={offset:10,method:"auto",target:""},ae={offset:"number",method:"string",target:"(string|element)"},se=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),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,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":ne,n="auto"===this._config.method?e:this._config.method,i=n===ne?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,a=d.getSelectorFromElement(t);if(a&&(e=document.querySelector(a)),e){var s=e.getBoundingClientRect();if(s.width||s.height)return[o.default(e)[n]().top+i,a]}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])}))},e.dispose=function(){o.default.removeData(this._element,Zt),o.default(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},e._getConfig=function(t){if("string"!=typeof(t=r({},oe,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(Gt),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(Gt,t,ae),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._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]&&("undefined"==typeof this._offsets[o+1]||t li > .active",ge=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&o.default(this._element).hasClass(ue)||o.default(this._element).hasClass("disabled"))){var e,n,i=o.default(this._element).closest(".nav, .list-group")[0],a=d.getSelectorFromElement(this._element);if(i){var s="UL"===i.nodeName||"OL"===i.nodeName?he:ce;n=(n=o.default.makeArray(o.default(i).find(s)))[n.length-1]}var l=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),r=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(l),o.default(this._element).trigger(r),!r.isDefaultPrevented()&&!l.isDefaultPrevented()){a&&(e=document.querySelector(a)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,le),this._element=null},e._activate=function(t,e,n){var i=this,a=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(ce):o.default(e).find(he))[0],s=n&&a&&o.default(a).hasClass(fe),l=function(){return i._transitionComplete(t,a,n)};if(a&&s){var r=d.getTransitionDurationFromElement(a);o.default(a).removeClass(de).one(d.TRANSITION_END,l).emulateTransitionEnd(r)}else l()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass(ue);var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass(ue),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}o.default(t).addClass(ue),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains(fe)&&t.classList.add(de);var a=t.parentNode;if(a&&"LI"===a.nodeName&&(a=a.parentNode),a&&o.default(a).hasClass("dropdown-menu")){var s=o.default(t).closest(".dropdown")[0];if(s){var l=[].slice.call(s.querySelectorAll(".dropdown-toggle"));o.default(l).addClass(ue)}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(le);if(i||(i=new t(this),n.data(le,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ge._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=ge._jQueryInterface,o.default.fn.tab.Constructor=ge,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=re,ge._jQueryInterface};var me="bs.toast",pe=o.default.fn.toast,_e="hide",ve="show",ye="showing",be="click.dismiss.bs.toast",Ee={animation:!0,autohide:!0,delay:500},Te={animation:"boolean",autohide:"boolean",delay:"number"},we=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove(ye),t._element.classList.add(ve),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove(_e),d.reflow(this._element),this._element.classList.add(ye),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains(ve)){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains(ve)&&this._element.classList.remove(ve),o.default(this._element).off(be),o.default.removeData(this._element,me),this._element=null,this._config=null},e._getConfig=function(t){return t=r({},Ee,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on(be,'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add(_e),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove(ve),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(me);if(i||(i=new t(this,"object"==typeof e&&e),n.data(me,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.1"}},{key:"DefaultType",get:function(){return Te}},{key:"Default",get:function(){return Ee}}]),t}();o.default.fn.toast=we._jQueryInterface,o.default.fn.toast.Constructor=we,o.default.fn.toast.noConflict=function(){return o.default.fn.toast=pe,we._jQueryInterface},t.Alert=g,t.Button=E,t.Carousel=P,t.Collapse=V,t.Dropdown=lt,t.Modal=Ct,t.Popover=Jt,t.Scrollspy=se,t.Tab=ge,t.Toast=we,t.Tooltip=Wt,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})})); -//# sourceMappingURL=bootstrap.min.js.map diff --git a/docs/_theme/rl4co/static/js/vendor/popper.min.js b/docs/_theme/rl4co/static/js/vendor/popper.min.js deleted file mode 100644 index bb1aaae3..00000000 --- a/docs/_theme/rl4co/static/js/vendor/popper.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/* - Copyright (C) Federico Zivolo 2020 - Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). - */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function i(e){return e&&e.referenceNode?e.referenceNode:e}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!fe),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=le({},E,e.attributes),e.styles=le({},m,e.styles),e.arrowStyles=le({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ge}); -//# sourceMappingURL=popper.min.js.map diff --git a/docs/_theme/rl4co/theme.conf b/docs/_theme/rl4co/theme.conf deleted file mode 100644 index 3051f1c4..00000000 --- a/docs/_theme/rl4co/theme.conf +++ /dev/null @@ -1,19 +0,0 @@ -[theme] -inherit = basic -stylesheet = css/theme.css -pygments_style = default - -[options] -canonical_url = -analytics_id = -collapse_navigation = True -sticky_navigation = True -navigation_depth = 4 -includehidden = False -titles_only = -logo = -logo_only = -display_version = True -prev_next_buttons_location = bottom -style_external_links = False -pytorch_project = diff --git a/docs/_theme/rl4co/theme_variables.jinja b/docs/_theme/rl4co/theme_variables.jinja deleted file mode 100644 index e5afc63b..00000000 --- a/docs/_theme/rl4co/theme_variables.jinja +++ /dev/null @@ -1,18 +0,0 @@ -{%- set external_urls = { - 'github': 'https://github.com/ai4co/rl4co', - 'github_issues': 'https://github.com/ai4co/rl4co/issues', - 'contributing': 'https://rl4co.readthedocs.io/en/latest/_content/general/contribute.html', - 'docs': 'https://rl4co.readthedocs.io/en/latest/', - 'discuss': 'https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4-0IkQ8NQH4TRXIX8PrRmDhQ', - 'tutorials': 'https://rl4co.readthedocs.io/en/latest/_collections/tutorials/1-training-loop-advanced.html', - 'home': 'https://rl4co.readthedocs.io/en/latest/', - 'get_started': 'https://rl4co.readthedocs.io/en/latest/_collections/1-quickstart.html', - 'features': 'https://rl4co.readthedocs.io/en/latest/', - 'blog': 'https://rl4co.readthedocs.io/en/latest/', - 'resources': 'https://rl4co.readthedocs.io/en/latest/', - 'support': 'https://rl4co.readthedocs.io/en/latest/_content/general/faq.html', - 'community': 'https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4-0IkQ8NQH4TRXIX8PrRmDhQ', - 'forums': 'https://join.slack.com/t/rl4co/shared_invite/zt-1ytz2c1v4-0IkQ8NQH4TRXIX8PrRmDhQ', - 'versions': '', -} --%} diff --git a/docs/_theme/rl4co/versions.html b/docs/_theme/rl4co/versions.html deleted file mode 100644 index 4b057d32..00000000 --- a/docs/_theme/rl4co/versions.html +++ /dev/null @@ -1,36 +0,0 @@ -{% if READTHEDOCS %} -{# Add rst-badge after rst-versions for small badge style. #} -
- - Read the Docs - v: {{ current_version }} - - -
-
-
{{ _('Versions') }}
- {% for slug, url in versions %} -
{{ slug }}
- {% endfor %} -
-
-
{{ _('Downloads') }}
- {% for type, url in downloads %} -
{{ type }}
- {% endfor %} -
-
-
{{ _('On Read the Docs') }}
-
- {{ _('Project Home') }} -
-
- {{ _('Builds') }} -
-
-
- {% trans %}Free document hosting provided by Read the Docs.{% endtrans %} - -
-
-{% endif %} diff --git a/docs/assets/figs/embeddings.png b/docs/assets/figs/embeddings.png new file mode 100644 index 00000000..bbfc3325 Binary files /dev/null and b/docs/assets/figs/embeddings.png differ diff --git a/docs/assets/figs/framework.png b/docs/assets/figs/framework.png new file mode 100644 index 00000000..b4750966 Binary files /dev/null and b/docs/assets/figs/framework.png differ diff --git a/docs/assets/figs/policies.png b/docs/assets/figs/policies.png new file mode 100644 index 00000000..862f9eb9 Binary files /dev/null and b/docs/assets/figs/policies.png differ diff --git a/docs/assets/figs/rl4co-logo.svg b/docs/assets/figs/rl4co-logo.svg new file mode 100644 index 00000000..041aa2e1 --- /dev/null +++ b/docs/assets/figs/rl4co-logo.svg @@ -0,0 +1,38 @@ + + + + + + Style 1-5 + + + diff --git a/docs/assets/rl4co_animated_full_tricks.svg b/docs/assets/rl4co_animated_full_tricks.svg new file mode 100644 index 00000000..2e1ac249 --- /dev/null +++ b/docs/assets/rl4co_animated_full_tricks.svg @@ -0,0 +1,77 @@ + + + + + + AI4CO + + + Text + + + + R L + 4 + C O + + + + + Style 1-5 + + + + diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index fca346f6..00000000 --- a/docs/conf.py +++ /dev/null @@ -1,121 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -import rl4co - -project = "rl4co" -copyright = "RL4CO Contributors" -author = "Federico Berto, Chuanbo Hua, Junyoung Park, Minsu Kim, Hyeonah Kim, Jiwoo Son, Haeyeon Kim, Joungho Kim, Jinkyoo Park" - - -release = rl4co.__version__ - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - - -# Most taken from: https://github.com/Lightning-AI/lightning/blob/master/docs/source-pytorch/conf.py -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.doctest", - "sphinx.ext.intersphinx", - "sphinx_toolbox.collapse", - "sphinx.ext.todo", - "sphinx.ext.coverage", - "sphinx.ext.viewcode", - "sphinx.ext.autosummary", - "sphinx.ext.napoleon", - "sphinx.ext.autosectionlabel", - "sphinxcontrib.video", - "sphinxcontrib.katex", - "myst_parser", - "nbsphinx", - "sphinx_autodoc_typehints", - "sphinx_copybutton", - "sphinx_paramlinks", - "sphinx_togglebutton", - "sphinxcontrib.collections", -] - - -# Include the folder from the main repo containing the notebooks -collections = { - "my_files": { - "driver": "copy_folder", - "source": "../examples/", - "target": "", - "ignore": ["*.ckpt"], - } -} - -templates_path = ["_templates"] -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -# SECTION: original theme set -# html_theme = 'alabaster' -# html_static_path = ['_static'] - -# SECTION: set sphinx_rtd_theme -# html_theme = "sphinx_rtd_theme" -# html_static_path = ['_static'] -# html_theme_options = { -# 'navigation_depth': 4, -# } - -# SECTION: set rl4co theme -html_theme = "rl4co" -html_theme_path = ["_theme"] - -# SECTION: set different parser for rst and md -source_suffix = { - ".rst": "restructuredtext", - ".md": "markdown", -} - -# intersphinx_mapping = { -# "python": ("https://docs.python.org/3", None), -# "torch": ("https://pytorch.org/docs/stable/", None), -# "torchmetrics": ("https://torchmetrics.readthedocs.io/en/stable/", None), -# "tensordict": ("https://pytorch-labs.github.io/tensordict/", None), -# "torchrl": ("https://pytorch.org/rl/", None), -# "torchaudio": ("https://pytorch.org/audio/stable/", None), -# "torchtext": ("https://pytorch.org/text/stable/", None), -# "torchvision": ("https://pytorch.org/vision/stable/", None), -# "numpy": ("https://numpy.org/doc/stable/", None), -# } - - -autosummary_generate = True - -autodoc_member_order = "groupwise" - -autoclass_content = "both" - -autodoc_default_options = { - "members": True, - "methods": True, - "special-members": "__call__", - "exclude-members": "_abc_impl", - "show-inheritance": True, -} - -# Sphinx will add β€œpermalinks” for each heading and description environment as paragraph signs that -# become visible when the mouse hovers over them. -# This value determines the text for the permalink; it defaults to "ΒΆ". Set it to None or the empty -# string to disable permalinks. -# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_add_permalinks -html_permalinks = True -html_permalinks_icon = "ΒΆ" - -# True to prefix each section label with the name of the document it is in, followed by a colon. -# For example, index:Introduction for a section called Introduction that appears in document index.rst. -# Useful for avoiding ambiguity when the same section heading appears in different documents. -# http://www.sphinx-doc.org/en/master/usage/extensions/autosectionlabel.html -autosectionlabel_prefix_document = True diff --git a/docs/content/api/data.md b/docs/content/api/data.md new file mode 100644 index 00000000..b316c783 --- /dev/null +++ b/docs/content/api/data.md @@ -0,0 +1,23 @@ +## Datasets + +:::data.dataset + options: + show_root_heading: false + +## Data Generation + +:::data.generate_data + options: + show_root_heading: false + +## Transforms + +:::data.transforms + options: + show_root_heading: false + +## Utils + +:::data.utils + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/content/api/decoding.md b/docs/content/api/decoding.md new file mode 100644 index 00000000..0a0b5ec0 --- /dev/null +++ b/docs/content/api/decoding.md @@ -0,0 +1,5 @@ +# Decoding Strategies + +:::utils.decoding + options: + show_root_heading: false diff --git a/docs/_content/api/envs/base.md b/docs/content/api/envs/base.md similarity index 50% rename from docs/_content/api/envs/base.md rename to docs/content/api/envs/base.md index 30e1a190..fe914cb6 100644 --- a/docs/_content/api/envs/base.md +++ b/docs/content/api/envs/base.md @@ -1,21 +1,15 @@ # Base Environment -## `RL4COEnvBase` - This is the base wrapper around TorchRL's `EnvBase`, with additional functionality. -```{eval-rst} -.. automodule:: rl4co.envs.common.base - :members: - :undoc-members: -``` +::: envs.common.base.RL4COEnvBase +::: envs.common.base.ImprovementEnvBase + ## Utilities These contain utilities such as the base `Generator` class and `get_sampler`. -```{eval-rst} -.. automodule:: rl4co.envs.common.utils - :members: - :undoc-members: -``` \ No newline at end of file +:::envs.common.utils.Generator +:::envs.common.utils.get_sampler +:::envs.common.utils.batch_to_scalar \ No newline at end of file diff --git a/docs/content/api/envs/eda.md b/docs/content/api/envs/eda.md new file mode 100644 index 00000000..c070e0f4 --- /dev/null +++ b/docs/content/api/envs/eda.md @@ -0,0 +1,14 @@ +# EDA Problems +Environment for Electronic Design Automation (EDA) problems + +## Decap Placement Problem (DPP) + +:::envs.eda.dpp.env.DPPEnv + +:::envs.eda.dpp.generator.DPPGenerator + +## Multi-port Decap Placement Problem (mDPP) + +:::envs.eda.mdpp.env.MDPPEnv + +:::envs.eda.mdpp.generator.MDPPGenerator diff --git a/docs/content/api/envs/routing.md b/docs/content/api/envs/routing.md new file mode 100644 index 00000000..7c5be49f --- /dev/null +++ b/docs/content/api/envs/routing.md @@ -0,0 +1,61 @@ +# Routing Problems + +See also the [Multi-Task VRP](#Multi-Task-Vehicle-Routing-Problem-(MTVRP)) at the bottom of this page, that includes 16 variants! + +## Asymmetric Traveling Salesman Problem (ATSP) + +:::envs.routing.atsp.env.ATSPEnv + +:::envs.routing.atsp.generator.ATSPGenerator + +## Capacitated Vehicle Routing Problem (CVRP) + +:::envs.routing.cvrp.env.CVRPEnv + +:::envs.routing.cvrp.generator.CVRPGenerator + +## Multiple Traveling Salesman Problem (mTSP) + +:::envs.routing.mtsp.env.MTSPEnv + +:::envs.routing.mtsp.generator.MTSPGenerator + + +## Orienteering Problem (OP) + +:::envs.routing.op.env.OPEnv + +:::envs.routing.op.generator.OPGenerator + +## Pickup and Delivery Problem (PDP) + +:::envs.routing.pdp.env.PDPEnv + +:::envs.routing.pdp.generator.PDPGenerator + +## Prize Collecting Traveling Salesman Problem (PCTSP) + +:::envs.routing.pctsp.env.PCTSPEnv + +:::envs.routing.pctsp.generator.PCTSPGenerator + +## Split Delivery Vehicle Routing Problem (SDVRP) + +:::envs.routing.sdvrp.env.SDVRPEnv + +## Stochastic Prize Collecting Traveling Salesman Problem (SPCTSP) + +:::envs.routing.spctsp.env.SPCTSPEnv + +## Traveling Salesman Problem (TSP) + +:::envs.routing.tsp.env.TSPEnv + +:::envs.routing.tsp.generator.TSPGenerator + +## Multi-Task Vehicle Routing Problem (MTVRP) + + +:::envs.routing.mtvrp.env.MTVRPEnv + +:::envs.routing.mtvrp.generator.MTVRPGenerator \ No newline at end of file diff --git a/docs/content/api/envs/scheduling.md b/docs/content/api/envs/scheduling.md new file mode 100644 index 00000000..62b172b6 --- /dev/null +++ b/docs/content/api/envs/scheduling.md @@ -0,0 +1,13 @@ +# Scheduling Problems + +## Flexible Flow Shop Problem (FFSP) + +:::envs.scheduling.ffsp.env.FFSPEnv + +:::envs.scheduling.ffsp.generator.FFSPGenerator + +## Single Machine Total Weighted Tardiness Problem (SMTWTP) + +:::envs.scheduling.smtwtp.env.SMTWTPEnv + +:::envs.scheduling.smtwtp.generator.SMTWTPGenerator \ No newline at end of file diff --git a/docs/content/api/networks/base_policies.md b/docs/content/api/networks/base_policies.md new file mode 100644 index 00000000..0d895afb --- /dev/null +++ b/docs/content/api/networks/base_policies.md @@ -0,0 +1,42 @@ + +# Constructive Policies Base Classes + +:::models.common.constructive.base + options: + show_root_heading: false + +## Autoregressive Policies + +:::models.common.constructive.autoregressive.encoder + options: + show_root_heading: false + +:::models.common.constructive.autoregressive.decoder + options: + show_root_heading: false + +:::models.common.constructive.autoregressive.policy + options: + show_root_heading: false + +## Nonautoregressive Policies + +:::models.common.constructive.nonautoregressive.encoder + options: + show_root_heading: false + +:::models.common.constructive.nonautoregressive.decoder + options: + show_root_heading: false + +:::models.common.constructive.nonautoregressive.policy + options: + show_root_heading: false + + +# Improvement Policies (Base Classes) + + +:::models.common.improvement.base + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/_content/api/models/env_embeddings.md b/docs/content/api/networks/env_embeddings.md similarity index 79% rename from docs/_content/api/models/env_embeddings.md rename to docs/content/api/networks/env_embeddings.md index 9d70ae6b..5056cb3b 100644 --- a/docs/_content/api/models/env_embeddings.md +++ b/docs/content/api/networks/env_embeddings.md @@ -9,39 +9,26 @@ In autoregressive policies, environment embeddings transfer data from feature sp policy - - ## Context Embeddings The context embedding is used to modify the query embedding of the problem node of the current partial solution. Usually consists of a projection of gathered node embeddings and features to the embedding space. - -```{eval-rst} -.. automodule:: rl4co.models.nn.env_embeddings.context - :members: - :undoc-members: -``` - ---- +:::models.nn.env_embeddings.context + options: + show_root_heading: false ## Dynamic Embeddings The dynamic embedding is used to modify query, key and value vectors of the attention mechanism based on the current state of the environment (which is changing during the rollout). Generally consists of a linear layer that projects the node features to the embedding space. -```{eval-rst} -.. automodule:: rl4co.models.nn.env_embeddings.dynamic - :members: - :undoc-members: -``` - ---- +:::models.nn.env_embeddings.dynamic + options: + show_root_heading: false ## Init Embeddings The init embedding is used to initialize the general embedding of the problem nodes without any solution information. Generally consists of a linear layer that projects the node features to the embedding space. -```{eval-rst} -.. automodule:: rl4co.models.nn.env_embeddings.init - :members: - :undoc-members: -``` \ No newline at end of file +:::models.nn.env_embeddings.init + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/content/api/networks/improvement_policies.md b/docs/content/api/networks/improvement_policies.md new file mode 100644 index 00000000..a4fdc075 --- /dev/null +++ b/docs/content/api/networks/improvement_policies.md @@ -0,0 +1,7 @@ +## Improvement Policies (Base Classes) + + + +:::models.common.improvement.base + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/content/api/networks/nn.md b/docs/content/api/networks/nn.md new file mode 100644 index 00000000..66cc5637 --- /dev/null +++ b/docs/content/api/networks/nn.md @@ -0,0 +1,29 @@ +# Neural Network Modules + +## Critic Network + +:::models.rl.common.critic.CriticNetwork + +## Graph Neural Networks + +:::models.nn.graph.attnnet.MultiHeadAttentionLayer +:::models.nn.graph.attnnet.GraphAttentionNetwork + +:::models.nn.graph.gcn.GCNEncoder + +:::models.nn.graph.mpnn.MessagePassingEncoder + +## Attention Mechanisms + +:::models.nn.attention + options: + show_root_heading: false + +## Multi-Layer Perceptron + +:::models.nn.mlp.MLP + +## Operations + +:::models.nn.ops.PositionalEncoding +:::models.nn.ops.RandomEncoding \ No newline at end of file diff --git a/docs/content/api/rl/a2c.md b/docs/content/api/rl/a2c.md new file mode 100644 index 00000000..77abe89f --- /dev/null +++ b/docs/content/api/rl/a2c.md @@ -0,0 +1 @@ +:::models.rl.a2c.a2c.A2C diff --git a/docs/content/api/rl/base.md b/docs/content/api/rl/base.md new file mode 100644 index 00000000..58ebf0aa --- /dev/null +++ b/docs/content/api/rl/base.md @@ -0,0 +1,19 @@ +# RL4COLitModule + +The `RL4COLitModule` is a wrapper around PyTorch Lightning's `LightningModule` that provides additional functionality for RL algorithms. It is the parent class for all RL algorithms in the library. + +::: models.rl.common.base.RL4COLitModule + + +## Transductive Learning + +Transductive models are learning algorithms that optimize on a specific instance. They improve solutions by updating policy parameters $\theta$, which means that we are running optimization (backprop) **at test time**. Transductive learning can be performed with different policies: for example EAS updates (a part of) AR policies parameters to obtain better solutions, but I guess there are ways (or papers out there I don't know of) that optimize at test time. + + +!!! tip + You may refer to the definition of [inductive vs transductive RL](https://en.wikipedia.org/wiki/Transduction_(machine_learning)) . In inductive RL, we train to generalize to new instances. In transductive RL we train (or finetune) to solve only specific ones. + + +:::models.common.transductive.base + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/content/api/rl/ppo.md b/docs/content/api/rl/ppo.md new file mode 100644 index 00000000..04c9a4bc --- /dev/null +++ b/docs/content/api/rl/ppo.md @@ -0,0 +1 @@ +:::models.rl.ppo.ppo.PPO \ No newline at end of file diff --git a/docs/content/api/rl/reinforce.md b/docs/content/api/rl/reinforce.md new file mode 100644 index 00000000..60e25ae7 --- /dev/null +++ b/docs/content/api/rl/reinforce.md @@ -0,0 +1,10 @@ +:::models.rl.reinforce.reinforce.REINFORCE +:::models.rl.reinforce.baselines.REINFORCEBaseline +:::models.rl.reinforce.baselines.NoBaseline +:::models.rl.reinforce.baselines.SharedBaseline +:::models.rl.reinforce.baselines.ExponentialBaseline +:::models.rl.reinforce.baselines.MeanBaseline +:::models.rl.reinforce.baselines.WarmupBaseline +:::models.rl.reinforce.baselines.CriticBaseline +:::models.rl.reinforce.baselines.RolloutBaseline +:::models.rl.reinforce.baselines.get_reinforce_baseline diff --git a/docs/content/api/tasks.md b/docs/content/api/tasks.md new file mode 100644 index 00000000..37e0ac7e --- /dev/null +++ b/docs/content/api/tasks.md @@ -0,0 +1,9 @@ +## Train +:::tasks.train + options: + show_root_heading: false + +## Evaluate +:::tasks.eval + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/_theme/rl4co/extensions/__init__.py b/docs/content/api/train_and_eval.md similarity index 100% rename from docs/_theme/rl4co/extensions/__init__.py rename to docs/content/api/train_and_eval.md diff --git a/docs/content/api/zoo/constructive_ar.md b/docs/content/api/zoo/constructive_ar.md new file mode 100644 index 00000000..5391eeb1 --- /dev/null +++ b/docs/content/api/zoo/constructive_ar.md @@ -0,0 +1,113 @@ +# Constructive Autoregressive Methods + +## Attention Model (AM) + +:::models.zoo.am.model + options: + show_root_heading: false + +:::models.zoo.am.policy + options: + show_root_heading: false + +## Attention Model - PPO (AM-PPO) + +:::models.zoo.amppo.model + options: + show_root_heading: false + +## Heterogeneous Attention Model (HAM) + +:::models.zoo.ham.model + options: + show_root_heading: false + +:::models.zoo.ham.policy + options: + show_root_heading: false + +:::models.zoo.ham.encoder + options: + show_root_heading: false + +:::models.zoo.ham.attention + options: + show_root_heading: false + +## Matrix Encoding Network (MatNet) + +:::models.zoo.matnet.model + options: + show_root_heading: false + +:::models.zoo.matnet.policy + options: + show_root_heading: false + +:::models.zoo.matnet.encoder + options: + show_root_heading: false + +:::models.zoo.matnet.decoder + options: + show_root_heading: false + +## Multi-Decoder Attention Model (MDAM) + +:::models.zoo.mdam.model + options: + show_root_heading: false + +:::models.zoo.mdam.policy + options: + show_root_heading: false + +:::models.zoo.mdam.encoder + options: + show_root_heading: false + +:::models.zoo.mdam.decoder + options: + show_root_heading: false + +## POMO + +:::models.zoo.pomo.model + options: + show_root_heading: false + +## Pointer Network (PtrNet) + +:::models.zoo.ptrnet.model + options: + show_root_heading: false + +:::models.zoo.ptrnet.policy + options: + show_root_heading: false + +:::models.zoo.ptrnet.encoder + options: + show_root_heading: false + +:::models.zoo.ptrnet.decoder + options: + show_root_heading: false + +:::models.zoo.ptrnet.critic + options: + show_root_heading: false + +## SymNCO + +:::models.zoo.symnco.model + options: + show_root_heading: false + +:::models.zoo.symnco.policy + options: + show_root_heading: false + +:::models.zoo.symnco.losses + options: + show_root_heading: false diff --git a/docs/content/api/zoo/constructive_nar.md b/docs/content/api/zoo/constructive_nar.md new file mode 100644 index 00000000..3e1860ec --- /dev/null +++ b/docs/content/api/zoo/constructive_nar.md @@ -0,0 +1,27 @@ + +# Constructive NonAutoregressive + +## DeepACO + +:::models.zoo.deepaco.antsystem + options: + show_root_heading: false + +:::models.zoo.deepaco.model + options: + show_root_heading: false + +:::models.zoo.deepaco.policy + options: + show_root_heading: false + + +## NAR-GNN + +:::models.zoo.nargnn.policy + options: + show_root_heading: false + +:::models.zoo.nargnn.encoder + options: + show_root_heading: false diff --git a/docs/content/api/zoo/improvement.md b/docs/content/api/zoo/improvement.md new file mode 100644 index 00000000..8ca68c75 --- /dev/null +++ b/docs/content/api/zoo/improvement.md @@ -0,0 +1,55 @@ +# Improvement Methods + +These methods are trained to improve existing solutions iteratively, akin to local search algorithms. They focus on refining existing solutions rather than generating them from scratch. + +### DACT + +:::models.zoo.dact.encoder + options: + show_root_heading: false + +:::models.zoo.dact.decoder + options: + show_root_heading: false + +:::models.zoo.dact.policy + options: + show_root_heading: false + +:::models.zoo.dact.model + options: + show_root_heading: false + + +### N2S + +:::models.zoo.n2s.encoder + options: + show_root_heading: false + +:::models.zoo.n2s.decoder + options: + show_root_heading: false + +:::models.zoo.n2s.policy + options: + show_root_heading: false + +:::models.zoo.n2s.model + options: + show_root_heading: false + + +### NeuOpt + +:::models.zoo.neuopt.decoder + options: + show_root_heading: false + +:::models.zoo.neuopt.policy + options: + show_root_heading: false + +:::models.zoo.neuopt.model + options: + show_root_heading: false \ No newline at end of file diff --git a/docs/content/api/zoo/transductive.md b/docs/content/api/zoo/transductive.md new file mode 100644 index 00000000..1b7281ad --- /dev/null +++ b/docs/content/api/zoo/transductive.md @@ -0,0 +1,23 @@ +## Transductive Methods + +These methods update policy parameters during online testing to improve the solutions of a specific instance. + +### Active Search (AS) + +:::models.zoo.active_search.search + options: + show_root_heading: false + +### Efficent Active Search (EAS) + +:::models.zoo.eas.search + options: + show_root_heading: false + +:::models.zoo.eas.decoder + options: + show_root_heading: false + +:::models.zoo.eas.nn + options: + show_root_heading: false diff --git a/docs/content/environments/eda.md b/docs/content/environments/eda.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/content/environments/routing.md b/docs/content/environments/routing.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/content/environments/scheduling.md b/docs/content/environments/scheduling.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/content/general/ai4co.md b/docs/content/general/ai4co.md new file mode 100644 index 00000000..66db67a3 --- /dev/null +++ b/docs/content/general/ai4co.md @@ -0,0 +1,14 @@ +# AI4CO Community + +We invite you to join our AI4CO community, an open and inclusive research group in Artificial Intelligence (AI) for Combinatorial Optimization (CO)! + + +## Links +- [GitHub](https://github.com/ai4co) +- [Slack](https://bit.ly/ai4co-slack) +- [Website](https://ai4co.org) (coming soon!) + + +
+ AI4CO Logo +
\ No newline at end of file diff --git a/docs/_content/general/contribute.md b/docs/content/general/contribute.md similarity index 100% rename from docs/_content/general/contribute.md rename to docs/content/general/contribute.md diff --git a/docs/content/general/faq.md b/docs/content/general/faq.md new file mode 100644 index 00000000..c84cb0f6 --- /dev/null +++ b/docs/content/general/faq.md @@ -0,0 +1,11 @@ +# FAQ + + + +You can submit your questions via [GitHub Issues](https://github.com/ai4co/rl4co/discussions) or [Discussions](https://github.com/ai4co/rl4co/discussions). You may search for your question in the existing issues or discussions before submitting a new one. + + +If ask more than a few times, we will add it here! + + + diff --git a/docs/content/intro/environments.md b/docs/content/intro/environments.md new file mode 100644 index 00000000..4de3c555 --- /dev/null +++ b/docs/content/intro/environments.md @@ -0,0 +1,28 @@ +## Definition + +Given a CO problem instance $\mathbf{x}$, we formulate the solution-generating procedure as a Markov Decision Process (MDP) characterized by a tuple $(\mathcal{S}, \mathcal{A}, \mathcal{T}, \mathcal{R}, \gamma)$ as follows: + +- **State** $\mathcal{S}$ is the space of states that represent the given problem $\mathbf{x}$ and the current partial solution being updated in the MDP. +- **Action** $\mathcal{A}$ is the action space, which includes all feasible actions $a_t$ that can be taken at each step $t$. +- **State Transition** $\mathcal{T}$ is the deterministic state transition function $s_{t+1} = \mathcal{T}(s_t, a_t)$ that updates a state $s_t$ to the next state $s_{t+1}$. +- **Reward** $\mathcal{R}$ is the reward function $\mathcal{R}(s_t, a_t)$ representing the immediate reward received after taking action $a_t$ in state $s_t$. +- **Discount Factor** $\gamma \in [0, 1]$ determines the importance of future rewards. + +Since the state transition is deterministic, we represent the solution for a problem $\mathbf{x}$ as a sequence of $T$ actions $\mathbf{a} = (a_1, \ldots, a_T)$. Then the total return $\sum_{t=1}^T \mathcal{R}(s_t, a_t)$ translates to the negative cost function of the CO problem. + +## Implementation + +Environments in our library fully specify the CO problems and their logic. They are based on the `RL4COEnvBase` class that extends from the [`EnvBase`](https://pytorch.org/rl/stable/reference/generated/torchrl.envs.EnvBase.html#torchrl.envs.EnvBase) in TorchRL. + +Key features: +- A modular `generator` can be provided to the environment. +- The generator provides CO instances to the environment, and different generators can be used to generate different data distributions. +- Static instance data and dynamic variables, such as the current state $s_t$, current solution $\mathbf{a}^k$ for improvement environments, policy actions $a_t$, rewards, and additional information are passed in a *stateless* fashion in a [`TensorDict`](https://pytorch.org/tensordict/stable/reference/generated/tensordict.TensorDict.html?highlight=tensordict#tensordict.TensorDict), that we call `td`, through the environment `reset` and `step` functions. + +Our environment API contains several functions: +- `render` +- `check_solution_validity` +- `select_start_nodes` (i.e., for POMO-based optimization) +- Optional API such as `local_search` for solution improvement + +It's worth noting that our library enhances the efficiency of environments when compared to vanilla TorchRL, by overriding and optimizing some methods in TorchRL [`EnvBase`](https://pytorch.org/rl/stable/reference/generated/torchrl.envs.EnvBase.html#torchrl.envs.EnvBase). For instance, our new `step` method brings a decrease of up to 50% in latency and halves the memory impact by avoiding saving duplicate components in the stateless [`TensorDict`](https://pytorch.org/tensordict/stable/reference/generated/tensordict.TensorDict.html?highlight=tensordict#tensordict.TensorDict). \ No newline at end of file diff --git a/docs/content/intro/intro.md b/docs/content/intro/intro.md new file mode 100644 index 00000000..ea9f6dd2 --- /dev/null +++ b/docs/content/intro/intro.md @@ -0,0 +1,34 @@ +# Introduction + +RL4CO is an extensive Reinforcement Learning (RL) for Combinatorial Optimization (CO) benchmark. Our goal is to provide a unified framework for RL-based CO algorithms, and to facilitate reproducible research in this field, decoupling the science from the engineering. + + + + +## Motivation + +### Why NCO? +Neural Combinatorial Optimization (NCO) is a subfield of AI that aims to solve combinatorial optimization problems using neural networks. NCO has been successfully applied to a wide range of problems, such as the routing problems in logistics, the scheduling problems in manufacturing, and electronic design automation. The key idea behind NCO is to learn a policy that maps the input data to the optimal solution, without the need for hand-crafted heuristics or domain-specific knowledge. + + +### Why RL? +Reinforcement Learning (RL) is a machine learning paradigm that enables agents to learn how to make decisions by interacting with an environment. RL has been successfully applied to a wide range of problems, such as playing games, controlling robots, and optimizing complex systems. The key idea behind RL is to learn a policy that maps the state of the environment to the optimal action, by maximizing a reward signal. Importantly, optimal solutions are not required for training, as RL agents learn from the feedback they receive from the environment. + + + +## Contents + +We explore in other pages the following components: + +- [Environments](environments.md): Markov Decision Process (MDP) for CO problems and base classes for environments. These are based on [TorchRL](https://pytorch.org/rl/stable/index.html). + +- [Policies](policies.md): the neural networks that are used to solve CO problems and their base classes. These are based on [PyTorch](https://pytorch.org/). + +- [RL Algorithms](rl.md): (broadly: "models"), which are the processes used to train the policies and their base classes. These are based on [PyTorch Lightning](https://lightning.ai/docs/pytorch/stable/). + + +
+ RL4CO-Overview +
+ + diff --git a/docs/content/intro/policies.md b/docs/content/intro/policies.md new file mode 100644 index 00000000..9b5ea4ec --- /dev/null +++ b/docs/content/intro/policies.md @@ -0,0 +1,53 @@ +# Policies + +The policies can be categorized into constructive policies, which generate a solution from scratch, and improvement policies, which refine an existing solution. + +## Constructive policies + +A policy $\pi$ is used to construct a solution from scratch for a given problem instance $\mathbf{x}$. It can be further categorized into autoregressive (AR) and non-autoregressive (NAR) policies. + + +### Autoregressive (AR) policies +An AR policy is composed of an encoder $f$ that maps the instance $\mathbf{x}$ into an embedding space $\mathbf{h}=f(\mathbf{x})$ and by a decoder $g$ that iteratively determines a sequence of actions $\mathbf{a}$ as follows: + +$$ +a_t \sim g(a_t | a_{t-1}, ... ,a_0, s_t, \mathbf{h}), \quad +\pi(\mathbf{a}|\mathbf{x}) \triangleq \prod_{t=1}^{T-1} g(a_{t} | a_{t-1}, \ldots ,a_0, s_t, \mathbf{h}). +$$ + +### Non-autoregressive (NAR) policies +A NAR policy encodes a problem $\mathbf{x}$ into a heuristic $\mathcal{H} = f(\mathbf{x}) \in \mathbb{R}^{N}_{+}$, where $N$ is the number of possible assignments across all decision variables. Each number in $\mathcal{H}$ represents a (unnormalized) probability of a particular assignment. To obtain a solution $\mathbf{a}$ from $\mathcal{H}$, one can sample a sequence of assignments from $\mathcal{H}$ while dynamically masking infeasible assignments to meet problem-specific constraints. It can also guide a search process, e.g., Ant Colony Optimization, or be incorporated into hybrid frameworks. Here, the heuristic helps identify promising transitions and improve the efficiency of finding an optimal or near-optimal solution. + + +
+ +
+ + +## Improvement policies + +A policy can be used for improving an initial solution $\mathbf{a}^{0}=(a_{0}^{0},\ldots, a_{T-1}^{0})$ into another one potentially with higher quality, which can be formulated as follows: + +$$ +\mathbf{a}^k \sim g(\mathbf{a}^{0}, \mathbf{h}), \quad\pi(\mathbf{a}^K|\mathbf{a}^0,\mathbf{x}) \triangleq \prod_{k=1}^{K-1} g(\mathbf{a}^k | \mathbf{a}^{k-1}, ... ,\mathbf{a}^0, \mathbf{h}), +$$ + +where $\mathbf{a}^{k}$ is the $k$-th updated solution and $K$ is the budget for number of improvements. This process allows continuous refinement for a long time to enhance the solution quality. + + + + +## Implementation + +Policies in our library are subclasses of PyTorch's [`nn.Module`](https://pytorch.org/docs/stable/generated/torch.nn.Module.html) and contain the encoding-decoding logic and neural network parameters $\theta$. Different policies in the RL4CO "zoo" can inherit from metaclasses like `ConstructivePolicy` or `ImprovementPolicy`. We modularize components to process raw features into the embedding space via a parametrized function $\phi_\omega$, called *feature embeddings*. + +1. *Node Embeddings $\phi_n$*: transform $m_n$ node features of instances $\mathbf{x}$ from the feature space to the embedding space $h$, i.e., $[B, N, m_n] \rightarrow [B, N, h]$. +2. *Edge Embeddings $\phi_e$*: transform $m_e$ edge features of instances $\mathbf{x}$ from the feature space to the embedding space $h$, i.e., $[B, E, m_e] \rightarrow [B, E, h]$, where $E$ is the number of edges. +3. *Context Embeddings $\phi_c$*: capture contextual information by transforming $m_c$ context features from the current decoding step $s_t$ from the feature space to the embedding space $h$, i.e., $[B, m_c] \rightarrow [B, h]$, for nodes or edges. + +
+ +
+ + + Embeddings can be automatically selected by our library at runtime by simply passing the `env_name` to the policy. Additionally, we allow for granular control of any higher-level policy component independently, such as encoders and decoders. \ No newline at end of file diff --git a/docs/content/intro/rl.md b/docs/content/intro/rl.md new file mode 100644 index 00000000..1e4510cf --- /dev/null +++ b/docs/content/intro/rl.md @@ -0,0 +1,43 @@ +# RL Algorithms + + +## Definitions + +The RL objective is to learn a policy $\pi$ that maximizes the expected cumulative reward (or equivalently minimizes the cost) over the distribution of problem instances: + +$$ +\theta^{*} = \underset{\theta}{\text{argmax}} \, \mathbb{E}_{\mathbf{x} \sim P(\mathbf{x})} \left[ \mathbb{E}_{\pi(\mathbf{a}|\mathbf{x})} \left[ \sum_{t=0}^{T-1} \gamma^t \mathcal{R}(s_t, a_t) \right] \right], +$$ + +where $\theta$ is the set of parameters of $\pi$ and $P(\mathbf{x})$ is the distribution of problem instances. + +This equation can be solved using algorithms such as variations of REINFORCE, Advantage Actor-Critic (A2C) methods, or Proximal Policy Optimization (PPO). + +These algorithms are employed to train the policy network $\pi$, by transforming the maximization problem into a minimization problem involving a loss function, which is then optimized using gradient descent algorithms. For instance, the REINFORCE loss function gradient is given by: + +$$ +\nabla_{\theta} \mathcal{L}_a(\theta|\mathbf{x}) = \mathbb{E}_{\pi(\mathbf{a}|\mathbf{x})} \left[(R(\mathbf{a}, \mathbf{x}) - b(\mathbf{x})) \nabla_{\theta}\log \pi(\mathbf{a}|\mathbf{x})\right], +$$ + +where $b(\cdot)$ is a baseline function used to stabilize training and reduce gradient variance. + +We also distinguish between two types of RL (pre)training: + +1. *Inductive RL*: The focus is on learning patterns from the training dataset to generalize to new instances, thus amortizing the inference procedure. +2. *Transductive RL* (or test-time optimization): Optimizes parameters during testing on target instances. + +Typically, a policy $\pi$ is trained using inductive RL, followed by transductive RL for test-time optimization. + +### Implementation + +RL algorithms in our library define the process that takes the `Environment` with its problem instances and the `Policy` to optimize its parameters $\theta$. The parent class of algorithms is the `RL4COLitModule`, inheriting from PyTorch Lightning's [`pl.LightningModule`](https://lightning.ai/docs/pytorch/stable/common/lightning_module.html). This allows for granular support of various methods including the `[train, val, test]_step`, automatic logging with several logging services such as Wandb via `log_metrics`, automatic optimizer configuration via `configure_optimizers` and several useful callbacks for RL methods such as `on_train_epoch_end`. + +RL algorithms are additionally attached to an `RL4COTrainer`, a wrapper we made with additional optimizations around `pl.Trainer`. This module seamlessly supports features of modern training pipelines, including: + +- Logging +- Checkpoint management +- Mixed-precision training +- Various hardware acceleration supports (e.g., CPU, GPU, TPU, and Apple Silicon) +- Multi-device hardware accelerator in distributed settings + +For instance, using mixed-precision training significantly decreases training time without sacrificing much convergence and enables us to leverage recent routines, e.g., FlashAttention. \ No newline at end of file diff --git a/docs/_content/start/hydra.md b/docs/content/start/hydra.md similarity index 90% rename from docs/_content/start/hydra.md rename to docs/content/start/hydra.md index 9126fae2..c34d570c 100644 --- a/docs/_content/start/hydra.md +++ b/docs/content/start/hydra.md @@ -9,8 +9,8 @@ Train model with default configuration (AM on TSP environment): python run.py ``` -> [!TIP] -> You may check out [this notebook](examples/advanced/1-hydra-config.ipynb) to get started with Hydra! +!!! tip + You may check out [this notebook](examples/advanced/1-hydra-config.ipynb) to get started with Hydra! ### Change experiment diff --git a/docs/_content/start/installation.md b/docs/content/start/installation.md similarity index 100% rename from docs/_content/start/installation.md rename to docs/content/start/installation.md diff --git a/docs/hooks.py b/docs/hooks.py new file mode 100644 index 00000000..24d6640b --- /dev/null +++ b/docs/hooks.py @@ -0,0 +1,52 @@ +import logging +import os +import shutil +from textwrap import dedent + +log = logging.getLogger("mkdocs") + +# Global variable to store the paths of created __init__.py files +created_files = [] + + +def on_startup(*args, **kwargs): + log.info("Creating missing __init__.py files in rl4co package") + for subdir, dirs, files in os.walk("rl4co"): + if "__init__.py" not in files: + init_file_path = os.path.join(subdir, "__init__.py") + with open(init_file_path, "w"): + pass # empty file + created_files.append(init_file_path) + log.info(f"{len(created_files)} __init__.py files created") + + # huge trick: we save a backup of README.md and append CSS content to hide some elements + log.info("Saving backup of README.md and appending CSS content") + shutil.copyfile("README.md", "README_backup.md") + # warning: don't touch any of the following. you have been warned :) + def append_tricks_to_readme(file_path): + # read the tricks from docs/overrides/fancylogo.txt + # and put them at the beginning of the file + with open("docs/overrides/fancylogo.txt", 'r') as fancylogo: + tricks = fancylogo.read() + if not os.path.exists(file_path): + print(f"Error: The file {file_path} does not exist.") + return + with open(file_path, 'r') as original: + data = original.read() + # remove first 33 lines. yeah, it's a hack to remove unneded stuff lol + data = '\n'.join(data.split('\n')[33:]) + with open(file_path, 'w') as modified: + modified.write(tricks + data) + print(f"CSS content has been appended to {file_path}") + + append_tricks_to_readme("README.md") + + +def on_shutdown(*args, **kwargs): + log.info(f"Removing {len(created_files)} created __init__.py files") + for file_path in created_files: + if os.path.exists(file_path): + os.remove(file_path) + + log.info("Replace README.md with README_backup.md") + shutil.move("README_backup.md", "README.md") \ No newline at end of file diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 87aae5fd..00000000 --- a/docs/index.md +++ /dev/null @@ -1,121 +0,0 @@ -# RL4CO - -
- -
- AI4CO Logo -
- -

- -An extensive Reinforcement Learning (RL) for Combinatorial Optimization (CO) benchmark. Our goal is to provide a unified framework for RL-based CO algorithms, and to facilitate reproducible research in this field, decoupling the science from the engineering. - -PyTorch -Lightning -base: TorchRL -config: Hydra [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) - -[![License: MIT](https://img.shields.io/badge/License-MIT-red.svg)](https://opensource.org/licenses/MIT) [![PyPI](https://img.shields.io/pypi/v/rl4co?logo=pypi)](https://pypi.org/project/rl4co) -[![Test](https://github.com/ai4co/rl4co/actions/workflows/tests.yml/badge.svg)](https://github.com/ai4co/rl4co/actions/workflows/tests.yml) - - - -
- - -RL4CO is built upon: -- [TorchRL](https://github.com/pytorch/rl): official PyTorch framework for RL algorithms and vectorized environments on GPUs -- [TensorDict](https://github.com/pytorch-labs/tensordict): a library to easily handle heterogeneous data such as states, actions and rewards -- [PyTorch Lightning](https://github.com/Lightning-AI/lightning): a lightweight PyTorch wrapper for high-performance AI research -- [Hydra](https://github.com/facebookresearch/hydra): a framework for elegantly configuring complex applications - -image - - -```{eval-rst} -.. toctree:: - :maxdepth: 3 - :caption: Getting started - - _content/start/installation - _collections/1-quickstart - _content/start/hydra - _content/api/models/common/__init__ - - -.. toctree:: - :maxdepth: 3 - :caption: Tutorials - - _collections/2-full-training - _collections/3-creating-new-env-model - _collections/modeling/1-decoding-strategies - _collections/modeling/2-transductive-methods - _collections/modeling/3-change-encoder - _collections/advanced/1-hydra-config - -.. toctree:: - :maxdepth: 3 - :caption: RL Algorithms - - _content/api/algos/base - _content/api/algos/reinforce - _content/api/algos/a2c - _content/api/algos/ppo - - -.. toctree:: - :maxdepth: 3 - :caption: Environments - - _content/api/envs/base - _content/api/envs/eda - _content/api/envs/routing - _content/api/envs/scheduling - -.. toctree:: - :maxdepth: 3 - :caption: Networks - - _content/api/models/nn - _content/api/models/env_embeddings - -.. toctree:: - :maxdepth: 3 - :caption: Base NCO Methods - - _content/api/models/common/constructive - _content/api/models/common/improvement - _content/api/models/common/transductive - - -.. toctree:: - :maxdepth: 3 - :caption: Model Zoo - - _content/api/models/common/zoo/__init__ - _content/api/models/common/zoo/constructive - _content/api/models/common/zoo/improvement - _content/api/models/common/zoo/transductive - -.. toctree:: - :maxdepth: 3 - :caption: Additional API - - _content/api/tasks - _content/api/decoding - _content/api/data - -.. toctree:: - :maxdepth: 3 - :caption: Other - - _content/general/contribute - _content/general/faq -``` - - -## Contributors - - - \ No newline at end of file diff --git a/docs/js/autolink.js b/docs/js/autolink.js new file mode 100644 index 00000000..30a295a5 --- /dev/null +++ b/docs/js/autolink.js @@ -0,0 +1,34 @@ +const convertLinks = ( input ) => { + + let text = input; + const linksFound = text.match( /(?:www|https?)[^\s]+/g ); + const aLink = []; + + if ( linksFound != null ) { + + for ( let i=0; i' ) + } + else if ( linkText.match( /vimeo/ ) ) { + let vimeoID = replace.split( '/' ).slice(-1)[0]; + aLink.push( '
' ) + } + else { + aLink.push( '' + linkText + '' ); + } + text = text.split( linksFound[i] ).map(item => { return aLink[i].includes('iframe') ? item.trim() : item } ).join( aLink[i] ); + } + return text; + + } + else { + return input; + } + } \ No newline at end of file diff --git a/docs/js/katex.js b/docs/js/katex.js new file mode 100644 index 00000000..841e35ad --- /dev/null +++ b/docs/js/katex.js @@ -0,0 +1,10 @@ +document$.subscribe(({ body }) => { + renderMathInElement(body, { + delimiters: [ + { left: "$$", right: "$$", display: true }, + { left: "$", right: "$", display: false }, + { left: "\\(", right: "\\)", display: false }, + { left: "\\[", right: "\\]", display: true } + ], + }) +}) \ No newline at end of file diff --git a/docs/js/tsparticles.js b/docs/js/tsparticles.js new file mode 100644 index 00000000..bf96e09b --- /dev/null +++ b/docs/js/tsparticles.js @@ -0,0 +1,2 @@ +/*! For license information please see tsparticles.bundle.min.js.LICENSE.txt */ +!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i=e();for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},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,{AnimatableColor:()=>Se,AnimationOptions:()=>Me,AnimationValueWithRandom:()=>Ee,Background:()=>le,BackgroundMask:()=>de,BackgroundMaskCover:()=>he,Circle:()=>yi,ClickEvent:()=>pe,Collisions:()=>Fe,CollisionsAbsorb:()=>De,CollisionsOverlap:()=>Te,ColorAnimation:()=>Pe,DivEvent:()=>fe,Events:()=>ge,ExternalInteractorBase:()=>Si,FullScreen:()=>ue,HoverEvent:()=>ye,HslAnimation:()=>Oe,HslColorManager:()=>Pi,Interactivity:()=>we,ManualParticle:()=>xe,Modes:()=>be,Move:()=>Xe,MoveAngle:()=>qe,MoveAttract:()=>He,MoveCenter:()=>Ve,MoveGravity:()=>Ue,MovePath:()=>We,MoveTrail:()=>je,Opacity:()=>Ze,OpacityAnimation:()=>Ye,Options:()=>li,OptionsColor:()=>ce,OutModes:()=>Ge,Parallax:()=>ve,ParticlesBounce:()=>Ae,ParticlesBounceFactor:()=>Le,ParticlesDensity:()=>Qe,ParticlesInteractorBase:()=>Di,ParticlesNumber:()=>Ke,ParticlesNumberLimit:()=>Je,ParticlesOptions:()=>ai,Point:()=>pi,Range:()=>fi,RangedAnimationOptions:()=>Ce,RangedAnimationValueWithRandom:()=>Ie,Rectangle:()=>vi,ResizeEvent:()=>me,Responsive:()=>_e,RgbColorManager:()=>Oi,Shadow:()=>ti,Shape:()=>ei,Size:()=>si,SizeAnimation:()=>ii,Spin:()=>Ne,Stroke:()=>oi,Theme:()=>ze,ThemeDefault:()=>ke,ValueWithRandom:()=>Re,Vector:()=>y,Vector3d:()=>v,ZIndex:()=>ni,addColorManager:()=>Pt,addEasing:()=>b,alterHsl:()=>se,areBoundsInside:()=>et,arrayRandomIndex:()=>J,calcExactPositionOrRandomFromSize:()=>B,calcExactPositionOrRandomFromSizeRanged:()=>q,calcPositionFromSize:()=>L,calcPositionOrRandomFromSize:()=>A,calcPositionOrRandomFromSizeRanged:()=>F,calculateBounds:()=>it,circleBounce:()=>lt,circleBounceDataFromParticle:()=>ct,clamp:()=>k,clear:()=>Zt,collisionVelocity:()=>I,colorMix:()=>Vt,colorToHsl:()=>Tt,colorToRgb:()=>Dt,deepExtend:()=>st,divMode:()=>rt,divModeExecute:()=>nt,drawEffect:()=>Jt,drawLine:()=>Nt,drawParticle:()=>Qt,drawParticlePlugin:()=>ie,drawPlugin:()=>ee,drawShape:()=>Kt,drawShapeAfterDraw:()=>te,errorPrefix:()=>f,executeOnSingleOrMultiple:()=>dt,findItemFromSingleOrMultiple:()=>pt,generatedAttribute:()=>i,getDistance:()=>T,getDistances:()=>D,getEasing:()=>w,getHslAnimationFromHsl:()=>jt,getHslFromAnimation:()=>$t,getLinkColor:()=>Ut,getLinkRandomColor:()=>Wt,getLogger:()=>W,getParticleBaseVelocity:()=>E,getParticleDirectionAngle:()=>R,getPosition:()=>yt,getRandom:()=>_,getRandomRgbColor:()=>Bt,getRangeMax:()=>O,getRangeMin:()=>P,getRangeValue:()=>C,getSize:()=>mt,getStyleFromHsl:()=>Ht,getStyleFromRgb:()=>qt,hasMatchMedia:()=>G,hslToRgb:()=>At,hslaToRgba:()=>Ft,initParticleNumericAnimationValue:()=>ft,isArray:()=>kt,isBoolean:()=>gt,isDivModeEnabled:()=>ot,isFunction:()=>xt,isInArray:()=>Z,isNumber:()=>wt,isObject:()=>_t,isPointInside:()=>tt,isSsr:()=>j,isString:()=>bt,itemFromArray:()=>K,itemFromSingleOrMultiple:()=>ut,loadFont:()=>Q,loadFull:()=>gn,loadOptions:()=>ri,loadParticlesOptions:()=>ci,loadSlim:()=>an,mix:()=>z,mouseDownEvent:()=>s,mouseLeaveEvent:()=>n,mouseMoveEvent:()=>r,mouseOutEvent:()=>a,mouseUpEvent:()=>o,paintBase:()=>Xt,paintImage:()=>Yt,parseAlpha:()=>H,randomInRange:()=>M,rangeColorToHsl:()=>Rt,rangeColorToRgb:()=>St,rectBounce:()=>ht,resizeEvent:()=>u,rgbToHsl:()=>Et,safeIntersectionObserver:()=>X,safeMatchMedia:()=>N,safeMutationObserver:()=>Y,setLogger:()=>U,setRandom:()=>x,setRangeValue:()=>S,singleDivModeExecute:()=>at,stringToAlpha:()=>It,stringToRgb:()=>Lt,touchCancelEvent:()=>d,touchEndEvent:()=>l,touchMoveEvent:()=>h,touchStartEvent:()=>c,tsParticles:()=>Ti,visibilityChangeEvent:()=>p});const i="generated",s="pointerdown",o="pointerup",n="pointerleave",a="pointerout",r="pointermove",c="touchstart",l="touchend",h="touchmove",d="touchcancel",u="resize",p="visibilitychange",f="tsParticles - Error";class v{constructor(t,e,i){if(this._updateFromAngle=(t,e)=>{this.x=Math.cos(t)*e,this.y=Math.sin(t)*e},!wt(t)&&t){this.x=t.x,this.y=t.y;const e=t;this.z=e.z?e.z:0}else{if(void 0===t||void 0===e)throw new Error(`${f} Vector3d not initialized correctly`);this.x=t,this.y=e,this.z=i??0}}static get origin(){return v.create(0,0,0)}get angle(){return Math.atan2(this.y,this.x)}set angle(t){this._updateFromAngle(t,this.length)}get length(){return Math.sqrt(this.getLengthSq())}set length(t){this._updateFromAngle(this.angle,t)}static clone(t){return v.create(t.x,t.y,t.z)}static create(t,e,i){return new v(t,e,i)}add(t){return v.create(this.x+t.x,this.y+t.y,this.z+t.z)}addTo(t){this.x+=t.x,this.y+=t.y,this.z+=t.z}copy(){return v.clone(this)}distanceTo(t){return this.sub(t).length}distanceToSq(t){return this.sub(t).getLengthSq()}div(t){return v.create(this.x/t,this.y/t,this.z/t)}divTo(t){this.x/=t,this.y/=t,this.z/=t}getLengthSq(){return this.x**2+this.y**2}mult(t){return v.create(this.x*t,this.y*t,this.z*t)}multTo(t){this.x*=t,this.y*=t,this.z*=t}normalize(){const t=this.length;0!=t&&this.multTo(1/t)}rotate(t){return v.create(this.x*Math.cos(t)-this.y*Math.sin(t),this.x*Math.sin(t)+this.y*Math.cos(t),0)}setTo(t){this.x=t.x,this.y=t.y;const e=t;this.z=e.z?e.z:0}sub(t){return v.create(this.x-t.x,this.y-t.y,this.z-t.z)}subFrom(t){this.x-=t.x,this.y-=t.y,this.z-=t.z}}class y extends v{constructor(t,e){super(t,e,0)}static get origin(){return y.create(0,0)}static clone(t){return y.create(t.x,t.y)}static create(t,e){return new y(t,e)}}let m=Math.random;const g=new Map;function b(t,e){g.get(t)||g.set(t,e)}function w(t){return g.get(t)||(t=>t)}function x(t=Math.random){m=t}function _(){return k(m(),0,1-1e-16)}function k(t,e,i){return Math.min(Math.max(t,e),i)}function z(t,e,i,s){return Math.floor((t*i+e*s)/(i+s))}function M(t){const e=O(t);let i=P(t);return e===i&&(i=0),_()*(e-i)+i}function C(t){return wt(t)?t:M(t)}function P(t){return wt(t)?t:t.min}function O(t){return wt(t)?t:t.max}function S(t,e){if(t===e||void 0===e&&wt(t))return t;const i=P(t),s=O(t);return void 0!==e?{min:Math.min(i,e),max:Math.max(s,e)}:S(i,s)}function D(t,e){const i=t.x-e.x,s=t.y-e.y;return{dx:i,dy:s,distance:Math.sqrt(i**2+s**2)}}function T(t,e){return D(t,e).distance}function R(t,e,i){if(wt(t))return t*Math.PI/180;switch(t){case"top":return.5*-Math.PI;case"top-right":return.25*-Math.PI;case"right":return 0;case"bottom-right":return.25*Math.PI;case"bottom":return.5*Math.PI;case"bottom-left":return.75*Math.PI;case"left":return Math.PI;case"top-left":return.75*-Math.PI;case"inside":return Math.atan2(i.y-e.y,i.x-e.x);case"outside":return Math.atan2(e.y-i.y,e.x-i.x);default:return _()*Math.PI*2}}function E(t){const e=y.origin;return e.length=1,e.angle=t,e}function I(t,e,i,s){return y.create(t.x*(i-s)/(i+s)+2*e.x*s/(i+s),t.y)}function L(t){return t.position&&void 0!==t.position.x&&void 0!==t.position.y?{x:t.position.x*t.size.width/100,y:t.position.y*t.size.height/100}:void 0}function A(t){return{x:(t.position?.x??100*_())*t.size.width/100,y:(t.position?.y??100*_())*t.size.height/100}}function F(t){const e={x:void 0!==t.position?.x?C(t.position.x):void 0,y:void 0!==t.position?.y?C(t.position.y):void 0};return A({size:t.size,position:e})}function B(t){return{x:t.position?.x??_()*t.size.width,y:t.position?.y??_()*t.size.height}}function q(t){const e={x:void 0!==t.position?.x?C(t.position.x):void 0,y:void 0!==t.position?.y?C(t.position.y):void 0};return B({size:t.size,position:e})}function H(t){return t?t.endsWith("%")?parseFloat(t)/100:parseFloat(t):1}const V={debug:console.debug,error:console.error,info:console.info,log:console.log,verbose:console.log,warning:console.warn};function U(t){V.debug=t.debug||V.debug,V.error=t.error||V.error,V.info=t.info||V.info,V.log=t.log||V.log,V.verbose=t.verbose||V.verbose,V.warning=t.warning||V.warning}function W(){return V}function $(t){const e={bounced:!1},{pSide:i,pOtherSide:s,rectSide:o,rectOtherSide:n,velocity:a,factor:r}=t;return s.minn.max||s.maxn.max||(i.max>=o.min&&i.max<=.5*(o.max+o.min)&&a>0||i.min<=o.max&&i.min>.5*(o.max+o.min)&&a<0)&&(e.velocity=a*-r,e.bounced=!0),e}function j(){return"undefined"==typeof window||!window||void 0===window.document||!window.document}function G(){return!j()&&"undefined"!=typeof matchMedia}function N(t){if(G())return matchMedia(t)}function X(t){if(!j()&&"undefined"!=typeof IntersectionObserver)return new IntersectionObserver(t)}function Y(t){if(!j()&&"undefined"!=typeof MutationObserver)return new MutationObserver(t)}function Z(t,e){return t===e||kt(e)&&e.indexOf(t)>-1}async function Q(t,e){try{await document.fonts.load(`${e??"400"} 36px '${t??"Verdana"}'`)}catch{}}function J(t){return Math.floor(_()*t.length)}function K(t,e,i=!0){return t[void 0!==e&&i?e%t.length:J(t)]}function tt(t,e,i,s,o){return et(it(t,s??0),e,i,o)}function et(t,e,i,s){let o=!0;return s&&"bottom"!==s||(o=t.topi.x),!o||s&&"right"!==s||(o=t.lefti.y),o}function it(t,e){return{bottom:t.y+e,left:t.x-e,right:t.x+e,top:t.y-e}}function st(t,...e){for(const i of e){if(null==i)continue;if(!_t(i)){t=i;continue}const e=Array.isArray(i);!e||!_t(t)&&t&&Array.isArray(t)?e||!_t(t)&&t&&!Array.isArray(t)||(t={}):t=[];for(const e in i){if("__proto__"===e)continue;const s=i[e],o=t;o[e]=_t(s)&&Array.isArray(s)?s.map((t=>st(o[e],t))):st(o[e],s)}}return t}function ot(t,e){return!!pt(e,(e=>e.enable&&Z(t,e.mode)))}function nt(t,e,i){dt(e,(e=>{const s=e.mode;e.enable&&Z(t,s)&&at(e,i)}))}function at(t,e){dt(t.selectors,(i=>{e(i,t)}))}function rt(t,e){if(e&&t)return pt(t,(t=>function(t,e){const i=dt(e,(e=>t.matches(e)));return kt(i)?i.some((t=>t)):i}(e,t.selectors)))}function ct(t){return{position:t.getPosition(),radius:t.getRadius(),mass:t.getMass(),velocity:t.velocity,factor:y.create(C(t.options.bounce.horizontal.value),C(t.options.bounce.vertical.value))}}function lt(t,e){const{x:i,y:s}=t.velocity.sub(e.velocity),[o,n]=[t.position,e.position],{dx:a,dy:r}=D(n,o);if(i*a+s*r<0)return;const c=-Math.atan2(r,a),l=t.mass,h=e.mass,d=t.velocity.rotate(c),u=e.velocity.rotate(c),p=I(d,u,l,h),f=I(u,d,l,h),v=p.rotate(-c),y=f.rotate(-c);t.velocity.x=v.x*t.factor.x,t.velocity.y=v.y*t.factor.y,e.velocity.x=y.x*e.factor.x,e.velocity.y=y.y*e.factor.y}function ht(t,e){const i=it(t.getPosition(),t.getRadius()),s=t.options.bounce,o=$({pSide:{min:i.left,max:i.right},pOtherSide:{min:i.top,max:i.bottom},rectSide:{min:e.left,max:e.right},rectOtherSide:{min:e.top,max:e.bottom},velocity:t.velocity.x,factor:C(s.horizontal.value)});o.bounced&&(void 0!==o.velocity&&(t.velocity.x=o.velocity),void 0!==o.position&&(t.position.x=o.position));const n=$({pSide:{min:i.top,max:i.bottom},pOtherSide:{min:i.left,max:i.right},rectSide:{min:e.top,max:e.bottom},rectOtherSide:{min:e.left,max:e.right},velocity:t.velocity.y,factor:C(s.vertical.value)});n.bounced&&(void 0!==n.velocity&&(t.velocity.y=n.velocity),void 0!==n.position&&(t.position.y=n.position))}function dt(t,e){return kt(t)?t.map(((t,i)=>e(t,i))):e(t,0)}function ut(t,e,i){return kt(t)?K(t,e,i):t}function pt(t,e){return kt(t)?t.find(((t,i)=>e(t,i))):e(t,0)?t:void 0}function ft(t,e){const i=t.value,s=t.animation,o={delayTime:1e3*C(s.delay),enable:s.enable,value:C(t.value)*e,max:O(i)*e,min:P(i)*e,loops:0,maxLoops:C(s.count),time:0};if(s.enable){switch(o.decay=1-C(s.decay),s.mode){case"increase":o.status="increasing";break;case"decrease":o.status="decreasing";break;case"random":o.status=_()>=.5?"increasing":"decreasing"}const t="auto"===s.mode;switch(s.startValue){case"min":o.value=o.min,t&&(o.status="increasing");break;case"max":o.value=o.max,t&&(o.status="decreasing");break;default:o.value=M(o),t&&(o.status=_()>=.5?"increasing":"decreasing")}}return o.initialValue=o.value,o}function vt(t,e){if(!("percent"===t.mode)){const{mode:e,...i}=t;return i}return"x"in t?{x:t.x/100*e.width,y:t.y/100*e.height}:{width:t.width/100*e.width,height:t.height/100*e.height}}function yt(t,e){return vt(t,e)}function mt(t,e){return vt(t,e)}function gt(t){return"boolean"==typeof t}function bt(t){return"string"==typeof t}function wt(t){return"number"==typeof t}function xt(t){return"function"==typeof t}function _t(t){return"object"==typeof t&&null!==t}function kt(t){return Array.isArray(t)}const zt="random",Mt="mid",Ct=new Map;function Pt(t){Ct.set(t.key,t)}function Ot(t){for(const[,e]of Ct)if(t.startsWith(e.stringPrefix))return e.parseString(t);const e=t.replace(/^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i,((t,e,i,s,o)=>e+e+i+i+s+s+(void 0!==o?o+o:""))),i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(e);return i?{a:void 0!==i[4]?parseInt(i[4],16)/255:1,b:parseInt(i[3],16),g:parseInt(i[2],16),r:parseInt(i[1],16)}:void 0}function St(t,e,i=!0){if(!t)return;const s=bt(t)?{value:t}:t;if(bt(s.value))return Dt(s.value,e,i);if(kt(s.value))return St({value:K(s.value,e,i)});for(const[,t]of Ct){const e=t.handleRangeColor(s);if(e)return e}}function Dt(t,e,i=!0){if(!t)return;const s=bt(t)?{value:t}:t;if(bt(s.value))return s.value===zt?Bt():Lt(s.value);if(kt(s.value))return Dt({value:K(s.value,e,i)});for(const[,t]of Ct){const e=t.handleColor(s);if(e)return e}}function Tt(t,e,i=!0){const s=Dt(t,e,i);return s?Et(s):void 0}function Rt(t,e,i=!0){const s=St(t,e,i);return s?Et(s):void 0}function Et(t){const e=t.r/255,i=t.g/255,s=t.b/255,o=Math.max(e,i,s),n=Math.min(e,i,s),a={h:0,l:.5*(o+n),s:0};return o!==n&&(a.s=a.l<.5?(o-n)/(o+n):(o-n)/(2-o-n),a.h=e===o?(i-s)/(o-n):a.h=i===o?2+(s-e)/(o-n):4+(e-i)/(o-n)),a.l*=100,a.s*=100,a.h*=60,a.h<0&&(a.h+=360),a.h>=360&&(a.h-=360),a}function It(t){return Ot(t)?.a}function Lt(t){return Ot(t)}function At(t){const e=(t.h%360+360)%360,i=Math.max(0,Math.min(100,t.s)),s=e/360,o=i/100,n=Math.max(0,Math.min(100,t.l))/100;if(0===i){const t=Math.round(255*n);return{r:t,g:t,b:t}}const a=(t,e,i)=>(i<0&&(i+=1),i>1&&(i-=1),6*i<1?t+6*(e-t)*i:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t),r=n<.5?n*(1+o):n+o-n*o,c=2*n-r,l=Math.min(255,255*a(c,r,s+1/3)),h=Math.min(255,255*a(c,r,s)),d=Math.min(255,255*a(c,r,s-1/3));return{r:Math.round(l),g:Math.round(h),b:Math.round(d)}}function Ft(t){const e=At(t);return{a:t.a,b:e.b,g:e.g,r:e.r}}function Bt(t){const e=t??0;return{b:Math.floor(M(S(e,256))),g:Math.floor(M(S(e,256))),r:Math.floor(M(S(e,256)))}}function qt(t,e){return`rgba(${t.r}, ${t.g}, ${t.b}, ${e??1})`}function Ht(t,e){return`hsla(${t.h}, ${t.s}%, ${t.l}%, ${e??1})`}function Vt(t,e,i,s){let o=t,n=e;return void 0===o.r&&(o=At(t)),void 0===n.r&&(n=At(e)),{b:z(o.b,n.b,i,s),g:z(o.g,n.g,i,s),r:z(o.r,n.r,i,s)}}function Ut(t,e,i){if(i===zt)return Bt();if(i!==Mt)return i;{const i=t.getFillColor()??t.getStrokeColor(),s=e?.getFillColor()??e?.getStrokeColor();if(i&&s&&e)return Vt(i,s,t.getRadius(),e.getRadius());{const t=i??s;if(t)return At(t)}}}function Wt(t,e,i){const s=bt(t)?t:t.value;return s===zt?i?St({value:s}):e?zt:Mt:s===Mt?Mt:St({value:s})}function $t(t){return void 0!==t?{h:t.h.value,s:t.s.value,l:t.l.value}:void 0}function jt(t,e,i){const s={h:{enable:!1,value:t.h},s:{enable:!1,value:t.s},l:{enable:!1,value:t.l}};return e&&(Gt(s.h,e.h,i),Gt(s.s,e.s,i),Gt(s.l,e.l,i)),s}function Gt(t,e,i){t.enable=e.enable,t.enable?(t.velocity=C(e.speed)/100*i,t.decay=1-C(e.decay),t.status="increasing",t.loops=0,t.maxLoops=C(e.count),t.time=0,t.delayTime=1e3*C(e.delay),e.sync||(t.velocity*=_(),t.value*=_()),t.initialValue=t.value):t.velocity=0}function Nt(t,e,i){t.beginPath(),t.moveTo(e.x,e.y),t.lineTo(i.x,i.y),t.closePath()}function Xt(t,e,i){t.fillStyle=i??"rgba(0,0,0,0)",t.fillRect(0,0,e.width,e.height)}function Yt(t,e,i,s){i&&(t.globalAlpha=s,t.drawImage(i,0,0,e.width,e.height),t.globalAlpha=1)}function Zt(t,e){t.clearRect(0,0,e.width,e.height)}function Qt(t){const{container:e,context:i,particle:s,delta:o,colorStyles:n,backgroundMask:a,composite:r,radius:c,opacity:l,shadow:h,transform:d}=t,u=s.getPosition(),p=s.rotation+(s.pathRotation?s.velocity.angle:0),f=Math.sin(p),v=Math.cos(p),y={a:v*(d.a??1),b:f*(d.b??1),c:-f*(d.c??1),d:v*(d.d??1)};i.setTransform(y.a,y.b,y.c,y.d,u.x,u.y),a&&(i.globalCompositeOperation=r);const m=s.shadowColor;h.enable&&m&&(i.shadowBlur=h.blur,i.shadowColor=qt(m),i.shadowOffsetX=h.offset.x,i.shadowOffsetY=h.offset.y),n.fill&&(i.fillStyle=n.fill);const g=s.strokeWidth??0;i.lineWidth=g,n.stroke&&(i.strokeStyle=n.stroke);const b={container:e,context:i,particle:s,radius:c,opacity:l,delta:o,transformData:y};i.beginPath(),Kt(b),s.shapeClose&&i.closePath(),g>0&&i.stroke(),s.shapeFill&&i.fill(),te(b),Jt(b),i.globalCompositeOperation="source-over",i.setTransform(1,0,0,1,0,0)}function Jt(t){const{container:e,context:i,particle:s,radius:o,opacity:n,delta:a,transformData:r}=t;if(!s.effect)return;const c=e.effectDrawers.get(s.effect);c&&c.draw({context:i,particle:s,radius:o,opacity:n,delta:a,pixelRatio:e.retina.pixelRatio,transformData:{...r}})}function Kt(t){const{container:e,context:i,particle:s,radius:o,opacity:n,delta:a,transformData:r}=t;if(!s.shape)return;const c=e.shapeDrawers.get(s.shape);c&&c.draw({context:i,particle:s,radius:o,opacity:n,delta:a,pixelRatio:e.retina.pixelRatio,transformData:{...r}})}function te(t){const{container:e,context:i,particle:s,radius:o,opacity:n,delta:a,transformData:r}=t;if(!s.shape)return;const c=e.shapeDrawers.get(s.shape);c&&c.afterDraw&&c.afterDraw({context:i,particle:s,radius:o,opacity:n,delta:a,pixelRatio:e.retina.pixelRatio,transformData:{...r}})}function ee(t,e,i){e.draw&&e.draw(t,i)}function ie(t,e,i,s){e.drawParticle&&e.drawParticle(t,i,s)}function se(t,e,i){return{h:t.h,s:t.s,l:t.l+("darken"===e?-1:1)*i}}function oe(t,e,i){const s=e[i];void 0!==s&&(t[i]=(t[i]??1)*s)}class ne{constructor(t){this.container=t,this._applyPostDrawUpdaters=t=>{for(const e of this._postDrawUpdaters)e.afterDraw&&e.afterDraw(t)},this._applyPreDrawUpdaters=(t,e,i,s,o,n)=>{for(const a of this._preDrawUpdaters){if(a.getColorStyles){const{fill:n,stroke:r}=a.getColorStyles(e,t,i,s);n&&(o.fill=n),r&&(o.stroke=r)}if(a.getTransformValues){const t=a.getTransformValues(e);for(const e in t)oe(n,t,e)}a.beforeDraw&&a.beforeDraw(e)}},this._applyResizePlugins=()=>{for(const t of this._resizePlugins)t.resize&&t.resize()},this._getPluginParticleColors=t=>{let e,i;for(const s of this._colorPlugins)if(!e&&s.particleFillColor&&(e=Rt(s.particleFillColor(t))),!i&&s.particleStrokeColor&&(i=Rt(s.particleStrokeColor(t))),e&&i)break;return[e,i]},this._initCover=()=>{const t=this.container.actualOptions.backgroundMask.cover,e=St(t.color);if(e){const i={...e,a:t.opacity};this._coverColorStyle=qt(i,i.a)}},this._initStyle=()=>{const t=this.element,e=this.container.actualOptions;if(t){this._fullScreen?(this._originalStyle=st({},t.style),this._setFullScreenStyle()):this._resetOriginalStyle();for(const i in e.style){if(!i||!e.style)continue;const s=e.style[i];s&&t.style.setProperty(i,s,"important")}}},this._initTrail=async()=>{const t=this.container.actualOptions,e=t.particles.move.trail,i=e.fill;if(e.enable)if(i.color){const e=St(i.color);if(!e)return;const s=t.particles.move.trail;this._trailFill={color:{...e},opacity:1/s.length}}else await new Promise(((t,s)=>{if(!i.image)return;const o=document.createElement("img");o.addEventListener("load",(()=>{this._trailFill={image:o,opacity:1/e.length},t()})),o.addEventListener("error",(t=>{s(t.error)})),o.src=i.image}))},this._paintBase=t=>{this.draw((e=>Xt(e,this.size,t)))},this._paintImage=(t,e)=>{this.draw((i=>Yt(i,this.size,t,e)))},this._repairStyle=()=>{const t=this.element;t&&(this._safeMutationObserver((t=>t.disconnect())),this._initStyle(),this.initBackground(),this._safeMutationObserver((e=>e.observe(t,{attributes:!0}))))},this._resetOriginalStyle=()=>{const t=this.element,e=this._originalStyle;if(!t||!e)return;const i=t.style;i.position=e.position,i.zIndex=e.zIndex,i.top=e.top,i.left=e.left,i.width=e.width,i.height=e.height},this._safeMutationObserver=t=>{this._mutationObserver&&t(this._mutationObserver)},this._setFullScreenStyle=()=>{const t=this.element;if(!t)return;const e="important",i=t.style;i.setProperty("position","fixed",e),i.setProperty("z-index",this.container.actualOptions.fullScreen.zIndex.toString(10),e),i.setProperty("top","0",e),i.setProperty("left","0",e),i.setProperty("width","100%",e),i.setProperty("height","100%",e)},this.size={height:0,width:0},this._context=null,this._generated=!1,this._preDrawUpdaters=[],this._postDrawUpdaters=[],this._resizePlugins=[],this._colorPlugins=[]}get _fullScreen(){return this.container.actualOptions.fullScreen.enable}clear(){const t=this.container.actualOptions,e=t.particles.move.trail,i=this._trailFill;t.backgroundMask.enable?this.paint():e.enable&&e.length>0&&i?i.color?this._paintBase(qt(i.color,i.opacity)):i.image&&this._paintImage(i.image,i.opacity):t.clear&&this.draw((t=>{Zt(t,this.size)}))}destroy(){if(this.stop(),this._generated){const t=this.element;t&&t.remove()}else this._resetOriginalStyle();this._preDrawUpdaters=[],this._postDrawUpdaters=[],this._resizePlugins=[],this._colorPlugins=[]}draw(t){const e=this._context;if(e)return t(e)}drawParticle(t,e){if(t.spawning||t.destroyed)return;const i=t.getRadius();if(i<=0)return;const s=t.getFillColor(),o=t.getStrokeColor()??s;let[n,a]=this._getPluginParticleColors(t);n||(n=s),a||(a=o),(n||a)&&this.draw((s=>{const o=this.container,r=o.actualOptions,c=t.options.zIndex,l=(1-t.zIndexFactor)**c.opacityRate,h=t.bubble.opacity??t.opacity?.value??1,d=h*l,u=(t.strokeOpacity??h)*l,p={},f={fill:n?Ht(n,d):void 0};f.stroke=a?Ht(a,u):f.fill,this._applyPreDrawUpdaters(s,t,i,d,f,p),Qt({container:o,context:s,particle:t,delta:e,colorStyles:f,backgroundMask:r.backgroundMask.enable,composite:r.backgroundMask.composite,radius:i*(1-t.zIndexFactor)**c.sizeRate,opacity:d,shadow:t.options.shadow,transform:p}),this._applyPostDrawUpdaters(t)}))}drawParticlePlugin(t,e,i){this.draw((s=>ie(s,t,e,i)))}drawPlugin(t,e){this.draw((i=>ee(i,t,e)))}async init(){this._safeMutationObserver((t=>t.disconnect())),this._mutationObserver=Y((t=>{for(const e of t)"attributes"===e.type&&"style"===e.attributeName&&this._repairStyle()})),this.resize(),this._initStyle(),this._initCover();try{await this._initTrail()}catch(t){W().error(t)}this.initBackground(),this._safeMutationObserver((t=>{this.element&&t.observe(this.element,{attributes:!0})})),this.initUpdaters(),this.initPlugins(),this.paint()}initBackground(){const t=this.container.actualOptions.background,e=this.element;if(!e)return;const i=e.style;if(i){if(t.color){const e=St(t.color);i.backgroundColor=e?qt(e,t.opacity):""}else i.backgroundColor="";i.backgroundImage=t.image||"",i.backgroundPosition=t.position||"",i.backgroundRepeat=t.repeat||"",i.backgroundSize=t.size||""}}initPlugins(){this._resizePlugins=[];for(const[,t]of this.container.plugins)t.resize&&this._resizePlugins.push(t),(t.particleFillColor||t.particleStrokeColor)&&this._colorPlugins.push(t)}initUpdaters(){this._preDrawUpdaters=[],this._postDrawUpdaters=[];for(const t of this.container.particles.updaters)t.afterDraw&&this._postDrawUpdaters.push(t),(t.getColorStyles||t.getTransformValues||t.beforeDraw)&&this._preDrawUpdaters.push(t)}loadCanvas(t){this._generated&&this.element&&this.element.remove(),this._generated=t.dataset&&i in t.dataset?"true"===t.dataset[i]:this._generated,this.element=t,this.element.ariaHidden="true",this._originalStyle=st({},this.element.style),this.size.height=t.offsetHeight,this.size.width=t.offsetWidth,this._context=this.element.getContext("2d"),this._safeMutationObserver((t=>{this.element&&t.observe(this.element,{attributes:!0})})),this.container.retina.init(),this.initBackground()}paint(){const t=this.container.actualOptions;this.draw((e=>{t.backgroundMask.enable&&t.backgroundMask.cover?(Zt(e,this.size),this._paintBase(this._coverColorStyle)):this._paintBase()}))}resize(){if(!this.element)return!1;const t=this.container,e=t.retina.pixelRatio,i=t.canvas.size,s=this.element.offsetWidth*e,o=this.element.offsetHeight*e;if(o===i.height&&s===i.width&&o===this.element.height&&s===this.element.width)return!1;const n={...i};return this.element.width=i.width=this.element.offsetWidth*e,this.element.height=i.height=this.element.offsetHeight*e,this.container.started&&t.particles.setResizeFactor({width:i.width/n.width,height:i.height/n.height}),!0}stop(){this._safeMutationObserver((t=>t.disconnect())),this._mutationObserver=void 0,this.draw((t=>Zt(t,this.size)))}async windowResize(){if(!this.element||!this.resize())return;const t=this.container,e=t.updateActualOptions();t.particles.setDensity(),this._applyResizePlugins(),e&&await t.refresh()}}function ae(t,e,i,s,o){if(s){let s={passive:!0};gt(o)?s.capture=o:void 0!==o&&(s=o),t.addEventListener(e,i,s)}else{const s=o;t.removeEventListener(e,i,s)}}class re{constructor(t){this.container=t,this._doMouseTouchClick=t=>{const e=this.container,i=e.actualOptions;if(this._canPush){const t=e.interactivity.mouse,s=t.position;if(!s)return;t.clickPosition={...s},t.clickTime=(new Date).getTime();dt(i.interactivity.events.onClick.mode,(t=>this.container.handleClickMode(t)))}"touchend"===t.type&&setTimeout((()=>this._mouseTouchFinish()),500)},this._handleThemeChange=t=>{const e=t,i=this.container,s=i.options,o=s.defaultThemes,n=e.matches?o.dark:o.light,a=s.themes.find((t=>t.name===n));a&&a.default.auto&&i.loadTheme(n)},this._handleVisibilityChange=()=>{const t=this.container,e=t.actualOptions;this._mouseTouchFinish(),e.pauseOnBlur&&(document&&document.hidden?(t.pageHidden=!0,t.pause()):(t.pageHidden=!1,t.getAnimationStatus()?t.play(!0):t.draw(!0)))},this._handleWindowResize=async()=>{this._resizeTimeout&&(clearTimeout(this._resizeTimeout),delete this._resizeTimeout),this._resizeTimeout=setTimeout((async()=>{const t=this.container.canvas;t&&await t.windowResize()}),1e3*this.container.actualOptions.interactivity.events.resize.delay)},this._manageInteractivityListeners=(t,e)=>{const i=this._handlers,n=this.container,a=n.actualOptions,u=n.interactivity.element;if(!u)return;const p=u,f=n.canvas.element;f&&(f.style.pointerEvents=p===f?"initial":"none"),(a.interactivity.events.onHover.enable||a.interactivity.events.onClick.enable)&&(ae(u,r,i.mouseMove,e),ae(u,c,i.touchStart,e),ae(u,h,i.touchMove,e),a.interactivity.events.onClick.enable?(ae(u,l,i.touchEndClick,e),ae(u,o,i.mouseUp,e),ae(u,s,i.mouseDown,e)):ae(u,l,i.touchEnd,e),ae(u,t,i.mouseLeave,e),ae(u,d,i.touchCancel,e))},this._manageListeners=t=>{const e=this._handlers,i=this.container,s=i.actualOptions.interactivity.detectsOn,o=i.canvas.element;let r=n;"window"===s?(i.interactivity.element=window,r=a):i.interactivity.element="parent"===s&&o?o.parentElement??o.parentNode:o,this._manageMediaMatch(t),this._manageResize(t),this._manageInteractivityListeners(r,t),document&&ae(document,p,e.visibilityChange,t,!1)},this._manageMediaMatch=t=>{const e=this._handlers,i=N("(prefers-color-scheme: dark)");i&&(void 0===i.addEventListener?void 0!==i.addListener&&(t?i.addListener(e.oldThemeChange):i.removeListener(e.oldThemeChange)):ae(i,"change",e.themeChange,t))},this._manageResize=t=>{const e=this._handlers,i=this.container;if(!i.actualOptions.interactivity.events.resize)return;if("undefined"==typeof ResizeObserver)return void ae(window,u,e.resize,t);const s=i.canvas.element;this._resizeObserver&&!t?(s&&this._resizeObserver.unobserve(s),this._resizeObserver.disconnect(),delete this._resizeObserver):!this._resizeObserver&&t&&s&&(this._resizeObserver=new ResizeObserver((async t=>{t.find((t=>t.target===s))&&await this._handleWindowResize()})),this._resizeObserver.observe(s))},this._mouseDown=()=>{const{interactivity:t}=this.container;if(!t)return;const{mouse:e}=t;e.clicking=!0,e.downPosition=e.position},this._mouseTouchClick=t=>{const e=this.container,i=e.actualOptions,{mouse:s}=e.interactivity;s.inside=!0;let o=!1;const n=s.position;if(n&&i.interactivity.events.onClick.enable){for(const[,t]of e.plugins)if(t.clickPositionValid&&(o=t.clickPositionValid(n),o))break;o||this._doMouseTouchClick(t),s.clicking=!1}},this._mouseTouchFinish=()=>{const t=this.container.interactivity;if(!t)return;const e=t.mouse;delete e.position,delete e.clickPosition,delete e.downPosition,t.status=n,e.inside=!1,e.clicking=!1},this._mouseTouchMove=t=>{const e=this.container,i=e.actualOptions,s=e.interactivity,o=e.canvas.element;if(!s||!s.element)return;let n;if(s.mouse.inside=!0,t.type.startsWith("pointer")){this._canPush=!0;const e=t;if(s.element===window){if(o){const t=o.getBoundingClientRect();n={x:e.clientX-t.left,y:e.clientY-t.top}}}else if("parent"===i.interactivity.detectsOn){const t=e.target,i=e.currentTarget;if(t&&i&&o){const s=t.getBoundingClientRect(),a=i.getBoundingClientRect(),r=o.getBoundingClientRect();n={x:e.offsetX+2*s.left-(a.left+r.left),y:e.offsetY+2*s.top-(a.top+r.top)}}else n={x:e.offsetX??e.clientX,y:e.offsetY??e.clientY}}else e.target===o&&(n={x:e.offsetX??e.clientX,y:e.offsetY??e.clientY})}else if(this._canPush="touchmove"!==t.type,o){const e=t,i=e.touches[e.touches.length-1],s=o.getBoundingClientRect();n={x:i.clientX-(s.left??0),y:i.clientY-(s.top??0)}}const a=e.retina.pixelRatio;n&&(n.x*=a,n.y*=a),s.mouse.position=n,s.status=r},this._touchEnd=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.delete(t.identifier);this._mouseTouchFinish()},this._touchEndClick=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.delete(t.identifier);this._mouseTouchClick(t)},this._touchStart=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.set(t.identifier,performance.now());this._mouseTouchMove(t)},this._canPush=!0,this._touches=new Map,this._handlers={mouseDown:()=>this._mouseDown(),mouseLeave:()=>this._mouseTouchFinish(),mouseMove:t=>this._mouseTouchMove(t),mouseUp:t=>this._mouseTouchClick(t),touchStart:t=>this._touchStart(t),touchMove:t=>this._mouseTouchMove(t),touchEnd:t=>this._touchEnd(t),touchCancel:t=>this._touchEnd(t),touchEndClick:t=>this._touchEndClick(t),visibilityChange:()=>this._handleVisibilityChange(),themeChange:t=>this._handleThemeChange(t),oldThemeChange:t=>this._handleThemeChange(t),resize:()=>{this._handleWindowResize()}}}addListeners(){this._manageListeners(!0)}removeListeners(){this._manageListeners(!1)}}class ce{constructor(){this.value=""}static create(t,e){const i=new ce;return i.load(t),void 0!==e&&(bt(e)||kt(e)?i.load({value:e}):i.load(e)),i}load(t){void 0!==t?.value&&(this.value=t.value)}}class le{constructor(){this.color=new ce,this.color.value="",this.image="",this.position="",this.repeat="",this.size="",this.opacity=1}load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.image&&(this.image=t.image),void 0!==t.position&&(this.position=t.position),void 0!==t.repeat&&(this.repeat=t.repeat),void 0!==t.size&&(this.size=t.size),void 0!==t.opacity&&(this.opacity=t.opacity))}}class he{constructor(){this.color=new ce,this.color.value="#fff",this.opacity=1}load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.opacity&&(this.opacity=t.opacity))}}class de{constructor(){this.composite="destination-out",this.cover=new he,this.enable=!1}load(t){if(t){if(void 0!==t.composite&&(this.composite=t.composite),void 0!==t.cover){const e=t.cover,i=bt(t.cover)?{color:t.cover}:t.cover;this.cover.load(void 0!==e.color?e:{color:i})}void 0!==t.enable&&(this.enable=t.enable)}}}class ue{constructor(){this.enable=!0,this.zIndex=0}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.zIndex&&(this.zIndex=t.zIndex))}}class pe{constructor(){this.enable=!1,this.mode=[]}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.mode&&(this.mode=t.mode))}}class fe{constructor(){this.selectors=[],this.enable=!1,this.mode=[],this.type="circle"}load(t){t&&(void 0!==t.selectors&&(this.selectors=t.selectors),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.mode&&(this.mode=t.mode),void 0!==t.type&&(this.type=t.type))}}class ve{constructor(){this.enable=!1,this.force=2,this.smooth=10}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.force&&(this.force=t.force),void 0!==t.smooth&&(this.smooth=t.smooth))}}class ye{constructor(){this.enable=!1,this.mode=[],this.parallax=new ve}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.mode&&(this.mode=t.mode),this.parallax.load(t.parallax))}}class me{constructor(){this.delay=.5,this.enable=!0}load(t){void 0!==t&&(void 0!==t.delay&&(this.delay=t.delay),void 0!==t.enable&&(this.enable=t.enable))}}class ge{constructor(){this.onClick=new pe,this.onDiv=new fe,this.onHover=new ye,this.resize=new me}load(t){if(!t)return;this.onClick.load(t.onClick);const e=t.onDiv;void 0!==e&&(this.onDiv=dt(e,(t=>{const e=new fe;return e.load(t),e}))),this.onHover.load(t.onHover),this.resize.load(t.resize)}}class be{constructor(t,e){this._engine=t,this._container=e}load(t){if(!t)return;if(!this._container)return;const e=this._engine.interactors.get(this._container);if(e)for(const i of e)i.loadModeOptions&&i.loadModeOptions(this,t)}}class we{constructor(t,e){this.detectsOn="window",this.events=new ge,this.modes=new be(t,e)}load(t){if(!t)return;const e=t.detectsOn;void 0!==e&&(this.detectsOn=e),this.events.load(t.events),this.modes.load(t.modes)}}class xe{load(t){t&&(t.position&&(this.position={x:t.position.x??50,y:t.position.y??50,mode:t.position.mode??"percent"}),t.options&&(this.options=st({},t.options)))}}class _e{constructor(){this.maxWidth=1/0,this.options={},this.mode="canvas"}load(t){t&&(void 0!==t.maxWidth&&(this.maxWidth=t.maxWidth),void 0!==t.mode&&("screen"===t.mode?this.mode="screen":this.mode="canvas"),void 0!==t.options&&(this.options=st({},t.options)))}}class ke{constructor(){this.auto=!1,this.mode="any",this.value=!1}load(t){t&&(void 0!==t.auto&&(this.auto=t.auto),void 0!==t.mode&&(this.mode=t.mode),void 0!==t.value&&(this.value=t.value))}}class ze{constructor(){this.name="",this.default=new ke}load(t){t&&(void 0!==t.name&&(this.name=t.name),this.default.load(t.default),void 0!==t.options&&(this.options=st({},t.options)))}}class Me{constructor(){this.count=0,this.enable=!1,this.speed=1,this.decay=0,this.delay=0,this.sync=!1}load(t){t&&(void 0!==t.count&&(this.count=S(t.count)),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.speed&&(this.speed=S(t.speed)),void 0!==t.decay&&(this.decay=S(t.decay)),void 0!==t.delay&&(this.delay=S(t.delay)),void 0!==t.sync&&(this.sync=t.sync))}}class Ce extends Me{constructor(){super(),this.mode="auto",this.startValue="random"}load(t){super.load(t),t&&(void 0!==t.mode&&(this.mode=t.mode),void 0!==t.startValue&&(this.startValue=t.startValue))}}class Pe extends Me{constructor(){super(),this.offset=0,this.sync=!0}load(t){super.load(t),t&&void 0!==t.offset&&(this.offset=S(t.offset))}}class Oe{constructor(){this.h=new Pe,this.s=new Pe,this.l=new Pe}load(t){t&&(this.h.load(t.h),this.s.load(t.s),this.l.load(t.l))}}class Se extends ce{constructor(){super(),this.animation=new Oe}static create(t,e){const i=new Se;return i.load(t),void 0!==e&&(bt(e)||kt(e)?i.load({value:e}):i.load(e)),i}load(t){if(super.load(t),!t)return;const e=t.animation;void 0!==e&&(void 0!==e.enable?this.animation.h.load(e):this.animation.load(t.animation))}}class De{constructor(){this.speed=2}load(t){t&&void 0!==t.speed&&(this.speed=t.speed)}}class Te{constructor(){this.enable=!0,this.retries=0}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.retries&&(this.retries=t.retries))}}class Re{constructor(){this.value=0}load(t){t&&void 0!==t.value&&(this.value=S(t.value))}}class Ee extends Re{constructor(){super(),this.animation=new Me}load(t){if(super.load(t),!t)return;const e=t.animation;void 0!==e&&this.animation.load(e)}}class Ie extends Ee{constructor(){super(),this.animation=new Ce}load(t){super.load(t)}}class Le extends Re{constructor(){super(),this.value=1}}class Ae{constructor(){this.horizontal=new Le,this.vertical=new Le}load(t){t&&(this.horizontal.load(t.horizontal),this.vertical.load(t.vertical))}}class Fe{constructor(){this.absorb=new De,this.bounce=new Ae,this.enable=!1,this.maxSpeed=50,this.mode="bounce",this.overlap=new Te}load(t){t&&(this.absorb.load(t.absorb),this.bounce.load(t.bounce),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.maxSpeed&&(this.maxSpeed=S(t.maxSpeed)),void 0!==t.mode&&(this.mode=t.mode),this.overlap.load(t.overlap))}}class Be{constructor(){this.close=!0,this.fill=!0,this.options={},this.type=[]}load(t){if(!t)return;const e=t.options;if(void 0!==e)for(const t in e){const i=e[t];i&&(this.options[t]=st(this.options[t]??{},i))}void 0!==t.close&&(this.close=t.close),void 0!==t.fill&&(this.fill=t.fill),void 0!==t.type&&(this.type=t.type)}}class qe{constructor(){this.offset=0,this.value=90}load(t){t&&(void 0!==t.offset&&(this.offset=S(t.offset)),void 0!==t.value&&(this.value=S(t.value)))}}class He{constructor(){this.distance=200,this.enable=!1,this.rotate={x:3e3,y:3e3}}load(t){if(t&&(void 0!==t.distance&&(this.distance=S(t.distance)),void 0!==t.enable&&(this.enable=t.enable),t.rotate)){const e=t.rotate.x;void 0!==e&&(this.rotate.x=e);const i=t.rotate.y;void 0!==i&&(this.rotate.y=i)}}}class Ve{constructor(){this.x=50,this.y=50,this.mode="percent",this.radius=0}load(t){t&&(void 0!==t.x&&(this.x=t.x),void 0!==t.y&&(this.y=t.y),void 0!==t.mode&&(this.mode=t.mode),void 0!==t.radius&&(this.radius=t.radius))}}class Ue{constructor(){this.acceleration=9.81,this.enable=!1,this.inverse=!1,this.maxSpeed=50}load(t){t&&(void 0!==t.acceleration&&(this.acceleration=S(t.acceleration)),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.inverse&&(this.inverse=t.inverse),void 0!==t.maxSpeed&&(this.maxSpeed=S(t.maxSpeed)))}}class We{constructor(){this.clamp=!0,this.delay=new Re,this.enable=!1,this.options={}}load(t){t&&(void 0!==t.clamp&&(this.clamp=t.clamp),this.delay.load(t.delay),void 0!==t.enable&&(this.enable=t.enable),this.generator=t.generator,t.options&&(this.options=st(this.options,t.options)))}}class $e{load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.image&&(this.image=t.image))}}class je{constructor(){this.enable=!1,this.length=10,this.fill=new $e}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.fill&&this.fill.load(t.fill),void 0!==t.length&&(this.length=t.length))}}class Ge{constructor(){this.default="out"}load(t){t&&(void 0!==t.default&&(this.default=t.default),this.bottom=t.bottom??t.default,this.left=t.left??t.default,this.right=t.right??t.default,this.top=t.top??t.default)}}class Ne{constructor(){this.acceleration=0,this.enable=!1}load(t){t&&(void 0!==t.acceleration&&(this.acceleration=S(t.acceleration)),void 0!==t.enable&&(this.enable=t.enable),t.position&&(this.position=st({},t.position)))}}class Xe{constructor(){this.angle=new qe,this.attract=new He,this.center=new Ve,this.decay=0,this.distance={},this.direction="none",this.drift=0,this.enable=!1,this.gravity=new Ue,this.path=new We,this.outModes=new Ge,this.random=!1,this.size=!1,this.speed=2,this.spin=new Ne,this.straight=!1,this.trail=new je,this.vibrate=!1,this.warp=!1}load(t){if(!t)return;this.angle.load(wt(t.angle)?{value:t.angle}:t.angle),this.attract.load(t.attract),this.center.load(t.center),void 0!==t.decay&&(this.decay=S(t.decay)),void 0!==t.direction&&(this.direction=t.direction),void 0!==t.distance&&(this.distance=wt(t.distance)?{horizontal:t.distance,vertical:t.distance}:{...t.distance}),void 0!==t.drift&&(this.drift=S(t.drift)),void 0!==t.enable&&(this.enable=t.enable),this.gravity.load(t.gravity);const e=t.outModes;void 0!==e&&(_t(e)?this.outModes.load(e):this.outModes.load({default:e})),this.path.load(t.path),void 0!==t.random&&(this.random=t.random),void 0!==t.size&&(this.size=t.size),void 0!==t.speed&&(this.speed=S(t.speed)),this.spin.load(t.spin),void 0!==t.straight&&(this.straight=t.straight),this.trail.load(t.trail),void 0!==t.vibrate&&(this.vibrate=t.vibrate),void 0!==t.warp&&(this.warp=t.warp)}}class Ye extends Ce{constructor(){super(),this.destroy="none",this.speed=2}load(t){super.load(t),t&&void 0!==t.destroy&&(this.destroy=t.destroy)}}class Ze extends Ie{constructor(){super(),this.animation=new Ye,this.value=1}load(t){if(!t)return;super.load(t);const e=t.animation;void 0!==e&&this.animation.load(e)}}class Qe{constructor(){this.enable=!1,this.width=1920,this.height=1080}load(t){if(!t)return;void 0!==t.enable&&(this.enable=t.enable);const e=t.width;void 0!==e&&(this.width=e);const i=t.height;void 0!==i&&(this.height=i)}}class Je{constructor(){this.mode="delete",this.value=0}load(t){t&&(void 0!==t.mode&&(this.mode=t.mode),void 0!==t.value&&(this.value=t.value))}}class Ke{constructor(){this.density=new Qe,this.limit=new Je,this.value=0}load(t){t&&(this.density.load(t.density),this.limit.load(t.limit),void 0!==t.value&&(this.value=t.value))}}class ti{constructor(){this.blur=0,this.color=new ce,this.enable=!1,this.offset={x:0,y:0},this.color.value="#000"}load(t){t&&(void 0!==t.blur&&(this.blur=t.blur),this.color=ce.create(this.color,t.color),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.offset&&(void 0!==t.offset.x&&(this.offset.x=t.offset.x),void 0!==t.offset.y&&(this.offset.y=t.offset.y)))}}class ei{constructor(){this.close=!0,this.fill=!0,this.options={},this.type="circle"}load(t){if(!t)return;const e=t.options;if(void 0!==e)for(const t in e){const i=e[t];i&&(this.options[t]=st(this.options[t]??{},i))}void 0!==t.close&&(this.close=t.close),void 0!==t.fill&&(this.fill=t.fill),void 0!==t.type&&(this.type=t.type)}}class ii extends Ce{constructor(){super(),this.destroy="none",this.speed=5}load(t){super.load(t),t&&void 0!==t.destroy&&(this.destroy=t.destroy)}}class si extends Ie{constructor(){super(),this.animation=new ii,this.value=3}load(t){if(super.load(t),!t)return;const e=t.animation;void 0!==e&&this.animation.load(e)}}class oi{constructor(){this.width=0}load(t){t&&(void 0!==t.color&&(this.color=Se.create(this.color,t.color)),void 0!==t.width&&(this.width=S(t.width)),void 0!==t.opacity&&(this.opacity=S(t.opacity)))}}class ni extends Re{constructor(){super(),this.opacityRate=1,this.sizeRate=1,this.velocityRate=1}load(t){super.load(t),t&&(void 0!==t.opacityRate&&(this.opacityRate=t.opacityRate),void 0!==t.sizeRate&&(this.sizeRate=t.sizeRate),void 0!==t.velocityRate&&(this.velocityRate=t.velocityRate))}}class ai{constructor(t,e){this._engine=t,this._container=e,this.bounce=new Ae,this.collisions=new Fe,this.color=new Se,this.color.value="#fff",this.effect=new Be,this.groups={},this.move=new Xe,this.number=new Ke,this.opacity=new Ze,this.reduceDuplicates=!1,this.shadow=new ti,this.shape=new ei,this.size=new si,this.stroke=new oi,this.zIndex=new ni}load(t){if(!t)return;if(void 0!==t.groups)for(const e of Object.keys(t.groups)){if(!Object.hasOwn(t.groups,e))continue;const i=t.groups[e];void 0!==i&&(this.groups[e]=st(this.groups[e]??{},i))}void 0!==t.reduceDuplicates&&(this.reduceDuplicates=t.reduceDuplicates),this.bounce.load(t.bounce),this.color.load(Se.create(this.color,t.color)),this.effect.load(t.effect),this.move.load(t.move),this.number.load(t.number),this.opacity.load(t.opacity),this.shape.load(t.shape),this.size.load(t.size),this.shadow.load(t.shadow),this.zIndex.load(t.zIndex),this.collisions.load(t.collisions),void 0!==t.interactivity&&(this.interactivity=st({},t.interactivity));const e=t.stroke;if(e&&(this.stroke=dt(e,(t=>{const e=new oi;return e.load(t),e}))),this._container){const e=this._engine.updaters.get(this._container);if(e)for(const i of e)i.loadOptions&&i.loadOptions(this,t);const i=this._engine.interactors.get(this._container);if(i)for(const e of i)e.loadParticlesOptions&&e.loadParticlesOptions(this,t)}}}function ri(t,...e){for(const i of e)t.load(i)}function ci(t,e,...i){const s=new ai(t,e);return ri(s,...i),s}class li{constructor(t,e){this._findDefaultTheme=t=>this.themes.find((e=>e.default.value&&e.default.mode===t))??this.themes.find((t=>t.default.value&&"any"===t.default.mode)),this._importPreset=t=>{this.load(this._engine.getPreset(t))},this._engine=t,this._container=e,this.autoPlay=!0,this.background=new le,this.backgroundMask=new de,this.clear=!0,this.defaultThemes={},this.delay=0,this.fullScreen=new ue,this.detectRetina=!0,this.duration=0,this.fpsLimit=120,this.interactivity=new we(t,e),this.manualParticles=[],this.particles=ci(this._engine,this._container),this.pauseOnBlur=!0,this.pauseOnOutsideViewport=!0,this.responsive=[],this.smooth=!1,this.style={},this.themes=[],this.zLayers=100}load(t){if(!t)return;void 0!==t.preset&&dt(t.preset,(t=>this._importPreset(t))),void 0!==t.autoPlay&&(this.autoPlay=t.autoPlay),void 0!==t.clear&&(this.clear=t.clear),void 0!==t.name&&(this.name=t.name),void 0!==t.delay&&(this.delay=S(t.delay));const e=t.detectRetina;void 0!==e&&(this.detectRetina=e),void 0!==t.duration&&(this.duration=S(t.duration));const i=t.fpsLimit;void 0!==i&&(this.fpsLimit=i),void 0!==t.pauseOnBlur&&(this.pauseOnBlur=t.pauseOnBlur),void 0!==t.pauseOnOutsideViewport&&(this.pauseOnOutsideViewport=t.pauseOnOutsideViewport),void 0!==t.zLayers&&(this.zLayers=t.zLayers),this.background.load(t.background);const s=t.fullScreen;gt(s)?this.fullScreen.enable=s:this.fullScreen.load(s),this.backgroundMask.load(t.backgroundMask),this.interactivity.load(t.interactivity),t.manualParticles&&(this.manualParticles=t.manualParticles.map((t=>{const e=new xe;return e.load(t),e}))),this.particles.load(t.particles),this.style=st(this.style,t.style),this._engine.loadOptions(this,t),void 0!==t.smooth&&(this.smooth=t.smooth);const o=this._engine.interactors.get(this._container);if(o)for(const e of o)e.loadOptions&&e.loadOptions(this,t);if(void 0!==t.responsive)for(const e of t.responsive){const t=new _e;t.load(e),this.responsive.push(t)}if(this.responsive.sort(((t,e)=>t.maxWidth-e.maxWidth)),void 0!==t.themes)for(const e of t.themes){const t=this.themes.find((t=>t.name===e.name));if(t)t.load(e);else{const t=new ze;t.load(e),this.themes.push(t)}}this.defaultThemes.dark=this._findDefaultTheme("dark")?.name,this.defaultThemes.light=this._findDefaultTheme("light")?.name}setResponsive(t,e,i){this.load(i);const s=this.responsive.find((i=>"screen"===i.mode&&screen?i.maxWidth>screen.availWidth:i.maxWidth*e>t));return this.load(s?.options),s?.maxWidth}setTheme(t){if(t){const e=this.themes.find((e=>e.name===t));e&&this.load(e.options)}else{const t=N("(prefers-color-scheme: dark)"),e=t&&t.matches,i=this._findDefaultTheme(e?"dark":"light");i&&this.load(i.options)}}}class hi{constructor(t,e){this.container=e,this._engine=t,this._interactors=t.getInteractors(this.container,!0),this._externalInteractors=[],this._particleInteractors=[]}async externalInteract(t){for(const e of this._externalInteractors)e.isEnabled()&&await e.interact(t)}handleClickMode(t){for(const e of this._externalInteractors)e.handleClickMode&&e.handleClickMode(t)}init(){this._externalInteractors=[],this._particleInteractors=[];for(const t of this._interactors){switch(t.type){case"external":this._externalInteractors.push(t);break;case"particles":this._particleInteractors.push(t)}t.init()}}async particlesInteract(t,e){for(const i of this._externalInteractors)i.clear(t,e);for(const i of this._particleInteractors)i.isEnabled(t)&&await i.interact(t,e)}async reset(t){for(const e of this._externalInteractors)e.isEnabled()&&e.reset(t);for(const e of this._particleInteractors)e.isEnabled(t)&&e.reset(t)}}function di(t){if(!Z(t.outMode,t.checkModes))return;const e=2*t.radius;t.coord>t.maxCoord-e?t.setCb(-t.radius):t.coord{for(const[,s]of t.plugins){const t=void 0!==s.particlePosition?s.particlePosition(e,this):void 0;if(t)return v.create(t.x,t.y,i)}const o=B({size:t.canvas.size,position:e}),n=v.create(o.x,o.y,i),a=this.getRadius(),r=this.options.move.outModes,c=e=>{di({outMode:e,checkModes:["bounce","bounce-horizontal"],coord:n.x,maxCoord:t.canvas.size.width,setCb:t=>n.x+=t,radius:a})},l=e=>{di({outMode:e,checkModes:["bounce","bounce-vertical"],coord:n.y,maxCoord:t.canvas.size.height,setCb:t=>n.y+=t,radius:a})};return c(r.left??r.default),c(r.right??r.default),l(r.top??r.default),l(r.bottom??r.default),this._checkOverlap(n,s)?this._calcPosition(t,void 0,i,s+1):n},this._calculateVelocity=()=>{const t=E(this.direction).copy(),e=this.options.move;if("inside"===e.direction||"outside"===e.direction)return t;const i=Math.PI/180*C(e.angle.value),s=Math.PI/180*C(e.angle.offset),o={left:s-.5*i,right:s+.5*i};return e.straight||(t.angle+=M(S(o.left,o.right))),e.random&&"number"==typeof e.speed&&(t.length*=_()),t},this._checkOverlap=(t,e=0)=>{const i=this.options.collisions,s=this.getRadius();if(!i.enable)return!1;const o=i.overlap;if(o.enable)return!1;const n=o.retries;if(n>=0&&e>n)throw new Error(`${f} particle is overlapping and can't be placed`);return!!this.container.particles.find((e=>T(t,e.position){if(!t||!this.roll||!this.backColor&&!this.roll.alter)return t;const e=this.roll.horizontal&&this.roll.vertical?2:1,i=this.roll.horizontal?.5*Math.PI:0;return Math.floor(((this.roll.angle??0)+i)/(Math.PI/e))%2?this.backColor?this.backColor:this.roll.alter?se(t,this.roll.alter.type,this.roll.alter.value):t:t},this._initPosition=t=>{const e=this.container,i=C(this.options.zIndex.value);this.position=this._calcPosition(e,t,k(i,0,e.zLayers)),this.initialPosition=this.position.copy();const s=e.canvas.size;switch(this.moveCenter={...yt(this.options.move.center,s),radius:this.options.move.center.radius??0,mode:this.options.move.center.mode??"percent"},this.direction=R(this.options.move.direction,this.position,this.moveCenter),this.options.move.direction){case"inside":this.outType="inside";break;case"outside":this.outType="outside"}this.offset=y.origin},this._engine=t,this.init(e,s,o,n)}destroy(t){if(this.unbreakable||this.destroyed)return;this.destroyed=!0,this.bubble.inRange=!1,this.slow.inRange=!1;const e=this.container,i=this.pathGenerator,s=e.shapeDrawers.get(this.shape);s&&s.particleDestroy&&s.particleDestroy(this);for(const[,i]of e.plugins)i.particleDestroyed&&i.particleDestroyed(this,t);for(const i of e.particles.updaters)i.particleDestroyed&&i.particleDestroyed(this,t);i&&i.reset(this),this._engine.dispatchEvent("particleDestroyed",{container:this.container,data:{particle:this}})}draw(t){const e=this.container,i=e.canvas;for(const[,s]of e.plugins)i.drawParticlePlugin(s,this,t);i.drawParticle(this,t)}getFillColor(){return this._getRollColor(this.bubble.color??$t(this.color))}getMass(){return this.getRadius()**2*Math.PI*.5}getPosition(){return{x:this.position.x+this.offset.x,y:this.position.y+this.offset.y,z:this.position.z}}getRadius(){return this.bubble.radius??this.size.value}getStrokeColor(){return this._getRollColor(this.bubble.color??$t(this.strokeColor))}init(t,e,i,s){const o=this.container,n=this._engine;this.id=t,this.group=s,this.effectClose=!0,this.effectFill=!0,this.shapeClose=!0,this.shapeFill=!0,this.pathRotation=!1,this.lastPathTime=0,this.destroyed=!1,this.unbreakable=!1,this.rotation=0,this.misplaced=!1,this.retina={maxDistance:{}},this.outType="normal",this.ignoresResizeRatio=!0;const a=o.retina.pixelRatio,r=o.actualOptions,c=ci(this._engine,o,r.particles),l=c.effect.type,h=c.shape.type,{reduceDuplicates:d}=c;this.effect=ut(l,this.id,d),this.shape=ut(h,this.id,d);const u=c.effect,p=c.shape;if(i){if(i.effect&&i.effect.type){const t=ut(i.effect.type,this.id,d);t&&(this.effect=t,u.load(i.effect))}if(i.shape&&i.shape.type){const t=ut(i.shape.type,this.id,d);t&&(this.shape=t,p.load(i.shape))}}this.effectData=function(t,e,i,s){const o=e.options[t];if(o)return st({close:e.close,fill:e.fill},ut(o,i,s))}(this.effect,u,this.id,d),this.shapeData=function(t,e,i,s){const o=e.options[t];if(o)return st({close:e.close,fill:e.fill},ut(o,i,s))}(this.shape,p,this.id,d),c.load(i);const f=this.effectData;f&&c.load(f.particles);const v=this.shapeData;v&&c.load(v.particles);const y=new we(n,o);y.load(o.actualOptions.interactivity),y.load(c.interactivity),this.interactivity=y,this.effectFill=f?.fill??c.effect.fill,this.effectClose=f?.close??c.effect.close,this.shapeFill=v?.fill??c.shape.fill,this.shapeClose=v?.close??c.shape.close,this.options=c;const m=this.options.move.path;this.pathDelay=1e3*C(m.delay.value),m.generator&&(this.pathGenerator=this._engine.getPathGenerator(m.generator),this.pathGenerator&&o.addPath(m.generator,this.pathGenerator)&&this.pathGenerator.init(o)),o.retina.initParticle(this),this.size=ft(this.options.size,a),this.bubble={inRange:!1},this.slow={inRange:!1,factor:1},this._initPosition(e),this.initialVelocity=this._calculateVelocity(),this.velocity=this.initialVelocity.copy(),this.moveDecay=1-C(this.options.move.decay);const g=o.particles;g.setLastZIndex(this.position.z),this.zIndexFactor=this.position.z/o.zLayers,this.sides=24;let b=o.effectDrawers.get(this.effect);b||(b=this._engine.getEffectDrawer(this.effect),b&&o.effectDrawers.set(this.effect,b)),b&&b.loadEffect&&b.loadEffect(this);let w=o.shapeDrawers.get(this.shape);w||(w=this._engine.getShapeDrawer(this.shape),w&&o.shapeDrawers.set(this.shape,w)),w&&w.loadShape&&w.loadShape(this);const x=w?.getSidesCount;x&&(this.sides=x(this)),this.spawning=!1,this.shadowColor=St(this.options.shadow.color);for(const t of g.updaters)t.init(this);for(const t of g.movers)t.init&&t.init(this);b&&b.particleInit&&b.particleInit(o,this),w&&w.particleInit&&w.particleInit(o,this);for(const[,t]of o.plugins)t.particleCreated&&t.particleCreated(this)}isInsideCanvas(){const t=this.getRadius(),e=this.container.canvas.size,i=this.position;return i.x>=-t&&i.y>=-t&&i.y<=e.height+t&&i.x<=e.width+t}isVisible(){return!this.destroyed&&!this.spawning&&this.isInsideCanvas()}reset(){for(const t of this.container.particles.updaters)t.reset&&t.reset(this)}}class pi{constructor(t,e){this.position=t,this.particle=e}}class fi{constructor(t,e){this.position={x:t,y:e}}}class vi extends fi{constructor(t,e,i,s){super(t,e),this.size={height:s,width:i}}contains(t){const e=this.size.width,i=this.size.height,s=this.position;return t.x>=s.x&&t.x<=s.x+e&&t.y>=s.y&&t.y<=s.y+i}intersects(t){t instanceof yi&&t.intersects(this);const e=this.size.width,i=this.size.height,s=this.position,o=t.position,n=t instanceof vi?t.size:{width:0,height:0},a=n.width,r=n.height;return o.xs.x&&o.ys.y}}class yi extends fi{constructor(t,e,i){super(t,e),this.radius=i}contains(t){return T(t,this.position)<=this.radius}intersects(t){const e=this.position,i=t.position,s=Math.abs(i.x-e.x),o=Math.abs(i.y-e.y),n=this.radius;if(t instanceof yi){return n+t.radius>Math.sqrt(s**2+o**2)}if(t instanceof vi){const{width:e,height:i}=t.size;return Math.pow(s-e,2)+Math.pow(o-i,2)<=n**2||s<=n+e&&o<=n+i||s<=e||o<=i}return!1}}class mi{constructor(t,e){this.rectangle=t,this.capacity=e,this._subdivide=()=>{const{x:t,y:e}=this.rectangle.position,{width:i,height:s}=this.rectangle.size,{capacity:o}=this;for(let n=0;n<4;n++)this._subs.push(new mi(new vi(t+.5*i*(n%2),e+.5*s*(Math.round(.5*n)-n%2),.5*i,.5*s),o));this._divided=!0},this._points=[],this._divided=!1,this._subs=[]}insert(t){return!!this.rectangle.contains(t.position)&&(this._points.lengthe.insert(t)))))}query(t,e,i){const s=i||[];if(!t.intersects(this.rectangle))return[];for(const i of this._points)!t.contains(i.position)&&T(t.position,i.position)>i.particle.getRadius()&&(!e||e(i.particle))||s.push(i.particle);if(this._divided)for(const i of this._subs)i.query(t,e,s);return s}queryCircle(t,e,i){return this.query(new yi(t.x,t.y,e),i)}queryRectangle(t,e,i){return this.query(new vi(t.x,t.y,e.width,e.height),i)}}const gi=t=>{const{height:e,width:i}=t;return new vi(-.25*i,-.25*e,1.5*i,1.5*e)};class bi{constructor(t,e){this._addToPool=(...t)=>{for(const e of t)this._pool.push(e)},this._applyDensity=(t,e,i)=>{const s=t.number;if(!t.number.density?.enable)return void(void 0===i?this._limit=s.limit.value:s.limit&&this._groupLimits.set(i,s.limit.value));const o=this._initDensityFactor(s.density),n=s.value,a=s.limit.value>0?s.limit.value:n,r=Math.min(n,a)*o+e,c=Math.min(this.count,this.filter((t=>t.group===i)).length);void 0===i?this._limit=s.limit.value*o:this._groupLimits.set(i,s.limit.value*o),cr&&this.removeQuantity(c-r,i)},this._initDensityFactor=t=>{const e=this._container;if(!e.canvas.element||!t.enable)return 1;const i=e.canvas.element,s=e.retina.pixelRatio;return i.width*i.height/(t.height*t.width*s**2)},this._pushParticle=(t,e,i,s)=>{try{let o=this._pool.pop();o?o.init(this._nextId,t,e,i):o=new ui(this._engine,this._nextId,this._container,t,e,i);let n=!0;if(s&&(n=s(o)),!n)return;return this._array.push(o),this._zArray.push(o),this._nextId++,this._engine.dispatchEvent("particleAdded",{container:this._container,data:{particle:o}}),o}catch(t){return void W().warning(`${f} adding particle: ${t}`)}},this._removeParticle=(t,e,i)=>{const s=this._array[t];if(!s||s.group!==e)return!1;const o=this._zArray.indexOf(s);return this._array.splice(t,1),this._zArray.splice(o,1),s.destroy(i),this._engine.dispatchEvent("particleRemoved",{container:this._container,data:{particle:s}}),this._addToPool(s),!0},this._engine=t,this._container=e,this._nextId=0,this._array=[],this._zArray=[],this._pool=[],this._limit=0,this._groupLimits=new Map,this._needsSort=!1,this._lastZIndex=0,this._interactionManager=new hi(t,e);const i=e.canvas.size;this.quadTree=new mi(gi(i),4),this.movers=this._engine.getMovers(e,!0),this.updaters=this._engine.getUpdaters(e,!0)}get count(){return this._array.length}addManualParticles(){const t=this._container,e=t.actualOptions;for(const i of e.manualParticles)this.addParticle(i.position?yt(i.position,t.canvas.size):void 0,i.options)}addParticle(t,e,i,s){const o=this._container.actualOptions.particles.number.limit,n=void 0===i?this._limit:this._groupLimits.get(i)??this._limit,a=this.count;if(n>0)if("delete"===o.mode){const t=a+1-n;t>0&&this.removeQuantity(t)}else if("wait"===o.mode&&a>=n)return;return this._pushParticle(t,e,i,s)}clear(){this._array=[],this._zArray=[]}destroy(){this._array=[],this._zArray=[],this.movers=[],this.updaters=[]}async draw(t){const e=this._container,i=e.canvas;i.clear(),await this.update(t);for(const[,s]of e.plugins)i.drawPlugin(s,t);for(const e of this._zArray)e.draw(t)}filter(t){return this._array.filter(t)}find(t){return this._array.find(t)}get(t){return this._array[t]}handleClickMode(t){this._interactionManager.handleClickMode(t)}init(){const t=this._container,e=t.actualOptions;this._lastZIndex=0,this._needsSort=!1;let i=!1;this.updaters=this._engine.getUpdaters(t,!0),this._interactionManager.init();for(const[,e]of t.plugins)if(void 0!==e.particlesInitialization&&(i=e.particlesInitialization()),i)break;this._interactionManager.init();for(const[,e]of t.pathGenerators)e.init(t);if(this.addManualParticles(),!i){const t=e.particles,i=t.groups;for(const e in i){const s=i[e];for(let i=this.count,o=0;othis.count)return;let o=0;for(let n=t;o!i.has(t);this._array=this.filter(t),this._zArray=this._zArray.filter(t);for(const t of i)this._engine.dispatchEvent("particleRemoved",{container:this._container,data:{particle:t}});this._addToPool(...i)}await this._interactionManager.externalInteract(t);for(const e of this._array){for(const i of this.updaters)i.update(e,t);e.destroyed||e.spawning||await this._interactionManager.particlesInteract(e,t)}if(delete this._resizeFactor,this._needsSort){const t=this._zArray;t.sort(((t,e)=>e.position.z-t.position.z||t.id-e.id)),this._lastZIndex=t[t.length-1].position.z,this._needsSort=!1}}}class wi{constructor(t){this.container=t,this.pixelRatio=1,this.reduceFactor=1}init(){const t=this.container,e=t.actualOptions;this.pixelRatio=!e.detectRetina||j()?1:window.devicePixelRatio,this.reduceFactor=1;const i=this.pixelRatio,s=t.canvas;if(s.element){const t=s.element;s.size.width=t.offsetWidth*i,s.size.height=t.offsetHeight*i}const o=e.particles,n=o.move;this.maxSpeed=C(n.gravity.maxSpeed)*i,this.sizeAnimationSpeed=C(o.size.animation.speed)*i}initParticle(t){const e=t.options,i=this.pixelRatio,s=e.move,o=s.distance,n=t.retina;n.moveDrift=C(s.drift)*i,n.moveSpeed=C(s.speed)*i,n.sizeAnimationSpeed=C(e.size.animation.speed)*i;const a=n.maxDistance;a.horizontal=void 0!==o.horizontal?o.horizontal*i:void 0,a.vertical=void 0!==o.vertical?o.vertical*i:void 0,n.maxSpeed=C(s.gravity.maxSpeed)*i}}function xi(t){return t&&!t.destroyed}function _i(t,e,...i){const s=new li(t,e);return ri(s,...i),s}class ki{constructor(t,e,i){this._intersectionManager=t=>{if(xi(this)&&this.actualOptions.pauseOnOutsideViewport)for(const e of t)e.target===this.interactivity.element&&(e.isIntersecting?this.play:this.pause)()},this._nextFrame=async t=>{try{if(!this._smooth&&void 0!==this._lastFrameTime&&t1e3)return void this.draw(!1);if(await this.particles.draw(e),!this.alive())return void this.destroy();this.getAnimationStatus()&&this.draw(!1)}catch(t){W().error(`${f} in animation loop`,t)}},this._engine=t,this.id=Symbol(e),this.fpsLimit=120,this._smooth=!1,this._delay=0,this._duration=0,this._lifeTime=0,this._firstStart=!0,this.started=!1,this.destroyed=!1,this._paused=!0,this._lastFrameTime=0,this.zLayers=100,this.pageHidden=!1,this._sourceOptions=i,this._initialSourceOptions=i,this.retina=new wi(this),this.canvas=new ne(this),this.particles=new bi(this._engine,this),this.pathGenerators=new Map,this.interactivity={mouse:{clicking:!1,inside:!1}},this.plugins=new Map,this.effectDrawers=new Map,this.shapeDrawers=new Map,this._options=_i(this._engine,this),this.actualOptions=_i(this._engine,this),this._eventListeners=new re(this),this._intersectionObserver=X((t=>this._intersectionManager(t))),this._engine.dispatchEvent("containerBuilt",{container:this})}get options(){return this._options}get sourceOptions(){return this._sourceOptions}addClickHandler(t){if(!xi(this))return;const e=this.interactivity.element;if(!e)return;const i=(e,i,s)=>{if(!xi(this))return;const o=this.retina.pixelRatio,n={x:i.x*o,y:i.y*o},a=this.particles.quadTree.queryCircle(n,s*o);t(e,a)};let s=!1,o=!1;e.addEventListener("click",(t=>{if(!xi(this))return;const e=t,s={x:e.offsetX||e.clientX,y:e.offsetY||e.clientY};i(t,s,1)})),e.addEventListener("touchstart",(()=>{xi(this)&&(s=!0,o=!1)})),e.addEventListener("touchmove",(()=>{xi(this)&&(o=!0)})),e.addEventListener("touchend",(t=>{if(xi(this)){if(s&&!o){const e=t;let s=e.touches[e.touches.length-1];if(!s&&(s=e.changedTouches[e.changedTouches.length-1],!s))return;const o=this.canvas.element,n=o?o.getBoundingClientRect():void 0,a={x:s.clientX-(n?n.left:0),y:s.clientY-(n?n.top:0)};i(t,a,Math.max(s.radiusX,s.radiusY))}s=!1,o=!1}})),e.addEventListener("touchcancel",(()=>{xi(this)&&(s=!1,o=!1)}))}addLifeTime(t){this._lifeTime+=t}addPath(t,e,i=!1){return!(!xi(this)||!i&&this.pathGenerators.has(t))&&(this.pathGenerators.set(t,e),!0)}alive(){return!this._duration||this._lifeTime<=this._duration}destroy(){if(!xi(this))return;this.stop(),this.particles.destroy(),this.canvas.destroy();for(const[,t]of this.effectDrawers)t.destroy&&t.destroy(this);for(const[,t]of this.shapeDrawers)t.destroy&&t.destroy(this);for(const t of this.effectDrawers.keys())this.effectDrawers.delete(t);for(const t of this.shapeDrawers.keys())this.shapeDrawers.delete(t);this._engine.clearPlugins(this),this.destroyed=!0;const t=this._engine.dom(),e=t.findIndex((t=>t===this));e>=0&&t.splice(e,1),this._engine.dispatchEvent("containerDestroyed",{container:this})}draw(t){if(!xi(this))return;let e=t;this._drawAnimationFrame=requestAnimationFrame((async t=>{e&&(this._lastFrameTime=void 0,e=!1),await this._nextFrame(t)}))}async export(t,e={}){for(const[,i]of this.plugins){if(!i.export)continue;const s=await i.export(t,e);if(s.supported)return s.blob}W().error(`${f} - Export plugin with type ${t} not found`)}getAnimationStatus(){return!this._paused&&!this.pageHidden&&xi(this)}handleClickMode(t){if(xi(this)){this.particles.handleClickMode(t);for(const[,e]of this.plugins)e.handleClickMode&&e.handleClickMode(t)}}async init(){if(!xi(this))return;const t=this._engine.getSupportedEffects();for(const e of t){const t=this._engine.getEffectDrawer(e);t&&this.effectDrawers.set(e,t)}const e=this._engine.getSupportedShapes();for(const t of e){const e=this._engine.getShapeDrawer(t);e&&this.shapeDrawers.set(t,e)}this._options=_i(this._engine,this,this._initialSourceOptions,this.sourceOptions),this.actualOptions=_i(this._engine,this,this._options);const i=this._engine.getAvailablePlugins(this);for(const[t,e]of i)this.plugins.set(t,e);this.retina.init(),await this.canvas.init(),this.updateActualOptions(),this.canvas.initBackground(),this.canvas.resize(),this.zLayers=this.actualOptions.zLayers,this._duration=1e3*C(this.actualOptions.duration),this._delay=1e3*C(this.actualOptions.delay),this._lifeTime=0,this.fpsLimit=this.actualOptions.fpsLimit>0?this.actualOptions.fpsLimit:120,this._smooth=this.actualOptions.smooth;for(const[,t]of this.effectDrawers)t.init&&await t.init(this);for(const[,t]of this.shapeDrawers)t.init&&await t.init(this);for(const[,t]of this.plugins)t.init&&await t.init();this._engine.dispatchEvent("containerInit",{container:this}),this.particles.init(),this.particles.setDensity();for(const[,t]of this.plugins)t.particlesSetup&&t.particlesSetup();this._engine.dispatchEvent("particlesSetup",{container:this})}async loadTheme(t){xi(this)&&(this._currentTheme=t,await this.refresh())}pause(){if(xi(this)&&(void 0!==this._drawAnimationFrame&&(cancelAnimationFrame(this._drawAnimationFrame),delete this._drawAnimationFrame),!this._paused)){for(const[,t]of this.plugins)t.pause&&t.pause();this.pageHidden||(this._paused=!0),this._engine.dispatchEvent("containerPaused",{container:this})}}play(t){if(!xi(this))return;const e=this._paused||t;if(!this._firstStart||this.actualOptions.autoPlay){if(this._paused&&(this._paused=!1),e)for(const[,t]of this.plugins)t.play&&t.play();this._engine.dispatchEvent("containerPlay",{container:this}),this.draw(e||!1)}else this._firstStart=!1}async refresh(){if(xi(this))return this.stop(),this.start()}async reset(){if(xi(this))return this._initialSourceOptions=void 0,this._options=_i(this._engine,this),this.actualOptions=_i(this._engine,this,this._options),this.refresh()}async start(){xi(this)&&!this.started&&(await this.init(),this.started=!0,await new Promise((t=>{this._delayTimeout=setTimeout((async()=>{this._eventListeners.addListeners(),this.interactivity.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.observe(this.interactivity.element);for(const[,t]of this.plugins)t.start&&await t.start();this._engine.dispatchEvent("containerStarted",{container:this}),this.play(),t()}),this._delay)})))}stop(){if(xi(this)&&this.started){this._delayTimeout&&(clearTimeout(this._delayTimeout),delete this._delayTimeout),this._firstStart=!0,this.started=!1,this._eventListeners.removeListeners(),this.pause(),this.particles.clear(),this.canvas.stop(),this.interactivity.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.unobserve(this.interactivity.element);for(const[,t]of this.plugins)t.stop&&t.stop();for(const t of this.plugins.keys())this.plugins.delete(t);this._sourceOptions=this._options,this._engine.dispatchEvent("containerStopped",{container:this})}}updateActualOptions(){this.actualOptions.responsive=[];const t=this.actualOptions.setResponsive(this.canvas.size.width,this.retina.pixelRatio,this._options);return this.actualOptions.setTheme(this._currentTheme),this._responsiveMaxWidth!==t&&(this._responsiveMaxWidth=t,!0)}}class zi{constructor(){this._listeners=new Map}addEventListener(t,e){this.removeEventListener(t,e);let i=this._listeners.get(t);i||(i=[],this._listeners.set(t,i)),i.push(e)}dispatchEvent(t,e){const i=this._listeners.get(t);i&&i.forEach((t=>t(e)))}hasEventListener(t){return!!this._listeners.get(t)}removeAllEventListeners(t){t?this._listeners.delete(t):this._listeners=new Map}removeEventListener(t,e){const i=this._listeners.get(t);if(!i)return;const s=i.length,o=i.indexOf(e);o<0||(1===s?this._listeners.delete(t):i.splice(o,1))}}function Mi(t,e,i,s=!1){let o=e.get(t);return o&&!s||(o=[...i.values()].map((e=>e(t))),e.set(t,o)),o}class Ci{constructor(){this._configs=new Map,this._domArray=[],this._eventDispatcher=new zi,this._initialized=!1,this.plugins=[],this._initializers={interactors:new Map,movers:new Map,updaters:new Map},this.interactors=new Map,this.movers=new Map,this.updaters=new Map,this.presets=new Map,this.effectDrawers=new Map,this.shapeDrawers=new Map,this.pathGenerators=new Map}get configs(){const t={};for(const[e,i]of this._configs)t[e]=i;return t}get version(){return"3.0.2"}addConfig(t){const e=t.name??"default";this._configs.set(e,t),this._eventDispatcher.dispatchEvent("configAdded",{data:{name:e,config:t}})}async addEffect(t,e,i=!0){dt(t,(t=>{!this.getEffectDrawer(t)&&this.effectDrawers.set(t,e)})),await this.refresh(i)}addEventListener(t,e){this._eventDispatcher.addEventListener(t,e)}async addInteractor(t,e,i=!0){this._initializers.interactors.set(t,e),await this.refresh(i)}async addMover(t,e,i=!0){this._initializers.movers.set(t,e),await this.refresh(i)}async addParticleUpdater(t,e,i=!0){this._initializers.updaters.set(t,e),await this.refresh(i)}async addPathGenerator(t,e,i=!0){!this.getPathGenerator(t)&&this.pathGenerators.set(t,e),await this.refresh(i)}async addPlugin(t,e=!0){!this.getPlugin(t.id)&&this.plugins.push(t),await this.refresh(e)}async addPreset(t,e,i=!1,s=!0){(i||!this.getPreset(t))&&this.presets.set(t,e),await this.refresh(s)}async addShape(t,e,i=!0){dt(t,(t=>{!this.getShapeDrawer(t)&&this.shapeDrawers.set(t,e)})),await this.refresh(i)}clearPlugins(t){this.updaters.delete(t),this.movers.delete(t),this.interactors.delete(t)}dispatchEvent(t,e){this._eventDispatcher.dispatchEvent(t,e)}dom(){return this._domArray}domItem(t){const e=this.dom(),i=e[t];if(i&&!i.destroyed)return i;e.splice(t,1)}getAvailablePlugins(t){const e=new Map;for(const i of this.plugins)i.needsPlugin(t.actualOptions)&&e.set(i.id,i.getPlugin(t));return e}getEffectDrawer(t){return this.effectDrawers.get(t)}getInteractors(t,e=!1){return Mi(t,this.interactors,this._initializers.interactors,e)}getMovers(t,e=!1){return Mi(t,this.movers,this._initializers.movers,e)}getPathGenerator(t){return this.pathGenerators.get(t)}getPlugin(t){return this.plugins.find((e=>e.id===t))}getPreset(t){return this.presets.get(t)}getShapeDrawer(t){return this.shapeDrawers.get(t)}getSupportedEffects(){return this.effectDrawers.keys()}getSupportedShapes(){return this.shapeDrawers.keys()}getUpdaters(t,e=!1){return Mi(t,this.updaters,this._initializers.updaters,e)}init(){this._initialized||(this._initialized=!0)}async load(t){const e=t.id??`tsparticles${Math.floor(1e4*_())}`,{index:s,url:o}=t,n=o?await async function(t){const e=ut(t.url,t.index);if(!e)return t.fallback;const i=await fetch(e);return i.ok?i.json():(W().error(`${f} ${i.status} while retrieving config file`),t.fallback)}({fallback:t.options,url:o,index:s}):t.options;let a=t.element??document.getElementById(e);a||(a=document.createElement("div"),a.id=e,document.body.append(a));const r=ut(n,s),c=this.dom(),l=c.findIndex((t=>t.id.description===e));if(l>=0){const t=this.domItem(l);t&&!t.destroyed&&(t.destroy(),c.splice(l,1))}let h;if("canvas"===a.tagName.toLowerCase())h=a,h.dataset[i]="false";else{const t=a.getElementsByTagName("canvas");t.length?(h=t[0],h.dataset[i]="false"):(h=document.createElement("canvas"),h.dataset[i]="true",a.appendChild(h))}h.style.width||(h.style.width="100%"),h.style.height||(h.style.height="100%");const d=new ki(this,e,r);return l>=0?c.splice(l,0,d):c.push(d),d.canvas.loadCanvas(h),await d.start(),d}loadOptions(t,e){for(const i of this.plugins)i.loadOptions(t,e)}loadParticlesOptions(t,e,...i){const s=this.updaters.get(t);if(s)for(const t of s)t.loadOptions&&t.loadOptions(e,...i)}async refresh(t=!0){t&&this.dom().forEach((t=>t.refresh()))}removeEventListener(t,e){this._eventDispatcher.removeEventListener(t,e)}setOnClickHandler(t){const e=this.dom();if(!e.length)throw new Error(`${f} can only set click handlers after calling tsParticles.load()`);for(const i of e)i.addClickHandler(t)}}class Pi{constructor(){this.key="hsl",this.stringPrefix="hsl"}handleColor(t){const e=t.value.hsl??t.value;if(void 0!==e.h&&void 0!==e.s&&void 0!==e.l)return At(e)}handleRangeColor(t){const e=t.value.hsl??t.value;if(void 0!==e.h&&void 0!==e.l)return At({h:C(e.h),l:C(e.l),s:C(e.s)})}parseString(t){if(!t.startsWith("hsl"))return;const e=/hsla?\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([\d.%]+)\s*)?\)/i.exec(t);return e?Ft({a:e.length>4?H(e[5]):1,h:parseInt(e[1],10),l:parseInt(e[3],10),s:parseInt(e[2],10)}):void 0}}class Oi{constructor(){this.key="rgb",this.stringPrefix="rgb"}handleColor(t){const e=t.value.rgb??t.value;if(void 0!==e.r)return e}handleRangeColor(t){const e=t.value.rgb??t.value;if(void 0!==e.r)return{r:C(e.r),g:C(e.g),b:C(e.b)}}parseString(t){if(!t.startsWith(this.stringPrefix))return;const e=/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d.%]+)\s*)?\)/i.exec(t);return e?{a:e.length>4?H(e[5]):1,b:parseInt(e[3],10),g:parseInt(e[2],10),r:parseInt(e[1],10)}:void 0}}class Si{constructor(t){this.container=t,this.type="external"}}class Di{constructor(t){this.container=t,this.type="particles"}}const Ti=function(){const t=new Oi,e=new Pi;Pt(t),Pt(e);const i=new Ci;return i.init(),i}();j()||(window.tsParticles=Ti);class Ri{constructor(){this.radius=0,this.mass=0}load(t){t&&(void 0!==t.mass&&(this.mass=t.mass),void 0!==t.radius&&(this.radius=t.radius))}}class Ei extends Re{constructor(){super(),this.density=5,this.value=50,this.limit=new Ri}load(t){t&&(super.load(t),void 0!==t.density&&(this.density=t.density),wt(t.limit)?this.limit.radius=t.limit:this.limit.load(t.limit))}}class Ii{constructor(){this.color=new ce,this.color.value="#000000",this.draggable=!1,this.opacity=1,this.destroy=!0,this.orbits=!1,this.size=new Ei}load(t){void 0!==t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.draggable&&(this.draggable=t.draggable),this.name=t.name,void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.position&&(this.position={},void 0!==t.position.x&&(this.position.x=S(t.position.x)),void 0!==t.position.y&&(this.position.y=S(t.position.y))),void 0!==t.size&&this.size.load(t.size),void 0!==t.destroy&&(this.destroy=t.destroy),void 0!==t.orbits&&(this.orbits=t.orbits))}}class Li{constructor(t,e,i,s){this.absorbers=t,this.container=e,this._calcPosition=()=>{const t=F({size:this.container.canvas.size,position:this.options.position});return y.create(t.x,t.y)},this._updateParticlePosition=(t,e)=>{if(t.destroyed)return;const i=this.container,s=i.canvas.size;if(t.needsNewPosition){const e=A({size:s});t.position.setTo(e),t.velocity.setTo(t.initialVelocity),t.absorberOrbit=void 0,t.needsNewPosition=!1}if(this.options.orbits){if(void 0===t.absorberOrbit&&(t.absorberOrbit=y.create(0,0),t.absorberOrbit.length=T(t.getPosition(),this.position),t.absorberOrbit.angle=_()*Math.PI*2),t.absorberOrbit.length<=this.size&&!this.options.destroy){const e=Math.min(s.width,s.height);t.absorberOrbit.length=e*(.2*_()-.1+1)}void 0===t.absorberOrbitDirection&&(t.absorberOrbitDirection=t.velocity.x>=0?"clockwise":"counter-clockwise");const o=t.absorberOrbit.length,n=t.absorberOrbit.angle,a=t.absorberOrbitDirection;t.velocity.setTo(y.origin);const r={x:"clockwise"===a?Math.cos:Math.sin,y:"clockwise"===a?Math.sin:Math.cos};t.position.x=this.position.x+o*r.x(n),t.position.y=this.position.y+o*r.y(n),t.absorberOrbit.length-=e.length,t.absorberOrbit.angle+=(t.retina.moveSpeed??0)*i.retina.pixelRatio/100*i.retina.reduceFactor}else{const i=y.origin;i.length=e.length,i.angle=e.angle,t.velocity.addTo(i)}},this.initialPosition=s?y.create(s.x,s.y):void 0,i instanceof Ii?this.options=i:(this.options=new Ii,this.options.load(i)),this.dragging=!1,this.name=this.options.name,this.opacity=this.options.opacity,this.size=C(this.options.size.value)*e.retina.pixelRatio,this.mass=this.size*this.options.size.density*e.retina.reduceFactor;const o=this.options.size.limit;this.limit={radius:o.radius*e.retina.pixelRatio*e.retina.reduceFactor,mass:o.mass},this.color=St(this.options.color)??{b:0,g:0,r:0},this.position=this.initialPosition?.copy()??this._calcPosition()}attract(t){const e=this.container,i=this.options;if(i.draggable){const t=e.interactivity.mouse;if(t.clicking&&t.downPosition){T(this.position,t.downPosition)<=this.size&&(this.dragging=!0)}else this.dragging=!1;this.dragging&&t.position&&(this.position.x=t.position.x,this.position.y=t.position.y)}const s=t.getPosition(),{dx:o,dy:n,distance:a}=D(this.position,s),r=y.create(o,n);if(r.length=this.mass/Math.pow(a,2)*e.retina.reduceFactor,at.getRadius()&&avoid 0===t||wt(t)?this.array[t||0]:this.array.find((e=>e.name===t)),t.addAbsorber=(t,e)=>this.addAbsorber(t,e)}addAbsorber(t,e){const i=new Li(this,this.container,t,e);return this.array.push(i),i}draw(t){for(const e of this.array)e.draw(t)}handleClickMode(t){const e=this.absorbers,i=this.interactivityAbsorbers;if("absorber"===t){const t=ut(i)??ut(e),s=this.container.interactivity.mouse.clickPosition;this.addAbsorber(t,s)}}async init(){this.absorbers=this.container.actualOptions.absorbers,this.interactivityAbsorbers=this.container.actualOptions.interactivity.modes.absorbers,dt(this.absorbers,(t=>{this.addAbsorber(t)}))}particleUpdate(t){for(const e of this.array)if(e.attract(t),t.destroyed)break}removeAbsorber(t){const e=this.array.indexOf(t);e>=0&&this.array.splice(e,1)}resize(){for(const t of this.array)t.resize()}stop(){this.array=[]}}class Fi{constructor(){this.id="absorbers"}getPlugin(t){return new Ai(t)}loadOptions(t,e){(this.needsPlugin(t)||this.needsPlugin(e))&&(e?.absorbers&&(t.absorbers=dt(e.absorbers,(t=>{const e=new Ii;return e.load(t),e}))),t.interactivity.modes.absorbers=dt(e?.interactivity?.modes?.absorbers,(t=>{const e=new Ii;return e.load(t),e})))}needsPlugin(t){if(!t)return!1;const e=t.absorbers;return kt(e)?!!e.length:!!e||!(!t.interactivity?.events?.onClick?.mode||!Z("absorber",t.interactivity.events.onClick.mode))}}class Bi{load(t){t&&(void 0!==t.bottom&&(this.bottom=S(t.bottom)),void 0!==t.left&&(this.left=S(t.left)),void 0!==t.right&&(this.right=S(t.right)),void 0!==t.top&&(this.top=S(t.top)))}}class qi extends Re{constructor(){super(),this.value=3}}class Hi extends Re{constructor(){super(),this.value={min:4,max:9}}}class Vi{constructor(){this.count=1,this.factor=new qi,this.rate=new Hi,this.sizeOffset=!0}load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.count&&(this.count=t.count),this.factor.load(t.factor),this.rate.load(t.rate),this.particles=dt(t.particles,(t=>st({},t))),void 0!==t.sizeOffset&&(this.sizeOffset=t.sizeOffset),t.colorOffset&&(this.colorOffset=this.colorOffset??{},void 0!==t.colorOffset.h&&(this.colorOffset.h=t.colorOffset.h),void 0!==t.colorOffset.s&&(this.colorOffset.s=t.colorOffset.s),void 0!==t.colorOffset.l&&(this.colorOffset.l=t.colorOffset.l)))}}class Ui{constructor(){this.bounds=new Bi,this.mode="none",this.split=new Vi}load(t){t&&(t.mode&&(this.mode=t.mode),t.bounds&&this.bounds.load(t.bounds),this.split.load(t.split))}}function Wi(t,e,i,s){const o=i.options.destroy;if(!o)return;const n=o.split,a=ci(t,e,i.options),r=C(n.factor.value),c=i.getFillColor();n.color?a.color.load(n.color):n.colorOffset&&c?a.color.load({value:{hsl:{h:c.h+C(n.colorOffset.h??0),s:c.s+C(n.colorOffset.s??0),l:c.l+C(n.colorOffset.l??0)}}}):a.color.load({value:{hsl:i.getFillColor()}}),a.move.load({center:{x:i.position.x,y:i.position.y,mode:"precise"}}),wt(a.size.value)?a.size.value/=r:(a.size.value.min/=r,a.size.value.max/=r),a.load(s);const l=n.sizeOffset?S(-i.size.value,i.size.value):0,h={x:i.position.x+M(l),y:i.position.y+M(l)};return e.particles.addParticle(h,a,i.group,(t=>!(t.size.value<.5)&&(t.velocity.length=M(S(i.velocity.length,t.velocity.length)),t.splitCount=(i.splitCount??0)+1,t.unbreakable=!0,setTimeout((()=>{t.unbreakable=!1}),500),!0)))}class $i{constructor(t,e){this.engine=t,this.container=e}init(t){const e=this.container,i=t.options.destroy;if(!i)return;t.splitCount=0;const s=i.bounds;t.destroyBounds||(t.destroyBounds={});const{bottom:o,left:n,right:a,top:r}=s,{destroyBounds:c}=t,l=e.canvas.size;o&&(c.bottom=C(o)*l.height/100),n&&(c.left=C(n)*l.width/100),a&&(c.right=C(a)*l.width/100),r&&(c.top=C(r)*l.height/100)}isEnabled(t){return!t.destroyed}loadOptions(t,...e){t.destroy||(t.destroy=new Ui);for(const i of e)t.destroy.load(i?.destroy)}particleDestroyed(t,e){if(e)return;const i=t.options.destroy;i&&"split"===i.mode&&function(t,e,i){const s=i.options.destroy;if(!s)return;const o=s.split;if(o.count>=0&&(void 0===i.splitCount||i.splitCount++>o.count))return;const n=C(o.rate.value),a=ut(o.particles);for(let s=0;s=i.bottom||void 0!==i.left&&e.x<=i.left||void 0!==i.right&&e.x>=i.right||void 0!==i.top&&e.y<=i.top)&&t.destroy()}}class ji{constructor(){this.wait=!1}load(t){t&&(void 0!==t.count&&(this.count=t.count),void 0!==t.delay&&(this.delay=S(t.delay)),void 0!==t.duration&&(this.duration=S(t.duration)),void 0!==t.wait&&(this.wait=t.wait))}}class Gi{constructor(){this.quantity=1,this.delay=.1}load(t){void 0!==t&&(void 0!==t.quantity&&(this.quantity=S(t.quantity)),void 0!==t.delay&&(this.delay=S(t.delay)))}}class Ni{constructor(){this.color=!1,this.opacity=!1}load(t){t&&(void 0!==t.color&&(this.color=t.color),void 0!==t.opacity&&(this.opacity=t.opacity))}}class Xi{constructor(){this.options={},this.replace=new Ni,this.type="square"}load(t){t&&(void 0!==t.options&&(this.options=st({},t.options??{})),this.replace.load(t.replace),void 0!==t.type&&(this.type=t.type))}}class Yi{constructor(){this.mode="percent",this.height=0,this.width=0}load(t){void 0!==t&&(void 0!==t.mode&&(this.mode=t.mode),void 0!==t.height&&(this.height=t.height),void 0!==t.width&&(this.width=t.width))}}class Zi{constructor(){this.autoPlay=!0,this.fill=!0,this.life=new ji,this.rate=new Gi,this.shape=new Xi,this.startCount=0}load(t){t&&(void 0!==t.autoPlay&&(this.autoPlay=t.autoPlay),void 0!==t.size&&(this.size||(this.size=new Yi),this.size.load(t.size)),void 0!==t.direction&&(this.direction=t.direction),this.domId=t.domId,void 0!==t.fill&&(this.fill=t.fill),this.life.load(t.life),this.name=t.name,this.particles=dt(t.particles,(t=>st({},t))),this.rate.load(t.rate),this.shape.load(t.shape),void 0!==t.position&&(this.position={},void 0!==t.position.x&&(this.position.x=S(t.position.x)),void 0!==t.position.y&&(this.position.y=S(t.position.y))),void 0!==t.spawnColor&&(void 0===this.spawnColor&&(this.spawnColor=new Se),this.spawnColor.load(t.spawnColor)),void 0!==t.startCount&&(this.startCount=t.startCount))}}function Qi(t,e){t.color?t.color.value=e:t.color={value:e}}class Ji{constructor(t,e,i,s,o){this.emitters=e,this.container=i,this._destroy=()=>{this._mutationObserver?.disconnect(),this._mutationObserver=void 0,this._resizeObserver?.disconnect(),this._resizeObserver=void 0,this.emitters.removeEmitter(this),this._engine.dispatchEvent("emitterDestroyed",{container:this.container,data:{emitter:this}})},this._prepareToDie=()=>{if(this._paused)return;const t=void 0!==this.options.life?.duration?C(this.options.life.duration):void 0;this.container.retina.reduceFactor&&(this._lifeCount>0||this._immortal)&&void 0!==t&&t>0&&(this._duration=1e3*t)},this._setColorAnimation=(t,e,i)=>{const s=this.container;if(!t.enable)return e;const o=M(t.offset),n=1e3*C(this.options.rate.delay)/s.retina.reduceFactor;return(e+C(t.speed??0)*s.fpsLimit/n+3.6*o)%i},this._engine=t,this._currentDuration=0,this._currentEmitDelay=0,this._currentSpawnDelay=0,this._initialPosition=o,s instanceof Zi?this.options=s:(this.options=new Zi,this.options.load(s)),this._spawnDelay=1e3*C(this.options.life.delay??0)/this.container.retina.reduceFactor,this.position=this._initialPosition??this._calcPosition(),this.name=this.options.name,this.fill=this.options.fill,this._firstSpawn=!this.options.life.wait,this._startParticlesAdded=!1;let n=st({},this.options.particles);if(n??={},n.move??={},n.move.direction??=this.options.direction,this.options.spawnColor&&(this.spawnColor=Rt(this.options.spawnColor)),this._paused=!this.options.autoPlay,this._particlesOptions=n,this._size=this._calcSize(),this.size=mt(this._size,this.container.canvas.size),this._lifeCount=this.options.life.count??-1,this._immortal=this._lifeCount<=0,this.options.domId){const t=document.getElementById(this.options.domId);t&&(this._mutationObserver=new MutationObserver((()=>{this.resize()})),this._resizeObserver=new ResizeObserver((()=>{this.resize()})),this._mutationObserver.observe(t,{attributes:!0,attributeFilter:["style","width","height"]}),this._resizeObserver.observe(t))}const a=this.options.shape,r=this._engine.emitterShapeManager?.getShapeGenerator(a.type);r&&(this._shape=r.generate(this.position,this.size,this.fill,a.options)),this._engine.dispatchEvent("emitterCreated",{container:i,data:{emitter:this}}),this.play()}externalPause(){this._paused=!0,this.pause()}externalPlay(){this._paused=!1,this.play()}async init(){await(this._shape?.init())}pause(){this._paused||delete this._emitDelay}play(){if(!this._paused&&this.container.retina.reduceFactor&&(this._lifeCount>0||this._immortal||!this.options.life.count)&&(this._firstSpawn||this._currentSpawnDelay>=(this._spawnDelay??0))){if(void 0===this._emitDelay){const t=C(this.options.rate.delay);this._emitDelay=1e3*t/this.container.retina.reduceFactor}(this._lifeCount>0||this._immortal)&&this._prepareToDie()}}resize(){const t=this._initialPosition;this.position=t&&tt(t,this.container.canvas.size,y.origin)?t:this._calcPosition(),this._size=this._calcSize(),this.size=mt(this._size,this.container.canvas.size),this._shape?.resize(this.position,this.size)}async update(t){this._paused||(this._firstSpawn&&(this._firstSpawn=!1,this._currentSpawnDelay=this._spawnDelay??0,this._currentEmitDelay=this._emitDelay??0),this._startParticlesAdded||(this._startParticlesAdded=!0,await this._emitParticles(this.options.startCount)),void 0!==this._duration&&(this._currentDuration+=t.value,this._currentDuration>=this._duration&&(this.pause(),void 0!==this._spawnDelay&&delete this._spawnDelay,this._immortal||this._lifeCount--,this._lifeCount>0||this._immortal?(this.position=this._calcPosition(),this._shape?.resize(this.position,this.size),this._spawnDelay=1e3*C(this.options.life.delay??0)/this.container.retina.reduceFactor):this._destroy(),this._currentDuration-=this._duration,delete this._duration)),void 0!==this._spawnDelay&&(this._currentSpawnDelay+=t.value,this._currentSpawnDelay>=this._spawnDelay&&(this._engine.dispatchEvent("emitterPlay",{container:this.container}),this.play(),this._currentSpawnDelay-=this._currentSpawnDelay,delete this._spawnDelay)),void 0!==this._emitDelay&&(this._currentEmitDelay+=t.value,this._currentEmitDelay>=this._emitDelay&&(this._emit(),this._currentEmitDelay-=this._emitDelay)))}_calcPosition(){if(this.options.domId){const t=this.container,e=document.getElementById(this.options.domId);if(e){const i=e.getBoundingClientRect();return{x:(i.x+i.width/2)*t.retina.pixelRatio,y:(i.y+i.height/2)*t.retina.pixelRatio}}}return F({size:this.container.canvas.size,position:this.options.position})}_calcSize(){const t=this.container;if(this.options.domId){const e=document.getElementById(this.options.domId);if(e){const i=e.getBoundingClientRect();return{width:i.width*t.retina.pixelRatio,height:i.height*t.retina.pixelRatio,mode:"precise"}}}return this.options.size??(()=>{const t=new Yi;return t.load({height:0,mode:"percent",width:0}),t})()}async _emit(){if(this._paused)return;const t=C(this.options.rate.quantity);await this._emitParticles(t)}async _emitParticles(t){const e=ut(this._particlesOptions);for(let i=0;ivoid 0===t||wt(t)?this.array[t||0]:this.array.find((e=>e.name===t)),e.addEmitter=async(t,e)=>this.addEmitter(t,e),e.removeEmitter=t=>{const i=e.getEmitter(t);i&&this.removeEmitter(i)},e.playEmitter=t=>{const i=e.getEmitter(t);i&&i.externalPlay()},e.pauseEmitter=t=>{const i=e.getEmitter(t);i&&i.externalPause()}}async addEmitter(t,e){const i=new Zi;i.load(t);const s=new Ji(this._engine,this,this.container,i,e);return await s.init(),this.array.push(s),s}handleClickMode(t){const e=this.emitters,i=this.interactivityEmitters;if("emitter"!==t)return;let s;if(i&&kt(i.value))if(i.value.length>0&&i.random.enable){s=[];const t=[];for(let e=0;e{this.addEmitter(t,n)}))}async init(){if(this.emitters=this.container.actualOptions.emitters,this.interactivityEmitters=this.container.actualOptions.interactivity.modes.emitters,this.emitters)if(kt(this.emitters))for(const t of this.emitters)await this.addEmitter(t);else await this.addEmitter(this.emitters)}pause(){for(const t of this.array)t.pause()}play(){for(const t of this.array)t.play()}removeEmitter(t){const e=this.array.indexOf(t);e>=0&&this.array.splice(e,1)}resize(){for(const t of this.array)t.resize()}stop(){this.array=[]}async update(t){for(const e of this.array)await e.update(t)}}const ts=new Map;class es{constructor(t){this._engine=t}addShapeGenerator(t,e){this.getShapeGenerator(t)||ts.set(t,e)}getShapeGenerator(t){return ts.get(t)}getSupportedShapeGenerators(){return ts.keys()}}class is{constructor(t,e,i,s){this.position=t,this.size=e,this.fill=i,this.options=s}resize(t,e){this.position=t,this.size=e}}class ss{constructor(t){this._engine=t,this.id="emitters"}getPlugin(t){return new Ki(this._engine,t)}loadOptions(t,e){if(!this.needsPlugin(t)&&!this.needsPlugin(e))return;e?.emitters&&(t.emitters=dt(e.emitters,(t=>{const e=new Zi;return e.load(t),e})));const i=e?.interactivity?.modes?.emitters;if(i)if(kt(i))t.interactivity.modes.emitters={random:{count:1,enable:!0},value:i.map((t=>{const e=new Zi;return e.load(t),e}))};else{const e=i;if(void 0!==e.value)if(kt(e.value))t.interactivity.modes.emitters={random:{count:e.random.count??1,enable:e.random.enable??!1},value:e.value.map((t=>{const e=new Zi;return e.load(t),e}))};else{const i=new Zi;i.load(e.value),t.interactivity.modes.emitters={random:{count:e.random.count??1,enable:e.random.enable??!1},value:i}}else{(t.interactivity.modes.emitters={random:{count:1,enable:!1},value:new Zi}).value.load(i)}}}needsPlugin(t){if(!t)return!1;const e=t.emitters;return kt(e)&&!!e.length||void 0!==e||!!t.interactivity?.events?.onClick?.mode&&Z("emitter",t.interactivity.events.onClick.mode)}}class os extends is{constructor(t,e,i,s){super(t,e,i,s)}async init(){}async randomPosition(){const t=this.size,e=this.fill,i=this.position,[s,o]=[t.width/2,t.height/2],n=((t,e)=>{const i=_()/4,s=Math.atan(e/t*Math.tan(2*Math.PI*i)),o=_();return o<.25?s:o<.5?Math.PI-s:o<.75?Math.PI+s:-s})(s,o),a=(h=n,(c=s)*(l=o)/Math.sqrt((l*Math.cos(h))**2+(c*Math.sin(h))**2)),r=e?a*Math.sqrt(_()):a;var c,l,h;return{position:{x:i.x+r*Math.cos(n),y:i.y+r*Math.sin(n)}}}}class ns{generate(t,e,i,s){return new os(t,e,i,s)}}function as(t,e){return t+e*(_()-.5)}class rs extends is{constructor(t,e,i,s){super(t,e,i,s)}async init(){}async randomPosition(){const t=this.fill,e=this.position,i=this.size;if(t)return{position:{x:as(e.x,i.width),y:as(e.y,i.height)}};{const t=i.width/2,s=i.height/2,o=Math.floor(4*_()),n=2*(_()-.5);switch(o){case 0:return{position:{x:e.x+n*t,y:e.y-s}};case 1:return{position:{x:e.x-t,y:e.y+n*s}};case 2:return{position:{x:e.x+n*t,y:e.y+s}};default:return{position:{x:e.x+t,y:e.y+n*s}}}}}}class cs{generate(t,e,i,s){return new rs(t,e,i,s)}}class ls{constructor(){this.delay=1,this.pauseOnStop=!1,this.quantity=1}load(t){t&&(void 0!==t.delay&&(this.delay=t.delay),void 0!==t.quantity&&(this.quantity=t.quantity),void 0!==t.particles&&(this.particles=st({},t.particles)),void 0!==t.pauseOnStop&&(this.pauseOnStop=t.pauseOnStop))}}const hs="trail";class ds extends Si{constructor(t){super(t),this._delay=0}clear(){}init(){}async interact(t){const e=this.container,{interactivity:i}=e;if(!e.retina.reduceFactor)return;const s=e.actualOptions.interactivity.modes.trail;if(!s)return;const o=1e3*s.delay/this.container.retina.reduceFactor;if(this._delay=.5?"darken":"enlighten";t.roll.alter={type:i,value:C("darken"===i?e.darken.value:e.enlighten.value)}}else e.darken.enable?t.roll.alter={type:"darken",value:C(e.darken.value)}:e.enlighten.enable&&(t.roll.alter={type:"enlighten",value:C(e.enlighten.value)});else t.roll={enable:!1,horizontal:!1,vertical:!1,angle:0,speed:0}}(t)}isEnabled(t){const e=t.options.roll;return!t.destroyed&&!t.spawning&&!!e?.enable}loadOptions(t,...e){t.roll||(t.roll=new ps);for(const i of e)t.roll.load(i?.roll)}update(t,e){this.isEnabled(t)&&function(t,e){const i=t.options.roll,s=t.roll;if(!s||!i?.enable)return;const o=s.speed*e.factor,n=2*Math.PI;s.angle+=o,s.angle>n&&(s.angle-=n)}(t,e)}}function vs(t,e,i,s,o,n){!function(t,e){const i=t.options,s=i.move.path;if(!s.enable)return;if(t.lastPathTime<=t.pathDelay)return void(t.lastPathTime+=e.value);const o=t.pathGenerator?.generate(t,e);o&&t.velocity.addTo(o);s.clamp&&(t.velocity.x=k(t.velocity.x,-1,1),t.velocity.y=k(t.velocity.y,-1,1));t.lastPathTime-=t.pathDelay}(t,n);const a=t.gravity,r=a?.enable&&a.inverse?-1:1;o&&i&&(t.velocity.x+=o*n.factor/(60*i)),a?.enable&&i&&(t.velocity.y+=r*(a.acceleration*n.factor)/(60*i));const c=t.moveDecay;t.velocity.multTo(c);const l=t.velocity.mult(i);a?.enable&&s>0&&(!a.inverse&&l.y>=0&&l.y>=s||a.inverse&&l.y<=0&&l.y<=-s)&&(l.y=r*s,i&&(t.velocity.y=l.y/i));const h=t.options.zIndex,d=(1-t.zIndexFactor)**h.velocityRate;l.multTo(d);const{position:u}=t;u.addTo(l),e.vibrate&&(u.x+=Math.sin(u.x*Math.cos(u.y)),u.y+=Math.cos(u.y*Math.sin(u.x)))}class ys{constructor(){this._initSpin=t=>{const e=t.container,i=t.options.move.spin;if(!i.enable)return;const s=i.position??{x:50,y:50},o={x:.01*s.x*e.canvas.size.width,y:.01*s.y*e.canvas.size.height},n=T(t.getPosition(),o),a=C(i.acceleration);t.retina.spinAcceleration=a*e.retina.pixelRatio,t.spin={center:o,direction:t.velocity.x>=0?"clockwise":"counter-clockwise",angle:t.velocity.angle,radius:n,acceleration:t.retina.spinAcceleration}}}init(t){const e=t.options.move.gravity;t.gravity={enable:e.enable,acceleration:C(e.acceleration),inverse:e.inverse},this._initSpin(t)}isEnabled(t){return!t.destroyed&&t.options.move.enable}move(t,e){const i=t.options,s=i.move;if(!s.enable)return;const o=t.container,n=o.retina.pixelRatio,a=function(t){return t.slow.inRange?t.slow.factor:1}(t),r=(t.retina.moveSpeed??=C(s.speed)*n)*o.retina.reduceFactor,c=t.retina.moveDrift??=C(t.options.move.drift)*n,l=O(i.size.value)*n,h=r*(s.size?t.getRadius()/l:1)*a*(e.factor||1)/2,d=t.retina.maxSpeed??o.retina.maxSpeed;s.spin.enable?function(t,e){const i=t.container;if(!t.spin)return;const s={x:"clockwise"===t.spin.direction?Math.cos:Math.sin,y:"clockwise"===t.spin.direction?Math.sin:Math.cos};t.position.x=t.spin.center.x+t.spin.radius*s.x(t.spin.angle),t.position.y=t.spin.center.y+t.spin.radius*s.y(t.spin.angle),t.spin.radius+=t.spin.acceleration;const o=Math.max(i.canvas.size.width,i.canvas.size.height),n=.5*o;t.spin.radius>n?(t.spin.radius=n,t.spin.acceleration*=-1):t.spin.radius<0&&(t.spin.radius=0,t.spin.acceleration*=-1),t.spin.angle+=.01*e*(1-t.spin.radius/o)}(t,h):vs(t,s,h,d,c,e),function(t){const e=t.initialPosition,{dx:i,dy:s}=D(e,t.position),o=Math.abs(i),n=Math.abs(s),{maxDistance:a}=t.retina,r=a.horizontal,c=a.vertical;if(r||c)if((r&&o>=r||c&&n>=c)&&!t.misplaced)t.misplaced=!!r&&o>r||!!c&&n>c,r&&(t.velocity.x=.5*t.velocity.y-t.velocity.x),c&&(t.velocity.y=.5*t.velocity.x-t.velocity.y);else if((!r||oe.x&&s.x>0)&&(s.x*=-_()),c&&(i.ye.y&&s.y>0)&&(s.y*=-_())}}(t)}}class ms{draw(t){const{context:e,particle:i,radius:s}=t;i.circleRange||(i.circleRange={min:0,max:2*Math.PI});const o=i.circleRange;e.arc(0,0,s,o.min,o.max,!1)}getSidesCount(){return 12}particleInit(t,e){const i=e.shapeData,s=i?.angle??{max:360,min:0};e.circleRange=_t(s)?{min:s.min*Math.PI/180,max:s.max*Math.PI/180}:{min:0,max:s*Math.PI/180}}}function gs(t,e,i,s,o){if(!e||!i.enable||(e.maxLoops??0)>0&&(e.loops??0)>(e.maxLoops??0))return;if(e.time||(e.time=0),(e.delayTime??0)>0&&e.time<(e.delayTime??0)&&(e.time+=t.value),(e.delayTime??0)>0&&e.time<(e.delayTime??0))return;const n=M(i.offset),a=(e.velocity??0)*t.factor+3.6*n,r=e.decay??1;o&&"increasing"!==e.status?(e.value-=a,e.value<0&&(e.loops||(e.loops=0),e.loops++,e.status="increasing",e.value+=e.value)):(e.value+=a,e.value>s&&(e.loops||(e.loops=0),e.loops++,o&&(e.status="decreasing",e.value-=e.value%s))),e.velocity&&1!==r&&(e.velocity*=r),e.value>s&&(e.value%=s)}class bs{constructor(t){this.container=t}init(t){const e=Rt(t.options.color,t.id,t.options.reduceDuplicates);e&&(t.color=jt(e,t.options.color.animation,this.container.retina.reduceFactor))}isEnabled(t){const{h:e,s:i,l:s}=t.options.color.animation,{color:o}=t;return!t.destroyed&&!t.spawning&&(void 0!==o?.h.value&&e.enable||void 0!==o?.s.value&&i.enable||void 0!==o?.l.value&&s.enable)}update(t,e){!function(t,e){const{h:i,s,l:o}=t.options.color.animation,{color:n}=t;if(!n)return;const{h:a,s:r,l:c}=n;a&&gs(e,a,i,360,!1),r&&gs(e,r,s,100,!0),c&&gs(e,c,o,100,!0)}(t,e)}}class ws{constructor(t){this.container=t}init(t){const e=t.options.opacity;t.opacity=ft(e,1);const i=e.animation;i.enable&&(t.opacity.velocity=C(i.speed)/100*this.container.retina.reduceFactor,i.sync||(t.opacity.velocity*=_()))}isEnabled(t){return!t.destroyed&&!t.spawning&&!!t.opacity&&t.opacity.enable&&((t.opacity.maxLoops??0)<=0||(t.opacity.maxLoops??0)>0&&(t.opacity.loops??0)<(t.opacity.maxLoops??0))}reset(t){t.opacity&&(t.opacity.time=0,t.opacity.loops=0)}update(t,e){this.isEnabled(t)&&function(t,e){const i=t.opacity;if(t.destroyed||!i?.enable||(i.maxLoops??0)>0&&(i.loops??0)>(i.maxLoops??0))return;const s=i.min,o=i.max,n=i.decay??1;if(i.time||(i.time=0),(i.delayTime??0)>0&&i.time<(i.delayTime??0)&&(i.time+=e.value),!((i.delayTime??0)>0&&i.time<(i.delayTime??0))){switch(i.status){case"increasing":i.value>=o?(i.status="decreasing",i.loops||(i.loops=0),i.loops++):i.value+=(i.velocity??0)*e.factor;break;case"decreasing":i.value<=s?(i.status="increasing",i.loops||(i.loops=0),i.loops++):i.value-=(i.velocity??0)*e.factor}i.velocity&&1!==i.decay&&(i.velocity*=n),function(t,e,i,s){switch(t.options.opacity.animation.destroy){case"max":e>=s&&t.destroy();break;case"min":e<=i&&t.destroy()}}(t,i.value,s,o),t.destroyed||(i.value=k(i.value,s,o))}}(t,e)}}class xs{constructor(t){this.container=t,this.modes=["bounce","bounce-vertical","bounce-horizontal","bounceVertical","bounceHorizontal","split"]}update(t,e,i,s){if(!this.modes.includes(s))return;const o=this.container;let n=!1;for(const[,s]of o.plugins)if(void 0!==s.particleBounce&&(n=s.particleBounce(t,i,e)),n)break;if(n)return;const a=t.getPosition(),r=t.offset,c=t.getRadius(),l=it(a,c),h=o.canvas.size;!function(t){if("bounce"!==t.outMode&&"bounce-horizontal"!==t.outMode&&"bounceHorizontal"!==t.outMode&&"split"!==t.outMode||"left"!==t.direction&&"right"!==t.direction)return;t.bounds.right<0&&"left"===t.direction?t.particle.position.x=t.size+t.offset.x:t.bounds.left>t.canvasSize.width&&"right"===t.direction&&(t.particle.position.x=t.canvasSize.width-t.size-t.offset.x);const e=t.particle.velocity.x;let i=!1;if("right"===t.direction&&t.bounds.right>=t.canvasSize.width&&e>0||"left"===t.direction&&t.bounds.left<=0&&e<0){const e=C(t.particle.options.bounce.horizontal.value);t.particle.velocity.x*=-e,i=!0}if(!i)return;const s=t.offset.x+t.size;t.bounds.right>=t.canvasSize.width&&"right"===t.direction?t.particle.position.x=t.canvasSize.width-s:t.bounds.left<=0&&"left"===t.direction&&(t.particle.position.x=s),"split"===t.outMode&&t.particle.destroy()}({particle:t,outMode:s,direction:e,bounds:l,canvasSize:h,offset:r,size:c}),function(t){if("bounce"!==t.outMode&&"bounce-vertical"!==t.outMode&&"bounceVertical"!==t.outMode&&"split"!==t.outMode||"bottom"!==t.direction&&"top"!==t.direction)return;t.bounds.bottom<0&&"top"===t.direction?t.particle.position.y=t.size+t.offset.y:t.bounds.top>t.canvasSize.height&&"bottom"===t.direction&&(t.particle.position.y=t.canvasSize.height-t.size-t.offset.y);const e=t.particle.velocity.y;let i=!1;if("bottom"===t.direction&&t.bounds.bottom>=t.canvasSize.height&&e>0||"top"===t.direction&&t.bounds.top<=0&&e<0){const e=C(t.particle.options.bounce.vertical.value);t.particle.velocity.y*=-e,i=!0}if(!i)return;const s=t.offset.y+t.size;t.bounds.bottom>=t.canvasSize.height&&"bottom"===t.direction?t.particle.position.y=t.canvasSize.height-s:t.bounds.top<=0&&"top"===t.direction&&(t.particle.position.y=s),"split"===t.outMode&&t.particle.destroy()}({particle:t,outMode:s,direction:e,bounds:l,canvasSize:h,offset:r,size:c})}}class _s{constructor(t){this.container=t,this.modes=["destroy"]}update(t,e,i,s){if(!this.modes.includes(s))return;const o=this.container;switch(t.outType){case"normal":case"outside":if(tt(t.position,o.canvas.size,y.origin,t.getRadius(),e))return;break;case"inside":{const{dx:e,dy:i}=D(t.position,t.moveCenter),{x:s,y:o}=t.velocity;if(s<0&&e>t.moveCenter.radius||o<0&&i>t.moveCenter.radius||s>=0&&e<-t.moveCenter.radius||o>=0&&i<-t.moveCenter.radius)return;break}}o.particles.remove(t,void 0,!0)}}class ks{constructor(t){this.container=t,this.modes=["none"]}update(t,e,i,s){if(!this.modes.includes(s))return;if(t.options.move.distance.horizontal&&("left"===e||"right"===e)||t.options.move.distance.vertical&&("top"===e||"bottom"===e))return;const o=t.options.move.gravity,n=this.container,a=n.canvas.size,r=t.getRadius();if(o.enable){const i=t.position;(!o.inverse&&i.y>a.height+r&&"bottom"===e||o.inverse&&i.y<-r&&"top"===e)&&n.particles.remove(t)}else{if(t.velocity.y>0&&t.position.y<=a.height+r||t.velocity.y<0&&t.position.y>=-r||t.velocity.x>0&&t.position.x<=a.width+r||t.velocity.x<0&&t.position.x>=-r)return;tt(t.position,n.canvas.size,y.origin,r,e)||n.particles.remove(t)}}}class zs{constructor(t){this.container=t,this.modes=["out"]}update(t,e,i,s){if(!this.modes.includes(s))return;const o=this.container;switch(t.outType){case"inside":{const{x:e,y:i}=t.velocity,s=y.origin;s.length=t.moveCenter.radius,s.angle=t.velocity.angle+Math.PI,s.addTo(y.create(t.moveCenter));const{dx:n,dy:a}=D(t.position,s);if(e<=0&&n>=0||i<=0&&a>=0||e>=0&&n<=0||i>=0&&a<=0)return;t.position.x=Math.floor(M({min:0,max:o.canvas.size.width})),t.position.y=Math.floor(M({min:0,max:o.canvas.size.height}));const{dx:r,dy:c}=D(t.position,t.moveCenter);t.direction=Math.atan2(-c,-r),t.velocity.angle=t.direction;break}default:if(tt(t.position,o.canvas.size,y.origin,t.getRadius(),e))return;switch(t.outType){case"outside":{t.position.x=Math.floor(M({min:-t.moveCenter.radius,max:t.moveCenter.radius}))+t.moveCenter.x,t.position.y=Math.floor(M({min:-t.moveCenter.radius,max:t.moveCenter.radius}))+t.moveCenter.y;const{dx:e,dy:i}=D(t.position,t.moveCenter);t.moveCenter.radius&&(t.direction=Math.atan2(i,e),t.velocity.angle=t.direction);break}case"normal":{const i=t.options.move.warp,s=o.canvas.size,n={bottom:s.height+t.getRadius()+t.offset.y,left:-t.getRadius()-t.offset.x,right:s.width+t.getRadius()+t.offset.x,top:-t.getRadius()-t.offset.y},a=t.getRadius(),r=it(t.position,a);"right"===e&&r.left>s.width+t.offset.x?(t.position.x=n.left,t.initialPosition.x=t.position.x,i||(t.position.y=_()*s.height,t.initialPosition.y=t.position.y)):"left"===e&&r.right<-t.offset.x&&(t.position.x=n.right,t.initialPosition.x=t.position.x,i||(t.position.y=_()*s.height,t.initialPosition.y=t.position.y)),"bottom"===e&&r.top>s.height+t.offset.y?(i||(t.position.x=_()*s.width,t.initialPosition.x=t.position.x),t.position.y=n.top,t.initialPosition.y=t.position.y):"top"===e&&r.bottom<-t.offset.y&&(i||(t.position.x=_()*s.width,t.initialPosition.x=t.position.x),t.position.y=n.bottom,t.initialPosition.y=t.position.y);break}}}}}class Ms{constructor(t){this.container=t,this._updateOutMode=(t,e,i,s)=>{for(const o of this.updaters)o.update(t,s,e,i)},this.updaters=[new xs(t),new _s(t),new zs(t),new ks(t)]}init(){}isEnabled(t){return!t.destroyed&&!t.spawning}update(t,e){const i=t.options.move.outModes;this._updateOutMode(t,e,i.bottom??i.default,"bottom"),this._updateOutMode(t,e,i.left??i.default,"left"),this._updateOutMode(t,e,i.right??i.default,"right"),this._updateOutMode(t,e,i.top??i.default,"top")}}class Cs{init(t){const e=t.container,i=t.options.size.animation;i.enable&&(t.size.velocity=(t.retina.sizeAnimationSpeed??e.retina.sizeAnimationSpeed)/100*e.retina.reduceFactor,i.sync||(t.size.velocity*=_()))}isEnabled(t){return!t.destroyed&&!t.spawning&&t.size.enable&&((t.size.maxLoops??0)<=0||(t.size.maxLoops??0)>0&&(t.size.loops??0)<(t.size.maxLoops??0))}reset(t){t.size.loops=0}update(t,e){this.isEnabled(t)&&function(t,e){const i=t.size;if(t.destroyed||!i||!i.enable||(i.maxLoops??0)>0&&(i.loops??0)>(i.maxLoops??0))return;const s=(i.velocity??0)*e.factor,o=i.min,n=i.max,a=i.decay??1;if(i.time||(i.time=0),(i.delayTime??0)>0&&i.time<(i.delayTime??0)&&(i.time+=e.value),!((i.delayTime??0)>0&&i.time<(i.delayTime??0))){switch(i.status){case"increasing":i.value>=n?(i.status="decreasing",i.loops||(i.loops=0),i.loops++):i.value+=s;break;case"decreasing":i.value<=o?(i.status="increasing",i.loops||(i.loops=0),i.loops++):i.value-=s}i.velocity&&1!==a&&(i.velocity*=a),function(t,e,i,s){switch(t.options.size.animation.destroy){case"max":e>=s&&t.destroy();break;case"min":e<=i&&t.destroy()}}(t,i.value,o,n),t.destroyed||(i.value=k(i.value,o,n))}}(t,e)}}async function Ps(t,e=!0){await async function(t,e=!0){await t.addMover("base",(()=>new ys),e)}(t,!1),await async function(t,e=!0){await t.addShape("circle",new ms,e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("color",(t=>new bs(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("opacity",(t=>new ws(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("outModes",(t=>new Ms(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("size",(()=>new Cs),e)}(t,!1),await t.refresh(e)}const Os=["emoji"],Ss='"Twemoji Mozilla", Apple Color Emoji, "Segoe UI Emoji", "Noto Color Emoji", "EmojiOne Color"';class Ds{constructor(){this._emojiShapeDict=new Map}destroy(){for(const[,t]of this._emojiShapeDict)t instanceof ImageBitmap&&t?.close()}draw(t){const{context:e,particle:i,radius:s,opacity:o}=t,n=i.emojiData;n&&(e.globalAlpha=o,e.drawImage(n,-s,-s,2*s,2*s),e.globalAlpha=1)}async init(t){const e=t.actualOptions;if(Os.find((t=>Z(t,e.particles.shape.type)))){const t=[Q(Ss)],i=Os.map((t=>e.particles.shape.options[t])).find((t=>!!t));i&&dt(i,(e=>{e.font&&t.push(Q(e.font))})),await Promise.all(t)}}particleDestroy(t){delete t.emojiData}particleInit(t,e){if(!e.emojiData){const t=e.shapeData;if(!t?.value)return;const i=ut(t.value,e.randomIndexData),s=t.font??Ss;if(!i)return;const o=`${i}_${s}`,n=this._emojiShapeDict.get(o);if(n)return void(e.emojiData=n);const a=2*O(e.size.value);let r;if("undefined"!=typeof OffscreenCanvas){const t=new OffscreenCanvas(a,a),o=t.getContext("2d");if(!o)return;o.font=`400 ${2*O(e.size.value)}px ${s}`,o.textBaseline="middle",o.textAlign="center",o.fillText(i,O(e.size.value),O(e.size.value)),r=t.transferToImageBitmap()}else{const t=document.createElement("canvas");t.width=a,t.height=a;const o=t.getContext("2d");if(!o)return;o.font=`400 ${2*O(e.size.value)}px ${s}`,o.textBaseline="middle",o.textAlign="center",o.fillText(i,O(e.size.value),O(e.size.value)),r=t}this._emojiShapeDict.set(o,r),e.emojiData=r}}}class Ts{constructor(){this.distance=200,this.duration=.4,this.easing="ease-out-quad",this.factor=1,this.maxSpeed=50,this.speed=1}load(t){t&&(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.easing&&(this.easing=t.easing),void 0!==t.factor&&(this.factor=t.factor),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.speed&&(this.speed=t.speed))}}const Rs="attract";class Es extends Si{constructor(t,e){super(e),this._clickAttract=()=>{const t=this.container;t.attract||(t.attract={particles:[]});const{attract:e}=t;if(e.finish||(e.count||(e.count=0),e.count++,e.count===t.particles.count&&(e.finish=!0)),e.clicking){const e=t.interactivity.mouse.clickPosition,i=t.retina.attractModeDistance;if(!i||i<0||!e)return;this._processAttract(e,i,new yi(e.x,e.y,i))}else!1===e.clicking&&(e.particles=[])},this._hoverAttract=()=>{const t=this.container,e=t.interactivity.mouse.position,i=t.retina.attractModeDistance;!i||i<0||!e||this._processAttract(e,i,new yi(e.x,e.y,i))},this._processAttract=(t,e,i)=>{const s=this.container,o=s.actualOptions.interactivity.modes.attract;if(!o)return;const n=s.particles.quadTree.query(i,(t=>this.isEnabled(t)));for(const i of n){const{dx:s,dy:n,distance:a}=D(i.position,t),r=o.speed*o.factor,c=k(w(o.easing)(1-a/e)*r,0,o.maxSpeed),l=y.create(0===a?r:s/a*c,0===a?r:n/a*c);i.position.subFrom(l)}},this._engine=t,e.attract||(e.attract={particles:[]}),this.handleClickMode=t=>{const i=this.container.actualOptions.interactivity.modes.attract;if(i&&t===Rs){e.attract||(e.attract={particles:[]}),e.attract.clicking=!0,e.attract.count=0;for(const t of e.attract.particles)this.isEnabled(t)&&t.velocity.setTo(t.initialVelocity);e.attract.particles=[],e.attract.finish=!1,setTimeout((()=>{e.destroyed||(e.attract||(e.attract={particles:[]}),e.attract.clicking=!1)}),1e3*i.duration)}}}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.attract;e&&(t.retina.attractModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const t=this.container,e=t.actualOptions,i=t.interactivity.status===r,s=e.interactivity.events,o=s.onHover.enable,n=s.onHover.mode,a=s.onClick.enable,c=s.onClick.mode;i&&o&&Z(Rs,n)?this._hoverAttract():a&&Z(Rs,c)&&this._clickAttract()}isEnabled(t){const e=this.container,i=e.actualOptions,s=e.interactivity.mouse,o=(t?.interactivity??i.interactivity).events;if(!(s.position&&o.onHover.enable||s.clickPosition&&o.onClick.enable))return!1;const n=o.onHover.mode,a=o.onClick.mode;return Z(Rs,n)||Z(Rs,a)}loadModeOptions(t,...e){t.attract||(t.attract=new Ts);for(const i of e)t.attract.load(i?.attract)}reset(){}}class Is{constructor(){this.distance=200}load(t){t&&void 0!==t.distance&&(this.distance=t.distance)}}const Ls="bounce";class As extends Si{constructor(t){super(t),this._processBounce=(t,e,i)=>{const s=this.container.particles.quadTree.query(i,(t=>this.isEnabled(t)));for(const o of s)i instanceof yi?lt(ct(o),{position:t,radius:e,mass:e**2*Math.PI/2,velocity:y.origin,factor:y.origin}):i instanceof vi&&ht(o,it(t,e))},this._processMouseBounce=()=>{const t=this.container,e=10*t.retina.pixelRatio,i=t.interactivity.mouse.position,s=t.retina.bounceModeDistance;!s||s<0||!i||this._processBounce(i,s,new yi(i.x,i.y,s+e))},this._singleSelectorBounce=(t,e)=>{const i=this.container,s=document.querySelectorAll(t);s.length&&s.forEach((t=>{const s=t,o=i.retina.pixelRatio,n={x:(s.offsetLeft+s.offsetWidth/2)*o,y:(s.offsetTop+s.offsetHeight/2)*o},a=s.offsetWidth/2*o,r=10*o,c="circle"===e.type?new yi(n.x,n.y,a+r):new vi(s.offsetLeft*o-r,s.offsetTop*o-r,s.offsetWidth*o+2*r,s.offsetHeight*o+2*r);this._processBounce(n,a,c)}))}}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.bounce;e&&(t.retina.bounceModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const t=this.container,e=t.actualOptions.interactivity.events,i=t.interactivity.status===r,s=e.onHover.enable,o=e.onHover.mode,n=e.onDiv;i&&s&&Z(Ls,o)?this._processMouseBounce():nt(Ls,n,((t,e)=>this._singleSelectorBounce(t,e)))}isEnabled(t){const e=this.container,i=e.actualOptions,s=e.interactivity.mouse,o=(t?.interactivity??i.interactivity).events,n=o.onDiv;return s.position&&o.onHover.enable&&Z(Ls,o.onHover.mode)||ot(Ls,n)}loadModeOptions(t,...e){t.bounce||(t.bounce=new Is);for(const i of e)t.bounce.load(i?.bounce)}reset(){}}class Fs{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(t){if(t){if(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.mix&&(this.mix=t.mix),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.color){const e=kt(this.color)?void 0:this.color;this.color=dt(t.color,(t=>ce.create(e,t)))}void 0!==t.size&&(this.size=t.size)}}}class Bs extends Fs{constructor(){super(),this.selectors=[]}load(t){super.load(t),t&&void 0!==t.selectors&&(this.selectors=t.selectors)}}class qs extends Fs{load(t){super.load(t),t&&(this.divs=dt(t.divs,(t=>{const e=new Bs;return e.load(t),e})))}}function Hs(t,e,i,s){if(e>=i){return k(t+(e-i)*s,t,e)}if(e{const t=this.container,e=t.actualOptions,i=t.interactivity.mouse.clickPosition,s=e.interactivity.modes.bubble;if(!s||!i)return;t.bubble||(t.bubble={});const o=t.retina.bubbleModeDistance;if(!o||o<0)return;const n=t.particles.quadTree.queryCircle(i,o,(t=>this.isEnabled(t))),{bubble:a}=t;for(const e of n){if(!a.clicking)continue;e.bubble.inRange=!a.durationEnd;const n=T(e.getPosition(),i),r=((new Date).getTime()-(t.interactivity.mouse.clickTime||0))/1e3;r>s.duration&&(a.durationEnd=!0),r>2*s.duration&&(a.clicking=!1,a.durationEnd=!1);const c={bubbleObj:{optValue:t.retina.bubbleModeSize,value:e.bubble.radius},particlesObj:{optValue:O(e.options.size.value)*t.retina.pixelRatio,value:e.size.value},type:"size"};this._process(e,n,r,c);const l={bubbleObj:{optValue:s.opacity,value:e.bubble.opacity},particlesObj:{optValue:O(e.options.opacity.value),value:e.opacity?.value??1},type:"opacity"};this._process(e,n,r,l),!a.durationEnd&&n<=o?this._hoverBubbleColor(e,n):delete e.bubble.color}},this._hoverBubble=()=>{const t=this.container,e=t.interactivity.mouse.position,i=t.retina.bubbleModeDistance;if(!i||i<0||void 0===e)return;const s=t.particles.quadTree.queryCircle(e,i,(t=>this.isEnabled(t)));for(const o of s){o.bubble.inRange=!0;const s=T(o.getPosition(),e),a=1-s/i;s<=i?a>=0&&t.interactivity.status===r&&(this._hoverBubbleSize(o,a),this._hoverBubbleOpacity(o,a),this._hoverBubbleColor(o,a)):this.reset(o),t.interactivity.status===n&&this.reset(o)}},this._hoverBubbleColor=(t,e,i)=>{const s=this.container.actualOptions,o=i??s.interactivity.modes.bubble;if(o){if(!t.bubble.finalColor){const e=o.color;if(!e)return;const i=ut(e);t.bubble.finalColor=Rt(i)}if(t.bubble.finalColor)if(o.mix){t.bubble.color=void 0;const i=t.getFillColor();t.bubble.color=i?Et(Vt(i,t.bubble.finalColor,1-e,e)):t.bubble.finalColor}else t.bubble.color=t.bubble.finalColor}},this._hoverBubbleOpacity=(t,e,i)=>{const s=this.container.actualOptions,o=i?.opacity??s.interactivity.modes.bubble?.opacity;if(!o)return;const n=t.options.opacity.value,a=Hs(t.opacity?.value??1,o,O(n),e);void 0!==a&&(t.bubble.opacity=a)},this._hoverBubbleSize=(t,e,i)=>{const s=this.container,o=i?.size?i.size*s.retina.pixelRatio:s.retina.bubbleModeSize;if(void 0===o)return;const n=O(t.options.size.value)*s.retina.pixelRatio,a=Hs(t.size.value,o,n,e);void 0!==a&&(t.bubble.radius=a)},this._process=(t,e,i,s)=>{const o=this.container,n=s.bubbleObj.optValue,a=o.actualOptions.interactivity.modes.bubble;if(!a||void 0===n)return;const r=a.duration,c=o.retina.bubbleModeDistance,l=s.particlesObj.optValue,h=s.bubbleObj.value,d=s.particlesObj.value||0,u=s.type;if(c&&!(c<0)&&n!==l)if(o.bubble||(o.bubble={}),o.bubble.durationEnd)h&&("size"===u&&delete t.bubble.radius,"opacity"===u&&delete t.bubble.opacity);else if(e<=c){if((h??d)!==n){const e=d-i*(d-n)/r;"size"===u&&(t.bubble.radius=e),"opacity"===u&&(t.bubble.opacity=e)}}else"size"===u&&delete t.bubble.radius,"opacity"===u&&delete t.bubble.opacity},this._singleSelectorHover=(t,e,i)=>{const s=this.container,o=document.querySelectorAll(e),n=s.actualOptions.interactivity.modes.bubble;n&&o.length&&o.forEach((e=>{const o=e,a=s.retina.pixelRatio,r={x:(o.offsetLeft+o.offsetWidth/2)*a,y:(o.offsetTop+o.offsetHeight/2)*a},c=o.offsetWidth/2*a,l="circle"===i.type?new yi(r.x,r.y,c):new vi(o.offsetLeft*a,o.offsetTop*a,o.offsetWidth*a,o.offsetHeight*a),h=s.particles.quadTree.query(l,(t=>this.isEnabled(t)));for(const e of h){if(!l.contains(e.getPosition()))continue;e.bubble.inRange=!0;const i=rt(n.divs,o);e.bubble.div&&e.bubble.div===o||(this.clear(e,t,!0),e.bubble.div=o),this._hoverBubbleSize(e,1,i),this._hoverBubbleOpacity(e,1,i),this._hoverBubbleColor(e,1,i)}}))},t.bubble||(t.bubble={}),this.handleClickMode=e=>{e===Vs&&(t.bubble||(t.bubble={}),t.bubble.clicking=!0)}}clear(t,e,i){t.bubble.inRange&&!i||(delete t.bubble.div,delete t.bubble.opacity,delete t.bubble.radius,delete t.bubble.color)}init(){const t=this.container,e=t.actualOptions.interactivity.modes.bubble;e&&(t.retina.bubbleModeDistance=e.distance*t.retina.pixelRatio,void 0!==e.size&&(t.retina.bubbleModeSize=e.size*t.retina.pixelRatio))}async interact(t){const e=this.container.actualOptions.interactivity.events,i=e.onHover,s=e.onClick,o=i.enable,n=i.mode,a=s.enable,r=s.mode,c=e.onDiv;o&&Z(Vs,n)?this._hoverBubble():a&&Z(Vs,r)?this._clickBubble():nt(Vs,c,((e,i)=>this._singleSelectorHover(t,e,i)))}isEnabled(t){const e=this.container,i=e.actualOptions,s=e.interactivity.mouse,o=(t?.interactivity??i.interactivity).events,{onClick:n,onDiv:a,onHover:r}=o,c=ot(Vs,a);return!!(c||r.enable&&s.position||n.enable&&s.clickPosition)&&(Z(Vs,r.mode)||Z(Vs,n.mode)||c)}loadModeOptions(t,...e){t.bubble||(t.bubble=new qs);for(const i of e)t.bubble.load(i?.bubble)}reset(t){t.bubble.inRange=!1}}class Ws{constructor(){this.opacity=.5}load(t){t&&void 0!==t.opacity&&(this.opacity=t.opacity)}}class $s{constructor(){this.distance=80,this.links=new Ws,this.radius=60}load(t){t&&(void 0!==t.distance&&(this.distance=t.distance),this.links.load(t.links),void 0!==t.radius&&(this.radius=t.radius))}}function js(t,e,i,s){const o=t.actualOptions.interactivity.modes.connect;if(o)return function(t,e,i,s){const o=Math.floor(i.getRadius()/e.getRadius()),n=e.getFillColor(),a=i.getFillColor();if(!n||!a)return;const r=e.getPosition(),c=i.getPosition(),l=Vt(n,a,e.getRadius(),i.getRadius()),h=t.createLinearGradient(r.x,r.y,c.x,c.y);return h.addColorStop(0,Ht(n,s)),h.addColorStop(o>1?1:o,qt(l,s)),h.addColorStop(1,Ht(a,s)),h}(e,i,s,o.links.opacity)}function Gs(t,e,i){t.canvas.draw((s=>{const o=js(t,s,e,i);if(!o)return;const n=e.getPosition(),a=i.getPosition();!function(t,e,i,s,o){Nt(t,s,o),t.lineWidth=e,t.strokeStyle=i,t.stroke()}(s,e.retina.linksWidth??0,o,n,a)}))}class Ns extends Si{constructor(t){super(t)}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.connect;e&&(t.retina.connectModeDistance=e.distance*t.retina.pixelRatio,t.retina.connectModeRadius=e.radius*t.retina.pixelRatio)}async interact(){const t=this.container;if(t.actualOptions.interactivity.events.onHover.enable&&"pointermove"===t.interactivity.status){const e=t.interactivity.mouse.position;if(!t.retina.connectModeDistance||t.retina.connectModeDistance<0||!t.retina.connectModeRadius||t.retina.connectModeRadius<0||!e)return;const i=Math.abs(t.retina.connectModeRadius),s=t.particles.quadTree.queryCircle(e,i,(t=>this.isEnabled(t)));let o=0;for(const e of s){const i=e.getPosition();for(const n of s.slice(o+1)){const s=n.getPosition(),o=Math.abs(t.retina.connectModeDistance),a=Math.abs(i.x-s.x),r=Math.abs(i.y-s.y);a{const n=e.getPosition();!function(t,e,i,s,o,n){Nt(t,i,s),t.strokeStyle=qt(o,n),t.lineWidth=e,t.stroke()}(t,e.retina.linksWidth??0,n,o,i,s)}))}class Qs extends Si{constructor(t){super(t)}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.grab;e&&(t.retina.grabModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const t=this.container,e=t.actualOptions.interactivity;if(!e.modes.grab||!e.events.onHover.enable||t.interactivity.status!==r)return;const i=t.interactivity.mouse.position;if(!i)return;const s=t.retina.grabModeDistance;if(!s||s<0)return;const o=t.particles.quadTree.queryCircle(i,s,(t=>this.isEnabled(t)));for(const n of o){const o=T(n.getPosition(),i);if(o>s)continue;const a=e.modes.grab.links,r=a.opacity,c=r-o*r/s;if(c<=0)continue;const l=a.color??n.options.links?.color;if(!t.particles.grabLineColor&&l){const i=e.modes.grab.links;t.particles.grabLineColor=Wt(l,i.blink,i.consent)}const h=Ut(n,void 0,t.particles.grabLineColor);h&&Zs(t,n,h,c,i)}}isEnabled(t){const e=this.container,i=e.interactivity.mouse,s=(t?.interactivity??e.actualOptions.interactivity).events;return s.onHover.enable&&!!i.position&&Z("grab",s.onHover.mode)}loadModeOptions(t,...e){t.grab||(t.grab=new Ys);for(const i of e)t.grab.load(i?.grab)}reset(){}}class Js extends Si{constructor(t){super(t),this.handleClickMode=t=>{if("pause"!==t)return;const e=this.container;e.getAnimationStatus()?e.pause():e.play()}}clear(){}init(){}async interact(){}isEnabled(){return!0}reset(){}}class Ks{constructor(){this.default=!0,this.groups=[],this.quantity=4}load(t){if(!t)return;void 0!==t.default&&(this.default=t.default),void 0!==t.groups&&(this.groups=t.groups.map((t=>t))),this.groups.length||(this.default=!0);const e=t.quantity;void 0!==e&&(this.quantity=S(e))}}class to extends Si{constructor(t){super(t),this.handleClickMode=t=>{if("push"!==t)return;const e=this.container,i=e.actualOptions.interactivity.modes.push;if(!i)return;const s=C(i.quantity);if(s<=0)return;const o=K([void 0,...i.groups]),n=void 0!==o?e.actualOptions.particles.groups[o]:void 0;e.particles.push(s,e.interactivity.mouse,n,o)}}clear(){}init(){}async interact(){}isEnabled(){return!0}loadModeOptions(t,...e){t.push||(t.push=new Ks);for(const i of e)t.push.load(i?.push)}reset(){}}class eo{constructor(){this.quantity=2}load(t){if(!t)return;const e=t.quantity;void 0!==e&&(this.quantity=S(e))}}class io extends Si{constructor(t){super(t),this.handleClickMode=t=>{const e=this.container,i=e.actualOptions;if(!i.interactivity.modes.remove||"remove"!==t)return;const s=C(i.interactivity.modes.remove.quantity);e.particles.removeQuantity(s)}}clear(){}init(){}async interact(){}isEnabled(){return!0}loadModeOptions(t,...e){t.remove||(t.remove=new eo);for(const i of e)t.remove.load(i?.remove)}reset(){}}class so{constructor(){this.distance=200,this.duration=.4,this.factor=100,this.speed=1,this.maxSpeed=50,this.easing="ease-out-quad"}load(t){t&&(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.easing&&(this.easing=t.easing),void 0!==t.factor&&(this.factor=t.factor),void 0!==t.speed&&(this.speed=t.speed),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed))}}class oo extends so{constructor(){super(),this.selectors=[]}load(t){super.load(t),t&&void 0!==t.selectors&&(this.selectors=t.selectors)}}class no extends so{load(t){super.load(t),t&&(this.divs=dt(t.divs,(t=>{const e=new oo;return e.load(t),e})))}}const ao="repulse";class ro extends Si{constructor(t,e){super(e),this._clickRepulse=()=>{const t=this.container,e=t.actualOptions.interactivity.modes.repulse;if(!e)return;const i=t.repulse||{particles:[]};if(i.finish||(i.count||(i.count=0),i.count++,i.count===t.particles.count&&(i.finish=!0)),i.clicking){const s=t.retina.repulseModeDistance;if(!s||s<0)return;const o=Math.pow(s/6,3),n=t.interactivity.mouse.clickPosition;if(void 0===n)return;const a=new yi(n.x,n.y,o),r=t.particles.quadTree.query(a,(t=>this.isEnabled(t)));for(const t of r){const{dx:s,dy:a,distance:r}=D(n,t.position),c=r**2,l=-o*e.speed/c;if(c<=o){i.particles.push(t);const e=y.create(s,a);e.length=l,t.velocity.setTo(e)}}}else if(!1===i.clicking){for(const t of i.particles)t.velocity.setTo(t.initialVelocity);i.particles=[]}},this._hoverRepulse=()=>{const t=this.container,e=t.interactivity.mouse.position,i=t.retina.repulseModeDistance;!i||i<0||!e||this._processRepulse(e,i,new yi(e.x,e.y,i))},this._processRepulse=(t,e,i,s)=>{const o=this.container,n=o.particles.quadTree.query(i,(t=>this.isEnabled(t))),a=o.actualOptions.interactivity.modes.repulse;if(!a)return;const{easing:r,speed:c,factor:l,maxSpeed:h}=a,d=w(r),u=(s?.speed??c)*l;for(const i of n){const{dx:s,dy:o,distance:n}=D(i.position,t),a=k(d(1-n/e)*u,0,h),r=y.create(0===n?u:s/n*a,0===n?u:o/n*a);i.position.addTo(r)}},this._singleSelectorRepulse=(t,e)=>{const i=this.container,s=i.actualOptions.interactivity.modes.repulse;if(!s)return;const o=document.querySelectorAll(t);o.length&&o.forEach((t=>{const o=t,n=i.retina.pixelRatio,a={x:(o.offsetLeft+o.offsetWidth/2)*n,y:(o.offsetTop+o.offsetHeight/2)*n},r=o.offsetWidth/2*n,c="circle"===e.type?new yi(a.x,a.y,r):new vi(o.offsetLeft*n,o.offsetTop*n,o.offsetWidth*n,o.offsetHeight*n),l=rt(s.divs,o);this._processRepulse(a,r,c,l)}))},this._engine=t,e.repulse||(e.repulse={particles:[]}),this.handleClickMode=t=>{const i=this.container.actualOptions.interactivity.modes.repulse;if(!i||t!==ao)return;e.repulse||(e.repulse={particles:[]});const s=e.repulse;s.clicking=!0,s.count=0;for(const t of e.repulse.particles)this.isEnabled(t)&&t.velocity.setTo(t.initialVelocity);s.particles=[],s.finish=!1,setTimeout((()=>{e.destroyed||(s.clicking=!1)}),1e3*i.duration)}}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.repulse;e&&(t.retina.repulseModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const t=this.container,e=t.actualOptions,i=t.interactivity.status===r,s=e.interactivity.events,o=s.onHover,n=o.enable,a=o.mode,c=s.onClick,l=c.enable,h=c.mode,d=s.onDiv;i&&n&&Z(ao,a)?this._hoverRepulse():l&&Z(ao,h)?this._clickRepulse():nt(ao,d,((t,e)=>this._singleSelectorRepulse(t,e)))}isEnabled(t){const e=this.container,i=e.actualOptions,s=e.interactivity.mouse,o=(t?.interactivity??i.interactivity).events,n=o.onDiv,a=o.onHover,r=o.onClick,c=ot(ao,n);if(!(c||a.enable&&s.position||r.enable&&s.clickPosition))return!1;const l=a.mode,h=r.mode;return Z(ao,l)||Z(ao,h)||c}loadModeOptions(t,...e){t.repulse||(t.repulse=new no);for(const i of e)t.repulse.load(i?.repulse)}reset(){}}class co{constructor(){this.factor=3,this.radius=200}load(t){t&&(void 0!==t.factor&&(this.factor=t.factor),void 0!==t.radius&&(this.radius=t.radius))}}class lo extends Si{constructor(t){super(t)}clear(t,e,i){t.slow.inRange&&!i||(t.slow.factor=1)}init(){const t=this.container,e=t.actualOptions.interactivity.modes.slow;e&&(t.retina.slowModeRadius=e.radius*t.retina.pixelRatio)}async interact(){}isEnabled(t){const e=this.container,i=e.interactivity.mouse,s=(t?.interactivity??e.actualOptions.interactivity).events;return s.onHover.enable&&!!i.position&&Z("slow",s.onHover.mode)}loadModeOptions(t,...e){t.slow||(t.slow=new co);for(const i of e)t.slow.load(i?.slow)}reset(t){t.slow.inRange=!1;const e=this.container,i=e.actualOptions,s=e.interactivity.mouse.position,o=e.retina.slowModeRadius,n=i.interactivity.modes.slow;if(!n||!o||o<0||!s)return;const a=T(s,t.getPosition()),r=a/o,c=n.factor,{slow:l}=t;a>o||(l.inRange=!0,l.factor=r/c)}}const ho=[0,4,2,1],uo=[8,8,4,2];class po{constructor(t){this.pos=0,this.data=new Uint8ClampedArray(t)}getString(t){const e=this.data.slice(this.pos,this.pos+t);return this.pos+=e.length,e.reduce(((t,e)=>t+String.fromCharCode(e)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let t="",e=0;do{e=this.data[this.pos++];for(let i=e;--i>=0;t+=String.fromCharCode(this.data[this.pos++]));}while(0!==e);return t}readSubBlocksBin(){let t=0,e=0;for(let i=0;0!==(t=this.data[this.pos+i]);i+=t+1)e+=t;const i=new Uint8Array(e);for(let e=0;0!==(t=this.data[this.pos++]);)for(let s=t;--s>=0;i[e++]=this.data[this.pos++]);return i}skipSubBlocks(){for(;0!==this.data[this.pos];this.pos+=this.data[this.pos]+1);this.pos++}}function fo(t,e){const i=[];for(let s=0;s>>3;const h=1<<1+(7&r);c&&(a.localColorTable=fo(t,h));const d=t=>{const{r:s,g:n,b:r}=(c?a.localColorTable:e.globalColorTable)[t];return{r:s,g:n,b:r,a:t===o(null)?i?~~((s+n+r)/3):0:255}},u=(()=>{try{return new ImageData(a.width,a.height,{colorSpace:"srgb"})}catch(t){if(t instanceof DOMException&&"IndexSizeError"===t.name)return null;throw t}})();if(null==u)throw new EvalError("GIF frame size is to large");const p=t.nextByte(),f=t.readSubBlocksBin(),v=1<{const i=t>>>3,s=7&t;return(f[i]+(f[i+1]<<8)+(f[i+2]<<16)&(1<>>s};if(l){for(let i=0,o=p+1,r=0,c=[[0]],l=0;l<4;l++){if(ho[l]=c.length?c.push(c[s].concat(c[s][0])):s!==v&&c.push(c[s].concat(c[i][0]));for(let s=0;s=a.height))break}n?.(t.pos/(t.data.length-1),s(!1)+1,u,{x:a.left,y:a.top},{width:e.width,height:e.height})}a.image=u,a.bitmap=await createImageBitmap(u)}else{for(let t=0,e=p+1,i=0,s=[[0]],o=-4;;){const n=t;if(t=y(i,e),i+=e,t===v){e=p+1,s.length=v+2;for(let t=0;t=s.length?s.push(s[n].concat(s[n][0])):n!==v&&s.push(s[n].concat(s[t][0]));for(let e=0;e=1<>>5,o.disposalMethod=(28&n)>>>2,o.userInputDelayFlag=2==(2&n);const a=1==(1&n);o.delayTime=10*t.nextTwoBytes();const r=t.nextByte();a&&s(r),t.pos++;break}case 255:{t.pos++;const i={identifier:t.getString(8),authenticationCode:t.getString(3),data:t.readSubBlocksBin()};e.applicationExtensions.push(i);break}case 254:e.comments.push([i(!1),t.readSubBlocks()]);break;case 1:if(0===e.globalColorTable.length)throw new EvalError("plain text extension without global color table");t.pos++,e.frames[i(!1)].plainTextData={left:t.nextTwoBytes(),top:t.nextTwoBytes(),width:t.nextTwoBytes(),height:t.nextTwoBytes(),charSize:{width:t.nextTwoBytes(),height:t.nextTwoBytes()},foregroundColor:t.nextByte(),backgroundColor:t.nextByte(),text:t.readSubBlocks()};break;default:t.skipSubBlocks()}}(t,e,s,o);break;default:throw new EvalError("undefined block found")}return!1}const yo=/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;async function mo(t){return new Promise((e=>{t.loading=!0;const i=new Image;t.element=i,i.addEventListener("load",(()=>{t.loading=!1,e()})),i.addEventListener("error",(()=>{t.element=void 0,t.error=!0,t.loading=!1,W().error(`${f} loading image: ${t.source}`),e()})),i.src=t.source}))}async function go(t){if("gif"===t.type){t.loading=!0;try{t.gifData=await async function(t,e,i){i||(i=!1);const s=await fetch(t);if(!s.ok&&404===s.status)throw new EvalError("file not found");const o=await s.arrayBuffer(),n={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},a=new po(new Uint8ClampedArray(o));if("GIF89a"!==a.getString(6))throw new Error("not a supported GIF file");n.width=a.nextTwoBytes(),n.height=a.nextTwoBytes();const r=a.nextByte(),c=128==(128&r);n.colorRes=(112&r)>>>4,n.sortFlag=8==(8&r);const l=1<<1+(7&r),h=a.nextByte();n.pixelAspectRatio=a.nextByte(),0!==n.pixelAspectRatio&&(n.pixelAspectRatio=(n.pixelAspectRatio+15)/64),c&&(n.globalColorTable=fo(a,l));const d=(()=>{try{return new ImageData(n.width,n.height,{colorSpace:"srgb"})}catch(t){if(t instanceof DOMException&&"IndexSizeError"===t.name)return null;throw t}})();if(null==d)throw new Error("GIF frame size is to large");const{r:u,g:p,b:f}=n.globalColorTable[h];d.data.set(c?[u,p,f,255]:[0,0,0,0]);for(let t=4;t(t&&(y=!0),v),b=t=>(null!=t&&(m=t),m);try{do{y&&(n.frames.push({left:0,top:0,width:0,height:0,disposalMethod:0,image:new ImageData(1,1,{colorSpace:"srgb"}),plainTextData:null,userInputDelayFlag:!1,delayTime:0,sortFlag:!1,localColorTable:[],reserved:0,GCreserved:0}),v++,m=-1,y=!1)}while(!await vo(a,n,i,g,b,e));n.frames.length--;for(const t of n.frames){if(t.userInputDelayFlag&&0===t.delayTime){n.totalTime=1/0;break}n.totalTime+=t.delayTime}return n}catch(t){if(t instanceof EvalError)throw new Error(`error while parsing frame ${v} "${t.message}"`);throw t}}(t.source),t.gifLoopCount=function(t){for(const e of t.applicationExtensions)if(e.identifier+e.authenticationCode==="NETSCAPE2.0")return e.data[1]+(e.data[2]<<8);return NaN}(t.gifData)??0,0===t.gifLoopCount&&(t.gifLoopCount=1/0)}catch{t.error=!0}t.loading=!1}else await mo(t)}async function bo(t){if("svg"!==t.type)return void await mo(t);t.loading=!0;const e=await fetch(t.source);e.ok?t.svgData=await e.text():(W().error(`${f} Image not found`),t.error=!0),t.loading=!1}function wo(t,e,i,s){const o=function(t,e,i){const{svgData:s}=t;if(!s)return"";const o=Ht(e,i);if(s.includes("fill"))return s.replace(yo,(()=>o));const n=s.indexOf(">");return`${s.substring(0,n)} fill="${o}"${s.substring(n)}`}(t,i,s.opacity?.value??1),n={color:i,gif:e.gif,data:{...t,svgData:o},loaded:!1,ratio:e.width/e.height,replaceColor:e.replaceColor,source:e.src};return new Promise((e=>{const i=new Blob([o],{type:"image/svg+xml"}),s=URL||window.URL||window.webkitURL||window,a=s.createObjectURL(i),r=new Image;r.addEventListener("load",(()=>{n.loaded=!0,n.element=r,e(n),s.revokeObjectURL(a)})),r.addEventListener("error",(async()=>{s.revokeObjectURL(a);const i={...t,error:!1,loading:!0};await mo(i),n.loaded=!0,n.element=i.element,e(n)})),r.src=a}))}class xo{constructor(t){this.loadImageShape=async t=>{if(!this._engine.loadImage)throw new Error(`${f} image shape not initialized`);await this._engine.loadImage({gif:t.gif,name:t.name,replaceColor:t.replaceColor??!1,src:t.src})},this._engine=t}addImage(t){this._engine.images||(this._engine.images=[]),this._engine.images.push(t)}draw(t){const{context:e,radius:i,particle:s,opacity:o,delta:n}=t,a=s.image,r=a?.element;if(a){if(e.globalAlpha=o,a.gif&&a.gifData){const t=new OffscreenCanvas(a.gifData.width,a.gifData.height),o=t.getContext("2d");if(!o)throw new Error("could not create offscreen canvas context");o.imageSmoothingQuality="low",o.imageSmoothingEnabled=!1,o.clearRect(0,0,t.width,t.height),void 0===s.gifLoopCount&&(s.gifLoopCount=a.gifLoopCount??0);let r=s.gifFrame??0;const c={x:.5*-a.gifData.width,y:.5*-a.gifData.height},l=a.gifData.frames[r];if(void 0===s.gifTime&&(s.gifTime=0),!l.bitmap)return;switch(e.scale(i/a.gifData.width,i/a.gifData.height),l.disposalMethod){case 4:case 5:case 6:case 7:case 0:o.drawImage(l.bitmap,l.left,l.top),e.drawImage(t,c.x,c.y),o.clearRect(0,0,t.width,t.height);break;case 1:o.drawImage(l.bitmap,l.left,l.top),e.drawImage(t,c.x,c.y);break;case 2:o.drawImage(l.bitmap,l.left,l.top),e.drawImage(t,c.x,c.y),o.clearRect(0,0,t.width,t.height),0===a.gifData.globalColorTable.length?o.putImageData(a.gifData.frames[0].image,c.x+l.left,c.y+l.top):o.putImageData(a.gifData.backgroundImage,c.x,c.y);break;case 3:{const i=o.getImageData(0,0,t.width,t.height);o.drawImage(l.bitmap,l.left,l.top),e.drawImage(t,c.x,c.y),o.clearRect(0,0,t.width,t.height),o.putImageData(i,0,0)}}if(s.gifTime+=n.value,s.gifTime>l.delayTime){if(s.gifTime-=l.delayTime,++r>=a.gifData.frames.length){if(--s.gifLoopCount<=0)return;r=0,o.clearRect(0,0,t.width,t.height)}s.gifFrame=r}e.scale(a.gifData.width/i,a.gifData.height/i)}else if(r){const t=a.ratio,s={x:-i,y:-i},o=2*i;e.drawImage(r,s.x,s.y,o,o/t)}e.globalAlpha=1}}getSidesCount(){return 12}async init(t){const e=t.actualOptions;if(e.preload&&this._engine.loadImage)for(const t of e.preload)await this._engine.loadImage(t)}loadShape(t){if("image"!==t.shape&&"images"!==t.shape)return;this._engine.images||(this._engine.images=[]);const e=t.shapeData;if(!e)return;this._engine.images.find((t=>t.name===e.name||t.source===e.src))||this.loadImageShape(e).then((()=>{this.loadShape(t)}))}particleInit(t,e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const i=this._engine.images,s=e.shapeData;if(!s)return;const o=e.getFillColor(),n=i.find((t=>t.name===s.name||t.source===s.src));if(!n)return;const a=s.replaceColor??n.replaceColor;n.loading?setTimeout((()=>{this.particleInit(t,e)})):(async()=>{let t;t=n.svgData&&o?await wo(n,s,o,e):{color:o,data:n,element:n.element,gif:n.gif,gifData:n.gifData,gifLoopCount:n.gifLoopCount,loaded:!0,ratio:s.width&&s.height?s.width/s.height:n.ratio??1,replaceColor:a,source:s.src},t.ratio||(t.ratio=1);const i={image:t,fill:s.fill??e.shapeFill,close:s.close??e.shapeClose};e.image=i.image,e.shapeFill=i.fill,e.shapeClose=i.close})()}}class _o{constructor(){this.src="",this.gif=!1}load(t){t&&(void 0!==t.gif&&(this.gif=t.gif),void 0!==t.height&&(this.height=t.height),void 0!==t.name&&(this.name=t.name),void 0!==t.replaceColor&&(this.replaceColor=t.replaceColor),void 0!==t.src&&(this.src=t.src),void 0!==t.width&&(this.width=t.width))}}class ko{constructor(t){this.id="imagePreloader",this._engine=t}getPlugin(){return{}}loadOptions(t,e){if(!e||!e.preload)return;t.preload||(t.preload=[]);const i=t.preload;for(const t of e.preload){const e=i.find((e=>e.name===t.name||e.src===t.src));if(e)e.load(t);else{const e=new _o;e.load(t),i.push(e)}}}needsPlugin(){return!0}}async function zo(t,e=!0){!function(t){t.loadImage||(t.loadImage=async e=>{if(!e.name&&!e.src)throw new Error(`${f} no image source provided`);if(t.images||(t.images=[]),!t.images.find((t=>t.name===e.name||t.source===e.src)))try{const i={gif:e.gif??!1,name:e.name??e.src,source:e.src,type:e.src.substring(e.src.length-3),error:!1,loading:!0,replaceColor:e.replaceColor,ratio:e.width&&e.height?e.width/e.height:void 0};t.images.push(i);const s=e.gif?go:e.replaceColor?bo:mo;await s(i)}catch{throw new Error(`${f} ${e.name??e.src} not found`)}})}(t);const i=new ko(t);await t.addPlugin(i,e),await t.addShape(["image","images"],new xo(t),e)}class Mo extends Re{constructor(){super(),this.sync=!1}load(t){t&&(super.load(t),void 0!==t.sync&&(this.sync=t.sync))}}class Co extends Re{constructor(){super(),this.sync=!1}load(t){t&&(super.load(t),void 0!==t.sync&&(this.sync=t.sync))}}class Po{constructor(){this.count=0,this.delay=new Mo,this.duration=new Co}load(t){t&&(void 0!==t.count&&(this.count=t.count),this.delay.load(t.delay),this.duration.load(t.duration))}}class Oo{constructor(t){this.container=t}init(t){const e=this.container,i=t.options.life;i&&(t.life={delay:e.retina.reduceFactor?C(i.delay.value)*(i.delay.sync?1:_())/e.retina.reduceFactor*1e3:0,delayTime:0,duration:e.retina.reduceFactor?C(i.duration.value)*(i.duration.sync?1:_())/e.retina.reduceFactor*1e3:0,time:0,count:i.count},t.life.duration<=0&&(t.life.duration=-1),t.life.count<=0&&(t.life.count=-1),t.life&&(t.spawning=t.life.delay>0))}isEnabled(t){return!t.destroyed}loadOptions(t,...e){t.life||(t.life=new Po);for(const i of e)t.life.load(i?.life)}update(t,e){if(!this.isEnabled(t)||!t.life)return;const i=t.life;let s=!1;if(t.spawning){if(i.delayTime+=e.value,!(i.delayTime>=t.life.delay))return;s=!0,t.spawning=!1,i.delayTime=0,i.time=0}if(-1===i.duration)return;if(t.spawning)return;if(s?i.time=0:i.time+=e.value,i.time0&&t.life.count--,0===t.life.count)return void t.destroy();const o=this.container.canvas.size,n=S(0,o.width),a=S(0,o.width);t.position.x=M(n),t.position.y=M(a),t.spawning=!0,i.delayTime=0,i.time=0,t.reset();const r=t.options.life;r&&(i.delay=1e3*C(r.delay.value),i.duration=1e3*C(r.duration.value))}}class So{draw(t){const{context:e,particle:i,radius:s}=t,o=i.shapeData;e.moveTo(-s/2,0),e.lineTo(s/2,0),e.lineCap=o?.cap??"butt"}getSidesCount(){return 1}}class Do{init(){}isEnabled(t){return!j()&&!t.destroyed&&t.container.actualOptions.interactivity.events.onHover.parallax.enable}move(t){const e=t.container,i=e.actualOptions.interactivity.events.onHover.parallax;if(j()||!i.enable)return;const s=i.force,o=e.interactivity.mouse.position;if(!o)return;const n=e.canvas.size,a=.5*n.width,r=.5*n.height,c=i.smooth,l=t.getRadius()/s,h=(o.x-a)*l,d=(o.y-r)*l,{offset:u}=t;u.x+=(h-u.x)/c,u.y+=(d-u.y)/c}}class To extends Di{constructor(t){super(t)}clear(){}init(){}async interact(t){const e=this.container;void 0===t.attractDistance&&(t.attractDistance=C(t.options.move.attract.distance)*e.retina.pixelRatio);const i=t.attractDistance,s=t.getPosition(),o=e.particles.quadTree.queryCircle(s,i);for(const e of o){if(t===e||!e.options.move.attract.enable||e.destroyed||e.spawning)continue;const i=e.getPosition(),{dx:o,dy:n}=D(s,i),a=t.options.move.attract.rotate,r=o/(1e3*a.x),c=n/(1e3*a.y),l=e.size.value/t.size.value,h=1/l;t.velocity.x-=r*l,t.velocity.y-=c*l,e.velocity.x+=r*h,e.velocity.y+=c*h}}isEnabled(t){return t.options.move.attract.enable}reset(){}}function Ro(t,e,i,s,o,n){const a=k(t.options.collisions.absorb.speed*o.factor/10,0,s);t.size.value+=a/2,i.size.value-=a,s<=n&&(i.size.value=0,i.destroy())}const Eo=t=>{void 0===t.collisionMaxSpeed&&(t.collisionMaxSpeed=C(t.options.collisions.maxSpeed)),t.velocity.length>t.collisionMaxSpeed&&(t.velocity.length=t.collisionMaxSpeed)};function Io(t,e){lt(ct(t),ct(e)),Eo(t),Eo(e)}function Lo(t,e,i,s){switch(t.options.collisions.mode){case"absorb":!function(t,e,i,s){const o=t.getRadius(),n=e.getRadius();void 0===o&&void 0!==n?t.destroy():void 0!==o&&void 0===n?e.destroy():void 0!==o&&void 0!==n&&(o>=n?Ro(t,0,e,n,i,s):Ro(e,0,t,o,i,s))}(t,e,i,s);break;case"bounce":Io(t,e);break;case"destroy":!function(t,e){t.unbreakable||e.unbreakable||Io(t,e),void 0===t.getRadius()&&void 0!==e.getRadius()?t.destroy():void 0!==t.getRadius()&&void 0===e.getRadius()?e.destroy():void 0!==t.getRadius()&&void 0!==e.getRadius()&&(t.getRadius()>=e.getRadius()?e:t).destroy()}(t,e)}}class Ao extends Di{constructor(t){super(t)}clear(){}init(){}async interact(t,e){if(t.destroyed||t.spawning)return;const i=this.container,s=t.getPosition(),o=t.getRadius(),n=i.particles.quadTree.queryCircle(s,2*o);for(const a of n){if(t===a||!a.options.collisions.enable||t.options.collisions.mode!==a.options.collisions.mode||a.destroyed||a.spawning)continue;const n=a.getPosition(),r=a.getRadius();if(Math.abs(Math.round(s.z)-Math.round(n.z))>o+r)continue;T(s,n)>o+r||Lo(t,a,e,i.retina.pixelRatio)}}isEnabled(t){return t.options.collisions.enable}reset(){}}class Fo extends yi{constructor(t,e,i,s){super(t,e,i),this.canvasSize=s,this.canvasSize={...s}}contains(t){const{width:e,height:i}=this.canvasSize,{x:s,y:o}=t;return super.contains(t)||super.contains({x:s-e,y:o})||super.contains({x:s-e,y:o-i})||super.contains({x:s,y:o-i})}intersects(t){if(super.intersects(t))return!0;const e=t,i=t,s={x:t.position.x-this.canvasSize.width,y:t.position.y-this.canvasSize.height};if(void 0!==i.radius){const t=new yi(s.x,s.y,2*i.radius);return super.intersects(t)}if(void 0!==e.size){const t=new vi(s.x,s.y,2*e.size.width,2*e.size.height);return super.intersects(t)}return!1}}class Bo{constructor(){this.blur=5,this.color=new ce,this.color.value="#000",this.enable=!1}load(t){t&&(void 0!==t.blur&&(this.blur=t.blur),this.color=ce.create(this.color,t.color),void 0!==t.enable&&(this.enable=t.enable))}}class qo{constructor(){this.enable=!1,this.frequency=1}load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.frequency&&(this.frequency=t.frequency),void 0!==t.opacity&&(this.opacity=t.opacity))}}class Ho{constructor(){this.blink=!1,this.color=new ce,this.color.value="#fff",this.consent=!1,this.distance=100,this.enable=!1,this.frequency=1,this.opacity=1,this.shadow=new Bo,this.triangles=new qo,this.width=1,this.warp=!1}load(t){t&&(void 0!==t.id&&(this.id=t.id),void 0!==t.blink&&(this.blink=t.blink),this.color=ce.create(this.color,t.color),void 0!==t.consent&&(this.consent=t.consent),void 0!==t.distance&&(this.distance=t.distance),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.frequency&&(this.frequency=t.frequency),void 0!==t.opacity&&(this.opacity=t.opacity),this.shadow.load(t.shadow),this.triangles.load(t.triangles),void 0!==t.width&&(this.width=t.width),void 0!==t.warp&&(this.warp=t.warp))}}function Vo(t,e,i,s,o){const{dx:n,dy:a,distance:r}=D(t,e);if(!o||r<=i)return r;const c={x:Math.abs(n),y:Math.abs(a)},l=Math.min(c.x,s.width-c.x),h=Math.min(c.y,s.height-c.y);return Math.sqrt(l**2+h**2)}class Uo extends Di{constructor(t){super(t),this._setColor=t=>{if(!t.options.links)return;const e=this.linkContainer,i=t.options.links;let s=void 0===i.id?e.particles.linksColor:e.particles.linksColors.get(i.id);if(s)return;s=Wt(i.color,i.blink,i.consent),void 0===i.id?e.particles.linksColor=s:e.particles.linksColors.set(i.id,s)},this.linkContainer=t}clear(){}init(){this.linkContainer.particles.linksColor=void 0,this.linkContainer.particles.linksColors=new Map}async interact(t){if(!t.options.links)return;t.links=[];const e=t.getPosition(),i=this.container,s=i.canvas.size;if(e.x<0||e.y<0||e.x>s.width||e.y>s.height)return;const o=t.options.links,n=o.opacity,a=t.retina.linksDistance??0,r=o.warp,c=r?new Fo(e.x,e.y,a,s):new yi(e.x,e.y,a),l=i.particles.quadTree.query(c);for(const i of l){const c=i.options.links;if(t===i||!c?.enable||o.id!==c.id||i.spawning||i.destroyed||!i.links||t.links.some((t=>t.destination===i))||i.links.some((e=>e.destination===t)))continue;const l=i.getPosition();if(l.x<0||l.y<0||l.x>s.width||l.y>s.height)continue;const h=Vo(e,l,a,s,r&&c.warp);if(h>a)continue;const d=(1-h/a)*n;this._setColor(t),t.links.push({destination:i,opacity:d})}}isEnabled(t){return!!t.options.links?.enable}loadParticlesOptions(t,...e){t.links||(t.links=new Ho);for(const i of e)t.links.load(i?.links)}reset(){}}function Wo(t,e){const i=((s=t.map((t=>t.id))).sort(((t,e)=>t-e)),s.join("_"));var s;let o=e.get(i);return void 0===o&&(o=_(),e.set(i,o)),o}class $o{constructor(t){this.container=t,this._drawLinkLine=(t,e)=>{const i=t.options.links;if(!i?.enable)return;const s=this.container,o=s.actualOptions,n=e.destination,a=t.getPosition(),r=n.getPosition();let c=e.opacity;s.canvas.draw((e=>{let l;const h=t.options.twinkle?.lines;if(h?.enable){const t=h.frequency,e=St(h.color);_(){const s=t.options.links;if(!s?.enable)return;const o=s.triangles;if(!o.enable)return;const n=this.container,a=n.actualOptions,r=e.destination,c=i.destination,l=o.opacity??(e.opacity+i.opacity)/2;l<=0||n.canvas.draw((e=>{const i=t.getPosition(),h=r.getPosition(),d=c.getPosition(),u=t.retina.linksDistance??0;if(T(i,h)>u||T(d,h)>u||T(d,i)>u)return;let p=St(o.color);if(!p){const e=void 0!==s.id?n.particles.linksColors.get(s.id):n.particles.linksColor;p=Ut(t,r,e)}p&&function(t){const{context:e,pos1:i,pos2:s,pos3:o,backgroundMask:n,colorTriangle:a,opacityTriangle:r}=t;!function(t,e,i,s){t.beginPath(),t.moveTo(e.x,e.y),t.lineTo(i.x,i.y),t.lineTo(s.x,s.y),t.closePath()}(e,i,s,o),n.enable&&(e.globalCompositeOperation=n.composite),e.fillStyle=qt(a,r),e.fill()}({context:e,pos1:i,pos2:h,pos3:d,backgroundMask:a.backgroundMask,colorTriangle:p,opacityTriangle:l})}))},this._drawTriangles=(t,e,i,s)=>{const o=i.destination;if(!t.links?.triangles.enable||!o.options.links?.triangles.enable)return;const n=o.links?.filter((t=>{const e=this._getLinkFrequency(o,t.destination);return o.options.links&&e<=o.options.links.frequency&&s.findIndex((e=>e.destination===t.destination))>=0}));if(n?.length)for(const s of n){const n=s.destination;this._getTriangleFrequency(e,o,n)>t.links.triangles.frequency||this._drawLinkTriangle(e,i,s)}},this._getLinkFrequency=(t,e)=>Wo([t,e],this._freqs.links),this._getTriangleFrequency=(t,e,i)=>Wo([t,e,i],this._freqs.triangles),this._freqs={links:new Map,triangles:new Map}}drawParticle(t,e){const{links:i,options:s}=e;if(!i||i.length<=0)return;const o=i.filter((t=>s.links&&this._getLinkFrequency(e,t.destination)<=s.links.frequency));for(const t of o)this._drawTriangles(s,e,t,o),t.opacity>0&&(e.retina.linksWidth??0)>0&&this._drawLinkLine(e,t)}async init(){this._freqs.links=new Map,this._freqs.triangles=new Map}particleCreated(t){if(t.links=[],!t.options.links)return;const e=this.container.retina.pixelRatio,{retina:i}=t,{distance:s,width:o}=t.options.links;i.linksDistance=s*e,i.linksWidth=o*e}particleDestroyed(t){t.links=[]}}class jo{constructor(){this.id="links"}getPlugin(t){return new $o(t)}loadOptions(){}needsPlugin(){return!0}}async function Go(t,e=!0){await async function(t,e=!0){await t.addInteractor("particlesLinks",(t=>new Uo(t)),e)}(t,e),await async function(t,e=!0){const i=new jo;await t.addPlugin(i,e)}(t,e)}class No{draw(t){const{context:e,particle:i,radius:s}=t,o=this.getCenter(i,s),n=this.getSidesData(i,s),a=n.count.numerator*n.count.denominator,r=n.count.numerator/n.count.denominator,c=180*(r-2)/r,l=Math.PI-Math.PI*c/180;if(e){e.beginPath(),e.translate(o.x,o.y),e.moveTo(0,0);for(let t=0;t0?"counter-clockwise":"clockwise"}switch(i){case"counter-clockwise":case"counterClockwise":t.rotate.status="decreasing";break;case"clockwise":t.rotate.status="increasing"}const s=e.animation;s.enable&&(t.rotate.decay=1-C(s.decay),t.rotate.velocity=C(s.speed)/360*this.container.retina.reduceFactor,s.sync||(t.rotate.velocity*=_())),t.rotation=t.rotate.value}isEnabled(t){const e=t.options.rotate;return!!e&&(!t.destroyed&&!t.spawning&&e.animation.enable&&!e.path)}loadOptions(t,...e){t.rotate||(t.rotate=new Jo);for(const i of e)t.rotate.load(i?.rotate)}update(t,e){this.isEnabled(t)&&(!function(t,e){const i=t.rotate,s=t.options.rotate;if(!i||!s)return;const o=s.animation,n=(i.velocity??0)*e.factor,a=2*Math.PI,r=i.decay??1;o.enable&&("increasing"===i.status?(i.value+=n,i.value>a&&(i.value-=a)):(i.value-=n,i.value<0&&(i.value+=a)),i.velocity&&1!==r&&(i.velocity*=r))}(t,e),t.rotation=t.rotate?.value??0)}}const tn=Math.sqrt(2);class en{draw(t){const{context:e,radius:i}=t,s=i/tn,o=2*s;e.rect(-s,-s,o,o)}getSidesCount(){return 4}}class sn{draw(t){const{context:e,particle:i,radius:s}=t,o=i.sides,n=i.starInset??2;e.moveTo(0,0-s);for(let t=0;t0&&(e.loops??0)>(e.maxLoops??0))return;if(e.time||(e.time=0),(e.delayTime??0)>0&&e.time<(e.delayTime??0)&&(e.time+=t.value),(e.delayTime??0)>0&&e.time<(e.delayTime??0))return;const n=M(i.offset),a=(e.velocity??0)*t.factor+3.6*n,r=e.decay??1;o&&"increasing"!==e.status?(e.value-=a,e.value<0&&(e.loops||(e.loops=0),e.loops++,e.status="increasing",e.value+=e.value)):(e.value+=a,e.value>s&&(e.loops||(e.loops=0),e.loops++,o&&(e.status="decreasing",e.value-=e.value%s))),e.velocity&&1!==r&&(e.velocity*=r),e.value>s&&(e.value%=s)}class nn{constructor(t){this.container=t}init(t){const e=this.container,i=t.options,s=ut(i.stroke,t.id,i.reduceDuplicates);t.strokeWidth=C(s.width)*e.retina.pixelRatio,t.strokeOpacity=C(s.opacity??1),t.strokeAnimation=s.color?.animation;const o=Rt(s.color)??t.getFillColor();o&&(t.strokeColor=jt(o,t.strokeAnimation,e.retina.reduceFactor))}isEnabled(t){const e=t.strokeAnimation,{strokeColor:i}=t;return!t.destroyed&&!t.spawning&&!!e&&(void 0!==i?.h.value&&i.h.enable||void 0!==i?.s.value&&i.s.enable||void 0!==i?.l.value&&i.l.enable)}update(t,e){this.isEnabled(t)&&function(t,e){if(!t.strokeColor||!t.strokeAnimation)return;const{h:i,s,l:o}=t.strokeColor,{h:n,s:a,l:r}=t.strokeAnimation;i&&on(e,i,n,360,!1),s&&on(e,s,a,100,!0),o&&on(e,o,r,100,!0)}(t,e)}}async function an(t,e=!0){await async function(t,e=!0){await t.addMover("parallax",(()=>new Do),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalAttract",(e=>new Es(t,e)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalBounce",(t=>new As(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalBubble",(t=>new Us(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalConnect",(t=>new Ns(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalGrab",(t=>new Qs(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalPause",(t=>new Js(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalPush",(t=>new to(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalRemove",(t=>new io(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalRepulse",(e=>new ro(t,e)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalSlow",(t=>new lo(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("particlesAttract",(t=>new To(t)),e)}(t,!1),await async function(t,e=!0){await t.addInteractor("particlesCollisions",(t=>new Ao(t)),e)}(t,!1),await Go(t,!1),await async function(){b("ease-in-quad",(t=>t**2)),b("ease-out-quad",(t=>1-(1-t)**2)),b("ease-in-out-quad",(t=>t<.5?2*t**2:1-(-2*t+2)**2/2))}(),await async function(t,e=!0){await t.addShape(Os,new Ds,e)}(t,!1),await zo(t,!1),await async function(t,e=!0){await t.addShape("line",new So,e)}(t,!1),await Zo(t,!1),await async function(t,e=!0){await t.addShape(["edge","square"],new en,e)}(t,!1),await async function(t,e=!0){await t.addShape("star",new sn,e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("life",(t=>new Oo(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("rotate",(t=>new Ko(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("strokeColor",(t=>new nn(t)),e)}(t,!1),await Ps(t,e)}const rn=["text","character","char","multiline-text"];class cn{constructor(){this._drawLine=(t,e,i,s,o,n)=>{const a={x:-(e.length*i/2),y:i/2},r=2*i;n?t.fillText(e,a.x,a.y+r*o):t.strokeText(e,a.x,a.y+r*o)}}draw(t){const{context:e,particle:i,radius:s,opacity:o}=t,n=i.shapeData;if(!n)return;const a=n.value;if(void 0===a)return;void 0===i.text&&(i.text=ut(a,i.randomIndexData));const r=i.text,c=n.style??"",l=n.weight??"400",h=2*Math.round(s),d=n.font??"Verdana",u=i.shapeFill,p=r?.split("\n");if(p){e.font=`${c} ${l} ${h}px "${d}"`,e.globalAlpha=o;for(let t=0;tZ(t,e.particles.shape.type)))){const t=rn.map((t=>e.particles.shape.options[t])).find((t=>!!t)),i=[];dt(t,(t=>{i.push(Q(t.font,t.weight))})),await Promise.all(i)}}particleInit(t,e){if(!e.shape||!rn.includes(e.shape))return;const i=e.shapeData;if(void 0===i)return;const s=i.value;void 0!==s&&(e.text=ut(s,e.randomIndexData))}}class ln{constructor(){this.enable=!1,this.speed=0,this.decay=0,this.sync=!1}load(t){t&&(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.speed&&(this.speed=S(t.speed)),void 0!==t.decay&&(this.decay=S(t.decay)),void 0!==t.sync&&(this.sync=t.sync))}}class hn extends Re{constructor(){super(),this.animation=new ln,this.direction="clockwise",this.enable=!1,this.value=0}load(t){super.load(t),t&&(this.animation.load(t.animation),void 0!==t.direction&&(this.direction=t.direction),void 0!==t.enable&&(this.enable=t.enable))}}class dn{constructor(t){this.container=t}getTransformValues(t){const e=t.tilt?.enable&&t.tilt;return{b:e?Math.cos(e.value)*e.cosDirection:void 0,c:e?Math.sin(e.value)*e.sinDirection:void 0}}init(t){const e=t.options.tilt;if(!e)return;t.tilt={enable:e.enable,value:C(e.value)*Math.PI/180,sinDirection:_()>=.5?1:-1,cosDirection:_()>=.5?1:-1};let i=e.direction;if("random"===i){i=Math.floor(2*_())>0?"counter-clockwise":"clockwise"}switch(i){case"counter-clockwise":case"counterClockwise":t.tilt.status="decreasing";break;case"clockwise":t.tilt.status="increasing"}const s=t.options.tilt?.animation;s?.enable&&(t.tilt.decay=1-C(s.decay),t.tilt.velocity=C(s.speed)/360*this.container.retina.reduceFactor,s.sync||(t.tilt.velocity*=_()))}isEnabled(t){const e=t.options.tilt?.animation;return!t.destroyed&&!t.spawning&&!!e?.enable}loadOptions(t,...e){t.tilt||(t.tilt=new hn);for(const i of e)t.tilt.load(i?.tilt)}update(t,e){this.isEnabled(t)&&function(t,e){if(!t.tilt||!t.options.tilt)return;const i=t.options.tilt.animation,s=(t.tilt.velocity??0)*e.factor,o=2*Math.PI,n=t.tilt.decay??1;i.enable&&("increasing"===t.tilt.status?(t.tilt.value+=s,t.tilt.value>o&&(t.tilt.value-=o)):(t.tilt.value-=s,t.tilt.value<0&&(t.tilt.value+=o)),t.tilt.velocity&&1!==n&&(t.tilt.velocity*=n))}(t,e)}}class un{constructor(){this.enable=!1,this.frequency=.05,this.opacity=1}load(t){t&&(void 0!==t.color&&(this.color=ce.create(this.color,t.color)),void 0!==t.enable&&(this.enable=t.enable),void 0!==t.frequency&&(this.frequency=t.frequency),void 0!==t.opacity&&(this.opacity=S(t.opacity)))}}class pn{constructor(){this.lines=new un,this.particles=new un}load(t){t&&(this.lines.load(t.lines),this.particles.load(t.particles))}}class fn{getColorStyles(t,e,i,s){const o=t.options.twinkle;if(!o)return{};const n=o.particles,a=n.enable&&_()a&&(s.angle-=a),r.x+=n*Math.cos(s.angle),r.y+=n*Math.abs(Math.sin(s.angle))}(t,e)}}async function gn(t,e=!0){await async function(t,e=!0){await t.addParticleUpdater("destroy",(e=>new $i(t,e)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("roll",(()=>new fs),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("tilt",(t=>new dn(t)),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("twinkle",(()=>new fn),e)}(t,!1),await async function(t,e=!0){await t.addParticleUpdater("wobble",(t=>new mn(t)),e)}(t,!1),await async function(t,e=!0){await t.addShape(rn,new cn,e)}(t,!1),await async function(t,e=!0){await t.addInteractor("externalTrail",(t=>new ds(t)),e)}(t,!1),await async function(t,e=!0){await t.addPlugin(new Fi,e)}(t,!1),await async function(t,e=!0){t.emitterShapeManager||(t.emitterShapeManager=new es(t)),t.addEmitterShapeGenerator||(t.addEmitterShapeGenerator=(e,i)=>{t.emitterShapeManager?.addShapeGenerator(e,i)});const i=new ss(t);await t.addPlugin(i,e)}(t,!1),await async function(t,e=!0){const i=t;i.addEmitterShapeGenerator&&i.addEmitterShapeGenerator("circle",new ns),await i.refresh(e)}(t,!1),await async function(t,e=!0){const i=t;i.addEmitterShapeGenerator&&i.addEmitterShapeGenerator("square",new cs),await i.refresh(e)}(t,!1),await an(t,e)}return gn(Ti),e})())); \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 32bb2452..00000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/overrides/fancylogo.txt b/docs/overrides/fancylogo.txt new file mode 100644 index 00000000..230d5476 --- /dev/null +++ b/docs/overrides/fancylogo.txt @@ -0,0 +1,257 @@ +--- +hide: +- navigation +- toc +--- + +
+ +
+ + +
+
+
+ + +
+
Loading...
+
+
+ AI4CO Logo +
+
+ + +
+
+
\ No newline at end of file diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 00000000..9114c614 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block content %} +{% if page.nb_url %} + + {% include ".icons/material/download.svg" %} + + +{% endif %} + +{{ super() }} +{% endblock content %} diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 627184b2..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Install with local version. Need to run from root of repo -.[graph] - -sphinx >6.0, <7.0 -myst-parser ==2.0.0 -nbsphinx >=0.8.5, <=0.8.9 -pandoc >=1.0, <=2.3 -docutils >=0.16, <0.20 -sphinxcontrib-fulltoc >=1.0, <=1.2.0 -sphinxcontrib-mockautodoc -sphinx-autobuild -sphinx-autodoc-typehints >=1.16 -sphinx-paramlinks >=0.5.1, <=0.5.4 -sphinx-togglebutton >=0.2, <=0.3.2 -sphinx-copybutton >=0.3, <=0.5.2 -sphinx-multiproject -sphinx-toolbox ==3.4.0 -sphinx-rtd-dark-mode -sphinxcontrib-video ==0.2.0 -jinja2 >=3.0.0,<3.2.0 -sphinxcontrib.katex==0.8.6 -sphinx-collections==0.0.1 \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 00000000..377d9c59 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,32 @@ +/* Custom colors */ +:root { + --md-primary-fg-color: #B92B0F; + --md-primary-fg-color--light: #F05F42; + --md-primary-fg-color--dark: #B92B0F; + + --md-accent-fg-color: #B92B0F; + --md-accent-fg-color--transparent: #B92B0F; + --md-accent-bg-color: #ffffff; + --md-accent-bg-color--light: #B92B0F; + } + +[data-md-color-scheme="aiforco"] { + --md-primary-fg-color: #B92B0F; + --md-primary-fg-color--light: #F05F42; + --md-primary-fg-color--dark: #B92B0F; +} + +/* [data-md-color-accent=indigo] { + --md-accent-fg-color: #B92B0F; +} */ + +/* Ensure code blocks wrap text */ +.codehilite pre { + white-space: pre-wrap; /* Allow text to wrap within the pre element */ + word-break: break-word; /* Break the word at the edge of the container if necessary */ +} + +/* Improve overall readability of code by adding some padding */ +.codehilite { + padding: 8px; /* Adjust padding to fit your design */ +} diff --git a/docs/stylesheets/mkdocstrings.css b/docs/stylesheets/mkdocstrings.css new file mode 100644 index 00000000..abea38a6 --- /dev/null +++ b/docs/stylesheets/mkdocstrings.css @@ -0,0 +1,54 @@ +/* Indentation. */ +div.doc-contents:not(.first) { + padding-left: 15px; + border-left: .05rem solid var(--md-typeset-table-color); +} + + +/* Fancier color for operators such as * and |. */ +.doc-signature .o { + color: var(--md-code-hl-special-color); +} + +/* Fancier color for constants such as None, True, and False. */ +.doc-signature .kc { + color: var(--md-code-hl-constant-color); +} + +/* Fancier color for built-in types (only useful when cross-references are used). */ +.doc-signature .n > a[href^="https://docs.python.org/"][href*="/functions.html#"], +.doc-signature .n > a[href^="https://docs.python.org/"][href*="/stdtypes.html#"] { + color: var(--md-code-hl-constant-color); +} + + +/* Nice names only in TOC */ +.doc-symbol-toc.doc-symbol-method::after { + content: "m"; +} + +.doc-symbol-toc.doc-symbol-function::after { + content: "f"; +} + +.doc-symbol-toc.doc-symbol-class::after { + content: "C"; +} + +.doc-symbol-toc.doc-symbol-module::after { + content: "M"; +} + +.doc-symbol-toc.doc-symbol-attribute::after { + content: "A"; +} + +.doc-symbol-toc.doc-symbol-parameter::after { + content: "P"; +} + +/* Line under link as solid */ +.doc-signature .autorefs { + color: inherit; + border-bottom: 1px solid currentcolor; +} \ No newline at end of file diff --git a/examples/2d-meta_train.py b/examples/2d-meta_train.py new file mode 100644 index 00000000..1f3fb8d4 --- /dev/null +++ b/examples/2d-meta_train.py @@ -0,0 +1,80 @@ +from lightning.pytorch.callbacks import ModelCheckpoint, RichModelSummary +from lightning.pytorch.loggers import WandbLogger + +from rl4co.envs import CVRPEnv +from rl4co.models.zoo.am import AttentionModelPolicy +from rl4co.models.zoo.pomo import POMO +from rl4co.utils.trainer import RL4COTrainer +from rl4co.utils.meta_trainer import ReptileCallback + +def main(): + # Set device + device_id = 0 + + # RL4CO env based on TorchRL + env = CVRPEnv(generator_params={'num_loc': 50}) + + # Policy: neural network, in this case with encoder-decoder architecture + # Note that this is adapted the same as POMO did in the original paper + policy = AttentionModelPolicy(env_name=env.name, + embed_dim=128, + num_encoder_layers=6, + num_heads=8, + normalization="instance", + use_graph_context=False + ) + + # RL Model (POMO) + model = POMO(env, + policy, + batch_size=64, # meta_batch_size + train_data_size=64 * 50, # equals to (meta_batch_size) * (gradient decent steps in the inner-loop optimization of meta-learning method) + val_data_size=0, + optimizer_kwargs={"lr": 1e-4, "weight_decay": 1e-6}, + ) + + # Example callbacks + checkpoint_callback = ModelCheckpoint( + dirpath="meta_pomo/checkpoints", # save to checkpoints/ + filename="epoch_{epoch:03d}", # save as epoch_XXX.ckpt + save_top_k=1, # save only the best model + save_last=True, # save the last model + monitor="val/reward", # monitor validation reward + mode="max", # maximize validation reward + ) + rich_model_summary = RichModelSummary(max_depth=3) # model summary callback + + # Meta callbacks + meta_callback = ReptileCallback( + num_tasks = 1, # the number of tasks in a mini-batch, i.e. `B` in the original paper + alpha = 0.9, # initial weight of the task model for the outer-loop optimization of reptile + alpha_decay = 1, # weight decay of the task model for the outer-loop optimization of reptile. No decay performs better. + min_size = 20, # minimum of sampled size in meta tasks (only supported in cross-size generalization) + max_size= 150, # maximum of sampled size in meta tasks (only supported in cross-size generalization) + data_type="size_distribution", # choose from ["size", "distribution", "size_distribution"] + sch_bar=0.9, # for the task scheduler of size setting, where lr_decay_epoch = sch_bar * epochs, i.e. after this epoch, learning rate will decay with a weight 0.1 + print_log=True # whether to print the sampled tasks in each meta iteration + ) + callbacks = [meta_callback, checkpoint_callback, rich_model_summary] + + # Logger + logger = WandbLogger(project="rl4co", name=f"{env.name}_pomo_reptile") + # logger = None # uncomment this line if you don't want logging + + # Adjust your trainer to the number of epochs you want to run + trainer = RL4COTrainer( + max_epochs=15000, # (the number of meta_model updates) * (the number of tasks in a mini-batch) + callbacks=callbacks, + accelerator="gpu", + devices=[device_id], + logger=logger, + limit_train_batches=50 # gradient decent steps in the inner-loop optimization of meta-learning method + ) + + # Fit + trainer.fit(model) + + +if __name__ == "__main__": + main() + diff --git a/examples/other/2-scheduling.ipynb b/examples/other/2-scheduling.ipynb index 4c4c029e..2fc6856b 100644 --- a/examples/other/2-scheduling.ipynb +++ b/examples/other/2-scheduling.ipynb @@ -13,15 +13,27 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [ { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning_utilities/core/imports.py:14: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html\n", + " import pkg_resources\n", + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/fabric/__init__.py:41: Deprecated call to `pkg_resources.declare_namespace('lightning.fabric')`.\n", + "Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages\n", + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/pkg_resources/__init__.py:2317: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('lightning')`.\n", + "Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages\n", + " declare_namespace(parent)\n", + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/__init__.py:37: Deprecated call to `pkg_resources.declare_namespace('lightning.pytorch')`.\n", + "Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages\n", + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/pkg_resources/__init__.py:2317: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('lightning')`.\n", + "Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages\n", + " declare_namespace(parent)\n", + "/home/laurin.luttmann/miniconda3/envs/cuda1203/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" ] } ], @@ -59,7 +71,7 @@ " \"min_processing_time\": 1, # the minimum time required for a machine to process an operation\n", " \"max_processing_time\": 20, # the maximum time required for a machine to process an operation\n", " \"min_eligible_ma_per_op\": 1, # the minimum number of machines capable to process an operation\n", - " \"max_eligible_ma_per_op\": 3, # the maximum number of machines capable to process an operation\n", + " \"max_eligible_ma_per_op\": 2, # the maximum number of machines capable to process an operation\n", "}" ] }, @@ -91,11 +103,15 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -171,7 +187,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Build a Model to Solve the FJSP\n", + "## Build a Model to Solve the FJSP\n", "\n", "In the FJSP we typically encode Operations and Machines separately, since they pose different node types in a k-partite Graph. Therefore, the encoder for the FJSP returns two hidden representations, the first containing machine embeddings and the second containing operation embeddings:" ] @@ -208,8 +224,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "torch.Size([1, 5, 32])\n", - "torch.Size([1, 60, 32])\n" + "torch.Size([1, 60, 32])\n", + "torch.Size([1, 5, 32])\n" ] } ], @@ -235,7 +251,7 @@ { "data": { "text/plain": [ - "tensor([[ 0, 5, 10, 16, 20, 24, 29, 34, 40, 44]])" + "tensor([[ 0, 4, 9, 15, 21, 27, 31, 37, 41, 45]])" ] }, "execution_count": 8, @@ -250,7 +266,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -270,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -286,7 +302,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Visualize solution construction\n", + "## Visualize solution construction\n", "\n", "Starting at $t=0$, the decoder uses the machine-operation embeddings of the encoder to decide which machine-**job**-combination to schedule next. Note, that due to the precedence relationship, the operations to be scheduled next are fixed per job. Therefore, it is sufficient to determine the next job to be scheduled, which significantly reduces the action space. \n", "\n", @@ -299,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -313,7 +329,7 @@ }, { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnYAAAHWCAYAAAD6oMSKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAACjGElEQVR4nOzdeVxU5f7A8c8MMOz7riwqKIpouGSamlqZe1rdvFlZhrfS6ucamllpVmqZ1/JW3psrLV695VJ6u1ppmFIa7rsgKqiobMMOw8DM7w9icmSHmQHp+369eL2Yc57zPN9zZvvOc87zHIVer9cjhBBCCCFue8qmDkAIIYQQQpiGJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCCGEEC2EJHZCCHGT2NhYFAoFX3/9dVOHIoQQ9SaJnRCiWhcvXuSll16iQ4cOODg44ODgQHh4OC+++CLHjx83e/sLFy5k69atlZb/8ssvzJ8/n+zs7HrVFxsby8MPP4yfnx8qlQofHx9GjRrF5s2bTRNwA6xfv54PPvigydoXQrQsktgJIaq0fft2IiIi+Pzzz7n//vtZtmwZH374IcOGDeO7774jMjKS5ORks8ZQU2L35ptv1iuxmzdvHoMGDeLkyZM8//zz/POf/yQ6Opr8/HweeeQR1q9fb7rA60ESOyGEKVk3dQBCiOYnKSmJxx57jODgYHbt2oW/v7/R+nfffZdPPvkEpfL2+G349ddfs2DBAv7yl7+wfv16bGxsDOuio6PZuXMnWq3WojEVFBTg6Oho0TaFEH8CeiGEuMVzzz2nB/T79++v8zbHjh3TP/300/q2bdvqbW1t9b6+vvpnnnlGn5GRYVRu3rx5ekCfmJiof/rpp/Wurq56FxcX/YQJE/QFBQWGckClv6efftqw/a1/Fy9erDa2jh076j08PPS5ubm17sdPP/2kB/QbN27Uv/322/rWrVvrbW1t9ffee68+MTHRqOzPP/+s/8tf/qIPDAzUq1QqfUBAgH7atGn6wsJCo3JPP/203tHRUX/+/Hn9sGHD9E5OTvrRo0frBwwYUGk/goODaz/YQghRDemxE0JUsn37dkJDQ7nrrrvqvM0PP/zAhQsXeOaZZ/Dz8+PUqVN8+umnnDp1iv3796NQKIzKjx07lrZt27Jo0SIOHz7MqlWr8PHx4d133wXg888/529/+xu9evXiueeeAyAkJARHR0cSEhL497//zbJly/Dy8gLA29u7yrgSExM5e/YsUVFRODs713l/Fi9ejFKp5OWXXyYnJ4f33nuPJ554ggMHDhjKfPXVVxQWFjJ58mQ8PT357bff+Mc//sGVK1f46quvjOorLS1lyJAh9OvXj/fffx8HBwf8/PzIycnhypUrLFu2DAAnJ6c6xyiEEJU0dWYphGhecnJy9IB+zJgxldap1Wp9enq64e/mnqlbe6n0er3+3//+tx7Q//zzz4ZlFT1uUVFRRmUfeughvaenp9EyR0dH/dNPP12p3iVLltTaS1fhm2++0QP6ZcuW1VpWr/+jx65Tp056jUZjWP7hhx/qAf2JEycMy6ra50WLFukVCoU+OTnZsOzpp5/WA/pXXnmlUvkRI0ZIL50QwmRujwtkhBAWk5ubC1TdczRw4EC8vb0Nfx9//LFhnb29veH/4uJiMjIy6N27NwCHDx+uVNekSZOMHvfv35/MzExD+6ZSUV99eusAnnnmGVQqlVF8ABcuXDAsu3mfCwoKyMjI4O6770av13PkyJFKdU6ePLleMQghRH1JYieEMFKRAOXn51da969//YsffviBL774otK6rKwspk6diq+vL/b29nh7e9O2bVsAcnJyKpUPCgoyeuzu7g6AWq1u9D7czMXFBYC8vLx6bVeX+FJSUpgwYQIeHh44OTnh7e3NgAEDgMr7bG1tTUBAQL3jF0KI+pBr7IQQRlxdXfH39+fkyZOV1lVcc3fp0qVK68aOHcsvv/xCdHQ0kZGRODk5odPpGDp0KDqdrlJ5KyurKtvX6/WN24FbdOzYEYATJ07Ua7va4isrK2Pw4MFkZWUxe/ZsOnbsiKOjI1evXmXChAmV9tnW1va2GUUshLh9SWInhKhkxIgRrFq1it9++41evXrVWl6tVrNr1y7efPNN3njjDcPyxMTERsVx64CL2pZXpUOHDoSFhfHNN9/w4YcfmmxwwokTJ0hISCAmJoannnrKsPyHH36oVz312RchhKiN/HwUQlQya9YsHBwciIqK4saNG5XW39qrVtG7devyxk686+joWOUkxBXzv9V1guI333yTzMxM/va3v1FaWlpp/ffff8/27dvrFVtV+6zX6/nwww/rVY+jo2OV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CQEBAcjKymrijImIDIeFHRFJwo4dO+Dg4ICTJ0/igw8+wPTp0/HGG2/g+eefR2xsLHx9fREQEIDi4mIAQF5eHl566SV4enri9OnT+PXXX5GRkYExY8YYORMiooZjYUdEktC7d28sWrQInTt3xsKFC2FhYQEHBwe888476Ny5M5YsWYLs7GycPXsWAPDNN9/A09MTK1euRLdu3eDp6YmtW7ciMjISycnJRs6GiKhheI4dEUlCr169dD+bmprC3t4eHh4eujYnJycAQGZmJgDgzJkziIyMrPV8vZSUFHTp0qWRIyYiMjwWdkQkCWZmZnrPZTKZXtu9q221Wi0AoLCwEMOHD8eaNWtqvJazs3MjRkpE1HhY2BFRi+Tl5YX//ve/cHNzg1zOTSERSQPPsSOiFikwMBA5OTkYN24cTp06hZSUFBw8eBCTJ09GVVWVscMjImoQFnZE1CK5uLjg2LFjqKqqgq+vLzw8PBAUFASVSgUTE24aiah5kgnevp2IiIhIEvhvKREREZFEsLAjIiIikggWdkREREQSwcKOiIiISCJY2BERERFJBAs7IiIiIolgYUdEREQkESzsiIiIiCSChR0RERGRRLCwIyIiIpIIFnZEREREEsHCjoiIiEgi/j90atEjyqZvZQAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -358,97 +374,75 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "if torch.cuda.is_available():\n", + " accelerator = \"gpu\"\n", + " batch_size = 256\n", + " train_data_size = 2_000\n", + " embed_dim = 128\n", + " num_encoder_layers = 4\n", + "else:\n", + " accelerator = \"cpu\"\n", + " batch_size = 32\n", + " train_data_size = 1_000\n", + " embed_dim = 64\n", + " num_encoder_layers = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/Users/luttmann/opt/miniconda3/envs/rl4co/lib/python3.9/site-packages/lightning/pytorch/utilities/parsing.py:198: Attribute 'env' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['env'])`.\n", - "/Users/luttmann/opt/miniconda3/envs/rl4co/lib/python3.9/site-packages/lightning/pytorch/utilities/parsing.py:198: Attribute 'policy' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['policy'])`.\n", - "/Users/luttmann/opt/miniconda3/envs/rl4co/lib/python3.9/site-packages/lightning/pytorch/trainer/connectors/accelerator_connector.py:551: You passed `Trainer(accelerator='cpu', precision='16-mixed')` but AMP with fp16 is not supported on CPU. Using `precision='bf16-mixed'` instead.\n", - "Using bfloat16 Automatic Mixed Precision (AMP)\n", - "GPU available: False, used: False\n", + "Using 16bit Automatic Mixed Precision (AMP)\n", + "GPU available: True (cuda), used: True\n", "TPU available: False, using: 0 TPU cores\n", "IPU available: False, using: 0 IPUs\n", "HPU available: False, using: 0 HPUs\n", - "/Users/luttmann/opt/miniconda3/envs/rl4co/lib/python3.9/site-packages/lightning/pytorch/trainer/connectors/logger_connector/logger_connector.py:67: Starting from v1.9.0, `tensorboardX` has been removed as a dependency of the `lightning.pytorch` package, due to potential conflicts with other packages in the ML ecosystem. For this reason, `logger=True` will use `CSVLogger` as the default logger, unless the `tensorboard` or `tensorboardX` packages are found. Please `pip install lightning[extra]` or one of them to enable TensorBoard support by default\n", - "Missing logger folder: /Users/luttmann/Documents/Diss/Repos/nco/ai4co/rl4co/examples/other/lightning_logs\n", "val_file not set. Generating dataset instead\n", - "test_file not set. Generating dataset instead\n", - "\n", - " | Name | Type | Params\n", - "--------------------------------------------\n", - "0 | env | FJSPEnv | 0 \n", - "1 | policy | L2DPolicy | 15.9 K\n", - "2 | baseline | WarmupBaseline | 15.9 K\n", - "--------------------------------------------\n", - "31.9 K Trainable params\n", - "0 Non-trainable params\n", - "31.9 K Total params\n", - "0.127 Total estimated model params size (MB)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c543880423f84865a05170d16a5aa6fd", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Sanity Checking: | | 0/? [00:00 20\u001b[0m \u001b[43mtrainer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/utils/trainer.py:146\u001b[0m, in \u001b[0;36mRL4COTrainer.fit\u001b[0;34m(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)\u001b[0m\n\u001b[1;32m 141\u001b[0m log\u001b[38;5;241m.\u001b[39mwarning(\n\u001b[1;32m 142\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOverriding gradient_clip_val to None for \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mautomatic_optimization=False\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m models\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 143\u001b[0m )\n\u001b[1;32m 144\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgradient_clip_val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m--> 146\u001b[0m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 147\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 148\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrain_dataloaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrain_dataloaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 149\u001b[0m \u001b[43m \u001b[49m\u001b[43mval_dataloaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mval_dataloaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 150\u001b[0m \u001b[43m \u001b[49m\u001b[43mdatamodule\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdatamodule\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 151\u001b[0m \u001b[43m \u001b[49m\u001b[43mckpt_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mckpt_path\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 152\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/trainer.py:544\u001b[0m, in \u001b[0;36mTrainer.fit\u001b[0;34m(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)\u001b[0m\n\u001b[1;32m 542\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mstatus \u001b[38;5;241m=\u001b[39m TrainerStatus\u001b[38;5;241m.\u001b[39mRUNNING\n\u001b[1;32m 543\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtraining \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m--> 544\u001b[0m \u001b[43mcall\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_and_handle_interrupt\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 545\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_fit_impl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_dataloaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mval_dataloaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdatamodule\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mckpt_path\u001b[49m\n\u001b[1;32m 546\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/call.py:44\u001b[0m, in \u001b[0;36m_call_and_handle_interrupt\u001b[0;34m(trainer, trainer_fn, *args, **kwargs)\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mstrategy\u001b[38;5;241m.\u001b[39mlauncher \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mstrategy\u001b[38;5;241m.\u001b[39mlauncher\u001b[38;5;241m.\u001b[39mlaunch(trainer_fn, \u001b[38;5;241m*\u001b[39margs, trainer\u001b[38;5;241m=\u001b[39mtrainer, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m---> 44\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtrainer_fn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 46\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m _TunerExitException:\n\u001b[1;32m 47\u001b[0m _call_teardown_hook(trainer)\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/trainer.py:580\u001b[0m, in \u001b[0;36mTrainer._fit_impl\u001b[0;34m(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)\u001b[0m\n\u001b[1;32m 573\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mfn \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 574\u001b[0m ckpt_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_checkpoint_connector\u001b[38;5;241m.\u001b[39m_select_ckpt_path(\n\u001b[1;32m 575\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mfn,\n\u001b[1;32m 576\u001b[0m ckpt_path,\n\u001b[1;32m 577\u001b[0m model_provided\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 578\u001b[0m model_connected\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlightning_module \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 579\u001b[0m )\n\u001b[0;32m--> 580\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mckpt_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mckpt_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 582\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mstopped\n\u001b[1;32m 583\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtraining \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/trainer.py:949\u001b[0m, in \u001b[0;36mTrainer._run\u001b[0;34m(self, model, ckpt_path)\u001b[0m\n\u001b[1;32m 946\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: preparing data\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 947\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data_connector\u001b[38;5;241m.\u001b[39mprepare_data()\n\u001b[0;32m--> 949\u001b[0m \u001b[43mcall\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_setup_hook\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# allow user to set up LightningModule in accelerator environment\u001b[39;00m\n\u001b[1;32m 950\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: configuring model\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 951\u001b[0m call\u001b[38;5;241m.\u001b[39m_call_configure_model(\u001b[38;5;28mself\u001b[39m)\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/call.py:94\u001b[0m, in \u001b[0;36m_call_setup_hook\u001b[0;34m(trainer)\u001b[0m\n\u001b[1;32m 92\u001b[0m _call_lightning_datamodule_hook(trainer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msetup\u001b[39m\u001b[38;5;124m\"\u001b[39m, stage\u001b[38;5;241m=\u001b[39mfn)\n\u001b[1;32m 93\u001b[0m _call_callback_hooks(trainer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msetup\u001b[39m\u001b[38;5;124m\"\u001b[39m, stage\u001b[38;5;241m=\u001b[39mfn)\n\u001b[0;32m---> 94\u001b[0m \u001b[43m_call_lightning_module_hook\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtrainer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msetup\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfn\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 96\u001b[0m trainer\u001b[38;5;241m.\u001b[39mstrategy\u001b[38;5;241m.\u001b[39mbarrier(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost_setup\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/lightning/pytorch/trainer/call.py:157\u001b[0m, in \u001b[0;36m_call_lightning_module_hook\u001b[0;34m(trainer, hook_name, pl_module, *args, **kwargs)\u001b[0m\n\u001b[1;32m 154\u001b[0m pl_module\u001b[38;5;241m.\u001b[39m_current_fx_name \u001b[38;5;241m=\u001b[39m hook_name\n\u001b[1;32m 156\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mprofile(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[LightningModule]\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpl_module\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mhook_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m):\n\u001b[0;32m--> 157\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 159\u001b[0m \u001b[38;5;66;03m# restore current_fx when nested context\u001b[39;00m\n\u001b[1;32m 160\u001b[0m pl_module\u001b[38;5;241m.\u001b[39m_current_fx_name \u001b[38;5;241m=\u001b[39m prev_fx_name\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/common/base.py:155\u001b[0m, in \u001b[0;36mRL4COLitModule.setup\u001b[0;34m(self, stage)\u001b[0m\n\u001b[1;32m 153\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataloader_names \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msetup_loggers()\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpost_setup_hook\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/reinforce.py:119\u001b[0m, in \u001b[0;36mREINFORCE.post_setup_hook\u001b[0;34m(self, stage)\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpost_setup_hook\u001b[39m(\u001b[38;5;28mself\u001b[39m, stage\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 118\u001b[0m \u001b[38;5;66;03m# Make baseline taking model itself and train_dataloader from model as input\u001b[39;00m\n\u001b[0;32m--> 119\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbaseline\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msetup\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 120\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpolicy\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 121\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43menv\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 122\u001b[0m \u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mval_batch_size\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 123\u001b[0m \u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mget_lightning_device\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 124\u001b[0m \u001b[43m \u001b[49m\u001b[43mdataset_size\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdata_cfg\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mval_data_size\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 125\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:117\u001b[0m, in \u001b[0;36mWarmupBaseline.setup\u001b[0;34m(self, *args, **kw)\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21msetup\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkw):\n\u001b[0;32m--> 117\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbaseline\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msetup\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkw\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:174\u001b[0m, in \u001b[0;36mRolloutBaseline.setup\u001b[0;34m(self, *args, **kw)\u001b[0m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21msetup\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkw):\n\u001b[0;32m--> 174\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_update_policy\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkw\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:187\u001b[0m, in \u001b[0;36mRolloutBaseline._update_policy\u001b[0;34m(self, policy, env, batch_size, device, dataset_size, dataset)\u001b[0m\n\u001b[1;32m 183\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdataset \u001b[38;5;241m=\u001b[39m env\u001b[38;5;241m.\u001b[39mdataset(batch_size\u001b[38;5;241m=\u001b[39m[dataset_size])\n\u001b[1;32m 185\u001b[0m log\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEvaluating baseline policy on evaluation dataset\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 186\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbl_vals \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 187\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrollout\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpolicy\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43menv\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdataset\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mcpu()\u001b[38;5;241m.\u001b[39mnumpy()\n\u001b[1;32m 188\u001b[0m )\n\u001b[1;32m 189\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmean \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbl_vals\u001b[38;5;241m.\u001b[39mmean()\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:242\u001b[0m, in \u001b[0;36mRolloutBaseline.rollout\u001b[0;34m(self, policy, env, batch_size, device, dataset)\u001b[0m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m policy(batch, env, decode_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgreedy\u001b[39m\u001b[38;5;124m\"\u001b[39m)[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreward\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 240\u001b[0m dl \u001b[38;5;241m=\u001b[39m DataLoader(dataset, batch_size\u001b[38;5;241m=\u001b[39mbatch_size, collate_fn\u001b[38;5;241m=\u001b[39mdataset\u001b[38;5;241m.\u001b[39mcollate_fn)\n\u001b[0;32m--> 242\u001b[0m rewards \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mcat([eval_policy(batch) \u001b[38;5;28;01mfor\u001b[39;00m batch \u001b[38;5;129;01min\u001b[39;00m dl], \u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 243\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m rewards\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:242\u001b[0m, in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m policy(batch, env, decode_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgreedy\u001b[39m\u001b[38;5;124m\"\u001b[39m)[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreward\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 240\u001b[0m dl \u001b[38;5;241m=\u001b[39m DataLoader(dataset, batch_size\u001b[38;5;241m=\u001b[39mbatch_size, collate_fn\u001b[38;5;241m=\u001b[39mdataset\u001b[38;5;241m.\u001b[39mcollate_fn)\n\u001b[0;32m--> 242\u001b[0m rewards \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mcat([\u001b[43meval_policy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbatch\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m batch \u001b[38;5;129;01min\u001b[39;00m dl], \u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 243\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m rewards\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/rl/reinforce/baselines.py:238\u001b[0m, in \u001b[0;36mRolloutBaseline.rollout..eval_policy\u001b[0;34m(batch)\u001b[0m\n\u001b[1;32m 236\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m torch\u001b[38;5;241m.\u001b[39minference_mode():\n\u001b[1;32m 237\u001b[0m batch \u001b[38;5;241m=\u001b[39m env\u001b[38;5;241m.\u001b[39mreset(batch\u001b[38;5;241m.\u001b[39mto(device))\n\u001b[0;32m--> 238\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mpolicy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbatch\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43menv\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdecode_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mgreedy\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreward\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/torch/nn/modules/module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1532\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_impl\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/cuda1203/lib/python3.10/site-packages/torch/nn/modules/module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1539\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1540\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1541\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforward_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1544\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/models/common/constructive/base.py:231\u001b[0m, in \u001b[0;36mConstructivePolicy.forward\u001b[0;34m(self, td, env, phase, calc_reward, return_actions, return_entropy, return_hidden, return_init_embeds, return_sum_log_likelihood, actions, max_steps, **decoding_kwargs)\u001b[0m\n\u001b[1;32m 229\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m td[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdone\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39mall():\n\u001b[1;32m 230\u001b[0m logits, mask \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdecoder(td, hidden, num_starts)\n\u001b[0;32m--> 231\u001b[0m td \u001b[38;5;241m=\u001b[39m \u001b[43mdecode_strategy\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstep\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 232\u001b[0m \u001b[43m \u001b[49m\u001b[43mlogits\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 233\u001b[0m \u001b[43m \u001b[49m\u001b[43mmask\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 234\u001b[0m \u001b[43m \u001b[49m\u001b[43mtd\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 235\u001b[0m \u001b[43m \u001b[49m\u001b[43maction\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mactions\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstep\u001b[49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mactions\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mis\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mnot\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 236\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 237\u001b[0m td \u001b[38;5;241m=\u001b[39m env\u001b[38;5;241m.\u001b[39mstep(td)[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnext\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 238\u001b[0m step \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/utils/decoding.py:343\u001b[0m, in \u001b[0;36mDecodingStrategy.step\u001b[0;34m(self, logits, mask, td, action, **kwargs)\u001b[0m\n\u001b[1;32m 340\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmask_logits: \u001b[38;5;66;03m# set mask_logit to None if mask_logits is False\u001b[39;00m\n\u001b[1;32m 341\u001b[0m mask \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m--> 343\u001b[0m logprobs \u001b[38;5;241m=\u001b[39m \u001b[43mprocess_logits\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 344\u001b[0m \u001b[43m \u001b[49m\u001b[43mlogits\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 345\u001b[0m \u001b[43m \u001b[49m\u001b[43mmask\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 346\u001b[0m \u001b[43m \u001b[49m\u001b[43mtemperature\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtemperature\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[43m \u001b[49m\u001b[43mtop_p\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtop_p\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 348\u001b[0m \u001b[43m \u001b[49m\u001b[43mtop_k\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtop_k\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 349\u001b[0m \u001b[43m \u001b[49m\u001b[43mtanh_clipping\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtanh_clipping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 350\u001b[0m \u001b[43m \u001b[49m\u001b[43mmask_logits\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmask_logits\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 351\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 352\u001b[0m logprobs, selected_action, td \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_step(\n\u001b[1;32m 353\u001b[0m logprobs, mask, td, action\u001b[38;5;241m=\u001b[39maction, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs\n\u001b[1;32m 354\u001b[0m )\n\u001b[1;32m 356\u001b[0m \u001b[38;5;66;03m# directly return for improvement methods, since the action for improvement methods is finalized in its own policy\u001b[39;00m\n", + "File \u001b[0;32m~/repos/ai4co/rl4co/rl4co/utils/decoding.py:177\u001b[0m, in \u001b[0;36mprocess_logits\u001b[0;34m(logits, mask, temperature, top_p, top_k, tanh_clipping, mask_logits)\u001b[0m\n\u001b[1;32m 175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mask_logits:\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m mask \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmask must be provided if mask_logits is True\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 177\u001b[0m \u001b[43mlogits\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m~\u001b[39;49m\u001b[43mmask\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m-inf\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 179\u001b[0m logits \u001b[38;5;241m=\u001b[39m logits \u001b[38;5;241m/\u001b[39m temperature \u001b[38;5;66;03m# temperature scaling\u001b[39;00m\n\u001b[1;32m 181\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m top_k \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m:\n", + "\u001b[0;31mIndexError\u001b[0m: The shape of the mask [256, 11] at index 1 does not match the shape of the indexed tensor [256, 101] at index 1" ] } ], "source": [ - "if torch.cuda.is_available():\n", - " accelerator = \"gpu\"\n", - " batch_size = 512\n", - " train_data_size = 100_000\n", - " embed_dim = 128\n", - " num_encoder_layers = 4\n", - "else:\n", - " accelerator = \"cpu\"\n", - " batch_size = 32\n", - " train_data_size = 1_000\n", - " embed_dim = 64\n", - " num_encoder_layers = 2\n", - "\n", "# Policy: neural network, in this case with encoder-decoder architecture\n", "policy = L2DPolicy(embed_dim=embed_dim, num_encoder_layers=num_encoder_layers, env_name=\"fjsp\")\n", "\n", @@ -470,11 +464,207 @@ "\n", "trainer.fit(model)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Solving the Job-Shop Scheduling Problem (JSSP)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import gc\n", + "from rl4co.envs import JSSPEnv\n", + "from rl4co.models.zoo.l2d.model import L2DPPOModel\n", + "from rl4co.models.zoo.l2d.policy import L2DPolicy4PPO\n", + "from torch.utils.data import DataLoader" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Lets generate a more complex instance\n", + "\n", + "generator_params = {\n", + " \"num_jobs\": 15, # the total number of jobs\n", + " \"num_machines\": 15, # the total number of machines that can process operations\n", + " \"min_processing_time\": 1, # the minimum time required for a machine to process an operation\n", + " \"max_processing_time\": 99, # the maximum time required for a machine to process an operation\n", + "}\n", + "\n", + "env = JSSPEnv(\n", + " generator_params=generator_params, \n", + " _torchrl_mode=True, \n", + " stepwise_reward=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train on synthetic data and test on Taillard benchmark" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using 16bit Automatic Mixed Precision (AMP)\n", + "GPU available: True (cuda), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "Overriding gradient_clip_val to None for 'automatic_optimization=False' models\n", + "val_file not set. Generating dataset instead\n", + "Provided file name data/../../data/jssp/taillard/15j_15m not found. Make sure to provide a file in the right path first or unset test_file to generate data automatically instead\n", + "LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0,1,2,3,4]\n", + "\n", + " | Name | Type | Params\n", + "---------------------------------------------\n", + "0 | env | JSSPEnv | 0 \n", + "1 | policy | L2DPolicy4PPO | 133 K \n", + "2 | policy_old | L2DPolicy4PPO | 133 K \n", + "---------------------------------------------\n", + "266 K Trainable params\n", + "0 Non-trainable params\n", + "266 K Total params\n", + "1.066 Total estimated model params size (MB)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 0: 100%|β–ˆ| 8/8 [03:40<00:00, 0.04it/s, v_num=9, train/loss=1.45e+3, train\n", + "Validation: | | 0/? [00:00AI4CO contributors +docs_dir: . + +nav: + - Home: README.md + - Getting Started: + - Installation: docs/content/start/installation.md + - Quick Start: examples/1-quickstart.ipynb + - Training with Hydra: docs/content/start/hydra.md + - Overview: + - docs/content/intro/intro.md + - docs/content/intro/environments.md + - docs/content/intro/policies.md + - docs/content/intro/rl.md + - Tutorials: + - Main: + - Quickstart: examples/1-quickstart.ipynb + - Training a Model: examples/2-full-training.ipynb + - Solving New Problems: examples/3-creating-new-env-model.ipynb + - Modeling: + - Decoding Strategies: examples/modeling/1-decoding-strategies.ipynb + - Transductive Methods: examples/modeling/2-transductive-methods.ipynb + - Encoder Customization: examples/modeling/3-change-encoder.ipynb + - Advanced: + - Hydra Configuration: examples/advanced/1-hydra-config.ipynb + - Local Search: examples/advanced/3-local-search.ipynb + - Routing: + - Multi-Task VRP: examples/other/1-mtvrp.ipynb + - TSPLib: examples/datasets/1-test-on-tsplib.ipynb + - CVRPLib: examples/datasets/2-test-on-cvrplib.ipynb + - Scheduling: + - Flexible Job Shop Scheduling: examples/other/2-scheduling.ipynb + - API Reference: + - Environments: + - Base Classes: docs/content/api/envs/base.md + - Routing Problems: docs/content/api/envs/routing.md + - Scheduling Problems: docs/content/api/envs/scheduling.md + - EDA Problems: docs/content/api/envs/eda.md + - Networks: + - Policy Base Classes: docs/content/api/networks/base_policies.md + - Neural Network Modules: docs/content/api/networks/nn.md + - Environment Embeddings: docs/content/api/networks/env_embeddings.md + - RL Algorithms: + - Base Classes: docs/content/api/rl/base.md + - Reinforce: docs/content/api/rl/reinforce.md + - PPO: docs/content/api/rl/ppo.md + - A2C: docs/content/api/rl/a2c.md + - Zoo: + - Constructive AR Methods: docs/content/api/zoo/constructive_ar.md + - Constructive NAR Methods: docs/content/api/zoo/constructive_nar.md + - Improvement Methods: docs/content/api/zoo/improvement.md + - Transductive Methods: docs/content/api/zoo/transductive.md + - Additional APIs: + - Train and Evaluation: docs/content/api/tasks.md + - Decoding Strategies: docs/content/api/decoding.md + - Data: docs/content/api/data.md + - About: + - Contributing to RL4CO: docs/content/general/contribute.md + - FAQ: docs/content/general/faq.md + - Join AI4CO: docs/content/general/ai4co.md + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/ai4co + - icon: fontawesome/brands/slack + link: https://bit.ly/ai4co-slack + - icon: fontawesome/solid/globe + link: https://ai4co.org + +theme: + name: material + logo: docs/assets/figs/rl4co-logo.svg + favicon: docs/assets/figs/rl4co-logo.svg + custom_dir: docs/overrides + primary: red + features: + - announce.dismiss + - content.code.copy + - content.code.annotate + - content.code.select + - content.tabs.link + - content.tooltips + - navigation.expand + - navigation.instant + - navigation.instant.prefetch + - navigation.instant.preview + - navigation.instant.progress + - navigation.indexes + - navigation.path + - navigation.sections + - navigation.top + - navigation.tracking + - navigation.tabs # horizontal tabs for navigation + - search.suggest + - search.highlight + - search.share + - toc.follow + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: custom + accent: custom + toggle: + icon: material/weather-sunny + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: custom + accent: custom + toggle: + icon: material/weather-night + name: Switch to system preference + font: + text: Noto Sans + code: Fira Code + +extra_css: + - docs/stylesheets/extra.css # Our custom CSS + - docs/stylesheets/mkdocstrings.css # mkdocstrings CSS + - https://unpkg.com/katex@0/dist/katex.min.css # Latex math rendering + +extra_javascript: + - docs/js/katex.js # Latex math rendering + - docs/js/particles.min.js + - https://unpkg.com/katex@0/dist/katex.min.js # Latex math rendering + - https://unpkg.com/katex@0/dist/contrib/auto-render.min.js # Latex math rendering + +extra: + version: + default: stable + +plugins: + - mkdocstrings: + enable_inventory: true # create .inv file for auto linking + handlers: + python: + paths: [rl4co] + options: + members_order: source + separate_signature: true + filters: ["!^_"] + docstring_options: + ignore_init_summary: true + merge_init_into_class: true + show_signature_annotations: true + docstring_section_style: list + heading_level: 2 + inherited_members: false + show_root_heading: true + show_root_toc_entry: false + show_root_full_path: false + show_source: true + show_symbol_type_heading: true + show_symbol_type_toc: true + signature_crossrefs: true + summary: true + extensions: + - griffe_inherited_docstrings + import: + - https://docs.python.org/3/objects.inv + - https://pytorch.org/rl/stable/objects.inv + - https://pytorch.org/tensordict/stable/objects.inv + - https://pytorch.org/docs/stable/objects.inv + - https://lightning.ai/docs/pytorch/stable/objects.inv + - mike: + alias_type: symlink + canonical_version: latest + - mkdocs-jupyter: + include_source: True + include: ["*ipynb"] + - search + - autorefs + - autolinks + - same-dir + +hooks: + - docs/hooks.py + +markdown_extensions: + - pymdownx.details + - pymdownx.superfences + - pymdownx.arithmatex: + generic: true + - pymdownx.highlight: + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.magiclink + - pymdownx.superfences + - tables + - toc: + permalink: true + title: Page contents + - admonition + - pymdownx.extra + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.tabbed: + alternate_style: true + - attr_list + - md_in_html + - def_list + - mdx_truly_sane_lists + - mdx_breakless_lists + - gfm_admonition + diff --git a/pyproject.toml b/pyproject.toml index 06bf7b2c..39c55371 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,57 +1,47 @@ -[build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" - -[tool.setuptools.packages.find] -include = ['rl4co*'] - -# Automatically determine version from package -[tool.setuptools.dynamic] -version = {attr = "rl4co.__version__"} - -[project] +[tool.poetry] name = "rl4co" -readme = "README.md" - - +version = "0.5.0.dev2" description = "RL4CO: an Extensive Reinforcement Learning for Combinatorial Optimization Benchmark" authors = [ - {name = "Federico Berto", email = "berto.federico2@gmail.com"}, - {name = "Chuanbo Hua", email="cbhua@kaist.ac.kr"}, - {name = "Junyoung Park", email="junyoungpark.ml@gmail.com"}, - {name = "Laurin Luttmann", email="laurin.luttmann@gmail.com"}, - {name = "Yining Ma"}, - {name = "Fanchen Bu"}, - {name = "Jiarui Wang"}, - {name = "Haoran Ye"}, - {name = "Minsu Kim"}, - {name = "Sanghyeok Choi"}, - {name = "Zepeda Gast"}, - {name = "Andre Hottung"}, - {name = "Jianan Zhou"}, - {name = "Jieyi Bi"}, - {name = "Yu Hu"}, - {name = "Fei Liu"}, - {name = "Hyeonah Kim"}, - {name = "Jiwoo Son"}, - {name = "Haeyeon Kim"}, - {name = "Davide Angioni"}, - {name = "Wouter Kool"}, - {name = "Zhiguang Cao"}, - {name = "Jie Zhang"}, - {name = "Kijung Shin"}, - {name = "Cathy Wu"}, - {name = "Sungsoo Ahn"}, - {name = "Guojie Song"}, - {name = "Changhyun Kwon"}, - {name = "Lin Xie"}, - {name = "Jinkyoo Park"}, - ] -dynamic = ["version"] - -license = {file = "LICENSE"} - -requires-python = ">=3.8" + "Federico Berto ", + "Chuanbo Hua ", + "Junyoung Park ", + "Laurin Luttmann ", + "Yining Ma", + "Fanchen Bu", + "Jiarui Wang", + "Haoran Ye", + "Minsu Kim", + "Sanghyeok Choi", + "Zepeda Gast", + "Andre Hottung", + "Jianan Zhou", + "Jieyi Bi", + "Yu Hu", + "Fei Liu", + "Hyeonah Kim", + "Jiwoo Son", + "Haeyeon Kim", + "Davide Angioni", + "Wouter Kool", + "Zhiguang Cao", + "Jie Zhang", + "Kijung Shin", + "Cathy Wu", + "Sungsoo Ahn", + "Guojie Song", + "Changhyun Kwon", + "Lin Xie", + "Jinkyoo Park", + "AI4CO", +] +readme = "README.md" +license = "MIT" +homepage = "https://rl4.co" +repository = "https://github.com/ai4co/rl4co" +documentation = "https://rl4co.readthedocs.io" +keywords = ["reinforcement learning", "combinatorial optimization", "benchmark"] +packages = [{ include = "rl4co" }] classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", @@ -59,69 +49,111 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "License :: OSI Approved :: MIT License", "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Operating System :: OS Independent", - "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Scientific/Engineering :: Artificial Intelligence" ] -dependencies = [ - "einops", - "hydra-core", - "hydra-colorlog", - "lightning>=2.1.0", - "matplotlib", - "omegaconf", - "pyrootutils", - "rich", - "robust-downloader", - "scipy", - "tensordict>=0.2.0", - "torchrl>=0.2.0", - "wandb" -] - -[project.optional-dependencies] +[tool.poetry.urls] +"Tracker" = "https://github.com/ai4co/rl4co/issues" + +[tool.poetry.dependencies] +# Required dependencies +python = ">=3.8" +einops = "*" +hydra-core = "*" +hydra-colorlog = "*" +lightning = ">=2.1.0" +matplotlib = "*" +omegaconf = "*" +pyrootutils = "*" +rich = "*" +robust-downloader = "*" +scipy = "*" +tensordict = ">=0.4.0" +torchrl = ">=0.4.0" +wandb = "*" +# Dev dependencies +black = { version = "*", optional = true } +pre-commit = { version = ">=3.3.3", optional = true } +ruff = { version = "*", optional = true } +pytest = { version = "*", optional = true } +pytest-cov = { version = "*", optional = true } +# Graph +torch_geometric = { version = "*", optional = true } +# Routing +numba = { version = ">=0.58.1", optional = true } +pyvrp = { version = ">=0.8.2", optional = true } +# Docs +mkdocs = { version = "*", optional = true } +mkdocs-material = { version = "*", optional = true } +mkdocstrings-python = { version = "*", optional = true } +mike = { version = "*", optional = true } +mkdocs-jupyter = { version = "*", optional = true } +mkdocs-redirects = { version = "*", optional = true } +mkdocs-autolinks-plugin = { version = "*", optional = true } +griffe-typingdoc = { version = "*", optional = true } +griffe-inherited-docstrings = { version = "*", optional = true } +griffe = { version = "*", optional = true } +mkdocs-same-dir = { version = "*", optional = true } +mdx-breakless-lists = { version = "*", optional = true } +mdx-truly-sane-lists = { version = "*", optional = true } +markdown-gfm-admonition = { version = "*", optional = true } + +[tool.poetry.extras] +dev = ["black", "pre-commit", "ruff", "pytest", "pytest-cov"] graph = ["torch_geometric"] -testing = ["pytest", "pytest-cov"] -dev = ["black", "ruff", "pre-commit>=3.3.3"] -routing = ["numba>=0.58.1", "pyvrp>=0.8.2"] +routing = ["numba", "pyvrp"] +docs = [ + "mkdocs", + "mkdocs-material", + "mkdocstrings-python", + "mike", + "mkdocs-jupyter", + "mkdocs-redirects", + "mkdocs-autolinks-plugin", + "griffe-typingdoc", + "griffe-inherited-docstrings", + "griffe", + "black", # for formatting docstrings + "mkdocs-same-dir", + "mdx-breakless-lists", + "mdx-truly-sane-lists", + "markdown-gfm-admonition", +] -[project.urls] -"Homepage" = "https://github.com/ai4co/rl4co" -"Bug Tracker" = "https://github.com/ai4co/rl4co/issues" +[tool.black] +line-length = 90 +target-version = ["py311"] +include = '\.pyi?$' +exclude = ''' +( + /( + \.direnv + | \.eggs + | \.git + | \.tox + | \.venv + | _build + | build + | dist + | venv + )/ +) +''' -# Ruff + Black + isort combo for code formatting -# Adapted from https://github.com/AntonOsika/gpt-engineer (kudos!) -# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml [tool.ruff] select = ["F", "E", "W", "I001"] line-length = 90 show-fixes = false -target-version = "py310" +target-version = "py311" task-tags = ["TODO", "FIXME"] -exclude = [ - ".bzr", - ".direnv", - ".eggs", - ".git", - ".ruff_cache", - ".svn", - ".tox", - ".venv", - "__pypackages__", - "_build", - "buck-out", - "build", - "dist", - "node_modules", - "venv", -] ignore = ["E501"] # never enforce `E501` (line length violations), done in Black -# Ignore `E402` (import violations) and "F401" (unused imports) in all `__init__.py` files [tool.ruff.per-file-ignores] "__init__.py" = ["E402", "F401"] @@ -139,27 +171,6 @@ combine-as-imports = true split-on-trailing-comma = false lines-between-types = 1 -# https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html -[tool.black] -line-length = 90 -target-version = ["py311"] -include = '\.pyi?$' -exclude = ''' -( - /( - \.direnv - | \.eggs - | \.git - | \.tox - | \.venv - | _build - | build - | dist - | venv - )/ -) -''' - [tool.coverage] include = ["rl4co.*"] @@ -170,3 +181,7 @@ exclude_lines = [ "pragma: no cover", "if __name__ == .__main__.:", ] + +[build-system] +requires = ["poetry"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/rl4co/__init__.py b/rl4co/__init__.py index 2d299658..1830875a 100644 --- a/rl4co/__init__.py +++ b/rl4co/__init__.py @@ -1 +1,4 @@ -__version__ = "0.5.0dev0" +from importlib.metadata import version as get_version + +# The package version is obtained from the pyproject.toml file +__version__ = get_version(__package__) diff --git a/rl4co/data/dataset.py b/rl4co/data/dataset.py index a1f03391..f3519ada 100644 --- a/rl4co/data/dataset.py +++ b/rl4co/data/dataset.py @@ -1,10 +1,44 @@ from typing import Union +import tensordict import torch +from packaging import version from tensordict.tensordict import TensorDict from torch.utils.data import Dataset +# Checks were removed in tensordict 0.5.0, so we should not pass the kwargs +if version.parse(tensordict.__version__) <= version.parse("0.4.0"): + td_kwargs = {"_run_checks": False} +else: + td_kwargs = {} + + +class FastTdDataset(Dataset): + """ + Note: + Check out the issue on tensordict for more details: + https://github.com/pytorch-labs/tensordict/issues/374. + """ + + def __init__(self, td: TensorDict): + self.data_len = td.batch_size[0] + self.data = td + + def __len__(self): + return self.data_len + + def __getitems__(self, idx): + return self.data[idx] + + def add_key(self, key, value): + return ExtraKeyDataset(self, value, key_name=key) + + @staticmethod + def collate_fn(batch: Union[dict, TensorDict]): + """Collate function compatible with TensorDicts that reassembles a list of dicts.""" + return batch + class TensorDictDataset(Dataset): """Dataset compatible with TensorDicts with low CPU usage. @@ -37,7 +71,7 @@ def collate_fn(batch: Union[dict, TensorDict]): return TensorDict( {key: torch.stack([b[key] for b in batch]) for key in batch[0].keys()}, batch_size=torch.Size([len(batch)]), - _run_checks=False, + **td_kwargs, ) @@ -87,7 +121,7 @@ def __getitems__(self, index): return TensorDict( {key: item[index] for key, item in self.data.items()}, batch_size=torch.Size([len(index)]), - _run_checks=False, # faster this way + **td_kwargs, ) def add_key(self, key, value): diff --git a/rl4co/envs/__init__.py b/rl4co/envs/__init__.py index f1de6e68..f3b65b7d 100644 --- a/rl4co/envs/__init__.py +++ b/rl4co/envs/__init__.py @@ -28,6 +28,9 @@ from rl4co.envs.scheduling import FFSPEnv, FJSPEnv, SMTWTPEnv from rl4co.envs.scheduling.jssp.env import JSSPEnv +# Graph +from rl4co.envs.graph import MCPEnv, FLPEnv + # Register environments ENV_REGISTRY = { "atsp": ATSPEnv, @@ -51,6 +54,8 @@ "mdcpdp": MDCPDPEnv, "mtvrp": MTVRPEnv, "tsp_kopt": TSPkoptEnv, + "mcp": MCPEnv, + "flp": FLPEnv, } diff --git a/rl4co/envs/common/base.py b/rl4co/envs/common/base.py index e477d7e3..d2f4aa55 100644 --- a/rl4co/envs/common/base.py +++ b/rl4co/envs/common/base.py @@ -291,7 +291,7 @@ def _set_seed(self, seed: Optional[int]): self.rng = rng def to(self, device): - """Override `to` device method for safety against `None` device (may be found in `TensorDict`))""" + """Override `to` device method for safety against `None` device (may be found in `TensorDict`)""" if device is None: return self else: @@ -336,8 +336,8 @@ def __setstate__(self, state): class ImprovementEnvBase(RL4COEnvBase, metaclass=abc.ABCMeta): """Base class for Improvement environments based on RL4CO EnvBase. Note that this class assumes that the solution is stored in a linked list format. - Here, if rec[i] = j, it means the node i is connected to node j, i.e., edge i-j is in the solution. - For example, if edge 0-1, edge 1-5, edge 2-10 are in the solution, so we have rec[0]=1, rec[1]=5 and rec[2]=10. + Here, if `rec[i] = j`, it means the node `i` is connected to node `j`, i.e., edge `i-j` is in the solution. + For example, if edge `0-1`, edge `1-5`, edge `2-10` are in the solution, so we have `rec[0]=1`, `rec[1]=5` and `rec[2]=10`. Kindly see https://github.com/yining043/VRP-DACT/blob/new_version/Play_with_DACT.ipynb for an example at the end for TSP. """ diff --git a/rl4co/envs/common/distribution_utils.py b/rl4co/envs/common/distribution_utils.py new file mode 100644 index 00000000..ab8e1449 --- /dev/null +++ b/rl4co/envs/common/distribution_utils.py @@ -0,0 +1,292 @@ +import random + +import torch + + +class Cluster: + """ + Multiple gaussian distributed clusters, as in the Solomon benchmark dataset + Following the setting in Bi et al. 2022 (https://arxiv.org/abs/2210.07686) + + Args: + n_cluster: Number of the gaussian distributed clusters + """ + + def __init__(self, n_cluster: int = 3): + super().__init__() + self.lower, self.upper = 0.2, 0.8 + self.std = 0.07 + self.n_cluster = n_cluster + + def sample(self, size): + + batch_size, num_loc, _ = size + + # Generate the centers of the clusters + center = self.lower + (self.upper - self.lower) * torch.rand( + batch_size, self.n_cluster * 2 + ) + + # Pre-define the coordinates + coords = torch.zeros(batch_size, num_loc, 2) + + # Calculate the size of each cluster + cluster_sizes = [num_loc // self.n_cluster] * self.n_cluster + for i in range(num_loc % self.n_cluster): + cluster_sizes[i] += 1 + + # Generate the coordinates + current_index = 0 + for i in range(self.n_cluster): + means = center[:, i * 2 : (i + 1) * 2] + stds = torch.full((batch_size, 2), self.std) + points = torch.normal( + means.unsqueeze(1).expand(-1, cluster_sizes[i], -1), + stds.unsqueeze(1).expand(-1, cluster_sizes[i], -1), + ) + coords[:, current_index : current_index + cluster_sizes[i], :] = points + current_index += cluster_sizes[i] + + # Confine the coordinates to range [0, 1] + coords.clamp_(0, 1) + + return coords + + +class Mixed: + """ + 50% nodes sampled from uniform distribution, 50% nodes sampled from gaussian distribution, as in the Solomon benchmark dataset + Following the setting in Bi et al. 2022 (https://arxiv.org/abs/2210.07686) + + Args: + n_cluster_mix: Number of the gaussian distributed clusters + """ + + def __init__(self, n_cluster_mix=1): + super().__init__() + self.lower, self.upper = 0.2, 0.8 + self.std = 0.07 + self.n_cluster_mix = n_cluster_mix + + def sample(self, size): + + batch_size, num_loc, _ = size + + # Generate the centers of the clusters + center = self.lower + (self.upper - self.lower) * torch.rand( + batch_size, self.n_cluster_mix * 2 + ) + + # Pre-define the coordinates sampled under uniform distribution + coords = torch.FloatTensor(batch_size, num_loc, 2).uniform_(0, 1) + + # Sample mutated index (default setting: 50% mutation) + mutate_idx = torch.stack( + [torch.randperm(num_loc)[: num_loc // 2] for _ in range(batch_size)] + ) + + # Generate the coordinates + segment_size = num_loc // (2 * self.n_cluster_mix) + remaining_indices = num_loc // 2 - segment_size * (self.n_cluster_mix - 1) + sizes = [segment_size] * (self.n_cluster_mix - 1) + [remaining_indices] + for i in range(self.n_cluster_mix): + indices = mutate_idx[:, sum(sizes[:i]) : sum(sizes[: i + 1])] + means_x = center[:, 2 * i].unsqueeze(1).expand(-1, sizes[i]) + means_y = center[:, 2 * i + 1].unsqueeze(1).expand(-1, sizes[i]) + coords.scatter_( + 1, + indices.unsqueeze(-1).expand(-1, -1, 2), + torch.stack( + [ + torch.normal(means_x.expand(-1, sizes[i]), self.std), + torch.normal(means_y.expand(-1, sizes[i]), self.std), + ], + dim=2, + ), + ) + + # Confine the coordinates to range [0, 1] + coords.clamp_(0, 1) + + return coords + + +class Gaussian_Mixture: + """ + Following Zhou et al. (2023): https://arxiv.org/abs/2305.19587 + + Args: + num_modes: the number of clusters/modes in the Gaussian Mixture. + cdist: scale of the uniform distribution for center generation. + """ + + def __init__(self, num_modes: int = 0, cdist: int = 0): + super().__init__() + self.num_modes = num_modes + self.cdist = cdist + + def sample(self, size): + + batch_size, num_loc, _ = size + + if self.num_modes == 0: # (0, 0) - uniform + return torch.rand((batch_size, num_loc, 2)) + elif self.num_modes == 1 and self.cdist == 1: # (1, 1) - gaussian + return self.generate_gaussian(batch_size, num_loc) + else: + res = [self.generate_gaussian_mixture(num_loc) for _ in range(batch_size)] + return torch.stack(res) + + def generate_gaussian_mixture(self, num_loc): + """Following the setting in Zhang et al. 2022 (https://arxiv.org/abs/2204.03236)""" + + # Randomly decide how many points each mode gets + nums = torch.multinomial( + input=torch.ones(self.num_modes) / self.num_modes, + num_samples=num_loc, + replacement=True, + ) + + # Prepare to collect points + coords = torch.empty((0, 2)) + + # Generate points for each mode + for i in range(self.num_modes): + num = (nums == i).sum() # Number of points in this mode + if num > 0: + center = torch.rand((1, 2)) * self.cdist + cov = torch.eye(2) # Covariance matrix + nxy = torch.distributions.MultivariateNormal( + center.squeeze(), covariance_matrix=cov + ).sample((num,)) + coords = torch.cat((coords, nxy), dim=0) + + return self._global_min_max_scaling(coords) + + def generate_gaussian(self, batch_size, num_loc): + """Following the setting in Xin et al. 2022 (https://openreview.net/pdf?id=nJuzV-izmPJ)""" + + # Mean and random covariances + mean = torch.full((batch_size, num_loc, 2), 0.5) + covs = torch.rand(batch_size) # Random covariances between 0 and 1 + + # Generate the coordinates + coords = torch.zeros((batch_size, num_loc, 2)) + for i in range(batch_size): + # Construct covariance matrix for each sample + cov_matrix = torch.tensor([[1.0, covs[i]], [covs[i], 1.0]]) + m = torch.distributions.MultivariateNormal( + mean[i], covariance_matrix=cov_matrix + ) + coords[i] = m.sample() + + # Shuffle the coordinates + indices = torch.randperm(coords.size(0)) + coords = coords[indices] + + return self._batch_normalize_and_center(coords) + + def _global_min_max_scaling(self, coords): + + # Scale the points to [0, 1] using min-max scaling + coords_min = coords.min(0, keepdim=True).values + coords_max = coords.max(0, keepdim=True).values + coords = (coords - coords_min) / (coords_max - coords_min) + + return coords + + def _batch_normalize_and_center(self, coords): + # Step 1: Compute min and max along each batch + coords_min = coords.min(dim=1, keepdim=True).values + coords_max = coords.max(dim=1, keepdim=True).values + + # Step 2: Normalize coordinates to range [0, 1] + coords = ( + coords - coords_min + ) # Broadcasting subtracts min value on each coordinate + range_max = ( + (coords_max - coords_min).max(dim=-1, keepdim=True).values + ) # The maximum range among both coordinates + coords = coords / range_max # Divide by the max range to normalize + + # Step 3: Center the batch in the middle of the [0, 1] range + coords = ( + coords + (1 - coords.max(dim=1, keepdim=True).values) / 2 + ) # Centering the batch + + return coords + + +class Mix_Distribution: + """ + Mixture of three exemplar distributions in batch-level, i.e. Uniform, Cluster, Mixed + Following the setting in Bi et al. 2022 (https://arxiv.org/abs/2210.07686) + + Args: + n_cluster: Number of the gaussian distributed clusters in Cluster distribution + n_cluster_mix: Number of the gaussian distributed clusters in Mixed distribution + """ + + def __init__(self, n_cluster=3, n_cluster_mix=1): + super().__init__() + self.lower, self.upper = 0.2, 0.8 + self.std = 0.07 + self.Mixed = Mixed(n_cluster_mix=n_cluster_mix) + self.Cluster = Cluster(n_cluster=n_cluster) + + def sample(self, size): + + batch_size, num_loc, _ = size + + # Pre-define the coordinates sampled under uniform distribution + coords = torch.FloatTensor(batch_size, num_loc, 2).uniform_(0, 1) + + # Random sample probability for the distribution of each sample + p = torch.rand(batch_size) + + # Mixed + mask = p <= 0.33 + n_mixed = mask.sum().item() + if n_mixed > 0: + coords[mask] = self.Mixed.sample((n_mixed, num_loc, 2)) + + # Cluster + mask = (p > 0.33) & (p <= 0.66) + n_cluster = mask.sum().item() + if n_cluster > 0: + coords[mask] = self.Cluster.sample((n_cluster, num_loc, 2)) + + # The remaining ones are uniformly distributed + return coords + + +class Mix_Multi_Distributions: + """ + Mixture of 11 Gaussian-like distributions in batch-level + Following the setting in Zhou et al. (2023): https://arxiv.org/abs/2305.19587 + """ + + def __init__(self): + super().__init__() + self.dist_set = [(0, 0), (1, 1)] + [ + (m, c) for m in [3, 5, 7] for c in [10, 30, 50] + ] + + def sample(self, size): + batch_size, num_loc, _ = size + coords = torch.zeros(batch_size, num_loc, 2) + + # Pre-select distributions for the entire batch + dists = [random.choice(self.dist_set) for _ in range(batch_size)] + unique_dists = list( + set(dists) + ) # Unique distributions to minimize re-instantiation + + # Instantiate Gaussian_Mixture only once per unique distribution + gm_instances = {dist: Gaussian_Mixture(*dist) for dist in unique_dists} + + # Batch process where possible + for i, dist in enumerate(dists): + coords[i] = gm_instances[dist].sample((1, num_loc, 2)).squeeze(0) + + return coords diff --git a/rl4co/envs/common/utils.py b/rl4co/envs/common/utils.py index 5d7612f7..043a2168 100644 --- a/rl4co/envs/common/utils.py +++ b/rl4co/envs/common/utils.py @@ -6,7 +6,7 @@ from tensordict.tensordict import TensorDict from torch.distributions import Exponential, Normal, Poisson, Uniform - +from rl4co.envs.common.distribution_utils import Cluster, Mixed, Gaussian_Mixture, Mix_Distribution, Mix_Multi_Distributions class Generator(metaclass=abc.ABCMeta): """Base data generator class, to be called with `env.generator(batch_size)`""" @@ -43,8 +43,10 @@ def get_sampler( kwargs: Additional arguments for the distribution Example: - >>> sampler_uniform = get_sampler("loc", "uniform", 0, 1) - >>> sampler_normal = get_sampler("loc", "normal", loc_mean=0.5, loc_std=.2) + ```python + sampler_uniform = get_sampler("loc", "uniform", 0, 1) + sampler_normal = get_sampler("loc", "normal", loc_mean=0.5, loc_std=.2) + ``` """ if isinstance(distribution, (int, float)): return Uniform(low=distribution, high=distribution) @@ -76,6 +78,16 @@ def get_sampler( ) # todo: should be also `low, high` and any other corner elif isinstance(distribution, Callable): return distribution(**kwargs) + elif distribution == "gaussian_mixture": + return Gaussian_Mixture(num_modes=kwargs['num_modes'], cdist=kwargs['cdist']) + elif distribution == "cluster": + return Cluster(kwargs['n_cluster']) + elif distribution == "mixed": + return Mixed(kwargs['n_cluster_mix']) + elif distribution == "mix_distribution": + return Mix_Distribution(kwargs['n_cluster'], kwargs['n_cluster_mix']) + elif distribution == "mix_multi_distributions": + return Mix_Multi_Distributions() else: raise ValueError(f"Invalid distribution type of {distribution}") @@ -87,3 +99,4 @@ def batch_to_scalar(param): if isinstance(param, torch.Tensor): return param.item() return param + diff --git a/rl4co/envs/graph/__init__.py b/rl4co/envs/graph/__init__.py new file mode 100644 index 00000000..d49826b1 --- /dev/null +++ b/rl4co/envs/graph/__init__.py @@ -0,0 +1,3 @@ +from rl4co.envs.graph.mcp.env import MCPEnv +from rl4co.envs.graph.flp.env import FLPEnv + diff --git a/rl4co/envs/graph/flp/env.py b/rl4co/envs/graph/flp/env.py new file mode 100644 index 00000000..aa73b3f9 --- /dev/null +++ b/rl4co/envs/graph/flp/env.py @@ -0,0 +1,169 @@ +from typing import Optional + +import torch + +from tensordict.tensordict import TensorDict + +from rl4co.envs.common.base import RL4COEnvBase +from rl4co.utils.ops import gather_by_index +from rl4co.utils.pylogger import get_pylogger + +from .generator import FLPGenerator + +log = get_pylogger(__name__) + + +class FLPEnv(RL4COEnvBase): + """Facility Location Problem (FLP) environment + At each step, the agent chooses a location. The reward is 0 unless enough number of locations are chosen. + The reward is (-) the total distance of each location to its closest chosen location. + + Observations: + - the locations + - the number of locations to choose + + Constraints: + - the given number of locations must be chosen + + Finish condition: + - the given number of locations are chosen + + Reward: + - (minus) the total distance of each location to its closest chosen location + + Args: + generator: FLPGenerator instance as the data generator + generator_params: parameters for the generator + """ + + name = "flp" + + def __init__( + self, + generator: FLPGenerator = None, + generator_params: dict = {}, + check_solution=False, + **kwargs, + ): + super().__init__(**kwargs) + if generator is None: + generator = FLPGenerator(**generator_params) + self.generator = generator + self.check_solution = check_solution + self._make_spec(self.generator) + + def _step(self, td: TensorDict) -> TensorDict: + # action: [batch_size, 1]; the location to be chosen in each instance + selected = td["action"] + batch_size = selected.shape[0] + + # Update location selection status + chosen = td["chosen"].clone() # (batch_size, n_locations) + n_points_ = chosen.shape[-1] + + chosen[torch.arange(batch_size).to(td.device), selected] = True + + # We are done if we choose enough locations + done = td["i"] >= (td["to_choose"] - 1) + + # The reward is calculated outside via get_reward for efficiency, so we set it to zero here + reward = torch.zeros_like(done) + + # Update distances + orig_distances = td["orig_distances"] # (batch_size, n_points, n_points) + + cur_min_dist = ( + gather_by_index( + orig_distances, chosen.nonzero(as_tuple=True)[1].view(batch_size, -1) + ) + .view(batch_size, -1, n_points_) + .min(dim=1) + .values + ) + + # We cannot choose the already-chosen locations + action_mask = ~chosen + + td.update( + { + "distances": cur_min_dist, # (batch_size, n_points) + # states changed by actions + "chosen": chosen, # each entry is binary; 1 iff the corresponding facility is chosen + "i": td["i"] + 1, # the number of sets we have chosen + "action_mask": action_mask, + "reward": reward, + "done": done, + } + ) + return td + + def _reset(self, td: Optional[TensorDict] = None, batch_size=None) -> TensorDict: + self.to(td.device) + + return TensorDict( + { + # given information + "locs": td["locs"], # (batch_size, n_points, dim_loc) + "orig_distances": td[ + "orig_distances" + ], # (batch_size, n_points, n_points) + "distances": td["distances"], # (batch_size, n_points, n_points) + # states changed by actions + "chosen": torch.zeros( + *td["locs"].shape[:-1], dtype=torch.bool, device=td.device + ), # each entry is binary; 1 iff the corresponding facility is chosen + "to_choose": td["to_choose"], # the number of sets to choose + "i": torch.zeros( + *batch_size, dtype=torch.int64, device=td.device + ), # the number of sets we have chosen + "action_mask": torch.ones( + *td["locs"].shape[:-1], dtype=torch.bool, device=td.device + ), + }, + batch_size=batch_size, + ) + + def _make_spec(self, generator: FLPGenerator): + # TODO: make spec + pass + + def _get_reward(self, td: TensorDict, actions: torch.Tensor) -> torch.Tensor: + if self.check_solution: + self.check_solution_validity(td, actions) + + # The reward is (minus) the total distance from each location to the closest chosen location + chosen = td["chosen"] # (batch_size, n_points) + batch_size_ = td["chosen"].shape[0] + n_points_ = td["chosen"].shape[-1] + orig_distances = td["orig_distances"] + cur_min_dist = ( + gather_by_index( + orig_distances, chosen.nonzero(as_tuple=True)[1].view(batch_size_, -1) + ) + .view(batch_size_, -1, n_points_) + .min(1) + .values.sum(-1) + ) + return -cur_min_dist + + @staticmethod + def check_solution_validity(td: TensorDict, actions: torch.Tensor) -> None: + # TODO: check solution validity + pass + + @staticmethod + def local_search(td: TensorDict, actions: torch.Tensor, **kwargs) -> torch.Tensor: + # TODO: local search + pass + + @staticmethod + def get_num_starts(td): + return td["action_mask"].shape[-1] + + @staticmethod + def select_start_nodes(td, num_starts): + num_loc = td["action_mask"].shape[-1] + return ( + torch.arange(num_starts, device=td.device).repeat_interleave(td.shape[0]) + % num_loc + ) diff --git a/rl4co/envs/graph/flp/generator.py b/rl4co/envs/graph/flp/generator.py new file mode 100644 index 00000000..adbc7de6 --- /dev/null +++ b/rl4co/envs/graph/flp/generator.py @@ -0,0 +1,74 @@ +import math + +from typing import Callable, Union + +import torch + +from tensordict.tensordict import TensorDict +from torch.distributions import Uniform + +from rl4co.envs.common.utils import Generator, get_sampler +from rl4co.utils.ops import get_distance_matrix +from rl4co.utils.pylogger import get_pylogger + +log = get_pylogger(__name__) + + +class FLPGenerator(Generator): + """Data generator for the Facility Location Problem (FLP). + + Args: + num_loc: number of locations in the FLP + min_loc: minimum value for the location coordinates + max_loc: maximum value for the location coordinates + loc_distribution: distribution for the location coordinates + + Returns: + A TensorDict with the following keys: + locs [batch_size, num_loc, 2]: locations + orig_distances [batch_size, num_loc, num_loc]: original distances between locations + distances [batch_size, num_loc]: the current minimum distance rom each location to the chosen locations + chosen [batch_size, num_loc]: indicators of chosen locations + to_choose [batch_size, 1]: number of locations to choose in the FLP + """ + + def __init__( + self, + num_loc: int = 100, + min_loc: float = 0.0, + max_loc: float = 1.0, + loc_distribution: Union[int, float, str, type, Callable] = Uniform, + to_choose: int = 10, + **kwargs, + ): + self.num_loc = num_loc + self.min_loc = min_loc + self.max_loc = max_loc + self.to_choose = to_choose + + # Location distribution + if kwargs.get("loc_sampler", None) is not None: + self.loc_sampler = kwargs["loc_sampler"] + else: + self.loc_sampler = get_sampler( + "loc", loc_distribution, min_loc, max_loc, **kwargs + ) + + def _generate(self, batch_size) -> TensorDict: + # Sample locations + locs = self.loc_sampler.sample((*batch_size, self.num_loc, 2)) + distances = get_distance_matrix(locs) + max_dist = math.sqrt(2) * (self.max_loc - self.min_loc) + + return TensorDict( + { + "locs": locs, + "orig_distances": distances, + "distances": torch.full( + (*batch_size, self.num_loc), max_dist, dtype=torch.float + ), + "chosen": torch.zeros(*batch_size, self.num_loc, dtype=torch.bool), + "to_choose": torch.ones(*batch_size, dtype=torch.long) * self.to_choose, + }, + batch_size=batch_size, + ) diff --git a/rl4co/envs/graph/mcp/env.py b/rl4co/envs/graph/mcp/env.py new file mode 100644 index 00000000..3f0275e0 --- /dev/null +++ b/rl4co/envs/graph/mcp/env.py @@ -0,0 +1,193 @@ +from typing import Optional + +import torch + +from tensordict.tensordict import TensorDict + +from rl4co.envs.common.base import RL4COEnvBase +from rl4co.utils.pylogger import get_pylogger + +from .generator import MCPGenerator + +log = get_pylogger(__name__) + + +class MCPEnv(RL4COEnvBase): + """Maximum Coverage Problem (MCP) environment + At each step, the agent chooses a set. The reward is 0 unless enough number of sets are chosen. + The reward is the total weights of the covered items (i.e., items in any chosen set). + + Observations: + - the weights of items + - the membership of items in sets + - the number of sets to choose + + Constraints: + - the given number of sets must be chosen + + Finish condition: + - the given number of sets are chosen + + Reward: + - the total weights of the covered items (i.e., items in any chosen set) + + Args: + generator: MCPGenerator instance as the data generator + generator_params: parameters for the generator + """ + + name = "mcp" + + def __init__( + self, + generator: MCPGenerator = None, + generator_params: dict = {}, + check_solution=False, + **kwargs, + ): + super().__init__(**kwargs) + if generator is None: + generator = MCPGenerator(**generator_params) + self.generator = generator + self.check_solution = check_solution + self._make_spec(self.generator) + + def _step(self, td: TensorDict) -> TensorDict: + # action: [batch_size, 1]; the set to be chosen in each instance + batch_size = td["action"].shape[0] + selected = td["action"] + + # Update set selection status + chosen = td["chosen"].clone() # (batch_size, n_sets) + chosen[torch.arange(batch_size).to(td.device), selected] = True + + # We are done if we choose enough sets + done = td["i"] >= (td["n_sets_to_choose"] - 1) + + # The reward is calculated outside via get_reward for efficiency, so we set it to -inf here + reward = torch.ones_like(done) * float("-inf") + + remaining_sets = ~chosen # (batch_size, n_sets) + + chosen_membership = chosen.unsqueeze(-1) * td["membership"] + chosen_membership_nonzero = chosen_membership.nonzero() + remaining_membership = remaining_sets.unsqueeze(-1) * td["membership"] + + batch_indices, set_indices, item_indices = chosen_membership_nonzero.T + chosen_items_indices = chosen_membership[ + batch_indices, set_indices, item_indices + ].long() + + batch_size, n_items = td["weights"].shape + + # We have batch_indices and chosen_items_indices + # chosen_items: (batch_size, n_items) + # for each i, chosen_items[batch_size[i], chosen_items_indices[i]] += 1 + chosen_items = torch.zeros(batch_size, n_items + 1, device=td.device) + chosen_items[batch_indices, chosen_items_indices] += 1 + chosen_items = chosen_items[:, 1:] # Remove the first column (invalid zeros) + + # chosen_item[i, j] > 0 means item j is chosen in batch i + covered_items = (chosen_items > 0).float() # (batch_size, n_items) + remaining_items = 1.0 - covered_items # (batch_size, n_items) + + # We cannot choose the already-chosen sets + action_mask = ~chosen + + td.update( + { + "membership": remaining_membership, # (batch_size, n_sets, max_size) + "weights": td["weights"] * remaining_items, # (batch_size, n_items) + "chosen": chosen, + "i": td["i"] + 1, + "action_mask": action_mask, + "reward": reward, + "done": done, + } + ) + return td + + def _reset(self, td: Optional[TensorDict] = None, batch_size=None) -> TensorDict: + self.to(td.device) + + return TensorDict( + { + # given information; constant for each given instance + "orig_membership": td["membership"], # (batch_size, n_sets, max_size) + "membership": td["membership"], # (batch_size, n_sets, max_size) + "orig_weights": td["weights"], # (batch_size, n_items) + "weights": td["weights"], # (batch_size, n_items) + "n_sets_to_choose": td["n_sets_to_choose"], # (batch_size, 1) + # states changed by actions + "chosen": torch.zeros( + *td["membership"].shape[:-1], dtype=torch.bool, device=td.device + ), # each entry is binary; 1 iff the corresponding set is chosen + "i": torch.zeros( + *batch_size, dtype=torch.int64, device=td.device + ), # the number of sets we have chosen + "action_mask": torch.ones( + *td["membership"].shape[:-1], dtype=torch.bool, device=td.device + ), + }, + batch_size=batch_size, + ) + + def _make_spec(self, generator: MCPGenerator): + # TODO: make spec + pass + + def _get_reward(self, td: TensorDict, actions: torch.Tensor) -> torch.Tensor: + if self.check_solution: + self.check_solution_validity(td, actions) + + membership = td[ + "orig_membership" + ] # (batch_size, n_sets, max_size); membership[i, j] = the items in set j in batch i (with 0 padding) + weights = td["orig_weights"] # (batch_size, n_items) + chosen_sets = td["chosen"] # (batch_size, n_set); 1 if chosen, 0 otherwise + + chosen_membership = chosen_sets.unsqueeze(-1) * membership + chosen_membership_nonzero = chosen_membership.nonzero() + + batch_indices, set_indices, item_indices = chosen_membership_nonzero.T + chosen_items_indices = chosen_membership[ + batch_indices, set_indices, item_indices + ].long() + + batch_size, n_items = weights.shape + + # We have batch_indices and chosen_items_indices + # chosen_items: (batch_size, n_items) + # For each i, chosen_items[batch_size[i], chosen_items_indices[i]] += 1 + chosen_items = torch.zeros(batch_size, n_items + 1, device=td.device) + chosen_items[batch_indices, chosen_items_indices] += 1 + chosen_items = chosen_items[:, 1:] # remove the first column + + # chosen_item[i, j] > 0 means item j is chosen in batch i + chosen_items = (chosen_items > 0).float() + # Compute the total weights of chosen items + chosen_weights = torch.sum(chosen_items * weights, dim=-1) + + return chosen_weights + + @staticmethod + def check_solution_validity(td: TensorDict, actions: torch.Tensor) -> None: + # TODO: check solution validity + pass + + @staticmethod + def local_search(td: TensorDict, actions: torch.Tensor, **kwargs) -> torch.Tensor: + # TODO: local search + pass + + @staticmethod + def get_num_starts(td): + return td["action_mask"].shape[-1] + + @staticmethod + def select_start_nodes(td, num_starts): + num_sets = td["action_mask"].shape[-1] + return ( + torch.arange(num_starts, device=td.device).repeat_interleave(td.shape[0]) + % num_sets + ) diff --git a/rl4co/envs/graph/mcp/generator.py b/rl4co/envs/graph/mcp/generator.py new file mode 100644 index 00000000..92b59410 --- /dev/null +++ b/rl4co/envs/graph/mcp/generator.py @@ -0,0 +1,111 @@ +import torch + +from tensordict.tensordict import TensorDict + +from rl4co.envs.common.utils import Generator +from rl4co.utils.pylogger import get_pylogger + +log = get_pylogger(__name__) + + +def remove_repeat(x: torch.Tensor) -> torch.Tensor: + """ + Remove the repeated elements in each row (i.e., the last dimension) of the input tensor x, + and change the repeated elements to 0 + + Ref: https://stackoverflow.com/questions/62300404 + + Args: + x: input tensor + """ + + # sorting the rows so that duplicate values appear together + # e.g., first row: [1, 2, 3, 3, 3, 4, 4] + y, indices = x.sort(dim=-1) + + # subtracting, so duplicate values will become 0 + # e.g., first row: [1, 2, 3, 0, 0, 4, 0] + y[..., 1:] *= ((y[..., 1:] - y[..., :-1]) != 0).long() + + # retrieving the original indices of elements + indices = indices.sort(dim=-1)[1] + + # re-organizing the rows following original order + # e.g., first row: [1, 2, 3, 4, 0, 0, 0] + return torch.gather(y, -1, indices) + + +class MCPGenerator(Generator): + """Data generator for the Maximum Coverage Problem (MCP). + + Args: + num_items: number of items in the MCP + num_sets: number of sets in the MCP + min_weight: minimum value for the item weights + max_weight: maximum value for the item weights + min_size: minimum size for the sets + max_size: maximum size for the sets + n_sets_to_choose: number of sets to choose in the MCP + + Returns: + A TensorDict with the following keys: + membership [batch_size, num_sets, max_size]: membership of items in sets + weights [batch_size, num_items]: weights of the items + n_sets_to_choose [batch_size, 1]: number of sets to choose in the MCP + """ + + def __init__( + self, + num_items: int = 200, + num_sets: int = 100, + min_weight: int = 1, + max_weight: int = 10, + min_size: int = 5, + max_size: int = 15, + n_sets_to_choose: int = 10, + **kwargs, + ): + self.num_items = num_items + self.num_sets = num_sets + self.min_weight = min_weight + self.max_weight = max_weight + self.min_size = min_size + self.max_size = max_size + self.n_sets_to_choose = n_sets_to_choose + + def _generate(self, batch_size) -> TensorDict: + try: + batch_size = batch_size[0] + except TypeError: + batch_size = batch_size + + weights_tensor = torch.randint( + self.min_weight, self.max_weight + 1, (batch_size, self.num_items) + ).float() + # Create membership tensor + membership_tensor_max_size = torch.randint( + 1, self.num_items + 1, (batch_size, self.num_sets, self.max_size) + ) + # Cutoffs for each set + cutoffs = torch.randint( + self.min_size, self.max_size + 1, (batch_size, self.num_sets) + ) + + cutoffs_masks = torch.arange(self.max_size).view(1, 1, -1) < cutoffs.unsqueeze(-1) + # Take the masked elements, 0 means the item is invalid + membership_tensor = ( + membership_tensor_max_size * cutoffs_masks + ) # (batch_size, num_sets, max_size) + + # Remove repeated items in each set + membership_tensor = remove_repeat(membership_tensor) + + return TensorDict( + { + "membership": membership_tensor.float(), # (batch_size, num_sets, max_size) + "weights": weights_tensor.float(), # (batch_size, num_items) + "n_sets_to_choose": torch.ones(batch_size, 1) + * self.n_sets_to_choose, # (batch_size, 1) + }, + batch_size=batch_size, + ) diff --git a/rl4co/envs/routing/mtvrp/env.py b/rl4co/envs/routing/mtvrp/env.py index 9a23895d..c4a32cc3 100644 --- a/rl4co/envs/routing/mtvrp/env.py +++ b/rl4co/envs/routing/mtvrp/env.py @@ -26,65 +26,48 @@ class MTVRPEnv(RL4COEnvBase): Features: - *Capacity (C)* - - Each vehicle has a maximum capacity :math:`Q`, restricting the total load that can be in the vehicle at any point of the route. + - Each vehicle has a maximum capacity $Q$, restricting the total load that can be in the vehicle at any point of the route. - The route must be planned such that the sum of demands and pickups for all customers visited does not exceed this capacity. - *Time Windows (TW)* - - Every node :math:`i` has an associated time window :math:`[e_i, l_i]` during which service must commence. - - Additionally, each node has a service time :math:`s_i`. Vehicles must reach node :math:`i` within its time window; early arrivals must wait at the node location until time :math:`e_i`. + - Every node $i$ has an associated time window $[e_i, l_i]$ during which service must commence. + - Additionally, each node has a service time $s_i$. Vehicles must reach node $i$ within its time window; early arrivals must wait at the node location until time $e_i$. - *Open Routes (O)* - Vehicles are not required to return to the depot after serving all customers. - - Note that this does not need to be counted as a constraint since it can be modelled by setting zero costs on arcs returning to the depot :math:`c_{i0} = 0` from any customer :math:`i \in C`, and not counting the return arc as part of the route. + - Note that this does not need to be counted as a constraint since it can be modelled by setting zero costs on arcs returning to the depot $c_{i0} = 0$ from any customer $i \in C$, and not counting the return arc as part of the route. - *Backhauls (B)* - Backhauls generalize demand to also account for return shipments. Customers are either linehaul or backhaul customers. - - Linehaul customers require delivery of a demand :math:`q_i > 0` that needs to be transported from the depot to the customer, whereas backhaul customers need a pickup of an amount :math:`p_i > 0` that is transported from the client back to the depot. + - Linehaul customers require delivery of a demand $q_i > 0$ that needs to be transported from the depot to the customer, whereas backhaul customers need a pickup of an amount $p_i > 0$ that is transported from the client back to the depot. - It is possible for vehicles to serve a combination of linehaul and backhaul customers in a single route, but then any linehaul customers must precede the backhaul customers in the route. - *Duration Limits (L)* - Imposes a limit on the total travel duration (or length) of each route, ensuring a balanced workload across vehicles. The environment covers the following 16 variants depending on the data generation: - - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRP Variant || Capacity (C) | Open Route (O) | Backhaul (B) | Duration Limit (L) | Time Window (TW) | - +==============++==============+================+==============+====================+==================+ - | CVRP || βœ” | | | | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRP || βœ” | βœ” | | | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPB || βœ” | | βœ” | | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPL || βœ” | | | βœ” | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPTW || βœ” | | | | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPTW || βœ” | βœ” | | | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPB || βœ” | βœ” | βœ” | | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPL || βœ” | βœ” | | βœ” | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPBL || βœ” | | βœ” | βœ” | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPBTW || βœ” | | βœ” | | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPLTW || βœ” | | | βœ” | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPBL || βœ” | βœ” | βœ” | βœ” | | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPBTW || βœ” | βœ” | βœ” | | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPLTW || βœ” | βœ” | | βœ” | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | VRPBLTW || βœ” | | βœ” | βœ” | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ - | OVRPBLTW || βœ” | βœ” | βœ” | βœ” | βœ” | - +--------------++--------------+----------------+--------------+--------------------+------------------+ + + | VRP Variant | Capacity (C) | Open Route (O) | Backhaul (B) | Duration Limit (L) | Time Window (TW) | + | :---------- | :----------: | :------------: | :----------: | :----------------: | :--------------: | + | CVRP | βœ” | | | | | + | OVRP | βœ” | βœ” | | | | + | VRPB | βœ” | | βœ” | | | + | VRPL | βœ” | | | βœ” | | + | VRPTW | βœ” | | | | βœ” | + | OVRPTW | βœ” | βœ” | | | βœ” | + | OVRPB | βœ” | βœ” | βœ” | | | + | OVRPL | βœ” | βœ” | | βœ” | | + | VRPBL | βœ” | | βœ” | βœ” | | + | VRPBTW | βœ” | | βœ” | | βœ” | + | VRPLTW | βœ” | | | βœ” | βœ” | + | OVRPBL | βœ” | βœ” | βœ” | βœ” | | + | OVRPBTW | βœ” | βœ” | βœ” | | βœ” | + | OVRPLTW | βœ” | βœ” | | βœ” | βœ” | + | VRPBLTW | βœ” | | βœ” | βœ” | βœ” | + | OVRPBLTW | βœ” | βœ” | βœ” | βœ” | βœ” | You may also check out the following papers as reference: - - `"Multi-Task Learning for Routing Problem with Cross-Problem Zero-Shot Generalization" (Liu et al, 2024) `_ - - `"MVMoE: Multi-Task Vehicle Routing Solver with Mixture-of-Experts" (Zhou et al, 2024) `_. - - `"RouteFinder: Towards Foundation Models for Vehicle Routing Problems" (Berto et al, 2024) `_. - - Note: + - ["Multi-Task Learning for Routing Problem with Cross-Problem Zero-Shot Generalization" (Liu et al, 2024)](https://arxiv.org/abs/2402.16891) + - ["MVMoE: Multi-Task Vehicle Routing Solver with Mixture-of-Experts" (Zhou et al, 2024)](https://arxiv.org/abs/2405.01029) + - ["RouteFinder: Towards Foundation Models for Vehicle Routing Problems" (Berto et al, 2024)](https://arxiv.org/abs/2406.15007) + + Tip: Have a look at https://pyvrp.org/ for more information about VRP and its variants and their solutions. Kudos to their help and great job! Args: diff --git a/rl4co/envs/routing/pdp/env.py b/rl4co/envs/routing/pdp/env.py index 6c46e4a3..dfa78904 100644 --- a/rl4co/envs/routing/pdp/env.py +++ b/rl4co/envs/routing/pdp/env.py @@ -235,7 +235,7 @@ def render(td: TensorDict, actions: torch.Tensor = None, ax=None): class PDPRuinRepairEnv(ImprovementEnvBase): - """Pickup and Delivery Problem (PDP) environment for performing neural rein-repair search. + """Pickup and Delivery Problem (PDP) environment for performing neural ruin-repair search. The environment is made of num_loc + 1 locations (cities): - 1 depot - `num_loc` / 2 pickup locations diff --git a/rl4co/envs/scheduling/ffsp/env.py b/rl4co/envs/scheduling/ffsp/env.py index da8eff24..c74ef4c2 100644 --- a/rl4co/envs/scheduling/ffsp/env.py +++ b/rl4co/envs/scheduling/ffsp/env.py @@ -13,6 +13,7 @@ UnboundedDiscreteTensorSpec, ) +from rl4co.data.dataset import FastTdDataset from rl4co.envs.common.base import RL4COEnvBase from .generator import FFSPGenerator @@ -57,7 +58,7 @@ def __init__( generator_params: dict = {}, **kwargs, ): - super().__init__(check_solution=False, **kwargs) + super().__init__(check_solution=False, dataset_cls=FastTdDataset, **kwargs) if generator is None: generator = FFSPGenerator(**generator_params) self.generator = generator @@ -150,15 +151,12 @@ def pre_step(self, td: TensorDict) -> TensorDict: batch_idx = torch.arange(*batch_size, dtype=torch.long, device=td.device) sub_time_idx = td["sub_time_idx"] # update machine index - machine_idx = self.tables.get_machine_index(batch_idx, sub_time_idx) + td["machine_idx"] = self.tables.get_machine_index(batch_idx, sub_time_idx) # update action mask and stage machine indx td = self._update_step_state(td) # perform some checks - stage_machine_idx = td["stage_machine_idx"] - stage_idx = td["stage_idx"] - is_stage_one = stage_idx == 0 - assert torch.all(stage_machine_idx[is_stage_one] == machine_idx[is_stage_one]) - assert is_stage_one.all(), "call pre_step only at beginning of env" + assert (td["stage_idx"] == 0).all(), "call pre_step only at beginning of env" + assert torch.all(td["stage_machine_idx"] == td["machine_idx"]) # return updated td return td @@ -215,9 +213,6 @@ def _step(self, td: TensorDict) -> TensorDict: time_idx = td["time_idx"] machine_idx = td["machine_idx"] - # create new td to avoid incplace ops and gradient problems resulting from this - # td = td.clone() - # increment the operation counter of the selected job td["job_location"][batch_idx, job_idx] += 1 # td["job_location"][:, :-1].clip_(0, self.num_stage) @@ -311,21 +306,7 @@ def _reset( dtype=torch.long, device=device, ) - if self.flatten_stages: - assert ( - len(td["run_time"].shape) == 3 - ), "cost matrix has shape other than (bs, jobs, ma_total)" - job_duration[..., : self.num_job, :] = td["run_time"] - else: - assert ( - len(td["run_time"].shape) == 4 - ), "cost matrix has shape other than (bs, jobs, ma, stages)" - job_duration[..., : self.num_job, :] = ( - td["run_time"] - .transpose(-2, -1) - .contiguous() - .view(*batch_size, self.num_job, self.num_machine_total) - ) + job_duration[..., : self.num_job, :] = td["run_time"] job_duration[..., self.num_job, :] = 0 # Finish status information @@ -429,16 +410,6 @@ def _make_spec(self, generator: FFSPGenerator): def _get_reward(self, td, actions) -> TensorDict: return td["reward"] - def _get_cmap(self, color_cnt): - from random import shuffle - - from matplotlib.colors import CSS4_COLORS, ListedColormap - - color_list = list(CSS4_COLORS.keys()) - shuffle(color_list) - cmap = ListedColormap(color_list, N=color_cnt) - return cmap - class IndexTables: def __init__(self, env: FFSPEnv): diff --git a/rl4co/envs/scheduling/ffsp/generator.py b/rl4co/envs/scheduling/ffsp/generator.py index 8ec3ce71..6b33b8b1 100644 --- a/rl4co/envs/scheduling/ffsp/generator.py +++ b/rl4co/envs/scheduling/ffsp/generator.py @@ -1,17 +1,9 @@ -import os -import zipfile -from typing import Union, Callable - import torch -import numpy as np -from robust_downloader import download -from torch.distributions import Uniform from tensordict.tensordict import TensorDict -from rl4co.data.utils import load_npz_to_tensordict +from rl4co.envs.common.utils import Generator from rl4co.utils.pylogger import get_pylogger -from rl4co.envs.common.utils import get_sampler, Generator log = get_pylogger(__name__) @@ -34,6 +26,7 @@ class FFSPGenerator(Generator): Note: - [IMPORTANT] This version of ffsp requires the number of machines in each stage to be the same """ + def __init__( self, num_stage: int = 2, @@ -42,7 +35,7 @@ def __init__( min_time: int = 2, max_time: int = 10, flatten_stages: bool = True, - **unused_kwargs + **unused_kwargs, ): self.num_stage = num_stage self.num_machine = num_machine @@ -61,16 +54,9 @@ def _generate(self, batch_size) -> TensorDict: run_time = torch.randint( low=self.min_time, high=self.max_time, - size=(*batch_size, self.num_job, self.num_machine, self.num_stage), + size=(*batch_size, self.num_job, self.num_machine_total), ) - if self.flatten_stages: - run_time = ( - run_time.transpose(-2, -1) - .contiguous() - .view(*batch_size, self.num_job, self.num_machine_total) - ) - return TensorDict( { "run_time": run_time, diff --git a/rl4co/envs/scheduling/fjsp/env.py b/rl4co/envs/scheduling/fjsp/env.py index dac1c8b6..dcf62608 100644 --- a/rl4co/envs/scheduling/fjsp/env.py +++ b/rl4co/envs/scheduling/fjsp/env.py @@ -79,14 +79,32 @@ def __init__( else: generator = FJSPGenerator(**generator_params) self.generator = generator - self.num_mas = generator.num_mas - self.num_jobs = generator.num_jobs - self.n_ops_max = generator.max_ops_per_job * self.num_jobs + self._num_mas = generator.num_mas + self._num_jobs = generator.num_jobs + self._n_ops_max = generator.max_ops_per_job * self.num_jobs + self.mask_no_ops = mask_no_ops self.check_mask = check_mask self.stepwise_reward = stepwise_reward self._make_spec(self.generator) + @property + def num_mas(self): + return self._num_mas + + @property + def num_jobs(self): + return self._num_jobs + + @property + def n_ops_max(self): + return self._n_ops_max + + def set_instance_params(self, td): + self._num_jobs = td["start_op_per_job"].size(1) + self._num_mas = td["proc_times"].size(1) + self._n_ops_max = td["proc_times"].size(2) + def _decode_graph_structure(self, td: TensorDict): batch_size = td.batch_size start_op_per_job = td["start_op_per_job"] @@ -142,6 +160,8 @@ def _decode_graph_structure(self, td: TensorDict): return td, n_ops_max def _reset(self, td: TensorDict = None, batch_size=None) -> TensorDict: + self.set_instance_params(td) + td_reset = td.clone() td_reset, n_ops_max = self._decode_graph_structure(td_reset) @@ -333,10 +353,10 @@ def _make_step(self, td: TensorDict) -> TensorDict: td["ops_sequence_order"] - gather_by_index(td["job_ops_adj"], selected_job, 1) ).clip(0) # some checks - assert torch.allclose( - td["proc_times"].sum(1).gt(0).sum(1), # num ops with eligible machine - (~(td["op_scheduled"] + td["pad_mask"])).sum(1), # num unscheduled ops - ) + # assert torch.allclose( + # td["proc_times"].sum(1).gt(0).sum(1), # num ops with eligible machine + # (~(td["op_scheduled"] + td["pad_mask"])).sum(1), # num unscheduled ops + # ) return td @@ -483,7 +503,6 @@ def get_num_starts(self, td): # NOTE in the paper they use N_s = 100 return 100 - @staticmethod - def load_data(fpath, batch_size=[]): + def load_data(self, fpath, batch_size=[]): g = FJSPFileGenerator(fpath) return g(batch_size=batch_size) diff --git a/rl4co/envs/scheduling/fjsp/generator.py b/rl4co/envs/scheduling/fjsp/generator.py index 60246a50..8d2f427f 100644 --- a/rl4co/envs/scheduling/fjsp/generator.py +++ b/rl4co/envs/scheduling/fjsp/generator.py @@ -15,7 +15,6 @@ class FJSPGenerator(Generator): - """Data generator for the Flexible Job-Shop Scheduling Problem (FJSP). Args: @@ -45,6 +44,7 @@ def __init__( max_processing_time: int = 20, min_eligible_ma_per_op: int = 1, max_eligible_ma_per_op: int = None, + same_mean_per_op: bool = True, **unused_kwargs, ): self.num_jobs = num_jobs @@ -58,7 +58,7 @@ def __init__( # determines whether to use a fixed number of total operations or let it vary between instances # NOTE: due to the way rl4co builds datasets, we need a fixed size here self.n_ops_max = max_ops_per_job * num_jobs - + self.same_mean_per_op = same_mean_per_op # FFSP environment doen't have any other kwargs if len(unused_kwargs) > 0: log.error(f"Found {len(unused_kwargs)} unused kwargs: {unused_kwargs}") @@ -86,12 +86,33 @@ def _simulate_processing_times( ma_ops_edges = ma_ops_edges_unshuffled.gather(2, idx).transpose(1, 2) # (bs, max_ops, machines) - proc_times = torch.ones((bs, n_ops_max, self.num_mas)) - proc_times = torch.randint( - self.min_processing_time, - self.max_processing_time + 1, - size=(bs, self.num_mas, n_ops_max), - ) + if self.same_mean_per_op: + proc_times = torch.ones((bs, self.num_mas, n_ops_max)) + proc_time_means = torch.randint( + self.min_processing_time, self.max_processing_time, (bs, n_ops_max) + ) + low_bounds = torch.maximum( + torch.full_like(proc_times, self.min_processing_time), + (proc_time_means * (1 - 0.2)).round().unsqueeze(1), + ) + high_bounds = ( + torch.minimum( + torch.full_like(proc_times, self.max_processing_time), + (proc_time_means * (1 + 0.2)).round().unsqueeze(1), + ) + + 1 + ) + proc_times = ( + torch.randint(2**63 - 1, size=proc_times.shape) + % (high_bounds - low_bounds) + + low_bounds + ) + else: + proc_times = torch.randint( + self.min_processing_time, + self.max_processing_time + 1, + size=(bs, self.num_mas, n_ops_max), + ) # remove proc_times for which there is no corresponding ma-ops connection proc_times = proc_times * ma_ops_edges @@ -187,6 +208,8 @@ def __init__(self, file_path: str, n_ops_max: int = None, **unused_kwargs): self.num_mas = num_machines self.num_jobs = num_jobs self.max_ops_per_job = max_ops_per_job + self.n_ops_max = max_ops_per_job * num_jobs + self.start_idx = 0 def _generate(self, batch_size: List[int]) -> TensorDict: diff --git a/rl4co/models/__init__.py b/rl4co/models/__init__.py index 16f27b18..339c3b01 100644 --- a/rl4co/models/__init__.py +++ b/rl4co/models/__init__.py @@ -43,6 +43,7 @@ from rl4co.models.zoo.n2s import N2S, N2SPolicy from rl4co.models.zoo.nargnn import NARGNNPolicy from rl4co.models.zoo.neuopt import NeuOpt, NeuOptPolicy +from rl4co.models.zoo.polynet import PolyNet from rl4co.models.zoo.pomo import POMO from rl4co.models.zoo.ptrnet import PointerNetwork, PointerNetworkPolicy from rl4co.models.zoo.symnco import SymNCO, SymNCOPolicy diff --git a/rl4co/models/nn/attention.py b/rl4co/models/nn/attention.py index 86217270..b65169f0 100644 --- a/rl4co/models/nn/attention.py +++ b/rl4co/models/nn/attention.py @@ -1,3 +1,4 @@ +import itertools import math import warnings @@ -360,9 +361,18 @@ def _project_out(self, out, attn_mask): num_nodes, num_available_nodes = attn_mask.size(-1), attn_mask.sum(-1) # only do this at the "second" step, which is depot -> pomo -> first select if (num_available_nodes >= num_nodes - 1).any(): - self.probs = F.softmax(self.dense_or_moe(out.view(-1, out.size(-1)).mean(dim=0, keepdim=True)), dim=-1) + self.probs = F.softmax( + self.dense_or_moe( + out.view(-1, out.size(-1)).mean(dim=0, keepdim=True) + ), + dim=-1, + ) selected = self.probs.multinomial(1).squeeze(0) - out = self.project_out_moe(out) if selected.item() == 1 else self.project_out(out) + out = ( + self.project_out_moe(out) + if selected.item() == 1 + else self.project_out(out) + ) glimpse = out * self.probs.squeeze(0)[selected] else: glimpse = self.project_out_moe(out) @@ -442,3 +452,86 @@ def forward(self, q, h=None, mask=None): compatibility_s2n = torch.matmul(Q, K.transpose(2, 3)) return compatibility_s2n + + +class PolyNetAttention(PointerAttention): + """Calculate logits given query, key and value and logit key. + This implements a modified version the pointer mechanism of Vinyals et al. (2015) (https://arxiv.org/abs/1506.03134) + as described in Hottung et al. (2024) (https://arxiv.org/abs/2402.14048) PolyNetAttention conditions the attention logits on + a set of k different binary vectors allowing to learn k different solution strategies. + + Note: + With Flash Attention, masking is not supported + + Performs the following: + 1. Apply cross attention to get the heads + 2. Project heads to get glimpse + 3. Apply PolyNet layers + 4. Compute attention score between glimpse and logit key + + Args: + k: Number unique bit vectors used to compute attention score + embed_dim: total dimension of the model + poly_layer_dim: Dimension of the PolyNet layers + num_heads: number of heads + mask_inner: whether to mask inner attention + linear_bias: whether to use bias in linear projection + check_nan: whether to check for NaNs in logits + sdpa_fn: scaled dot product attention function (SDPA) implementation + """ + + def __init__( + self, k: int, embed_dim: int, poly_layer_dim: int, num_heads: int, **kwargs + ): + super(PolyNetAttention, self).__init__(embed_dim, num_heads, **kwargs) + + self.k = k + self.binary_vector_dim = math.ceil(math.log2(k)) + self.binary_vectors = torch.nn.Parameter( + torch.Tensor( + list(itertools.product([0, 1], repeat=self.binary_vector_dim))[:k] + ), + requires_grad=False, + ) + + self.poly_layer_1 = nn.Linear(embed_dim + self.binary_vector_dim, poly_layer_dim) + self.poly_layer_2 = nn.Linear(poly_layer_dim, embed_dim) + + def forward(self, query, key, value, logit_key, attn_mask=None): + """Compute attention logits given query, key, value, logit key and attention mask. + + Args: + query: query tensor of shape [B, ..., L, E] + key: key tensor of shape [B, ..., S, E] + value: value tensor of shape [B, ..., S, E] + logit_key: logit key tensor of shape [B, ..., S, E] + attn_mask: attention mask tensor of shape [B, ..., S]. Note that `True` means that the value _should_ take part in attention + as described in the [PyTorch Documentation](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html) + """ + # Compute inner multi-head attention with no projections. + heads = self._inner_mha(query, key, value, attn_mask) + glimpse = self.project_out(heads) + + num_solutions = glimpse.shape[1] + z = self.binary_vectors.repeat(math.ceil(num_solutions / self.k), 1)[ + :num_solutions + ] + z = z[None].expand(glimpse.shape[0], num_solutions, self.binary_vector_dim) + + # PolyNet layers + poly_out = self.poly_layer_1(torch.cat((glimpse, z), dim=2)) + poly_out = F.relu(poly_out) + poly_out = self.poly_layer_2(poly_out) + + glimpse += poly_out + + # Batch matrix multiplication to compute logits (batch_size, num_steps, graph_size) + # bmm is slightly faster than einsum and matmul + logits = (torch.bmm(glimpse, logit_key.squeeze(-2).transpose(-2, -1))).squeeze( + -2 + ) / math.sqrt(glimpse.size(-1)) + + if self.check_nan: + assert not torch.isnan(logits).any(), "Logits contain NaNs" + + return logits diff --git a/rl4co/models/nn/env_embeddings/init.py b/rl4co/models/nn/env_embeddings/init.py index fa3b6fb6..06391cb2 100644 --- a/rl4co/models/nn/env_embeddings/init.py +++ b/rl4co/models/nn/env_embeddings/init.py @@ -407,6 +407,7 @@ def _op_features(self, td): mean_durations = proc_times.sum(1) / (proc_times.gt(0).sum(1) + 1e-9) feats = [ mean_durations / self.scaling_factor, + # td["lbs"] / self.scaling_factor, td["is_ready"], td["num_eligible"], td["ops_job_map"], @@ -430,20 +431,10 @@ def forward(self, td): class FJSPInitEmbedding(JSSPInitEmbedding): def __init__(self, embed_dim, linear_bias=False, scaling_factor: int = 100): - super().__init__(embed_dim, linear_bias, scaling_factor, num_op_feats=5) + super().__init__(embed_dim, linear_bias, scaling_factor) self.init_ma_embed = nn.Linear(1, self.embed_dim, bias=linear_bias) self.edge_embed = nn.Linear(1, embed_dim, bias=linear_bias) - def _op_features(self, td): - feats = [ - td["lbs"] / self.scaling_factor, - td["is_ready"], - td["num_eligible"], - td["op_scheduled"], - td["ops_job_map"], - ] - return torch.stack(feats, dim=-1) - def forward(self, td: TensorDict): ops_emb = self._init_ops_embed(td) ma_emb = self._init_machine_embed(td) @@ -471,19 +462,9 @@ def __init__( linear_bias: bool = False, scaling_factor: int = 1000, ): - super().__init__(embed_dim, linear_bias, scaling_factor, num_op_feats=5) + super().__init__(embed_dim, linear_bias, scaling_factor) self.init_ma_embed = nn.Linear(1, self.embed_dim, bias=linear_bias) - def _op_features(self, td): - feats = [ - td["lbs"] / self.scaling_factor, - td["is_ready"], - td["op_scheduled"], - td["num_eligible"], - td["ops_job_map"], - ] - return torch.stack(feats, dim=-1) - def _init_machine_embed(self, td: TensorDict): busy_for = (td["busy_until"] - td["time"].unsqueeze(1)) / self.scaling_factor ma_embeddings = self.init_ma_embed(busy_for.unsqueeze(2)) diff --git a/rl4co/models/rl/common/utils.py b/rl4co/models/rl/common/utils.py index b23149f7..6c16976a 100644 --- a/rl4co/models/rl/common/utils.py +++ b/rl4co/models/rl/common/utils.py @@ -20,6 +20,8 @@ def __init__(self, scale: str = None): def __call__(self, scores: torch.Tensor): if self.scale is None: return scores + elif isinstance(self.scale, int): + return scores / self.scale # Score scaling self.update(scores) tensor_to_kwargs = dict(dtype=scores.dtype, device=scores.device) diff --git a/rl4co/models/rl/ppo/__init__.py b/rl4co/models/rl/ppo/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rl4co/models/rl/ppo/ppo.py b/rl4co/models/rl/ppo/ppo.py index f8078036..7837b1e7 100644 --- a/rl4co/models/rl/ppo/ppo.py +++ b/rl4co/models/rl/ppo/ppo.py @@ -32,22 +32,22 @@ class PPO(RL4COLitModule): The commonly implemented definition of policy entropy is the entropy of the policy distribution, given by: - .. math:: H(\\pi(x_t)) = - \\sum_{a_t \\in A_t} \\pi(a_t|x_t) \\log \\pi(a_t|x_t) + $$H(\\pi(x_t)) = - \\sum_{a_t \\in A_t} \\pi(a_t|x_t) \\log \\pi(a_t|x_t)$$ - where :math:`x_t` represents the given state at step :math:`t`, :math:`A_t` is the set of all (admisible) actions - at step :math:`t`, and :math:`a_t` is the action taken at step :math:`t`. + where $x_t$ represents the given state at step $t$, $A_t$ is the set of all (admisible) actions + at step $t$, and $a_t$ is the action taken at step $t$. If we interpret autoregressive decoding steps as transition steps of an MDP, the entropy for the entire decoding process can be defined as the sum of entropies for each decoding step: - .. math:: H(\\pi) = \\sum_t H(\\pi(x_t)) + $$H(\\pi) = \\sum_t H(\\pi(x_t))$$ However, if we consider autoregressive decoding steps as an algorithmic choice, the entropy for the entire decoding process is defined as: - .. math:: H(\\pi) = - \\sum_{a \\in A} \\pi(a|x) \\log \\pi(a|x) + $$H(\\pi) = - \\sum_{a \\in A} \\pi(a|x) \\log \\pi(a|x)$$ - where :math:`x` represents the given CO problem instance, and :math:`A` is the set of all feasible solutions. + where $x$ represents the given CO problem instance, and $A$ is the set of all feasible solutions. Due to the intractability of computing the entropy of the policy distribution over all feasible solutions, we approximate it by computing the entropy over solutions generated by the policy itself. This approximation serves diff --git a/rl4co/models/rl/ppo/stepwise_ppo.py b/rl4co/models/rl/ppo/stepwise_ppo.py index 98186ea1..49d087d0 100644 --- a/rl4co/models/rl/ppo/stepwise_ppo.py +++ b/rl4co/models/rl/ppo/stepwise_ppo.py @@ -1,13 +1,13 @@ import copy -from typing import Any +from typing import Any, Union import torch import torch.nn as nn import torch.nn.functional as F from torchrl.data.replay_buffers import ( - LazyTensorStorage, + LazyMemmapStorage, ListStorage, SamplerWithoutReplacement, TensorDictReplayBuffer, @@ -23,13 +23,17 @@ def make_replay_buffer(buffer_size, batch_size, device="cpu"): if device == "cpu": - storage = LazyTensorStorage(buffer_size, device="cpu") + storage = LazyMemmapStorage(buffer_size, device="cpu") + prefetch = 3 else: storage = ListStorage(buffer_size) + prefetch = None return TensorDictReplayBuffer( storage=storage, batch_size=batch_size, sampler=SamplerWithoutReplacement(drop_last=True), + pin_memory=False, + prefetch=prefetch, ) @@ -51,7 +55,7 @@ def __init__( metrics: dict = { "train": ["loss", "surrogate_loss", "value_loss", "entropy"], }, - reward_scale: str = None, + reward_scale: Union[str, int] = None, **kwargs, ): super().__init__(env, policy, metrics=metrics, batch_size=batch_size, **kwargs) @@ -143,13 +147,12 @@ def shared_step( while not next_td["done"].all(): with torch.no_grad(): td = self.policy_old.act(next_td, self.env, phase="train") - - assert self.env._torchrl_mode, "Use torchrl mode in stepwise PPO" - td = self.env.step(td) - next_td = td.pop("next") + # get next state + next_td = self.env.step(td)["next"] + # get reward of action reward = self.env.get_reward(next_td, None) reward = self.scaler(reward) - + # add reward to prior state td.set("reward", reward) # add tensordict with action, logprobs and reward information to buffer self.rb.extend(td) diff --git a/rl4co/models/zoo/__init__.py b/rl4co/models/zoo/__init__.py index ba4345f3..7fbb41eb 100644 --- a/rl4co/models/zoo/__init__.py +++ b/rl4co/models/zoo/__init__.py @@ -24,6 +24,7 @@ from rl4co.models.zoo.n2s import N2S, N2SPolicy from rl4co.models.zoo.nargnn import NARGNNPolicy from rl4co.models.zoo.neuopt import NeuOpt, NeuOptPolicy +from rl4co.models.zoo.polynet import PolyNet from rl4co.models.zoo.pomo import POMO from rl4co.models.zoo.ptrnet import PointerNetwork, PointerNetworkPolicy from rl4co.models.zoo.symnco import SymNCO, SymNCOPolicy diff --git a/rl4co/models/zoo/deepaco/antsystem.py b/rl4co/models/zoo/deepaco/antsystem.py index d08df652..1965cd3d 100644 --- a/rl4co/models/zoo/deepaco/antsystem.py +++ b/rl4co/models/zoo/deepaco/antsystem.py @@ -273,7 +273,7 @@ def _update_pheromone(self, actions, reward): self.pheromone += delta_pheromone def _reward_map(self, x: Tensor): - """Map reward :math:`f: \\mathbb{R} \\rightarrow \\mathbb{R}^+`""" + """Map reward $f: \\mathbb{R} \\rightarrow \\mathbb{R}^+$""" M, _ = x.max(-1, keepdim=True) m, _ = x.min(-1, keepdim=True) v = ((x - m) / (M - m)) ** 2 * self.Q diff --git a/rl4co/models/zoo/l2d/decoder.py b/rl4co/models/zoo/l2d/decoder.py index b0ab3041..833e9c6e 100644 --- a/rl4co/models/zoo/l2d/decoder.py +++ b/rl4co/models/zoo/l2d/decoder.py @@ -178,7 +178,6 @@ def __init__( actor_hidden_dim: int = 128, actor_hidden_layers: int = 2, num_encoder_layers: int = 3, - num_heads: int = 8, normalization: str = "batch", het_emb: bool = False, stepwise: bool = False, diff --git a/rl4co/models/zoo/l2d/policy.py b/rl4co/models/zoo/l2d/policy.py index b4b9b11c..0cfac356 100644 --- a/rl4co/models/zoo/l2d/policy.py +++ b/rl4co/models/zoo/l2d/policy.py @@ -35,6 +35,7 @@ def __init__( env_name: str = "fjsp", het_emb: bool = True, scaling_factor: int = 1000, + normalization: str = "batch", init_embedding: Optional[nn.Module] = None, stepwise_encoding: bool = False, tanh_clipping: float = 10, @@ -77,6 +78,7 @@ def __init__( het_emb=het_emb, stepwise=stepwise_encoding, scaling_factor=scaling_factor, + normalization=normalization, ) # Pass to constructive policy @@ -101,6 +103,7 @@ def __init__( num_heads: int = 8, num_encoder_layers: int = 4, scaling_factor: int = 1000, + normalization: str = "batch", env_name: str = "fjsp", init_embedding: Optional[nn.Module] = None, tanh_clipping: float = 10, @@ -122,7 +125,7 @@ def __init__( embed_dim=embed_dim, num_heads=num_heads, num_layers=num_encoder_layers, - normalization="batch", + normalization=normalization, feedforward_hidden=embed_dim * 2, init_embedding=init_embedding, ) diff --git a/rl4co/models/zoo/matnet/decoder.py b/rl4co/models/zoo/matnet/decoder.py index ad8aef77..5a8d6e28 100644 --- a/rl4co/models/zoo/matnet/decoder.py +++ b/rl4co/models/zoo/matnet/decoder.py @@ -9,7 +9,8 @@ from rl4co.models.nn.env_embeddings.context import FFSPContext from rl4co.models.zoo.am.decoder import AttentionModelDecoder -from rl4co.utils.decoding import process_logits +from rl4co.utils.decoding import decode_logprobs, process_logits +from rl4co.utils.ops import gather_by_index @dataclass @@ -53,6 +54,8 @@ def __init__( self, embed_dim: int, num_heads: int, + linear_bias: bool = False, + out_bias_pointer_attn: bool = True, use_graph_context: bool = False, **kwargs, ): @@ -62,8 +65,10 @@ def __init__( env_name="ffsp", embed_dim=embed_dim, num_heads=num_heads, - use_graph_context=use_graph_context, context_embedding=context_embedding, + out_bias_pointer_attn=out_bias_pointer_attn, + linear_bias=linear_bias, + use_graph_context=use_graph_context, **kwargs, ) @@ -116,6 +121,7 @@ def __init__( embed_dim: int, num_heads: int, use_graph_context: bool = True, + tanh_clipping: float = 10, **kwargs, ): super().__init__( @@ -125,7 +131,7 @@ def __init__( **kwargs, ) self.cached_embs: PrecomputedCache = None - # self.encoded_wait_op = nn.Parameter(torch.rand((1, 1, embed_dim))) + self.tanh_clipping = tanh_clipping def _precompute_cache(self, embeddings: Tuple[Tensor], **kwargs): self.cached_embs = super()._precompute_cache(embeddings, **kwargs) @@ -137,38 +143,15 @@ def forward( num_starts: int = 1, **decoding_kwargs, ) -> Tuple[Tensor, Tensor, TensorDict]: - device = td.device - batch_size = td.size(0) - # TODO: we need to insert precompute cache inside the decoder logits, mask = super().forward(td, self.cached_embs, num_starts) logprobs = process_logits( logits, mask, + tanh_clipping=self.tanh_clipping, **decoding_kwargs, ) - all_job_probs = logprobs.exp() - - if "sampling" in decode_type: - # to fix pytorch.multinomial bug on selecting 0 probability elements - while True: - job_selected = all_job_probs.multinomial(1).squeeze(dim=1) - # shape: (batch) - job_prob = all_job_probs.gather(1, job_selected[:, None]).squeeze(dim=1) - # shape: (batch) - assert (job_prob[td["done"].squeeze()] == 1).all() - - if (job_prob != 0).all(): - break - - elif "greedy" in decode_type: - job_selected = all_job_probs.argmax(dim=1) - # shape: (batch) - job_prob = torch.zeros( - size=(batch_size,), device=device - ) # any number is okay - - else: - raise ValueError(f"decode type {decode_type} not understood") + job_selected = decode_logprobs(logprobs, mask, decode_type) + job_prob = gather_by_index(logprobs, job_selected, dim=1) return job_selected, job_prob diff --git a/rl4co/models/zoo/matnet/encoder.py b/rl4co/models/zoo/matnet/encoder.py index 3ad52309..0af88e23 100644 --- a/rl4co/models/zoo/matnet/encoder.py +++ b/rl4co/models/zoo/matnet/encoder.py @@ -6,7 +6,7 @@ from rl4co.models.nn.attention import MultiHeadCrossAttention from rl4co.models.nn.env_embeddings import env_init_embedding -from rl4co.models.nn.ops import Normalization +from rl4co.models.nn.ops import TransformerFFN class MixedScoresSDPA(nn.Module): @@ -47,14 +47,15 @@ def forward(self, q, k, v, attn_mask=None, dmat=None, dropout_p=0.0): # Calculate scaled dot product attn_scores = torch.matmul(q, k.transpose(-2, -1)) / (k.size(-1) ** 0.5) + # [b, h, m, n, num_scores+1] mix_attn_scores = torch.cat( [ attn_scores.unsqueeze(-1), dmat[:, None, ...].expand(b, self.num_heads, m, n, self.num_scores), ], dim=-1, - ) # [b, h, m, n, num_scores+1] - + ) + # [b, h, m, n] attn_scores = ( ( torch.matmul( @@ -68,7 +69,7 @@ def forward(self, q, k, v, attn_mask=None, dmat=None, dropout_p=0.0): ) .transpose(1, 2) .squeeze(-1) - ) # [b, h, m, n] + ) # Apply the provided attention mask if attn_mask is not None: @@ -141,7 +142,7 @@ def forward(self, row_emb, col_emb, dmat, attn_mask=None): return updated_row_emb, updated_col_emb -class MatNetMHALayer(nn.Module): +class MatNetLayer(nn.Module): def __init__( self, embed_dim: int, @@ -152,30 +153,8 @@ def __init__( ): super().__init__() self.MHA = MatNetMHA(embed_dim, num_heads, bias) - - self.F_a = nn.ModuleDict( - { - "norm1": Normalization(embed_dim, normalization), - "ffn": nn.Sequential( - nn.Linear(embed_dim, feedforward_hidden), - nn.ReLU(), - nn.Linear(feedforward_hidden, embed_dim), - ), - "norm2": Normalization(embed_dim, normalization), - } - ) - - self.F_b = nn.ModuleDict( - { - "norm1": Normalization(embed_dim, normalization), - "ffn": nn.Sequential( - nn.Linear(embed_dim, feedforward_hidden), - nn.ReLU(), - nn.Linear(feedforward_hidden, embed_dim), - ), - "norm2": Normalization(embed_dim, normalization), - } - ) + self.F_a = TransformerFFN(embed_dim, feedforward_hidden, normalization) + self.F_b = TransformerFFN(embed_dim, feedforward_hidden, normalization) def forward(self, row_emb, col_emb, dmat, attn_mask=None): """ @@ -190,63 +169,18 @@ def forward(self, row_emb, col_emb, dmat, attn_mask=None): """ row_emb_out, col_emb_out = self.MHA(row_emb, col_emb, dmat, attn_mask) - - row_emb_out = self.F_a["norm1"](row_emb + row_emb_out) - row_emb_out = self.F_a["norm2"](row_emb_out + self.F_a["ffn"](row_emb_out)) - - col_emb_out = self.F_b["norm1"](col_emb + col_emb_out) - col_emb_out = self.F_b["norm2"](col_emb_out + self.F_b["ffn"](col_emb_out)) + row_emb_out = self.F_a(row_emb_out, row_emb) + col_emb_out = self.F_b(col_emb_out, col_emb) return row_emb_out, col_emb_out -class MatNetMHANetwork(nn.Module): - def __init__( - self, - embed_dim: int = 128, - num_heads: int = 8, - num_layers: int = 3, - normalization: str = "batch", - feedforward_hidden: int = 512, - bias: bool = False, - ): - super().__init__() - self.layers = nn.ModuleList( - [ - MatNetMHALayer( - num_heads=num_heads, - embed_dim=embed_dim, - feedforward_hidden=feedforward_hidden, - normalization=normalization, - bias=bias, - ) - for _ in range(num_layers) - ] - ) - - def forward(self, row_emb, col_emb, dmat, attn_mask=None): - """ - Args: - row_emb (Tensor): [b, m, d] - col_emb (Tensor): [b, n, d] - dmat (Tensor): [b, m, n] - - Returns: - Updated row_emb (Tensor): [b, m, d] - Updated col_emb (Tensor): [b, n, d] - """ - - for layer in self.layers: - row_emb, col_emb = layer(row_emb, col_emb, dmat, attn_mask) - return row_emb, col_emb - - class MatNetEncoder(nn.Module): def __init__( self, embed_dim: int = 256, num_heads: int = 16, - num_layers: int = 5, - normalization: str = "instance", + num_layers: int = 3, + normalization: str = "batch", feedforward_hidden: int = 512, init_embedding: nn.Module = None, init_embedding_kwargs: dict = {}, @@ -261,15 +195,19 @@ def __init__( ) self.init_embedding = init_embedding - self.net = MatNetMHANetwork( - embed_dim=embed_dim, - num_heads=num_heads, - num_layers=num_layers, - normalization=normalization, - feedforward_hidden=feedforward_hidden, - bias=bias, - ) self.mask_non_neighbors = mask_non_neighbors + self.layers = nn.ModuleList( + [ + MatNetLayer( + embed_dim=embed_dim, + num_heads=num_heads, + bias=bias, + feedforward_hidden=feedforward_hidden, + normalization=normalization, + ) + for _ in range(num_layers) + ] + ) def forward(self, td, attn_mask: torch.Tensor = None): row_emb, col_emb, dmat = self.init_embedding(td) @@ -278,7 +216,8 @@ def forward(self, td, attn_mask: torch.Tensor = None): # attn_mask (keep 1s discard 0s) to only attend on neighborhood attn_mask = dmat.ne(0) - row_emb, col_emb = self.net(row_emb, col_emb, dmat, attn_mask) + for layer in self.layers: + row_emb, col_emb = layer(row_emb, col_emb, dmat, attn_mask) embedding = (row_emb, col_emb) init_embedding = None diff --git a/rl4co/models/zoo/matnet/policy.py b/rl4co/models/zoo/matnet/policy.py index 0c2af426..4e3ea980 100644 --- a/rl4co/models/zoo/matnet/policy.py +++ b/rl4co/models/zoo/matnet/policy.py @@ -96,15 +96,15 @@ class MultiStageFFSPPolicy(nn.Module): def __init__( self, stage_cnt: int, - embed_dim: int = 256, + embed_dim: int = 512, num_heads: int = 16, - num_encoder_layers: int = 3, + num_encoder_layers: int = 5, use_graph_context: bool = False, normalization: str = "instance", feedforward_hidden: int = 512, bias: bool = False, train_decode_type: str = "sampling", - val_decode_type: str = "sampling", # authors report better results for sampling + val_decode_type: str = "sampling", test_decode_type: str = "sampling", ): super().__init__() @@ -136,8 +136,9 @@ def __init__( self.test_decode_type = test_decode_type def pre_forward(self, td: TensorDict, env: FFSPEnv, num_starts: int): + run_time_list = td["run_time"].chunk(env.num_stage, dim=-1) for stage_idx in range(self.stage_cnt): - td["cost_matrix"] = td["run_time"][:, :, :, stage_idx] + td["cost_matrix"] = run_time_list[stage_idx] encoder = self.encoders[stage_idx] embeddings, _ = encoder(td) decoder = self.decoders[stage_idx] @@ -171,36 +172,36 @@ def forward( # NOTE: this must come after pre_forward due to batchify op batch_size = td.size(0) - prob_list = torch.zeros(size=(batch_size, 0), device=device) + logp_list = torch.zeros(size=(batch_size, 0), device=device) action_list = [] while not td["done"].all(): action_stack = torch.empty( size=(batch_size, self.stage_cnt), dtype=torch.long, device=device ) - prob_stack = torch.empty(size=(batch_size, self.stage_cnt), device=device) + logp_stack = torch.empty(size=(batch_size, self.stage_cnt), device=device) for stage_idx in range(self.stage_cnt): decoder = self.decoders[stage_idx] - action, prob = decoder(td, decode_type, num_starts, **decoder_kwargs) + action, logp = decoder(td, decode_type, num_starts, **decoder_kwargs) action_stack[:, stage_idx] = action - prob_stack[:, stage_idx] = prob + logp_stack[:, stage_idx] = logp gathering_index = td["stage_idx"][:, None] # shape: (batch, 1) action = action_stack.gather(dim=1, index=gathering_index).squeeze(dim=1) - prob = prob_stack.gather(dim=1, index=gathering_index).squeeze(dim=1) + logp = logp_stack.gather(dim=1, index=gathering_index).squeeze(dim=1) # shape: (batch) action_list.append(action) # transition td.set("action", action) td = env.step(td)["next"] - prob_list = torch.cat((prob_list, prob[:, None]), dim=1) + logp_list = torch.cat((logp_list, logp[:, None]), dim=1) out = { "reward": td["reward"], - "log_likelihood": prob_list.log().sum(1), + "log_likelihood": logp_list.sum(1), } if return_actions: diff --git a/rl4co/models/zoo/polynet/__init__.py b/rl4co/models/zoo/polynet/__init__.py new file mode 100644 index 00000000..1a908241 --- /dev/null +++ b/rl4co/models/zoo/polynet/__init__.py @@ -0,0 +1 @@ +from .model import PolyNet diff --git a/rl4co/models/zoo/polynet/decoder.py b/rl4co/models/zoo/polynet/decoder.py new file mode 100644 index 00000000..7a28fa1a --- /dev/null +++ b/rl4co/models/zoo/polynet/decoder.py @@ -0,0 +1,145 @@ +from dataclasses import dataclass +from typing import Tuple, Union + +import torch.nn as nn + +from torch import Tensor + +from rl4co.envs import RL4COEnvBase +from rl4co.models.nn.attention import PolyNetAttention +from rl4co.models.nn.env_embeddings import env_context_embedding, env_dynamic_embedding +from rl4co.models.nn.env_embeddings.dynamic import StaticEmbedding +from rl4co.models.zoo.am.decoder import AttentionModelDecoder +from rl4co.utils.pylogger import get_pylogger + +log = get_pylogger(__name__) + + +@dataclass +class PrecomputedCache: + node_embeddings: Tensor + graph_context: Union[Tensor, float] + glimpse_key: Tensor + glimpse_val: Tensor + logit_key: Tensor + + +class PolyNetDecoder(AttentionModelDecoder): + """ + PolyNet decoder for constructing diverse solutions for combinatorial optimization problems. + Given the environment state and the embeddings, compute the logits and sample actions autoregressively until + all the environments in the batch have reached a terminal state. + We additionally include support for multi-starts as it is more efficient to do so in the decoder as we can + natively perform the attention computation. + + Args: + k: Number of strategies to learn ("K" in the PolyNet paper) + encoder_type: Type of encoder that should be used. "AM" or "MatNet" are supported + embed_dim: Embedding dimension + poly_layer_dim: Dimension of the PolyNet layers + num_heads: Number of attention heads + env_name: Name of the environment used to initialize embeddings + context_embedding: Context embedding module + dynamic_embedding: Dynamic embedding module + mask_inner: Whether to mask the inner loop + out_bias_pointer_attn: Whether to use a bias in the pointer attention + linear_bias: Whether to use a bias in the linear layer + use_graph_context: Whether to use the graph context + check_nan: Whether to check for nan values during decoding + sdpa_fn: scaled_dot_product_attention function + """ + + def __init__( + self, + k: int, + encoder_type: str, + embed_dim: int = 128, + poly_layer_dim: int = 256, + num_heads: int = 8, + env_name: Union[str, RL4COEnvBase] = "tsp", + context_embedding: nn.Module = None, + dynamic_embedding: nn.Module = None, + mask_inner: bool = True, + out_bias_pointer_attn: bool = False, + linear_bias: bool = False, + use_graph_context: bool = True, + check_nan: bool = True, + sdpa_fn: callable = None, + **unused_kwargs, + ): + super().__init__() + + if isinstance(env_name, RL4COEnvBase): + env_name = env_name.name + self.env_name = env_name + self.embed_dim = embed_dim + self.num_heads = num_heads + self.encoder_type = encoder_type + + assert embed_dim % num_heads == 0 + + self.context_embedding = ( + env_context_embedding(self.env_name, {"embed_dim": embed_dim}) + if context_embedding is None + else context_embedding + ) + self.dynamic_embedding = ( + env_dynamic_embedding(self.env_name, {"embed_dim": embed_dim}) + if dynamic_embedding is None + else dynamic_embedding + ) + self.is_dynamic_embedding = ( + False if isinstance(self.dynamic_embedding, StaticEmbedding) else True + ) + + # MHA with Pointer mechanism (https://arxiv.org/abs/1506.03134) + self.pointer = PolyNetAttention( + k, + embed_dim, + poly_layer_dim, + num_heads, + mask_inner=mask_inner, + out_bias=out_bias_pointer_attn, + check_nan=check_nan, + sdpa_fn=sdpa_fn, + ) + + # For each node we compute (glimpse key, glimpse value, logit key) so 3 * embed_dim + self.project_node_embeddings = nn.Linear( + embed_dim, 3 * embed_dim, bias=linear_bias + ) + self.project_fixed_context = nn.Linear(embed_dim, embed_dim, bias=linear_bias) + self.use_graph_context = use_graph_context + + def _precompute_cache_matnet( + self, embeddings: Tuple[Tensor, Tensor], *args, **kwargs + ): + col_emb, row_emb = embeddings + ( + glimpse_key_fixed, + glimpse_val_fixed, + logit_key, + ) = self.project_node_embeddings( + col_emb + ).chunk(3, dim=-1) + + # Optionally disable the graph context from the initial embedding as done in POMO + if self.use_graph_context: + graph_context = self.project_fixed_context(col_emb.mean(1)) + else: + graph_context = 0 + + # Organize in a dataclass for easy access + return PrecomputedCache( + node_embeddings=row_emb, + graph_context=graph_context, + glimpse_key=glimpse_key_fixed, + glimpse_val=glimpse_val_fixed, + logit_key=logit_key, + ) + + def _precompute_cache(self, embeddings: Tuple[Tensor, Tensor], *args, **kwargs): + if self.encoder_type == "AM": + return super()._precompute_cache(embeddings, *args, **kwargs) + elif self.encoder_type == "MatNet": + return self._precompute_cache_matnet(embeddings, *args, **kwargs) diff --git a/rl4co/models/zoo/polynet/model.py b/rl4co/models/zoo/polynet/model.py new file mode 100644 index 00000000..a1271da8 --- /dev/null +++ b/rl4co/models/zoo/polynet/model.py @@ -0,0 +1,241 @@ +import logging + +from typing import Any, Optional, Union + +import torch + +from tensordict import TensorDict + +from rl4co.data.transforms import StateAugmentation +from rl4co.envs.common.base import RL4COEnvBase +from rl4co.models.rl.reinforce.reinforce import REINFORCE +from rl4co.models.zoo.polynet.policy import PolyNetPolicy +from rl4co.utils.ops import gather_by_index, unbatchify +from rl4co.utils.pylogger import get_pylogger + +log = get_pylogger(__name__) + + +class PolyNet(REINFORCE): + """PolyNet + Based on Hottung et al. (2024) https://arxiv.org/abs/2402.14048. + + Note: + PolyNet allows to learn diverse solution stratgies with a single model. This is achieved + through a modified decoder and the Poppy loss (Grinsztajn et al. (2021)). PolyNet can be used with the attention model encoder or the MatNet encoder by + setting encoder_type to "AM" or "MatNet", respectively. + + Args: + env: TorchRL Environment + policy: Policy to use for the algorithm + k: Number of strategies to learn ("K" in the paper) + val_num_solutions: Number of solutions that are generated per instance during validation + encoder_type: Type of encoder that should be used. "AM" or "MatNet" are supported + policy_kwargs: Keyword arguments for policy + baseline: Baseline to use for the algorithm. Note that PolyNet only supports shared baseline, + so we will throw an error if anything else is passed. + num_augment: Number of augmentations (used only for validation and test) + augment_fn: Function to use for augmentation, defaulting to dihedral8 + first_aug_identity: Whether to include the identity augmentation in the first position + feats: List of features to augment + **kwargs: Keyword arguments passed to the superclass + """ + + def __init__( + self, + env: RL4COEnvBase, + policy: PolyNetPolicy = None, + k: int = 128, + val_num_solutions: int = 800, + encoder_type="AM", + base_model_checkpoint_path: str = None, + policy_kwargs={}, + baseline: str = "shared", + num_augment: int = 8, + augment_fn: Union[str, callable] = "dihedral8", + first_aug_identity: bool = True, + feats: list = None, + **kwargs, + ): + self.save_hyperparameters(logger=False) + + self.k = k + self.val_num_solutions = val_num_solutions + + assert encoder_type in [ + "AM", + "MatNet", + ], "Supported encoder types are 'AM' and 'MatNet'" + + assert baseline == "shared", "PolyNet only supports shared baseline" + + if ( + policy_kwargs.get("val_decode_type") == "greedy" + or policy_kwargs.get("test_decode_type") == "greedy" + ): + assert ( + val_num_solutions <= k + ), "If greedy decoding is used val_num_solutions must be <= k" + + if encoder_type == "MatNet": + assert ( + num_augment == 1 + ), "MatNet does not use symmetric or dihedral augmentation" + + if policy is None: + policy = PolyNetPolicy( + env_name=env.name, k=k, encoder_type=encoder_type, **policy_kwargs + ) + + if base_model_checkpoint_path is not None: + logging.info( + f"Trying to load weights from baseline model {base_model_checkpoint_path}" + ) + checkpoint = torch.load(base_model_checkpoint_path) + state_dict = checkpoint["state_dict"] + state_dict = {k.replace("policy.", "", 1): v for k, v in state_dict.items()} + policy.load_state_dict(state_dict, strict=False) + + train_batch_size = kwargs["batch_size"] if "batch_size" in kwargs else 64 + kwargs_with_defaults = { + "val_batch_size": train_batch_size, + "test_batch_size": train_batch_size, + } + kwargs_with_defaults.update(kwargs) + + # Initialize with the shared baseline + super(PolyNet, self).__init__(env, policy, baseline, **kwargs_with_defaults) + + self.num_augment = num_augment + if self.num_augment > 1: + self.augment = StateAugmentation( + num_augment=self.num_augment, + augment_fn=augment_fn, + first_aug_identity=first_aug_identity, + feats=feats, + ) + else: + self.augment = None + + # Add `_multistart` to decode type for train, val and test in policy + # for phase in ["train", "val", "test"]: + # self.set_decode_type_multistart(phase) + + def shared_step( + self, batch: Any, batch_idx: int, phase: str, dataloader_idx: int = None + ): + td = self.env.reset(batch) + n_aug = self.num_augment + + # During training, we do not augment the data + if phase == "train": + n_aug = 0 + elif n_aug > 1: + td = self.augment(td) + + if phase == "train": + n_start = self.k + else: + n_start = self.val_num_solutions + + # Evaluate policy + out = self.policy( + td, + self.env, + phase=phase, + num_starts=n_start, + multisample=True, + return_actions=True, + ) + + # Unbatchify reward to [batch_size, num_augment, num_starts]. + reward = unbatchify(out["reward"], (n_aug, n_start)) + + # Training phase + if phase == "train": + assert n_start > 1, "num_starts must be > 1 during training" + log_likelihood = unbatchify(out["log_likelihood"], (n_aug, n_start)) + self.calculate_loss(td, batch, out, reward, log_likelihood) + max_reward, max_idxs = reward.max(dim=-1) + out.update({"max_reward": max_reward}) + # Get multi-start (=POMO) rewards and best actions only during validation and test + else: + if n_start > 1: + # max multi-start reward + max_reward, max_idxs = reward.max(dim=-1) + out.update({"max_reward": max_reward}) + + if out.get("actions", None) is not None: + # Reshape batch to [batch_size, num_augment, num_starts, ...] + actions = unbatchify(out["actions"], (n_aug, n_start)) + out.update( + { + "best_multistart_actions": gather_by_index( + actions, max_idxs.unsqueeze(2), dim=2 + ) + } + ) + out["actions"] = actions + + # Get augmentation score only during inference + if n_aug > 1: + # If multistart is enabled, we use the best multistart rewards + reward_ = max_reward if n_start > 1 else reward + max_aug_reward, max_idxs = reward_.max(dim=1) + out.update({"max_aug_reward": max_aug_reward}) + + if out.get("actions", None) is not None: + actions_ = ( + out["best_multistart_actions"] if n_start > 1 else out["actions"] + ) + out.update({"best_aug_actions": gather_by_index(actions_, max_idxs)}) + + metrics = self.log_metrics(out, phase, dataloader_idx=dataloader_idx) + return {"loss": out.get("loss", None), **metrics} + + def calculate_loss( + self, + td: TensorDict, + batch: TensorDict, + policy_out: dict, + reward: Optional[torch.Tensor] = None, + log_likelihood: Optional[torch.Tensor] = None, + ): + """Calculate loss following Poppy (https://arxiv.org/abs/2210.03475). + + Args: + td: TensorDict containing the current state of the environment + batch: Batch of data. This is used to get the extra loss terms, e.g., REINFORCE baseline + policy_out: Output of the policy network + reward: Reward tensor. If None, it is taken from `policy_out` + log_likelihood: Log-likelihood tensor. If None, it is taken from `policy_out` + """ + # Extra: this is used for additional loss terms, e.g., REINFORCE baseline + extra = batch.get("extra", None) + reward = reward if reward is not None else policy_out["reward"] + log_likelihood = ( + log_likelihood if log_likelihood is not None else policy_out["log_likelihood"] + ) + + # REINFORCE baseline + bl_val, bl_loss = ( + self.baseline.eval(td, reward, self.env) if extra is None else (extra, 0) + ) + + # Log-likelihood mask. Mask everything but the best rollout per instance + best_idx = (-reward).argsort(1).argsort(1) + mask = best_idx < 1 + + # Main loss function + advantage = reward - bl_val # advantage = reward - baseline + reinforce_loss = -(advantage * log_likelihood * mask).mean() + loss = reinforce_loss + bl_loss + policy_out.update( + { + "loss": loss, + "reinforce_loss": reinforce_loss, + "bl_loss": bl_loss, + "bl_val": bl_val, + } + ) + return policy_out diff --git a/rl4co/models/zoo/polynet/policy.py b/rl4co/models/zoo/polynet/policy.py new file mode 100644 index 00000000..d2128a6f --- /dev/null +++ b/rl4co/models/zoo/polynet/policy.py @@ -0,0 +1,101 @@ +from typing import Union + +import torch.nn as nn + +from rl4co.envs import RL4COEnvBase +from rl4co.models.common.constructive.autoregressive.policy import AutoregressivePolicy +from rl4co.models.zoo.am.encoder import AttentionModelEncoder +from rl4co.models.zoo.matnet.encoder import MatNetEncoder +from rl4co.models.zoo.polynet.decoder import PolyNetDecoder + + +class PolyNetPolicy(AutoregressivePolicy): + """ + # TODO + Polynet policy based on Hottung et al. (2024) https://arxiv.org/abs/2402.14048. + The model uses either the AttentionModel encoder or the MatNet encoder in combination with + a custom PolyNet decoder. + + Note: The default arguments for the AttentionModel encoder follow the POMO paper. The default decoding type + during validation and testing is 'sampling'. + + Args: + k: Number of strategies to learn ("K" in the paper) + encoder_type: Type of encoder that should be used. "AM" or "MatNet" are supported. + embed_dim: Dimension of the node embeddings + num_encoder_layers: Number of layers in the encoder + num_heads: Number of heads in the attention layers + normalization: Normalization type in the attention layers + feedforward_hidden: Dimension of the hidden layer in the feedforward network + env_name: Name of the environment used to initialize embeddings + temperature: Temperature for the softmax + tanh_clipping: Tanh clipping value (see Bello et al., 2016) + mask_logits: Whether to mask the logits during decoding + train_decode_type: Type of decoding to use during training + val_decode_type: Type of decoding to use during validation + test_decode_type: Type of decoding to use during testing + **kwargs: keyword arguments passed to the encoder and decoder modules + """ + + def __init__( + self, + k: int, + encoder: nn.Module = None, + encoder_type: str = "AM", + embed_dim: int = 128, + num_encoder_layers: int = 6, + num_heads: int = 8, + normalization: str = "instance", + feedforward_hidden: int = 512, + env_name: Union[str, RL4COEnvBase] = "tsp", + temperature: float = 1.0, + tanh_clipping: float = 10.0, + mask_logits: bool = True, + train_decode_type: str = "sampling", + val_decode_type: str = "sampling", + test_decode_type: str = "sampling", + **kwargs, + ): + if encoder is None: + if encoder_type == "AM": + encoder = AttentionModelEncoder( + embed_dim=embed_dim, + num_heads=num_heads, + num_layers=num_encoder_layers, + env_name=env_name, + normalization=normalization, + feedforward_hidden=feedforward_hidden, + **kwargs, + ) + elif encoder_type == "MatNet": + kwargs_with_defaults = {"init_embedding_kwargs": {"mode": "RandomOneHot"}} + kwargs_with_defaults.update(kwargs) + encoder = MatNetEncoder( + embed_dim=embed_dim, + num_heads=num_heads, + num_layers=num_encoder_layers, + normalization=normalization, + **kwargs_with_defaults, + ) + + decoder = PolyNetDecoder( + k=k, + encoder_type=encoder_type, + embed_dim=embed_dim, + num_heads=num_heads, + env_name=env_name, + **kwargs, + ) + + super(PolyNetPolicy, self).__init__( + encoder=encoder, + decoder=decoder, + env_name=env_name, + temperature=temperature, + tanh_clipping=tanh_clipping, + mask_logits=mask_logits, + train_decode_type=train_decode_type, + val_decode_type=val_decode_type, + test_decode_type=test_decode_type, + **kwargs, + ) diff --git a/rl4co/tasks/eval.py b/rl4co/tasks/eval.py index 10dda554..7580d374 100644 --- a/rl4co/tasks/eval.py +++ b/rl4co/tasks/eval.py @@ -51,17 +51,17 @@ def __call__(self, policy, dataloader, **kwargs): actions_list.append(actions) rewards = torch.cat(rewards_list) - + # Padding: pad actions to the same length with zeros - max_length = max(action.size(-1) for action in actions) + max_length = max(action.size(-1) for action in actions_list) actions = torch.cat( [ torch.nn.functional.pad(action, (0, max_length - action.size(-1))) - for action in actions + for action in actions_list ], 0, ) - + inference_time = time.time() - start tqdm.write(f"Mean reward for {self.name}: {rewards.mean():.4f}") diff --git a/rl4co/utils/decoding.py b/rl4co/utils/decoding.py index 35193555..f29e8214 100644 --- a/rl4co/utils/decoding.py +++ b/rl4co/utils/decoding.py @@ -263,7 +263,7 @@ def pre_decoder_hook( self, td: TensorDict, env: RL4COEnvBase, action: torch.Tensor = None ): """Pre decoding hook. This method is called before the main decoding operation.""" - + # Multi-start decoding. If num_starts is None, we use the number of actions in the action mask if self.multistart or self.multisample: if self.num_starts is None: diff --git a/rl4co/utils/meta_trainer.py b/rl4co/utils/meta_trainer.py new file mode 100644 index 00000000..ccd64352 --- /dev/null +++ b/rl4co/utils/meta_trainer.py @@ -0,0 +1,170 @@ +import lightning.pytorch as pl +import torch +import math +import copy +from torch.optim import Adam + +from lightning import Callback +from rl4co import utils +import random +log = utils.get_pylogger(__name__) + + +class ReptileCallback(Callback): + + """ Meta training framework for addressing the generalization issue (implement the Reptile algorithm only) + Based on Manchanda et al. 2022 (https://arxiv.org/abs/2206.00787) and Zhou et al. 2023 (https://arxiv.org/abs/2305.19587) + + Args: + - num_tasks: the number of tasks in a mini-batch, i.e. `B` in the original paper + - alpha: initial weight of the task model for the outer-loop optimization of reptile + - alpha_decay: weight decay of the task model for the outer-loop optimization of reptile + - min_size: minimum problem size of the task (only supported in cross-size generalization) + - max_size: maximum problem size of the task (only supported in cross-size generalization) + - sch_bar: for the task scheduler of size setting, where lr_decay_epoch = sch_bar * epochs, i.e. after this epoch, learning rate will decay with a weight 0.1 + - data_type: type of the tasks, chosen from ["size", "distribution", "size_distribution"] + - print_log: whether to print the specific task sampled in each inner-loop optimization + """ + def __init__(self, + num_tasks: int, + alpha: float, + alpha_decay: float, + min_size: int, + max_size: int, + sch_bar: float = 0.9, + data_type: str = "size", + print_log: bool =True): + + super().__init__() + + self.num_tasks = num_tasks + self.alpha = alpha + self.alpha_decay = alpha_decay + self.sch_bar = sch_bar + self.print_log = print_log + self.data_type = data_type + self.task_set = self._generate_task_set(data_type, min_size, max_size) + + def on_fit_start(self, trainer: pl.Trainer, pl_module: pl.LightningModule) -> None: + + # Sample a batch of tasks + self._sample_task() + + # Pre-set the distribution + if self.data_type == "size_distribution": + pl_module.env.generator.loc_distribution = "gaussian_mixture" + self.selected_tasks[0] = (pl_module.env.generator.num_loc, 0, 0) + elif self.data_type == "size": + pl_module.env.generator.loc_distribution = "uniform" + self.selected_tasks[0] = (pl_module.env.generator.num_loc, ) + elif self.data_type == "distribution": + pl_module.env.generator.loc_distribution = "gaussian_mixture" + self.selected_tasks[0] = (0, 0) + self.task_params = self.selected_tasks[0] + + def on_train_epoch_start(self, trainer: pl.Trainer, pl_module: pl.LightningModule) -> None: + + # Alpha scheduler (decay for the update of meta model) + self._alpha_scheduler() + + # Reinitialize the task model with the parameters of the meta model + if trainer.current_epoch % self.num_tasks == 0: # Save the meta model + self.meta_model_state_dict = copy.deepcopy(pl_module.state_dict()) + self.task_models = [] + # Print sampled tasks + if self.print_log: + print('\n>> Meta epoch: {} (Exact epoch: {}), Training task: {}'.format(trainer.current_epoch//self.num_tasks, trainer.current_epoch, self.selected_tasks)) + else: + pl_module.load_state_dict(self.meta_model_state_dict) + + # Reinitialize the optimizer every epoch + lr_decay = 0.1 if trainer.current_epoch+1 == int(self.sch_bar * trainer.max_epochs) else 1 + old_lr = trainer.optimizers[0].param_groups[0]['lr'] + new_optimizer = Adam(pl_module.parameters(), lr=old_lr * lr_decay) + trainer.optimizers = [new_optimizer] + + # Print + if self.print_log: + if hasattr(pl_module.env.generator, 'capacity'): + print('>> Training task: {}, capacity: {}'.format(self.task_params, pl_module.env.generator.capacity)) + else: + print('>> Training task: {}'.format(self.task_params)) + + def on_train_epoch_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule): + + # Save the task model + self.task_models.append(copy.deepcopy(pl_module.state_dict())) + if (trainer.current_epoch+1) % self.num_tasks == 0: + # Outer-loop optimization (update the meta model with the parameters of the task model) + with torch.no_grad(): + state_dict = {params_key: (self.meta_model_state_dict[params_key] + + self.alpha * torch.mean(torch.stack([fast_weight[params_key] - self.meta_model_state_dict[params_key] + for fast_weight in self.task_models], dim=0).float(), dim=0)) + for params_key in self.meta_model_state_dict} + pl_module.load_state_dict(state_dict) + + # Get ready for the next meta-training iteration + if (trainer.current_epoch + 1) % self.num_tasks == 0: + # Sample a batch of tasks + self._sample_task() + + # Load new training task (Update the environment) for the next meta-training iteration + self._load_task(pl_module, task_idx = (trainer.current_epoch+1) % self.num_tasks) + + def _sample_task(self): + + # Sample a batch of tasks + self.selected_tasks = [] + for b in range(self.num_tasks): + task_params = random.sample(self.task_set, 1)[0] + self.selected_tasks.append(task_params) + + def _load_task(self, pl_module: pl.LightningModule, task_idx=0): + + # Load new training task (Update the environment) + self.task_params = self.selected_tasks[task_idx] + + if self.data_type == "size_distribution": + assert len(self.task_params) == 3 + pl_module.env.generator.num_loc = self.task_params[0] + pl_module.env.generator.num_modes = self.task_params[1] + pl_module.env.generator.cdist = self.task_params[2] + elif self.data_type == "distribution": # fixed size + assert len(self.task_params) == 2 + pl_module.env.generator.num_modes = self.task_params[0] + pl_module.env.generator.cdist = self.task_params[1] + elif self.data_type == "size": # fixed distribution + assert len(self.task_params) == 1 + pl_module.env.generator.num_loc = self.task_params[0] + + if hasattr(pl_module.env.generator, 'capacity') and self.data_type in ["size_distribution", "size"]: + task_capacity = math.ceil(30 + self.task_params[0] / 5) if self.task_params[0] >= 20 else 20 + pl_module.env.generator.capacity = task_capacity + + def _alpha_scheduler(self): + self.alpha = max(self.alpha * self.alpha_decay, 0.0001) + + def _generate_task_set(self, data_type, min_size, max_size): + """ + Following the setting in Zhou et al. 2023 (https://arxiv.org/abs/2305.19587) + Current setting: + size: (n,) \in [20, 150] + distribution: (m, c) \in {(0, 0) + [1-9] * [1, 10, 20, 30, 40, 50]} + size_distribution: (n, m, c) \in [50, 200, 5] * {(0, 0) + (1, 1) + [3, 5, 7] * [10, 30, 50]} + """ + + if data_type == "distribution": # focus on TSP100 with gaussian mixture distributions + task_set = [(0, 0)] + [(m, c) for m in range(1, 10) for c in [1, 10, 20, 30, 40, 50]] + elif data_type == "size": # focus on uniform distribution with different sizes + task_set = [(n,) for n in range(min_size, max_size + 1)] + elif data_type == "size_distribution": + dist_set = [(0, 0), (1, 1)] + [(m, c) for m in [3, 5, 7] for c in [10, 30, 50]] + task_set = [(n, m, c) for n in range(50, 201, 5) for (m, c) in dist_set] + else: + raise NotImplementedError + + print(">> Generating training task set: {} tasks with type {}".format(len(task_set), data_type)) + print(">> Training task set: {}".format(task_set)) + + return task_set + diff --git a/rl4co/utils/ops.py b/rl4co/utils/ops.py index 86dc2a1e..b78821dc 100644 --- a/rl4co/utils/ops.py +++ b/rl4co/utils/ops.py @@ -147,7 +147,7 @@ def select_start_nodes(td, env, num_starts): num_starts: Number of nodes to select. This may be passed when calling the policy directly. See :class:`rl4co.models.AutoregressiveDecoder` """ num_loc = env.generator.num_loc if hasattr(env.generator, "num_loc") else 0xFFFFFFFF - if env.name in ["tsp", "atsp"]: + if env.name in ["tsp", "atsp", "flp", "mcp"]: selected = ( torch.arange(num_starts, device=td.device).repeat_interleave(td.shape[0]) % num_loc diff --git a/rl4co/utils/test_utils.py b/rl4co/utils/test_utils.py index 321bf99b..60e2a327 100644 --- a/rl4co/utils/test_utils.py +++ b/rl4co/utils/test_utils.py @@ -14,6 +14,8 @@ SMTWTPEnv, SPCTSPEnv, TSPEnv, + FLPEnv, + MCPEnv, ) @@ -44,6 +46,10 @@ def get_env(name, size): env = SMTWTPEnv() elif name == "pdp_ruin_repair": env = PDPRuinRepairEnv() + elif name == "mcp": + env = MCPEnv() + elif name == "flp": + env = FLPEnv() else: raise ValueError(f"Unknown env_name: {name}") diff --git a/tests/test_envs.py b/tests/test_envs.py index 775a46be..aa83d583 100644 --- a/tests/test_envs.py +++ b/tests/test_envs.py @@ -26,6 +26,8 @@ SPCTSPEnv, SVRPEnv, TSPEnv, + FLPEnv, + MCPEnv, ) from rl4co.utils.decoding import random_policy, rollout @@ -133,6 +135,13 @@ def test_jssp_lb(env_cls): assert torch.allclose(td["lbs"], lb_expected) +@pytest.mark.parametrize("env_cls", [FLPEnv, MCPEnv]) +def test_flp_mcp(env_cls, batch_size=2): + env = env_cls() + reward, td, actions = rollout(env, env.reset(batch_size=[batch_size]), random_policy) + assert reward.shape == (batch_size,) + + def test_scheduling_dataloader(): from tempfile import TemporaryDirectory diff --git a/tests/test_training.py b/tests/test_training.py index 4b50f3b0..07d23a25 100644 --- a/tests/test_training.py +++ b/tests/test_training.py @@ -17,6 +17,7 @@ DACT, MDAM, N2S, + POMO, ActiveSearch, AttentionModelPolicy, DeepACO, @@ -27,9 +28,11 @@ MatNet, NARGNNPolicy, NeuOpt, + PolyNet, SymNCO, ) from rl4co.utils import RL4COTrainer +from rl4co.utils.meta_trainer import ReptileCallback # Get env variable MAC_OS_GITHUB_RUNNER if "MAC_OS_GITHUB_RUNNER" in os.environ: @@ -128,6 +131,44 @@ def test_mdam(): trainer.test(model) +def test_pomo_reptile(): + env = TSPEnv(generator_params=dict(num_loc=20)) + policy = AttentionModelPolicy( + env_name=env.name, + embed_dim=128, + num_encoder_layers=6, + num_heads=8, + normalization="instance", + use_graph_context=False, + ) + model = POMO( + env, + policy, + batch_size=5, + train_data_size=5 * 3, + val_data_size=10, + test_data_size=10, + ) + meta_callback = ReptileCallback( + data_type="size", + sch_bar=0.9, + num_tasks=2, + alpha=0.99, + alpha_decay=0.999, + min_size=20, + max_size=50, + ) + trainer = RL4COTrainer( + max_epochs=2, + callbacks=[meta_callback], + devices=1, + accelerator=accelerator, + limit_train_batches=3, + ) + trainer.fit(model) + trainer.test(model) + + @pytest.mark.parametrize("SearchMethod", [ActiveSearch, EASEmb, EASLay]) def test_search_methods(SearchMethod): env = TSPEnv(generator_params=dict(num_loc=20)) @@ -159,9 +200,16 @@ def test_nargnn(): @pytest.mark.skipif( "torch_geometric" not in sys.modules, reason="PyTorch Geometric not installed" ) +@pytest.mark.skipfif("numba" not in sys.modules, reason="Numba not installed") def test_deepaco(): env = TSPEnv(generator_params=dict(num_loc=20)) - model = DeepACO(env, train_data_size=10, val_data_size=10, test_data_size=10) + model = DeepACO( + env, + train_data_size=10, + val_data_size=10, + test_data_size=10, + policy_kwargs={"n_ants": 5}, + ) trainer = RL4COTrainer( max_epochs=1, gradient_clip_val=1, devices=1, accelerator=accelerator ) @@ -248,3 +296,17 @@ def test_l2d_ppo(env_cls): ) trainer.fit(model) trainer.test(model) + + +def test_polynet(): + env = TSPEnv(generator_params=dict(num_loc=20)) + model = PolyNet( + env, + k=10, + train_data_size=10, + val_data_size=10, + test_data_size=10, + ) + trainer = RL4COTrainer(max_epochs=1, devices=1, accelerator=accelerator) + trainer.fit(model) + trainer.test(model)