diff --git a/.github/workflows/python-package-conda.yml b/.github/workflows/python-package-conda.yml new file mode 100644 index 00000000..67e8bdd3 --- /dev/null +++ b/.github/workflows/python-package-conda.yml @@ -0,0 +1,34 @@ +name: Mthree using Conda + +on: [push] + +jobs: + build-linux: + runs-on: ubuntu-latest + strategy: + max-parallel: 5 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Add conda to system path + run: | + # $CONDA is an environment variable pointing to the root of the miniconda directory + echo $CONDA/bin >> $GITHUB_PATH + - name: Install dependencies + run: | + conda config --set always_yes yes --set changeps1 no + pip install -U -r requirements.txt + python setup.py install + - name: Lint with pylint and pycodestyle + run: | + pip install -U -r requirements-dev.txt + pylint -rn mthree + pycodestyle --max-line-length=100 mthree + - name: Test no-Qiskit with pytest + run: | + conda install pytest + pytest -p no:warnings --pyargs mthree/test diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8e14e58a --- /dev/null +++ b/.gitignore @@ -0,0 +1,134 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ +.DS_Store +mthree/version.py +*.cpp + +docs/stubs/* diff --git a/LICENSE b/LICENSE.txt similarity index 99% rename from LICENSE rename to LICENSE.txt index 261eeb9e..5333c633 100644 --- a/LICENSE +++ b/LICENSE.txt @@ -1,3 +1,5 @@ + Copyright 2017 IBM and its contributors + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -186,7 +188,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2017 IBM and its contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md new file mode 100644 index 00000000..f62404a5 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# mthree + +Matrix-free Measurement Mitigation (M3). + +M3 is a measurement mitigation technique that solves for corrected counts using a dimensionality reduction step followed by a simple iterative method that nominally converges in O(1) steps, and can be computed in parallel. For example, M3 can compute corrections on 30 qubit GHZ problems in under one second on a quad-core machine (depending on the number of unique bitstrings in the output). + +## Installation + +Currently M3 needs to be installed from source: + +```bash +python setup.py install +``` + +To enable openmp one must have an openmp enabled compiler and install with: + +```bash +python setup.py install --with-openmp +``` + +Optionally one can also set `-march=native` using: + +```bash +python setup.py install --with-native +``` + +The `openmp` and `native` flags can be used simultaneously using a comma. + +### OpenMP on OSX + +On OSX one must install LLVM using homebrew (You cannot use GCC): + +```bash +brew install llvm +``` + +after which the following (or the like) must be executed in the terminal: + +```bash +export PATH="/usr/local/opt/llvm/bin:$PATH" +``` + +and + +```bash +export LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib" +export CPPFLAGS="-I/usr/local/opt/llvm/include" +``` + +Then installation with openmp can be accomplished using: + +```bash +CC=clang CXX=clang python setup.py install --with-openmp +``` + +## Usage + +M3 is simple to use: + +```python +import mthree +# Specify a mitigator object targeting a given backend +mit = mthree.M3Mitigation(backend) + +# Compute the tensored 1Q calibration matrices for the given qubits and given number of shots +# By default it is over all backend qubits at 8192 shots. +mit.tensored_cals_from_system(qubits, shots) + +# Apply mitigation to a given dict of raw counts over the specified qubits +m3_quasi = mit.apply_correction(raw_counts, qubits) +``` +Note that here `qubits` is a list of which qubits are measured to yield the bits in the output. +For example the list `[4,3,1,2,0]` indicates that a measurement on physical qubit 4 was written to +classical bit zero in the output bit-strings, physical qubit 3 maps to classical bit 1, etc. +The fact that the zeroth bit is right-most in the bitstring is handled internally. + +The results of M3 mitigation are quasi-probabilities that contain small negative values. +This is suitable for use in computing corrected expectation values. However, if one needs +a true probability distribution then it is possible to convert from quasi-probabilites to +the closest true probability distribution in L2-norm using: + +```python +closest_probs = m3_quasi.nearest_probability_distribution() +``` + +An additional benefit of the way M3 works is that it is possible to compute the effect of mitigation when only +looking at errors that are up to a given Hamming distance away. This slightly increases the computational cost, but +allows for investigating if large weight errors have much impact on the output. This can be controlled by the `distance` keyword argument in `apply_correction`: + +```python +m3_quasi = mit.apply_correction(raw_counts, qubits, distance=DIST) +``` +By default, M3 computes errors out to the full distance. + +## License + +(C) Copyright IBM Quantum 2021. +This code is for internal IBM Quantum use only. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..308f755d --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,28 @@ +# This code is part of Kaleidoscope +# +# (C) Copyright IBM 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# You can set these variables from the command line. +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/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..3f981b65 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,27 @@ +.toggle .header { + display: block; + clear: both; + background-color: #785EF0; + color: #f9f9f9; + height: 40px; + padding-top: 10px; + padding-left: 5px; + margin-bottom: 20px; +} + +.toggle .header:before { + float: left; + content: "▶ "; + font-size: 20px; + +} + +.toggle .header.open:before { + float: left; + content: "▼ "; + font-size: 20px; +} + +.toggle{ + background: #FBFBFB; +} diff --git a/docs/_static/gallery.css b/docs/_static/gallery.css new file mode 100644 index 00000000..a89b176b --- /dev/null +++ b/docs/_static/gallery.css @@ -0,0 +1,195 @@ +/* +Sphinx-Gallery has compatible CSS to fix default sphinx themes +Tested for Sphinx 1.3.1 for all themes: default, alabaster, sphinxdoc, +scrolls, agogo, traditional, nature, haiku, pyramid +Tested for Read the Docs theme 0.1.7 */ +.sphx-glr-thumbcontainer { + background: #fff; + border: solid #fff 1px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + box-shadow: none; + float: left; + margin: 5px; + min-height: 230px; + padding-top: 5px; + position: relative; +} +.sphx-glr-thumbcontainer:hover { + border: solid #fb8122 1px; + box-shadow: 0 0 15px rgba(163, 142, 202, 0.5); +} +.sphx-glr-thumbcontainer a.internal { + bottom: 0; + display: block; + left: 0; + padding: 150px 10px 0; + position: absolute; + right: 0; + top: 0; +} +/* Next one is to avoid Sphinx traditional theme to cover all the +thumbnail with its default link Background color */ +.sphx-glr-thumbcontainer a.internal:hover { + background-color: transparent; +} + +.sphx-glr-thumbcontainer p { + margin: 0 0 .1em 0; +} +.sphx-glr-thumbcontainer .figure { + margin: 10px; + width: 160px; +} +.sphx-glr-thumbcontainer img { + display: inline; + max-height: 112px; + max-width: 160px; +} +.sphx-glr-thumbcontainer[tooltip]:hover:after { + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + color: #fff; + content: attr(tooltip); + left: 95%; + padding: 5px 15px; + position: absolute; + z-index: 98; + width: 220px; + bottom: 52%; +} +.sphx-glr-thumbcontainer[tooltip]:hover:before { + border: solid; + border-color: #333 transparent; + border-width: 18px 0 0 20px; + bottom: 58%; + content: ''; + left: 85%; + position: absolute; + z-index: 99; +} + +.sphx-glr-script-out { + color: #888; + margin: 0; +} +p.sphx-glr-script-out { + padding-top: 0.7em; +} +.sphx-glr-script-out .highlight { + background-color: transparent; + margin-left: 2.5em; + margin-top: -2.1em; +} +.sphx-glr-script-out .highlight pre { + background-color: #fafae2; + border: 0; + max-height: 30em; + overflow: auto; + padding-left: 1ex; + margin: 0px; + word-break: break-word; +} +.sphx-glr-script-out + p { + margin-top: 1.8em; +} +blockquote.sphx-glr-script-out { + margin-left: 0pt; +} +.sphx-glr-script-out.highlight-pytb .highlight pre { + color: #000; + background-color: #ffe4e4; + border: 1px solid #f66; + margin-top: 10px; + padding: 7px; +} + +div.sphx-glr-footer { + text-align: center; +} + +div.sphx-glr-download { + margin: 1em auto; + vertical-align: middle; +} + +div.sphx-glr-download a { + background-color: #ffc; + background-image: linear-gradient(to bottom, #FFC, #d5d57e); + border-radius: 4px; + border: 1px solid #c2c22d; + color: #000; + display: inline-block; + font-weight: bold; + padding: 1ex; + text-align: center; +} + +div.sphx-glr-download code.download { + display: inline-block; + white-space: normal; + word-break: normal; + overflow-wrap: break-word; + /* border and background are given by the enclosing 'a' */ + border: none; + background: none; +} + +div.sphx-glr-download a:hover { + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + text-decoration: none; + background-image: none; + background-color: #d5d57e; +} + +.sphx-glr-example-title > :target::before { + display: block; + content: ""; + margin-top: -50px; + height: 50px; + visibility: hidden; +} + +ul.sphx-glr-horizontal { + list-style: none; + padding: 0; +} +ul.sphx-glr-horizontal li { + display: inline; +} +ul.sphx-glr-horizontal img { + height: auto !important; +} + +.sphx-glr-single-img { + margin: auto; + display: block; + max-width: 100%; +} + +.sphx-glr-multi-img { + max-width: 42%; + height: auto; +} + +p.sphx-glr-signature a.reference.external { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding: 3px; + font-size: 75%; + text-align: right; + margin-left: auto; + display: table; +} + +.sphx-glr-clear{ + clear: both; +} + +a.sphx-glr-backref-instance { + text-decoration: none; +} diff --git a/docs/_static/style.css b/docs/_static/style.css new file mode 100644 index 00000000..9817a3ef --- /dev/null +++ b/docs/_static/style.css @@ -0,0 +1,12 @@ +.wy-nav-content { + max-width: 90% !important; +} + +.wy-side-scroll { + background:#f1f2f1; +} + +.pre +{ +color:#BE8184; +} diff --git a/docs/_static/theme.css b/docs/_static/theme.css new file mode 100644 index 00000000..33a6ad3a --- /dev/null +++ b/docs/_static/theme.css @@ -0,0 +1,12285 @@ +@charset "UTF-8"; +/*! + * Bootstrap v4.0.0 (https://getbootstrap.com) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +:root { + --blue: #007bff; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #dc3545; + --orange: #fb8122; + --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: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --font-family-monospace: "IBM Plex Mono", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +*, +*::before, +*::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-family: "IBM Plex Sans", sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +@-ms-viewport { + width: device-width; +} +article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + 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: 0.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; +} + +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; +} + +dfn { + font-style: italic; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; + -webkit-text-decoration-skip: objects; +} +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: monospace, 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:not(:root) { + overflow: hidden; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: .5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +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; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +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-cancel-button, +[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: 0.5rem; + font-family: inherit; + font-weight: 500; + line-height: 1.2; + color: inherit; +} + +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, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.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: 0.5rem; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #6c757d; +} +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 90%; + color: #6c757d; +} + +code, +kbd, +pre, +samp { + font-family: "IBM Plex Mono", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +code { + font-size: 87.5%; + color: #e83e8c; + word-break: break-word; +} +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 87.5%; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; +} + +pre { + display: block; + font-size: 87.5%; + color: #212529; +} +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.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-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + min-height: 1px; + 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%; +} + +.col-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; +} + +.col-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; +} + +.col-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; +} + +.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.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; +} + +.col-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; +} + +.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.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; +} + +.col-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; +} + +.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.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; +} + +.col-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; +} + +.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.3333333333%; +} + +.offset-2 { + margin-left: 16.6666666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.3333333333%; +} + +.offset-5 { + margin-left: 41.6666666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.3333333333%; +} + +.offset-8 { + margin-left: 66.6666666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.3333333333%; +} + +.offset-11 { + margin-left: 91.6666666667%; +} + +@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%; + } + + .col-sm-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-sm-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + + .col-sm-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + + .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.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + + .col-sm-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + + .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.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + + .col-sm-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + + .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.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + + .col-sm-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + + .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.3333333333%; + } + + .offset-sm-2 { + margin-left: 16.6666666667%; + } + + .offset-sm-3 { + margin-left: 25%; + } + + .offset-sm-4 { + margin-left: 33.3333333333%; + } + + .offset-sm-5 { + margin-left: 41.6666666667%; + } + + .offset-sm-6 { + margin-left: 50%; + } + + .offset-sm-7 { + margin-left: 58.3333333333%; + } + + .offset-sm-8 { + margin-left: 66.6666666667%; + } + + .offset-sm-9 { + margin-left: 75%; + } + + .offset-sm-10 { + margin-left: 83.3333333333%; + } + + .offset-sm-11 { + margin-left: 91.6666666667%; + } +} +@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%; + } + + .col-md-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-md-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + + .col-md-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + + .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.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + + .col-md-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + + .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.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + + .col-md-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + + .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.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + + .col-md-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + + .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.3333333333%; + } + + .offset-md-2 { + margin-left: 16.6666666667%; + } + + .offset-md-3 { + margin-left: 25%; + } + + .offset-md-4 { + margin-left: 33.3333333333%; + } + + .offset-md-5 { + margin-left: 41.6666666667%; + } + + .offset-md-6 { + margin-left: 50%; + } + + .offset-md-7 { + margin-left: 58.3333333333%; + } + + .offset-md-8 { + margin-left: 66.6666666667%; + } + + .offset-md-9 { + margin-left: 75%; + } + + .offset-md-10 { + margin-left: 83.3333333333%; + } + + .offset-md-11 { + margin-left: 91.6666666667%; + } +} +@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%; + } + + .col-lg-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-lg-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + + .col-lg-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + + .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.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + + .col-lg-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + + .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.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + + .col-lg-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + + .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.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + + .col-lg-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + + .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.3333333333%; + } + + .offset-lg-2 { + margin-left: 16.6666666667%; + } + + .offset-lg-3 { + margin-left: 25%; + } + + .offset-lg-4 { + margin-left: 33.3333333333%; + } + + .offset-lg-5 { + margin-left: 41.6666666667%; + } + + .offset-lg-6 { + margin-left: 50%; + } + + .offset-lg-7 { + margin-left: 58.3333333333%; + } + + .offset-lg-8 { + margin-left: 66.6666666667%; + } + + .offset-lg-9 { + margin-left: 75%; + } + + .offset-lg-10 { + margin-left: 83.3333333333%; + } + + .offset-lg-11 { + margin-left: 91.6666666667%; + } +} +@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%; + } + + .col-xl-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-xl-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + + .col-xl-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + + .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.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + + .col-xl-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + + .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.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + + .col-xl-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + + .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.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + + .col-xl-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + + .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.3333333333%; + } + + .offset-xl-2 { + margin-left: 16.6666666667%; + } + + .offset-xl-3 { + margin-left: 25%; + } + + .offset-xl-4 { + margin-left: 33.3333333333%; + } + + .offset-xl-5 { + margin-left: 41.6666666667%; + } + + .offset-xl-6 { + margin-left: 50%; + } + + .offset-xl-7 { + margin-left: 58.3333333333%; + } + + .offset-xl-8 { + margin-left: 66.6666666667%; + } + + .offset-xl-9 { + margin-left: 75%; + } + + .offset-xl-10 { + margin-left: 83.3333333333%; + } + + .offset-xl-11 { + margin-left: 91.6666666667%; + } +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 1rem; + background-color: transparent; +} +.table th, +.table td { + padding: 0.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 .table { + background-color: #fff; +} + +.table-sm th, +.table-sm td { + padding: 0.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-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, 0.05); +} + +.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-primary, +.table-primary > th, +.table-primary > td { + background-color: #b8daff; +} + +.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-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-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-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-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-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-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-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, 0.075); +} + +.table-hover .table-active:hover { + background-color: rgba(0, 0, 0, 0.075); +} +.table-hover .table-active:hover > td, +.table-hover .table-active:hover > th { + background-color: rgba(0, 0, 0, 0.075); +} + +.table .thead-dark th { + color: #fff; + background-color: #212529; + border-color: #32383e; +} +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.table-dark { + color: #fff; + background-color: #212529; +} +.table-dark th, +.table-dark td, +.table-dark thead th { + border-color: #32383e; +} +.table-dark.table-bordered { + border: 0; +} +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, 0.05); +} +.table-dark.table-hover tbody tr:hover { + background-color: rgba(255, 255, 255, 0.075); +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .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; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-xl > .table-bordered { + border: 0; + } +} +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; +} +.table-responsive > .table-bordered { + border: 0; +} + +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #80bdff; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} +.form-control::-webkit-input-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; +} + +select.form-control:not([size]):not([multiple]) { + height: calc(2.25rem + 2px); +} +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-top: 0.375rem; + padding-bottom: 0.375rem; + margin-bottom: 0; + line-height: 1.5; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} +.form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control, +.input-group-sm > .input-group-prepend > .form-control-plaintext.input-group-text, +.input-group-sm > .input-group-append > .form-control-plaintext.input-group-text, +.input-group-sm > .input-group-prepend > .form-control-plaintext.btn, +.input-group-sm > .input-group-append > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control, +.input-group-lg > .input-group-prepend > .form-control-plaintext.input-group-text, +.input-group-lg > .input-group-append > .form-control-plaintext.input-group-text, +.input-group-lg > .input-group-prepend > .form-control-plaintext.btn, +.input-group-lg > .input-group-append > .form-control-plaintext.btn { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm, .input-group-sm > .form-control, +.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: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]), +.input-group-sm > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), +.input-group-sm > .input-group-append > select.input-group-text:not([size]):not([multiple]), +.input-group-sm > .input-group-prepend > select.btn:not([size]):not([multiple]), +.input-group-sm > .input-group-append > select.btn:not([size]):not([multiple]) { + height: calc(1.8125rem + 2px); +} + +.form-control-lg, .input-group-lg > .form-control, +.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: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), +.input-group-lg > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), +.input-group-lg > .input-group-append > select.input-group-text:not([size]):not([multiple]), +.input-group-lg > .input-group-prepend > select.btn:not([size]):not([multiple]), +.input-group-lg > .input-group-append > select.btn:not([size]):not([multiple]) { + height: calc(2.875rem + 2px); +} + +.form-group { + margin-bottom: 1rem; +} + +.form-text { + display: block; + margin-top: 0.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: 0.3rem; + margin-left: -1.25rem; +} +.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: 0.75rem; +} +.form-check-inline .form-check-input { + position: static; + margin-top: 0; + margin-right: 0.3125rem; + margin-left: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #28a745; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(40, 167, 69, 0.8); + border-radius: .2rem; +} + +.was-validated .form-control:valid, .form-control.is-valid, +.was-validated .custom-select:valid, +.custom-select.is-valid { + border-color: #28a745; +} +.was-validated .form-control:valid:focus, .form-control.is-valid:focus, +.was-validated .custom-select:valid:focus, +.custom-select.is-valid:focus { + border-color: #28a745; + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} +.was-validated .form-control:valid ~ .valid-feedback, +.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, +.form-control.is-valid ~ .valid-tooltip, +.was-validated .custom-select:valid ~ .valid-feedback, +.was-validated .custom-select:valid ~ .valid-tooltip, +.custom-select.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-tooltip { + display: block; +} + +.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 { + background-color: #71dd8a; +} +.was-validated .custom-control-input:valid ~ .valid-feedback, +.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-tooltip { + display: block; +} +.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { + 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 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.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 ~ .custom-file-label::before, .custom-file-input.is-valid ~ .custom-file-label::before { + border-color: inherit; +} +.was-validated .custom-file-input:valid ~ .valid-feedback, +.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback, +.custom-file-input.is-valid ~ .valid-tooltip { + display: block; +} +.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(220, 53, 69, 0.8); + border-radius: .2rem; +} + +.was-validated .form-control:invalid, .form-control.is-invalid, +.was-validated .custom-select:invalid, +.custom-select.is-invalid { + border-color: #dc3545; +} +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, +.was-validated .custom-select:invalid:focus, +.custom-select.is-invalid:focus { + border-color: #dc3545; + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} +.was-validated .form-control:invalid ~ .invalid-feedback, +.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, +.form-control.is-invalid ~ .invalid-tooltip, +.was-validated .custom-select:invalid ~ .invalid-feedback, +.was-validated .custom-select:invalid ~ .invalid-tooltip, +.custom-select.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-tooltip { + display: block; +} + +.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 { + background-color: #efa2a9; +} +.was-validated .custom-control-input:invalid ~ .invalid-feedback, +.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback, +.custom-control-input.is-invalid ~ .invalid-tooltip { + display: block; +} +.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { + 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 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.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 ~ .custom-file-label::before, .custom-file-input.is-invalid ~ .custom-file-label::before { + border-color: inherit; +} +.was-validated .custom-file-input:invalid ~ .invalid-feedback, +.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-tooltip { + display: block; +} +.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.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 { + 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; + margin-top: 0; + margin-right: 0.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; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} +.btn:hover, .btn:focus { + text-decoration: none; +} +.btn:focus, .btn.focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} +.btn.disabled, .btn:disabled { + opacity: 0.65; +} +.btn:not(:disabled):not(.disabled) { + cursor: pointer; +} +.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { + background-image: none; +} + +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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.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 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.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 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.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 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.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 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.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 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.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 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.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 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.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 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-primary { + color: #007bff; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #007bff; + background-color: transparent; +} +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-outline-secondary { + color: #6c757d; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #6c757d; + background-color: transparent; +} +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-success { + color: #28a745; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + background-image: none; + 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 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-link { + font-weight: 400; + color: #007bff; + background-color: transparent; +} +.btn-link:hover { + color: #0056b3; + text-decoration: underline; + background-color: transparent; + border-color: transparent; +} +.btn-link:focus, .btn-link.focus { + text-decoration: underline; + border-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link:disabled, .btn-link.disabled { + color: #6c757d; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 0.5rem; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.show { + opacity: 1; +} + +.collapse { + display: none; +} +.collapse.show { + display: block; +} + +tr.collapse.show { + display: table-row; +} + +tbody.collapse.show { + display: table-row-group; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0.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, 0.15); + border-radius: 0.25rem; +} + +.dropup .dropdown-menu { + margin-top: 0; + margin-bottom: 0.125rem; +} +.dropup .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-menu { + margin-top: 0; + margin-left: 0.125rem; +} +.dropright .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} +.dropright .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropright .dropdown-toggle::after { + vertical-align: 0; +} + +.dropleft .dropdown-menu { + margin-top: 0; + margin-right: 0.125rem; +} +.dropleft .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} +.dropleft .dropdown-toggle::after { + display: none; +} +.dropleft .dropdown-toggle::before { + display: inline-block; + width: 0; + height: 0; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} +.dropleft .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropleft .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid #e9ecef; +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; +} +.dropdown-item:hover, .dropdown-item:focus { + color: #16181b; + text-decoration: none; + background-color: #f8f9fa; +} +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #007bff; +} +.dropdown-item.disabled, .dropdown-item:disabled { + color: #6c757d; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1.5rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} + +.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: 0; + -ms-flex: 0 1 auto; + flex: 0 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-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group, +.btn-group-vertical .btn + .btn, +.btn-group-vertical .btn + .btn-group, +.btn-group-vertical .btn-group + .btn, +.btn-group-vertical .btn-group + .btn-group { + margin-left: -1px; +} + +.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:first-child { + margin-left: 0; +} +.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: 0.5625rem; + padding-left: 0.5625rem; +} +.dropdown-toggle-split::after { + margin-left: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.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 + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.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 > .custom-select, +.input-group > .custom-file { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; +} +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file:focus { + z-index: 3; +} +.input-group > .form-control + .form-control, +.input-group > .form-control + .custom-select, +.input-group > .form-control + .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:not(:last-child), +.input-group > .custom-select:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.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::before { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > .custom-file:not(:first-child) .custom-file-label, .input-group > .custom-file:not(:first-child) .custom-file-label::before { + border-top-left-radius: 0; + border-bottom-left-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 + .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: 0.375rem 0.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: 0.25rem; +} +.input-group-text input[type="radio"], +.input-group-text input[type="checkbox"] { + margin-top: 0; +} + +.input-group > .input-group-prepend > .btn, +.input-group > .input-group-prepend > .input-group-text, +.input-group > .input-group-append:not(:last-child) > .btn, +.input-group > .input-group-append:not(:last-child) > .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; + display: block; + min-height: 1.5rem; + padding-left: 1.5rem; +} + +.custom-control-inline { + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + margin-right: 1rem; +} + +.custom-control-input { + position: absolute; + z-index: -1; + opacity: 0; +} +.custom-control-input:checked ~ .custom-control-label::before { + color: #fff; + background-color: #007bff; +} +.custom-control-input:focus ~ .custom-control-label::before { + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} +.custom-control-input:active ~ .custom-control-label::before { + color: #fff; + background-color: #b3d7ff; +} +.custom-control-input:disabled ~ .custom-control-label { + color: #6c757d; +} +.custom-control-input:disabled ~ .custom-control-label::before { + background-color: #e9ecef; +} + +.custom-control-label { + margin-bottom: 0; +} +.custom-control-label::before { + position: absolute; + top: 0.25rem; + left: 0; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ""; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #dee2e6; +} +.custom-control-label::after { + position: absolute; + top: 0.25rem; + left: 0; + display: block; + width: 1rem; + height: 1rem; + content: ""; + background-repeat: no-repeat; + background-position: center center; + background-size: 50% 50%; +} + +.custom-checkbox .custom-control-label::before { + border-radius: 0.25rem; +} +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before { + background-color: #007bff; +} +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); +} +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + background-color: #007bff; +} +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' 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, 0.5); +} +.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-radio .custom-control-label::before { + border-radius: 50%; +} +.custom-radio .custom-control-input:checked ~ .custom-control-label::before { + background-color: #007bff; +} +.custom-radio .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' 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, 0.5); +} + +.custom-select { + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.custom-select:focus { + border-color: #80bdff; + outline: 0; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 5px rgba(128, 189, 255, 0.5); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 5px rgba(128, 189, 255, 0.5); +} +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} +.custom-select:disabled { + color: #6c757d; + background-color: #e9ecef; +} +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + margin-bottom: 0; +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(2.25rem + 2px); + margin: 0; + opacity: 0; +} +.custom-file-input:focus ~ .custom-file-control { + border-color: #80bdff; + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} +.custom-file-input:focus ~ .custom-file-control::before { + border-color: #80bdff; +} +.custom-file-input:lang(en) ~ .custom-file-label::after { + content: "Browse"; +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(2.25rem + 2px); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} +.custom-file-label::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 3; + display: block; + height: calc(calc(2.25rem + 2px) - 1px * 2); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + content: "Browse"; + background-color: #e9ecef; + border-left: 1px solid #ced4da; + border-radius: 0 0.25rem 0.25rem 0; +} + +.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: 0.5rem 1rem; +} +.nav-link:hover, .nav-link:focus { + text-decoration: none; +} +.nav-link.disabled { + color: #6c757d; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} +.nav-tabs .nav-item { + margin-bottom: -1px; +} +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.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: transparent; + border-color: transparent; +} +.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: 0.25rem; +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #007bff; +} + +.nav-fill .nav-item { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center; +} + +.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: 0.5rem 1rem; +} +.navbar > .container, +.navbar > .container-fluid { + 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: 0.3125rem; + padding-bottom: 0.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: 0.5rem; + padding-bottom: 0.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: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; +} +.navbar-toggler:hover, .navbar-toggler:focus { + text-decoration: none; +} +.navbar-toggler:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + background-size: 100% 100%; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + 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 .dropdown-menu-right { + right: 0; + left: auto; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .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; + } + .navbar-expand-sm .dropup .dropdown-menu { + top: auto; + bottom: 100%; + } +} +@media (max-width: 767.98px) { + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + 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 .dropdown-menu-right { + right: 0; + left: auto; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .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; + } + .navbar-expand-md .dropup .dropdown-menu { + top: auto; + bottom: 100%; + } +} +@media (max-width: 991.98px) { + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + 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 .dropdown-menu-right { + right: 0; + left: auto; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .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; + } + .navbar-expand-lg .dropup .dropdown-menu { + top: auto; + bottom: 100%; + } +} +@media (max-width: 1199.98px) { + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + 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 .dropdown-menu-right { + right: 0; + left: auto; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .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-xl .dropup .dropdown-menu { + top: auto; + bottom: 100%; + } +} +.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 { + 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 .dropdown-menu-right { + right: 0; + left: auto; +} +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} +.navbar-expand > .container, +.navbar-expand > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} +.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-expand .dropup .dropdown-menu { + top: auto; + bottom: 100%; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 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, 0.9); +} +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} +.navbar-light .navbar-text a { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { + color: rgba(0, 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, 0.5); +} +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.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, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.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, 0.125); + border-radius: 0.25rem; +} +.card > hr { + margin-right: 0; + margin-left: 0; +} +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.card-body { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1.25rem; +} + +.card-title { + margin-bottom: 0.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: 0.75rem 1.25rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} +.card-header + .list-group .list-group-item:first-child { + border-top: 0; +} + +.card-footer { + padding: 0.75rem 1.25rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 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; +} + +.card-img { + width: 100%; + border-radius: calc(0.25rem - 1px); +} + +.card-img-top { + width: 100%; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img-bottom { + width: 100%; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-deck { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} +.card-deck .card { + margin-bottom: 15px; +} +@media (min-width: 576px) { + .card-deck { + -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 { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px; + } +} + +.card-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} +.card-group > .card { + margin-bottom: 15px; +} +@media (min-width: 576px) { + .card-group { + -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:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:first-child .card-img-top, + .card-group > .card:first-child .card-header { + border-top-right-radius: 0; + } + .card-group > .card:first-child .card-img-bottom, + .card-group > .card:first-child .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:last-child .card-img-top, + .card-group > .card:last-child .card-header { + border-top-left-radius: 0; + } + .card-group > .card:last-child .card-img-bottom, + .card-group > .card:last-child .card-footer { + border-bottom-left-radius: 0; + } + .card-group > .card:only-child { + border-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-top, + .card-group > .card:only-child .card-header { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-bottom, + .card-group > .card:only-child .card-footer { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) { + border-radius: 0; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer { + border-radius: 0; + } +} + +.card-columns .card { + margin-bottom: 0.75rem; +} +@media (min-width: 576px) { + .card-columns { + -webkit-column-count: 3; + column-count: 3; + -webkit-column-gap: 1.25rem; + column-gap: 1.25rem; + } + .card-columns .card { + display: inline-block; + width: 100%; + } +} + +.breadcrumb { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding: 0.75rem 1rem; + margin-bottom: 1rem; + list-style: none; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + padding-left: 0.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: 0.25rem; +} + +.page-link { + position: relative; + display: block; + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #007bff; + background-color: #fff; + border: 1px solid #dee2e6; +} +.page-link:hover { + color: #0056b3; + text-decoration: none; + background-color: #e9ecef; + border-color: #dee2e6; +} +.page-link:focus { + z-index: 2; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} +.page-link:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} +.page-item.active .page-link { + z-index: 1; + 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: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.badge-pill { + padding-right: 0.6em; + padding-left: 0.6em; + border-radius: 10rem; +} + +.badge-primary { + color: #fff; + background-color: #007bff; +} +.badge-primary[href]:hover, .badge-primary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #0062cc; +} + +.badge-secondary { + color: #fff; + background-color: #6c757d; +} +.badge-secondary[href]:hover, .badge-secondary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #545b62; +} + +.badge-success { + color: #fff; + background-color: #28a745; +} +.badge-success[href]:hover, .badge-success[href]:focus { + color: #fff; + text-decoration: none; + background-color: #1e7e34; +} + +.badge-info { + color: #fff; + background-color: #17a2b8; +} +.badge-info[href]:hover, .badge-info[href]:focus { + color: #fff; + text-decoration: none; + background-color: #117a8b; +} + +.badge-warning { + color: #212529; + background-color: #ffc107; +} +.badge-warning[href]:hover, .badge-warning[href]:focus { + color: #212529; + text-decoration: none; + background-color: #d39e00; +} + +.badge-danger { + color: #fff; + background-color: #dc3545; +} +.badge-danger[href]:hover, .badge-danger[href]:focus { + color: #fff; + text-decoration: none; + background-color: #bd2130; +} + +.badge-light { + color: #212529; + background-color: #f8f9fa; +} +.badge-light[href]:hover, .badge-light[href]:focus { + color: #212529; + text-decoration: none; + background-color: #dae0e5; +} + +.badge-dark { + color: #fff; + background-color: #343a40; +} +.badge-dark[href]:hover, .badge-dark[href]:focus { + color: #fff; + text-decoration: none; + background-color: #1d2124; +} + +.jumbotron { + padding: 2rem 1rem; + margin-bottom: 2rem; + background-color: #e9ecef; + border-radius: 0.3rem; +} +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0; +} + +.alert { + position: relative; + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 4rem; +} +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: 0.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; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.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; + color: #fff; + text-align: center; + background-color: #007bff; + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.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: progress-bar-stripes 1s linear infinite; + animation: progress-bar-stripes 1s linear infinite; +} + +.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; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} +.list-group-item-action:hover, .list-group-item-action:focus { + 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: 0.75rem 1.25rem; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} +.list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.list-group-item:hover, .list-group-item:focus { + z-index: 1; + text-decoration: none; +} +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + background-color: #fff; +} +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0; +} +.list-group-flush:last-child .list-group-item:last-child { + border-bottom: 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, .close:focus { + color: #000; + text-decoration: none; + opacity: .75; +} +.close:not(:disabled):not(.disabled) { + cursor: pointer; +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + outline: 0; +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform 0.3s ease-out; + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; + -webkit-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.show .modal-dialog { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); +} + +.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% - (0.5rem * 2)); +} + +.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, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop.show { + opacity: 0.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; + border-bottom: 1px solid #e9ecef; + border-top-left-radius: 0.3rem; + border-top-right-radius: 0.3rem; +} +.modal-header .close { + padding: 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; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + padding: 1rem; + border-top: 1px solid #e9ecef; +} +.modal-footer > :not(:first-child) { + margin-left: .25rem; +} +.modal-footer > :not(:last-child) { + margin-right: .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-centered { + min-height: calc(100% - (1.75rem * 2)); + } + + .modal-sm { + max-width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + max-width: 800px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + 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: 0.9; +} +.tooltip .arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} +.tooltip .arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { + padding: 0.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: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { + padding: 0 0.4rem; +} +.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { + right: 0; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { + padding: 0.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 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { + padding: 0 0.4rem; +} +.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { + left: 0; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.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, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + 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, 0.2); + border-radius: 0.3rem; +} +.popover .arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; + margin: 0 0.3rem; +} +.popover .arrow::before, .popover .arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top, .bs-popover-auto[x-placement^="top"] { + margin-bottom: 0.5rem; +} +.bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow { + bottom: calc((0.5rem + 1px) * -1); +} +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before, +.bs-popover-top .arrow::after, +.bs-popover-auto[x-placement^="top"] .arrow::after { + border-width: 0.5rem 0.5rem 0; +} +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before { + bottom: 0; + border-top-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-top .arrow::after, .bs-popover-auto[x-placement^="top"] .arrow::after { + bottom: 1px; + border-top-color: #fff; +} + +.bs-popover-right, .bs-popover-auto[x-placement^="right"] { + margin-left: 0.5rem; +} +.bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow { + left: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before, +.bs-popover-right .arrow::after, +.bs-popover-auto[x-placement^="right"] .arrow::after { + border-width: 0.5rem 0.5rem 0.5rem 0; +} +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before { + left: 0; + border-right-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-right .arrow::after, .bs-popover-auto[x-placement^="right"] .arrow::after { + left: 1px; + border-right-color: #fff; +} + +.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { + margin-top: 0.5rem; +} +.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow { + top: calc((0.5rem + 1px) * -1); +} +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before, +.bs-popover-bottom .arrow::after, +.bs-popover-auto[x-placement^="bottom"] .arrow::after { + border-width: 0 0.5rem 0.5rem 0.5rem; +} +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before { + top: 0; + border-bottom-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-bottom .arrow::after, .bs-popover-auto[x-placement^="bottom"] .arrow::after { + top: 1px; + 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: 0.5rem; +} +.bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow { + right: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before, +.bs-popover-left .arrow::after, +.bs-popover-auto[x-placement^="left"] .arrow::after { + border-width: 0.5rem 0 0.5rem 0.5rem; +} +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before { + right: 0; + border-left-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-left .arrow::after, .bs-popover-auto[x-placement^="left"] .arrow::after { + right: 1px; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + color: inherit; + 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: 0.5rem 0.75rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-item { + position: relative; + display: none; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-transition: -webkit-transform 0.6s ease; + transition: -webkit-transform 0.6s ease; + transition: transform 0.6s ease; + transition: transform 0.6s ease, -webkit-transform 0.6s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0; +} + +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + -webkit-transform: translateX(0); + transform: translateX(0); +} +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next.carousel-item-left, + .carousel-item-prev.carousel-item-right { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.carousel-item-next, +.active.carousel-item-right { + -webkit-transform: translateX(100%); + transform: translateX(100%); +} +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next, + .active.carousel-item-right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.carousel-item-prev, +.active.carousel-item-left { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); +} +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-prev, + .active.carousel-item-left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + 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%; + color: #fff; + text-align: center; + opacity: 0.5; +} +.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: transparent no-repeat center center; + background-size: 100% 100%; +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 10px; + 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 { + position: relative; + -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; + background-color: rgba(255, 255, 255, 0.5); +} +.carousel-indicators li::before { + position: absolute; + top: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} +.carousel-indicators li::after { + position: absolute; + bottom: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; +} + +.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: transparent !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-right { + border-right: 1px solid #dee2e6 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-left { + border-left: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-right-0 { + border-right: 0 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-left-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #007bff !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.border-white { + border-color: #fff !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-right { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-left { + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-circle { + border-radius: 50% !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.8571428571%; +} + +.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; +} + +.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; + } + + .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; + } + + .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; + } + + .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; + } + + .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; + } +} +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + 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: -webkit-sticky) or (position: sticky)) { + .sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + border: 0; +} + +.sr-only-focusable:active, .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + overflow: visible; + clip: auto; + white-space: normal; + -webkit-clip-path: none; + clip-path: none; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.mh-100 { + max-height: 100% !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: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.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: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.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-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: 0.25rem !important; + } + + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + + .m-sm-2 { + margin: 0.5rem !important; + } + + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.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: 0.25rem !important; + } + + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + + .p-sm-2 { + padding: 0.5rem !important; + } + + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + + .pl-sm-2, + .px-sm-2 { + padding-left: 0.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-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: 0.25rem !important; + } + + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + + .m-md-2 { + margin: 0.5rem !important; + } + + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + + .ml-md-2, + .mx-md-2 { + margin-left: 0.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: 0.25rem !important; + } + + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + + .p-md-2 { + padding: 0.5rem !important; + } + + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + + .pl-md-2, + .px-md-2 { + padding-left: 0.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-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: 0.25rem !important; + } + + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + + .m-lg-2 { + margin: 0.5rem !important; + } + + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.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: 0.25rem !important; + } + + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + + .p-lg-2 { + padding: 0.5rem !important; + } + + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + + .pl-lg-2, + .px-lg-2 { + padding-left: 0.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-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: 0.25rem !important; + } + + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + + .m-xl-2 { + margin: 0.5rem !important; + } + + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.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: 0.25rem !important; + } + + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + + .p-xl-2 { + padding: 0.5rem !important; + } + + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + + .pl-xl-2, + .px-xl-2 { + padding-left: 0.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-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; + } +} +.text-justify { + text-align: justify !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-normal { + font-weight: 400 !important; +} + +.font-weight-bold { + font-weight: 700 !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: #0062cc !important; +} + +.text-secondary { + color: #6c757d !important; +} + +a.text-secondary:hover, a.text-secondary:focus { + color: #545b62 !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:hover, a.text-success:focus { + color: #1e7e34 !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:hover, a.text-info:focus { + color: #117a8b !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:hover, a.text-warning:focus { + color: #d39e00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:hover, a.text-danger:focus { + color: #bd2130 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:hover, a.text-light:focus { + color: #dae0e5 !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:hover, a.text-dark:focus { + color: #1d2124 !important; +} + +.text-muted { + color: #6c757d !important; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.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 #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + 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 #ddd !important; + } +} +/*Github syntax highlighting theme via Rouge*/ +.highlight table td { + padding: 5px; +} + +.highlight table pre { + margin: 0; +} + +.highlight .cm { + color: #999988; + font-style: italic; +} + +.highlight .cp { + color: #999999; + font-weight: bold; +} + +.highlight .c1 { + color: #999988; + font-style: italic; +} + +.highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; +} + +.highlight .c, .highlight .cd { + color: #999988; + font-style: italic; +} + +.highlight .err { + color: #a61717; + background-color: #e3d2d2; +} + +.highlight .gd { + color: #000000; + background-color: #ffdddd; +} + +.highlight .ge { + color: #000000; + font-style: italic; +} + +.highlight .gr { + color: #aa0000; +} + +.highlight .gh { + color: #999999; +} + +.highlight .gi { + color: #000000; + background-color: #ddffdd; +} + +.highlight .go { + color: #888888; +} + +.highlight .gp { + color: #555555; +} + +.highlight .gs { + font-weight: bold; +} + +.highlight .gu { + color: #aaaaaa; +} + +.highlight .gt { + color: #aa0000; +} + +.highlight .kc { + color: #000000; + font-weight: bold; +} + +.highlight .kd { + color: #000000; + font-weight: bold; +} + +.highlight .kn { + color: #000000; + font-weight: bold; +} + +.highlight .kp { + color: #000000; + font-weight: bold; +} + +.highlight .kr { + color: #000000; + font-weight: bold; +} + +.highlight .kt { + color: #445588; + font-weight: bold; +} + +.highlight .k, .highlight .kv { + color: #000000; + font-weight: bold; +} + +.highlight .mf { + color: #009999; +} + +.highlight .mh { + color: #009999; +} + +.highlight .il { + color: #009999; +} + +.highlight .mi { + color: #009999; +} + +.highlight .mo { + color: #009999; +} + +.highlight .m, .highlight .mb, .highlight .mx { + color: #009999; +} + +.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: #008080; +} + +.highlight .bp { + color: #999999; +} + +.highlight .nb { + color: #0086B3; +} + +.highlight .nc { + color: #445588; + font-weight: bold; +} + +.highlight .no { + color: #008080; +} + +.highlight .nd { + color: #3c5d5d; + font-weight: bold; +} + +.highlight .ni { + color: #800080; +} + +.highlight .ne { + color: #990000; + font-weight: bold; +} + +.highlight .nf { + color: #990000; + font-weight: bold; +} + +.highlight .nl { + color: #990000; + font-weight: bold; +} + +.highlight .nn { + color: #555555; +} + +.highlight .nt { + color: #000080; +} + +.highlight .vc { + color: #008080; +} + +.highlight .vg { + color: #008080; +} + +.highlight .vi { + color: #008080; +} + +.highlight .nv { + color: #008080; +} + +.highlight .ow { + color: #000000; + font-weight: bold; +} + +.highlight .o { + color: #000000; + font-weight: bold; +} + +.highlight .w { + color: #bbbbbb; +} + +.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; + unicode-range: u+0020-007f; + src: local("IBMPlexMono-SemiBold"), 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-Medium"), 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-Regular"), 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-Light"), url("../fonts/IBMPlexMono/IBMPlexMono-Light.woff2") format("woff2"), url("../fonts/IBMPlexMono/IBMPlexMono-Light.woff") format("woff"); +} +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: #e44c2c; +} + +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: #e44c2c; +} + +::-moz-placeholder { + color: #e44c2c; +} + +:-ms-input-placeholder { + color: #e44c2c; +} + +:-moz-placeholder { + color: #e44c2c; +} + +.email-subscribe-form input.email { + color: #e44c2c; + border: none; + border-bottom: 1px solid #939393; + width: 100%; + background-color: transparent; + outline: none; + font-size: 1.125rem; + letter-spacing: 0.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: transparent; + 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; +} + +code, kbd, pre, samp { + font-family: IBMPlexMono,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; +} +code span, kbd span, pre span, samp span { + font-family: IBMPlexMono,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; +} + +pre { + padding: 1.125rem; + background-color: #f3f4f7; +} +pre code { + font-size: 0.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: #4974D1; +} +a:link.has-code, +a:visited.has-code, +a:hover.has-code { + color: #4974D1; +} + +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: #ffffff; + 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: 23px; + width: 93px; + background-image: url("../images/logo.svg"); + background-repeat: no-repeat; + background-size: 93px 23px; + display: block; + float: left; + z-index: 10; +} +@media screen and (min-width: 1100px) { + .header-logo { + background-size: 108px 27px; + position: absolute; + height: 27px; + width: 108px; + top: 4px; + float: none; + } +} + +.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: 4px; +} +@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: #e44c2c; + font-size: 1.375rem; + left: 0; + position: absolute; + right: 0; + text-align: center; +} +.header-holder .main-menu ul li.active a { + color: #e44c2c; +} +.header-holder .main-menu ul li:last-of-type { + margin-right: 0; +} +.header-holder .main-menu ul li a { + color: #ffffff; + font-size: 1.125rem; + letter-spacing: 0; + line-height: 2.125rem; + text-align: center; + text-decoration: none; +} +@media screen and (min-width: 1100px) { + .header-holder .main-menu ul li a:hover { + color: #e44c2c; + } +} + +.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 { + -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-fluid:after { + content: ""; + display: table; +} +.mobile-main-menu .container-fluid:after { + clear: both; +} +.mobile-main-menu .container-fluid { + *zoom: 1; +} + +.mobile-main-menu.open ul { + list-style-type: none; + padding: 0; +} +.mobile-main-menu.open ul li a { + font-size: 2rem; + color: #ffffff; + letter-spacing: 0; + line-height: 4rem; + text-decoration: none; +} +.mobile-main-menu.open ul li.active a { + color: #e44c2c; +} + +.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: -4px; +} + +.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: 100%; + min-height: 100%; + margin-top: -68px; +} + +.site-footer { + padding: 2.5rem 0; + width: 100%; + background: #000000; + 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: #ffffff; +} +.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: 0.375rem; +} +.site-footer ul li.list-title { + padding-bottom: 0.75rem; + color: #ffffff; +} +.site-footer a:link, +.site-footer a:visited { + color: inherit; +} +@media screen and (min-width: 768px) { + .site-footer a:hover { + color: #e44c2c; + } +} + +.docs-tutorials-resources { + background-color: #262626; + color: #ffffff; + 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: 0.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: 0.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: #e44c2c; +} +.docs-tutorials-resources a:hover { + color: #ffffff; +} + +.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-size: 1.5rem; + letter-spacing: -0.25px; + line-height: 1.875rem; + 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: 0.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: 0.625rem; + color: #262626; +} +article.pytorch-article table td { + padding: 0.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: 0.3125rem; + padding-left: 0; +} +article.pytorch-article table.docutils.field-list td.field-body { + padding: 0.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: 0.625rem; +} +article.pytorch-article dl { + margin-bottom: 1.5rem; +} +article.pytorch-article dl dt { + margin-bottom: 0.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 img { + width: 100%; +} + +html { + height: 100%; +} +@media screen and (min-width: 768px) { + html { + font-size: 16px; + } +} + +body { + background: #ffffff; + 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: #e44c2c; + 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: #ee4c2c; +} + +.wy-breadcrumbs li a { + color: #ee4c2c; +} + +.wy-nav-top{ + background: #808080; +} + +ul.pytorch-breadcrumbs { + padding-left: 0; + list-style-type: none; +} +ul.pytorch-breadcrumbs li { + display: inline-block; + font-size: 0.875rem; +} +ul.pytorch-breadcrumbs a { + color: #ee4c2c; + 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-dark.svg"); +} +.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 .helpful-hr.hr-top { + margin-bottom: -0.0625rem; +} +.rst-content footer .helpful-hr.hr-bottom { + margin-top: -0.0625rem; +} +.rst-content footer .helpful-container { + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + font-size: 1.125rem; +} +.rst-content footer .helpful-container .helpful-question, .rst-content footer .helpful-container .was-helpful-thank-you { + padding: 0.625rem 1.25rem 0.625rem 1.25rem; +} +.rst-content footer .helpful-container .was-helpful-thank-you { + display: none; +} +.rst-content footer .helpful-container .helpful-question.yes-link, .rst-content footer .helpful-container .helpful-question.no-link { + color: #e44c2c; + cursor: pointer; +} +.rst-content footer .helpful-container .helpful-question.yes-link:hover, .rst-content footer .helpful-container .helpful-question.no-link:hover { + background-color: #e44c2c; + color: #ffffff; +} +.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; + 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: #4974D1; +} +a:link.has-code span, +a:hover.has-code span, +a:visited.has-code span { + color: #4974D1; +} + +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; +} + +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 { + font-size: 1rem; + color: #262626; + letter-spacing: 0; + line-height: 1.5rem; + text-decoration: none; +} +article.pytorch-article .sphx-glr-thumbcontainer:hover { + -webkit-box-shadow: none; + box-shadow: none; + border-bottom-color: #ffffff; +} +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: 0.10; +} +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: 0; + left: 0; + background-color: #e44c2c; + -webkit-transition: width .250s ease-in-out; + transition: width .250s ease-in-out; + } + article.pytorch-article .sphx-glr-thumbcontainer:hover:after { + width: 100%; + } +} +@media screen and (min-width: 768px) { + article.pytorch-article .sphx-glr-thumbcontainer:after { + background-color: #ee4c2c; + } +} + +article.pytorch-article .section :not(dt) > code { + color: #262626; + border-top: solid 2px #f3f4f7; + background-color: #f3f4f7; + border-bottom: solid 2px #f3f4f7; + 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 .attribute dt, article.pytorch-article .class .attribute dt, article.pytorch-article .class dt { + position: relative; + background: #f3f4f7; + padding: 0.5rem; + border-left: 3px solid #ee4c2c; + word-wrap: break-word; + padding-right: 100px; +} +article.pytorch-article .function dt em.property, article.pytorch-article .attribute dt em.property, article.pytorch-article .class dt em.property { + font-family: inherit; +} +article.pytorch-article .function dt em, article.pytorch-article .attribute dt em, article.pytorch-article .class .attribute dt em, article.pytorch-article .class dt em, article.pytorch-article .function dt .sig-paren, article.pytorch-article .attribute dt .sig-paren, article.pytorch-article .class dt .sig-paren { + font-family: IBMPlexMono,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; + font-size: 87.5%; +} +article.pytorch-article .function dt a, article.pytorch-article .attribute dt a, article.pytorch-article .class .attribute dt a, article.pytorch-article .class 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 .attribute dt:hover .viewcode-link, article.pytorch-article .class dt:hover .viewcode-link { + color: #ee4c2c; +} +article.pytorch-article .function .anchorjs-link, article.pytorch-article .attribute .anchorjs-link, article.pytorch-article .class .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 .attribute dt > code, article.pytorch-article .class .attribute dt > code, article.pytorch-article .class 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 .attribute .viewcode-link, article.pytorch-article .class .viewcode-link { + font-size: 0.875rem; + color: #979797; + letter-spacing: 0; + line-height: 1.5rem; + text-transform: uppercase; +} +article.pytorch-article .function dd, article.pytorch-article .attribute dd, article.pytorch-article .class .attribute dd, article.pytorch-article .class dd { + padding-left: 3.75rem; +} +article.pytorch-article .function dd p, article.pytorch-article .attribute dd p, article.pytorch-article .class .attribute dd p, article.pytorch-article .class dd p { + color: #262626; +} +article.pytorch-article .function table tbody tr th.field-name, article.pytorch-article .attribute table tbody tr th.field-name, article.pytorch-article .class 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 .attribute table tbody tr th.field-name, article.pytorch-article .class table tbody tr th.field-name { + width: 15%; + } +} +article.pytorch-article .function table tbody tr td.field-body, article.pytorch-article .attribute table tbody tr td.field-body, article.pytorch-article .class table tbody tr td.field-body { + padding: 0.625rem; + width: 80%; + color: #262626; +} +@media screen and (min-width: 768px) { + article.pytorch-article .function table tbody tr td.field-body, article.pytorch-article .attribute table tbody tr td.field-body, article.pytorch-article .class 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 .attribute table tbody tr td.field-body, article.pytorch-article .class table tbody tr td.field-body { + padding-left: 1.25rem; + } +} +article.pytorch-article .function table tbody tr td.field-body p, article.pytorch-article .attribute table tbody tr td.field-body p, article.pytorch-article .class 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 .attribute table tbody tr td.field-body p:last-of-type, article.pytorch-article .class 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 .attribute table tbody tr td.field-body ol, article.pytorch-article .class table tbody tr td.field-body ol, article.pytorch-article .function table tbody tr td.field-body ul, article.pytorch-article .attribute table tbody tr td.field-body ul, article.pytorch-article .class table tbody tr td.field-body ul { + padding-left: 1rem; + padding-bottom: 0; +} +article.pytorch-article .function table.docutils.field-list, article.pytorch-article .attribute table.docutils.field-list, article.pytorch-article .class table.docutils.field-list { + margin-bottom: 0.75rem; +} +article.pytorch-article .attribute .has-code { + float: none; +} +article.pytorch-article .class dt { + border-left: none; + border-top: 3px solid #ee4c2c; + padding-left: 4em; +} +article.pytorch-article .class dt em.property { + position: absolute; + left: 0.5rem; +} +article.pytorch-article .class dd .docutils dt { + padding-left: 0.5rem; +} +article.pytorch-article .class em.property { + text-transform: uppercase; + font-style: normal; + color: #ee4c2c; + font-size: 1rem; + letter-spacing: 0; + padding-right: 0.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 #ee4c2c; + border-top: none; +} +article.pytorch-article .class .method dt, +article.pytorch-article .class .staticmethod dt { + padding-left: 0.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 .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 .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: #ffffff; + letter-spacing: 1px; + text-transform: uppercase; + margin-bottom: 1.125rem; + padding: 3px 0 3px 1.375rem; + position: relative; + font-size: 0.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 .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: "\2022"; + position: absolute; + left: 9px; + color: #ffffff; + 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 .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 .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 .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: #ffffff; + 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 .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 #ffffff; + background-color: #ffffff; + border-bottom: solid 2px #ffffff; + 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 .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 .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 .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 .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 .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 .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 .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: 0.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: 0; + left: 0; + background-color: #e44c2c; + -webkit-transition: width .250s ease-in-out; + transition: width .250s ease-in-out; + } + .pytorch-article div.sphx-glr-download a:hover:after { + width: 100%; + } +} +@media screen and (min-width: 768px) { + .pytorch-article div.sphx-glr-download a:after { + background-color: #ee4c2c; + } +} +@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: transparent; + 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: #ffffff !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: 0.9375rem; + padding-right: 0.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: 0.9375rem; + font-size: 1rem; + line-height: 1.375rem; +} +article.pytorch-article .wy-table-responsive table tbody td .pre { + background: #ffffff; + outline: 1px solid #e9e9e9; + color: #ee4c2c; + 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: 0.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: 0.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: 75%; + } +} +@media screen and (min-width: 1600px) { + .pytorch-breadcrumbs-wrapper { + width: 850px; + margin-left: 1.875rem; + } +} +.pytorch-breadcrumbs-wrapper .pytorch-breadcrumbs-aside { + float: right; +} + +.pytorch-article .container { + padding-left: 0; + padding-right: 0; + max-width: none; +} + +a:link, +a:visited, +a:hover { + color: #ee4c2c; +} + +::-webkit-input-placeholder { + color: #ee4c2c; +} + +::-moz-placeholder { + color: #ee4c2c; +} + +:-ms-input-placeholder { + color: #ee4c2c; +} + +:-moz-placeholder { + color: #ee4c2c; +} + +@media screen and (min-width: 768px) { + .site-footer a:hover { + color: #ee4c2c; + } +} + +.docs-tutorials-resources a { + color: #ee4c2c; +} + +.header-holder { + position: relative; + z-index: 201; +} + +.header-holder .main-menu ul li.active:after { + color: #ee4c2c; +} +.header-holder .main-menu ul li.active a { + color: #ee4c2c; +} +@media screen and (min-width: 1100px) { + .header-holder .main-menu ul li a:hover { + color: #ee4c2c; + } +} + +.mobile-main-menu.open ul li.active a { + color: #ee4c2c; +} + +.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: #000000; + cursor: pointer; +} +.pytorch-call-to-action-links a:hover { + color: #e44c2c; +} +.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: 0.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: #e44c2c; + color: #e44c2c; +} + +#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-radius: 0; + border-color: #f3f4f7; + height: 98px; + margin-bottom: 1.25rem; + margin-bottom: 1.875rem; + overflow: scroll; + background-color: #f3f4f7; + cursor: pointer; +} +@media screen and (min-width: 1240px) { + #tutorial-cards-container .card.tutorials-card { + height: 200px; + overflow: inherit; + } +} +@media (min-width: 768px) and (max-width: 1239px) { + #tutorial-cards-container .card.tutorials-card { + height: 200px; + overflow: scroll; + } +} +#tutorial-cards-container .card.tutorials-card .tutorials-image { + position: absolute; + top: 0px; + right: 0px; + height: 96px; + width: 96px; + opacity: 0.5; +} +#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: 100%; + width: 25%; + } +} +@media (min-width: 768px) and (max-width: 1239px) { + #tutorial-cards-container .card.tutorials-card .tutorials-image { + height: 100%; + 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; + background: #000000; + opacity: .075; +} +#tutorial-cards-container .card.tutorials-card .card-title-container { + width: 70%; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; +} +@media screen and (min-width: 768px) { + #tutorial-cards-container .card.tutorials-card .card-title-container { + width: 75%; + } +} +@media (min-width: 768px) and (max-width: 1239px) { + #tutorial-cards-container .card.tutorials-card .card-title-container { + width: 70%; + } +} +#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 p.tags { + font-size: 0.9375rem; + line-height: 1.5rem; + margin-bottom: 0; + color: #6c6c6d; + font-weight: 400; + width: 70%; +} +@media screen and (min-width: 768px) { + #tutorial-cards-container .card.tutorials-card p.card-summary, #tutorial-cards-container .card.tutorials-card p.tags { + width: 75%; + } +} +@media (min-width: 768px) and (max-width: 1239px) { + #tutorial-cards-container .card.tutorials-card p.card-summary, #tutorial-cards-container .card.tutorials-card p.tags { + width: 70%; + } +} +#tutorial-cards-container .card.tutorials-card p.tags { + margin-top: 30px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +#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: 0; + left: 0; + background-color: #e44c2c; + -webkit-transition: width .250s ease-in-out; + transition: width .250s ease-in-out; + } + #tutorial-cards-container .card.tutorials-card:hover:after { + width: 100%; + } +} +#tutorial-cards-container .card.tutorials-card:hover { + background-color: #ffffff; + border: 1px solid #e2e2e2; + border-bottom: none; +} +#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: 75%; +} +#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: #e44c2c; +} +#tutorial-cards-container .tutorial-filter { + cursor: pointer; +} +#tutorial-cards-container .filter-btn { + color: #979797; + border: 1px solid #979797; + display: inline-block; + text-align: center; + white-space: nowrap; + vertical-align: middle; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + margin-bottom: 5px; +} +#tutorial-cards-container .filter-btn:hover { + border: 1px solid #e44c2c; + color: #e44c2c; +} +#tutorial-cards-container .filter-btn.selected { + background-color: #e44c2c; + border: 1px solid #e44c2c; + color: #ffffff; +} +#tutorial-cards-container .all-tag-selected { + background-color: #979797; + color: #ffffff; +} +#tutorial-cards-container .all-tag-selected:hover { + border-color: #979797; + color: #ffffff; +} +#tutorial-cards-container .pagination .page { + border: 1px solid #dee2e6; + padding: 0.5rem 0.75rem; +} +#tutorial-cards-container .pagination .active .page { + background-color: #dee2e6; +} + +article.pytorch-article .tutorials-callout-container { + padding-bottom: 50px; +} +article.pytorch-article .tutorials-callout-container .col-md-6 { + padding-bottom: 10px; +} +article.pytorch-article .tutorials-callout-container .text-container { + padding: 10px 0px 30px 0px; + padding-bottom: 10px; +} +article.pytorch-article .tutorials-callout-container .text-container .body-paragraph { + color: #666666; + font-weight: 300; + font-size: 1.125rem; + line-height: 1.875rem; +} +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: 0.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: 0; + left: 0; + background-color: #e44c2c; + -webkit-transition: width .250s ease-in-out; + transition: width .250s ease-in-out; + } + article.pytorch-article .tutorials-callout-container .btn.callout-button:hover:after { + width: 100%; + } +} +article.pytorch-article .tutorials-callout-container .btn.callout-button a { + color: inherit; +} + +.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: #ffffff; + 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: #ffffff; + width: 100%; + max-width: 700px; + position: relative; +} + +.pytorch-content-left { + margin-top: 2.5rem; + width: 100%; +} +@media screen and (min-width: 1101px) { + .pytorch-content-left { + margin-top: 0; + margin-left: 3%; + width: 75%; + float: left; + } +} +@media screen and (min-width: 1600px) { + .pytorch-content-left { + width: 850px; + margin-left: 30px; + } +} +.pytorch-content-left .main-content { + padding-top: 0.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: 19%; + float: left; + height: 100%; + } +} +@media screen and (min-width: 1600px) { + .pytorch-content-right { + width: 280px; + } +} + +@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: #f3f4f7; + color: #262626; + overflow: scroll; +} +@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: 25%; + 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: pointer; +} + +.hide-menu { + display: none; +} + +.left-nav-top-caption { + padding-top: 1rem; +} + +.pytorch-left-menu p.caption { + color: #262626; + display: block; + font-size: 1rem; + line-height: 1.375rem; + margin-bottom: 1rem; + text-transform: none; + white-space: nowrap; +} + +.pytorch-left-menu-search { + margin-bottom: 2.5rem; +} +@media screen and (min-width: 1101px) { + .pytorch-left-menu-search { + margin: 1.25rem 0.625rem 1.875rem 0; + } +} + +.pytorch-left-menu-search ::-webkit-input-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: 0.5rem 0.75rem; + border-color: #ffffff; + 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: #ffffff; +} +.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: 83.5%; + width: 14%; + } + .pytorch-right-menu.scrolling-absolute { + position: absolute; + left: 0; + } +} +@media screen and (min-width: 1600px) { + .pytorch-right-menu { + left: 0; + width: 380px; + } + .pytorch-right-menu.scrolling-fixed { + position: fixed; + top: 45px; + left: 1230px; + } + .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: 0.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 { + margin-bottom: 0.3125rem; + position: relative; +} +.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: 0.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: 0.8em; + line-height: 1.6em; +} +.pytorch-left-menu li.toctree-l1.current > a, +.pytorch-right-menu li.toctree-l1.current > a { + color: #ee4c2c; +} +.pytorch-left-menu li.toctree-l1.current > a:before, +.pytorch-right-menu li.toctree-l1.current > a:before { + content: "\2022"; + display: inline-block; + position: absolute; + left: -15px; + top: 1px; + font-size: 1.375rem; + color: #ee4c2c; +} +@media screen and (min-width: 1101px) { + .pytorch-left-menu li.toctree-l1.current > a:before, + .pytorch-right-menu li.toctree-l1.current > a:before { + left: -20px; + } +} +.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: 0.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: 0.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; +} + +.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: #ee4c2c; +} +.pytorch-right-menu li.active > a span.pre, .pytorch-right-menu li.active > a:before { + color: #ee4c2c; +} +.pytorch-right-menu li.active > a:after { + content: "\2022"; + color: #e44c2c; + 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: 120%; + } +} +@media screen and (min-width: 1600px) { + .pytorch-right-menu .pytorch-side-scroll { + width: 400px; + } +} +.pytorch-right-menu .pytorch-side-scroll > ul { + padding-left: 10%; + padding-right: 10%; + 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; +} + +.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 { + 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: #ffffff; + 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: 0.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: transparent; + 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 .ecosystem-dropdown, .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: transparent; +} +.main-menu ul li .dropdown-menu .dropdown-item:hover { + background-color: #e44c2c; +} +.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: #ffffff; +} +.main-menu ul li .dropdown-menu a.dropdown-item:hover p { + color: #ffffff; +} + +.ecosystem-dropdown-menu, .resources-dropdown-menu { + left: -75px; + width: 226px; + display: none; + position: absolute; + top: 3.125rem; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0.125rem 0 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.ecosystem-dropdown-menu.show-menu, .resources-dropdown-menu.show-menu { + display: block; +} + +.main-menu ul li .ecosystem-dropdown-menu, .main-menu ul li .resources-dropdown-menu { + border-radius: 0; + padding: 0; +} + +.main-menu ul li .ecosystem-dropdown-menu .dropdown-item, .main-menu ul li .resources-dropdown-menu .dropdown-item { + color: #6c6c6d; + border-bottom: 1px solid #e2e2e2; +} + +.header-holder .main-menu ul li a.nav-dropdown-item { + display: block; + font-size: 1rem; + line-height: 1.3125rem; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #979797; + text-align: center; + background-color: transparent; + border-bottom: 1px solid #e2e2e2; +} +.header-holder .main-menu ul li a.nav-dropdown-item:last-of-type { + border-bottom-color: transparent; +} +.header-holder .main-menu ul li a.nav-dropdown-item:hover { + background-color: #e44c2c; + color: white; +} +.header-holder .main-menu ul li a.nav-dropdown-item .dropdown-title { + font-size: 1.125rem; + color: #6c6c6d; + letter-spacing: 0; + line-height: 34px; +} + +.header-holder .main-menu ul li a.nav-dropdown-item:hover .dropdown-title { + background-color: #e44c2c; + color: white; +} + +/*# sourceMappingURL=theme.css.map */ \ No newline at end of file diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..b4e0d666 --- /dev/null +++ b/docs/_templates/autosummary/class.rst @@ -0,0 +1,32 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + {% block methods %} + + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + {%- if item not in inherited_members %} + {%- if not item.startswith('_') or item in ['__call__', '__mul__', '__getitem__', '__len__'] %} + ~{{ name }}.{{ item }} + {% endif %} + {% endif %} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 00000000..37977beb --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,322 @@ +{# 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 %} {% endblock %} + + {# Keep modernizr in head - http://modernizr.com/docs/#installing #} + + + + +
+
+
+ + + + + +
+ +
+
+ + + + + {% block extrabody %} {% endblock %} + + {# SIDE NAV, TOGGLES ON MOBILE #} + + {% include "versions.html" %} + + + + + +
+
+
+ {% include "breadcrumbs.html" %} +
+ +
+ Shortcuts +
+
+ +
+
+ + {%- block content %} + {% if theme_style_external_links|tobool %} + + +
+
+
+ {{ toc }} +
+
+
+
+
+ + {% 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 %} + +
+
+
+ + + +
+
+
+
+ + +
+
+
+ + +
+ + + + + + + + diff --git a/docs/_templates/theme_variables.jinja b/docs/_templates/theme_variables.jinja new file mode 100644 index 00000000..e8ed7384 --- /dev/null +++ b/docs/_templates/theme_variables.jinja @@ -0,0 +1,26 @@ +{%- set external_urls = { + 'github': 'https://github.com/Qiskit-Partners/qiskit-runtime', + 'github_issues': 'https://github.com/Qiskit-Partners/qiskit-runtime/issues', + 'contributing': 'https://github.com/Qiskit/qiskit/blob/master/CONTRIBUTING.md', + 'docs': 'https://qiskit.org/documentation/', + 'api': 'https://runtime-us-east.quantum-computing.ibm.com/openapi/', + 'ml': 'https://qiskit.org/documentation/machine-learning/', + 'nature': 'https://qiskit.org/documentation/nature/', + 'finance': 'https://qiskit.org/documentation/finance/', + 'optim': 'https://qiskit.org/documentation/optimization/', + 'experiments': 'https://qiskit.org/documentation/experiments/', + 'partners': 'https://qiskit.org/documentation/partners/', + 'twitter': 'https://twitter.com/qiskit', + 'events': 'https://qiskit.org/events', + 'textbook': 'https://qiskit.org/textbook', + 'slack': 'https://qiskit.slack.com', + 'home': 'https://qiskit.org/', + 'blog': 'https://pytorch.org/blog/', + 'resources': 'https://qiskit.org/learn', + 'support': 'https://pytorch.org/support', + 'youtube': 'https://www.youtube.com/qiskit', + 'iqx': 'https://quantum-computing.ibm.com/', + 'iqx_systems': 'https://quantum-computing.ibm.com/docs/manage/backends/', + 'ibm': 'https://www.ibm.com/quantum-computing/', +} +-%} diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html new file mode 100644 index 00000000..800a9581 --- /dev/null +++ b/docs/_templates/versions.html @@ -0,0 +1,24 @@ +
+ + {{ version_label }} + + +
+ {% if translations %} +
+
{{ _('Languages') }}
+ {% for code, language in translations_list %} +
{{ language }}
+ {% endfor %} +
+ {% endif %} +
+ +
diff --git a/docs/apidocs/main.rst b/docs/apidocs/main.rst new file mode 100644 index 00000000..27b9a3da --- /dev/null +++ b/docs/apidocs/main.rst @@ -0,0 +1,6 @@ +.. _mthree-main: + +.. automodule:: mthree + :no-members: + :no-inherited-members: + :no-special-members: diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..1fa47578 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- + +# (C) Copyright IBM 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# pylint: disable=invalid-name +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +import mthree as m3 + +""" +Sphinx documentation builder +""" + +# The short X.Y version +version = m3.__version__ +# The full version, including alpha/beta/rc tags +release = m3.__version__ + + +rst_prolog = """ +.. |version| replace:: {0} +""".format(m3.version.short_version) + +# -- Project information ----------------------------------------------------- +project = 'Mthree {}'.format(version) +copyright = '2021, Mthree Team' # pylint: disable=redefined-builtin +author = 'Mthree Development Team' +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.napoleon', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'sphinx.ext.extlinks', + 'jupyter_sphinx' +] +html_static_path = ['_static'] +templates_path = ['_templates'] +html_css_files = ['gallery.css'] + +exclude_patterns = ['_build', '**.ipynb_checkpoints'] + +# ----------------------------------------------------------------------------- +# Autosummary +# ----------------------------------------------------------------------------- +autosummary_generate = True + +# ----------------------------------------------------------------------------- +# Autodoc +# ----------------------------------------------------------------------------- + +autodoc_default_options = { + 'inherited-members': None, +} + +autoclass_content = 'init' + + +# If true, figures, tables and code-blocks are automatically numbered if they +# have a caption. +numfig = True + +# A dictionary mapping 'figure', 'table', 'code-block' and 'section' to +# strings that are used for format of figure numbers. As a special character, +# %s will be replaced to figure number. +numfig_format = { + 'table': 'Table %s' +} +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# A boolean that decides whether module names are prepended to all object names +# (for object types where a “module” of some kind is defined), e.g. for +# py:function directives. +add_module_names = False + +# A list of prefixes that are ignored for sorting the Python module index +# (e.g., if this is set to ['foo.'], then foo.bar is shown under B, not F). +# This can be handy if you document a project that consists of a single +# package. Works only for the HTML builder currently. +modindex_common_prefix = ['mthree.'] + +# -- Configuration for extlinks extension ------------------------------------ +# Refer to https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "qiskit_sphinx_theme" + + +#html_sidebars = {'**': ['globaltoc.html']} +html_last_updated_fmt = '%Y/%m/%d' diff --git a/docs/images/truncation.png b/docs/images/truncation.png new file mode 100644 index 00000000..415c0584 Binary files /dev/null and b/docs/images/truncation.png differ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..d5d855bc --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,35 @@ +################## +mthree (|version|) +################## + +mthree is a package for scalable quantum measurement error mitigation that need not +explicitly form the assignment matrix, or its inverse, as is thus a **m**\atrix-free +**m**\easurement **m**\itigation (M3) routine. + +M3 works in a reduced subspace defined by the noisy input bitstrings that are to be +corrected. Because the number of unique bitstrings can be much smaller than the +dimensionality of the full multi-qubit Hilbert space, the resulting linear system +of equations is nominally much easier to solve. + +.. figure:: images/truncation.png + :align: center + +It is often the case that this linear equation is trivial to solve using LU decomposition, +using only modest computing resources. However, if the number of unique bistrings is large, +and / or one has very tight memory constraints, then the problem can be solved in a matrix-free +manner using an preconditioned interative linear solution method, e.g. the Generalized minimal +residual (GMRES) or biconjugate gradient stabilized (BiCGSTAB) methods. + + +.. toctree:: + :maxdepth: 1 + :hidden: + + self + +.. toctree:: + :maxdepth: 1 + :caption: API Documentation + :hidden: + + Mitigation classes \ No newline at end of file diff --git a/examples/30Q_GHZ_Manhattan.ipynb b/examples/30Q_GHZ_Manhattan.ipynb new file mode 100644 index 00000000..4aa130a1 --- /dev/null +++ b/examples/30Q_GHZ_Manhattan.ipynb @@ -0,0 +1,326 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 30Q GHZ state trial on Manhattan\n", + "\n", + "This notebook requires: `Qiskit >= 0.24`, and of course `mthree >= 0.4.1`. The latter must be installed from source at the moment.\n", + "\n", + "This will attempt to execute a 30Q GHZ state using Manhattan. This is interesting as forming the full mitigation matrix would require $2^{60}$ elements.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy as np\n", + "from qiskit import *\n", + "from qiskit.ignis.mitigation import expectation_value" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "IBMQ.load_account()\n", + "provider = IBMQ.get_provider(group='deployed')\n", + "backend = provider.backend.ibmq_manhattan" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "# Matrix-free Measurement Mitigation (M3) version 0.4.1.dev1+1fabf99\n", + "# (C) Copyright IBM Quantum, 2021\n", + "# Paul Nation, Hwajung Kang, and Jay Gambetta\n", + "================================================================================\n" + ] + } + ], + "source": [ + "import mthree\n", + "mthree.about()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "30" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layers = [[4], \n", + " [5], \n", + " [6,11], \n", + " [7,17,3], \n", + " [8,18,2], \n", + " [12,19,1], \n", + " [21,25,0],\n", + " [22,33,10],\n", + " [23,32,13],\n", + " [26,31,14],\n", + " [37,39,15],\n", + " [45,24]]\n", + "\n", + "qubits = sum(layers, [])\n", + "len(qubits)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Build 30 qubit GHZ circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qc = QuantumCircuit(65, len(qubits))\n", + "qc.h(4)\n", + "#branch 1\n", + "qc.cx(4,5)\n", + "qc.cx(5,6)\n", + "qc.cx(6,7)\n", + "qc.cx(7,8)\n", + "qc.cx(8,12)\n", + "qc.cx(12,21)\n", + "qc.cx(21,22)\n", + "qc.cx(22,23)\n", + "qc.cx(23,26)\n", + "qc.cx(26,37)\n", + "#branch 2\n", + "qc.cx(4,11)\n", + "qc.cx(11,17)\n", + "qc.cx(17,18)\n", + "qc.cx(18,19)\n", + "qc.cx(19,25)\n", + "qc.cx(25,33)\n", + "qc.cx(33,32)\n", + "qc.cx(32,31)\n", + "qc.cx(31,39)\n", + "qc.cx(39,45)\n", + "#branch 3\n", + "qc.cx(4,3)\n", + "qc.cx(3,2)\n", + "qc.cx(2,1)\n", + "qc.cx(1,0)\n", + "qc.cx(0,10)\n", + "qc.cx(10,13)\n", + "qc.cx(13,14)\n", + "qc.cx(14,15)\n", + "qc.cx(15,24)\n", + "qc.measure(qubits, range(len(qubits)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Instantiate M3 Instance" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "mit = mthree.M3Mitigation(backend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calibration" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "mit.tensored_cals_from_system(qubits)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Execute the circuit on the backend and compute the expectation value" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "ghz_job = execute(qc, backend, shots=8192, optimization_level=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3874" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "real_counts = ghz_job.result().get_counts()\n", + "len(real_counts)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0849609375" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expectation_value(real_counts)[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Measurement mitigation by M3 and compute the expectation value" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'method': 'direct',\n", + " 'time': 0.7396790981292725,\n", + " 'dimension': 3874,\n", + " 'col_norms': array([0.9033827 , 0.42526317, 0.71993441, ..., 0.61167295, 0.52939782,\n", + " 0.78016068])}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "quasi, details = mit.apply_correction(real_counts, qubits=qubits, details=True)\n", + "details" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.5027474694623298" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expectation_value(quasi)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/M3_paper_example1.ipynb b/examples/M3_paper_example1.ipynb new file mode 100644 index 00000000..5cfddb7b --- /dev/null +++ b/examples/M3_paper_example1.ipynb @@ -0,0 +1,626 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# M3 paper example 1" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy as np\n", + "from qiskit import *\n", + "import mthree" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.quantum_info import Statevector" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.ignis.mitigation.expval import (expval_meas_mitigator_circuits ,\n", + " TensoredExpvalMeasMitigator,\n", + " ExpvalMeasMitigatorFitter, expectation_value)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "sns.set_theme()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IBMQ.load_account()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "provider = IBMQ.get_provider(group='deployed')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set backend and define circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "backend = provider.backend.ibmq_mumbai" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "qubits= [1,4,7,10,12,13,14,11,8,5,3,2]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
      ┌───┐┌───┐                         ┌───┐\n",
+       " q_0: ┤ X ├┤ H ├─────────────────────────┤ H ├\n",
+       "      ├───┤├───┤                    ┌───┐└─┬─┘\n",
+       " q_1: ┤ X ├┤ H ├────────────────────┤ H ├──■──\n",
+       "      ├───┤├───┤               ┌───┐└─┬─┘     \n",
+       " q_2: ┤ X ├┤ H ├───────────────┤ H ├──■───────\n",
+       "      ├───┤├───┤          ┌───┐└─┬─┘          \n",
+       " q_3: ┤ X ├┤ H ├──────────┤ H ├──■────────────\n",
+       "      ├───┤├───┤     ┌───┐└─┬─┘               \n",
+       " q_4: ┤ X ├┤ H ├─────┤ H ├──■─────────────────\n",
+       "      ├───┤├───┤┌───┐└─┬─┘                    \n",
+       " q_5: ┤ X ├┤ H ├┤ H ├──■──────────────────────\n",
+       "      ├───┤├───┤└─┬─┘                         \n",
+       " q_6: ┤ X ├┤ H ├──■────■──────────────────────\n",
+       "      ├───┤├───┤     ┌─┴─┐                    \n",
+       " q_7: ┤ X ├┤ H ├─────┤ H ├──■─────────────────\n",
+       "      ├───┤├───┤     └───┘┌─┴─┐               \n",
+       " q_8: ┤ X ├┤ H ├──────────┤ H ├──■────────────\n",
+       "      ├───┤├───┤          └───┘┌─┴─┐          \n",
+       " q_9: ┤ X ├┤ H ├───────────────┤ H ├──■───────\n",
+       "      ├───┤├───┤               └───┘┌─┴─┐     \n",
+       "q_10: ┤ X ├┤ H ├────────────────────┤ H ├──■──\n",
+       "      ├───┤├───┤                    └───┘┌─┴─┐\n",
+       "q_11: ┤ X ├┤ H ├─────────────────────────┤ H ├\n",
+       "      └───┘└───┘                         └───┘
" + ], + "text/plain": [ + " ┌───┐┌───┐ ┌───┐\n", + " q_0: ┤ X ├┤ H ├─────────────────────────┤ H ├\n", + " ├───┤├───┤ ┌───┐└─┬─┘\n", + " q_1: ┤ X ├┤ H ├────────────────────┤ H ├──■──\n", + " ├───┤├───┤ ┌───┐└─┬─┘ \n", + " q_2: ┤ X ├┤ H ├───────────────┤ H ├──■───────\n", + " ├───┤├───┤ ┌───┐└─┬─┘ \n", + " q_3: ┤ X ├┤ H ├──────────┤ H ├──■────────────\n", + " ├───┤├───┤ ┌───┐└─┬─┘ \n", + " q_4: ┤ X ├┤ H ├─────┤ H ├──■─────────────────\n", + " ├───┤├───┤┌───┐└─┬─┘ \n", + " q_5: ┤ X ├┤ H ├┤ H ├──■──────────────────────\n", + " ├───┤├───┤└─┬─┘ \n", + " q_6: ┤ X ├┤ H ├──■────■──────────────────────\n", + " ├───┤├───┤ ┌─┴─┐ \n", + " q_7: ┤ X ├┤ H ├─────┤ H ├──■─────────────────\n", + " ├───┤├───┤ └───┘┌─┴─┐ \n", + " q_8: ┤ X ├┤ H ├──────────┤ H ├──■────────────\n", + " ├───┤├───┤ └───┘┌─┴─┐ \n", + " q_9: ┤ X ├┤ H ├───────────────┤ H ├──■───────\n", + " ├───┤├───┤ └───┘┌─┴─┐ \n", + "q_10: ┤ X ├┤ H ├────────────────────┤ H ├──■──\n", + " ├───┤├───┤ └───┘┌─┴─┐\n", + "q_11: ┤ X ├┤ H ├─────────────────────────┤ H ├\n", + " └───┘└───┘ └───┘" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "N = 12\n", + "qc = QuantumCircuit(N)\n", + "\n", + "qc.x(range(0, N))\n", + "qc.h(range(0, N))\n", + "\n", + "for kk in range(N//2,0,-1):\n", + " qc.ch(kk, kk-1)\n", + "for kk in range(N//2, N-1):\n", + " qc.ch(kk, kk+1)\n", + "qc.draw(fold=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.44628906249999983" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state = Statevector.from_instruction(qc)\n", + "ideal_expval = expectation_value(state.probabilities_dict())[0]\n", + "ideal_expval" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "#add measurements to circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "qc.measure_all()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get raw data" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "raw_counts = execute([qc]*100, backend, shots=8192, initial_layout=qubits).result().get_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "raw_dist = []\n", + "for kk in range(100):\n", + " raw_dist.append(expectation_value(raw_counts[kk])[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Mitigate using Ignis tensored expval" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "circs, labels = expval_meas_mitigator_circuits(12, method='tensored')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "job = execute(circs, backend, shots=8192, initial_layout=qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "fitter = ExpvalMeasMitigatorFitter(job.result(), labels).fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TN time: 3.37315623998642\n" + ] + } + ], + "source": [ + "tn_dist = []\n", + "st = time.time()\n", + "for kk in range(100):\n", + " tn_dist.append(expectation_value(raw_counts[kk], meas_mitigator=fitter)[0])\n", + "print('TN time:', (time.time()-st)/100)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Mitigate using M3 and same calibration matrices as Ignis tensored" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "mit = mthree.M3Mitigation(None)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "mats = [None]*16\n", + "\n", + "for kk, mat in enumerate(fitter._assignment_mats):\n", + " mats[qubits[kk]] = mat" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "mit.single_qubit_cals = mats" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "M3 time: 0.013745360374450684\n" + ] + } + ], + "source": [ + "m3_dist = []\n", + "st = time.time()\n", + "for kk in range(100):\n", + " m3_counts = mit.apply_correction(raw_counts[kk], qubits)\n", + " m3_dist.append(expectation_value(m3_counts)[0])\n", + "print('M3 time:', (time.time()-st)/100)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "num_counts = []\n", + "for cnt in raw_counts:\n", + " num_counts.append(len(cnt))" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "697.1" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.mean(num_counts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Take a look at one of the subspace A-matrices used" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "A3, _ = mit.reduced_cal_matrix(raw_counts[-1], qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib.colors import LogNorm\n", + "fig, ax = plt.subplots(figsize=(10,8))\n", + "mat = ax.matshow(A3, cmap='plasma', norm=LogNorm(vmin=A3[A3>1e-3].min(), vmax=1))\n", + "cbar = plt.colorbar(mat);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulation with no measurement error (gate errors only)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.providers.aer.noise import NoiseModel\n", + "sim = Aer.get_backend('qasm_simulator')" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "nm = NoiseModel.from_backend(backend)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "for key, val in nm._local_readout_errors.items():\n", + " nm._local_readout_errors[key]._probabilities = np.identity(2)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "nm_meas_counts = execute([qc]*100, sim, noise_model=nm, shots=8192).result().get_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "no_meas_dist = []\n", + "st = time.time()\n", + "for kk in range(100):\n", + " no_meas_dist.append(expectation_value(nm_meas_counts[kk])[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate plot" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "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TU2Fv78/dDodnnzySWzdutWwfl5eHs6fP49mzZpVe/by+Pn5ISUlxfD66tWruHLlCvz9/c0V18BcucUe84rkzs7Oxvvvv49atWph1apVcHNzM1puqeP9sNyWPN6rV6/GV199ZdR24sQJQy4xx9uc2S11zNu2bYsdO3Zg48aNhi83NzeEh4dj1KhRAMQfc7Op7ummYoqNjRV69+4tpKenC7/88ovQrl07YevWrYIgCML169eFgoICQRCKpyB37NhRmDhxovDff/8JU6ZMETp16mS4HicqKkp4+umnhYMHDwr//POPMHToUKF3796CVqut9uz3+/7770tcMnDkyBHD9V0ZGRnCu+++KwwaNMjic4s95qbm/vzzz4V27doJf//9t9G1WTk5OYIgWO54l5fbUsf7yJEjQsuWLYVVq1YJZ8+eFb788kvB399fuHr1qmG5mONtzuyWOuYPevLJJ40udaiOMTcHSRW//Px8YezYsYK/v7/QpUsXYdmyZYZlpV242bdvX8HX11d49dVXhWPHjhmW5eXlCV988YXQpUsXwc/PTxg6dKhw+fJli8l+T2lFRBAEYcOGDUL37t0Ff39/Yfjw4UJWVpbF5xZ7zE3NHRwcLDRv3rzE1/3XPVnieJeX21LHWxAEYceOHcLzzz9v+Nm8d53cPWKOtzmzW/KY3+/B4icI4o+5OfCRRkREJDmSOedHRER0D4sfERFJDosfERFJDosfERFJDosfERFJDosfERFJDosfSUaPHj1KPCX73tcLL7xQ3fEAFN9NaOPGjRV6EvapU6fw22+/GV736NEDCxcurIJ05vHEE09g06ZN1R2DJE4yN7YmAoDBgwfjvffeK9Fe0dvEVZUjR44gMjISu3btMvk9w4cPx4svvoju3bsDAJKTky3+psJE1c0yfuKJROLo6GjRN9ytzD0nHnxP3bp1zRWHqMbiYU+i+yxduhS+vr6Gu+8XFhbihRdewJAhQwAAUVFRiIyMRGxsLAICAtC1a1fMnz/fqAD9+++/+OCDD+Dn54du3brh888/R05OjmG5VqtFfHw8QkJC4O/vjzfffBNpaWm4dOkS3n77bQDA008/jXnz5gEAfv75Z7z66qto27Yt/Pz88Oabb+Lo0aMAip/IfuHCBcyfPx89evQAUPKw565duxAaGgo/Pz90794d8+bNMzyt+6+//kKbNm3w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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.figure(figsize=(7,7))\n", + "gs = fig.add_gridspec(4, hspace=0.1)\n", + "axs = gs.subplots(sharex=True, sharey=True)\n", + "axs[0].hist(raw_dist, bins=5, color='#009d9a')\n", + "axs[0].legend(['Raw counts'], fontsize=12)\n", + "\n", + "axs[1].hist(tn_dist, bins=10, color='#002d9c')\n", + "axs[1].legend(['Full tensored mitigation'], fontsize=12)\n", + "\n", + "axs[2].hist(m3_dist, bins=10, color='#a56eff')\n", + "axs[2].legend(['M3 tensored mitigation'], fontsize=12)\n", + "axs[2].set_ylabel(' Occurrences', fontsize=15)\n", + "\n", + "axs[3].hist(no_meas_dist, bins=5, color='#9f1853')\n", + "axs[3].legend(['Gate errors only simulation'], fontsize=12)\n", + "axs[3].set_xlabel('Expectation value', fontsize=15)\n", + "for ax in axs:\n", + " ax.label_outer()\n", + " ax.tick_params(labelsize=14);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Look at how mitigation performs verses max Hamming distance" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "m3_weighted_dist = []\n", + "for dist in range(13):\n", + " _temp = []\n", + " for kk in range(100):\n", + " m3_counts = mit.apply_correction(raw_counts[kk], qubits, distance=dist)\n", + " _temp.append(expectation_value(m3_counts)[0])\n", + " m3_weighted_dist.append(_temp)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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jh07AmhoPwB06tTJlKGZRGBgID799FNUV1fD3t4eQMPfw6CgINMGZiSNj7mWlZXhyy+/NEiyBtiHfd/utVxoa3fmzBl88cUXmDNnDgICAiCTyTQ/lsDLywve3t6an7Zt28LW1hbe3t6mDs0ounbtiuHDh2PevHk4f/48Tp06hRUrVmDixIkW8YU1KCgIfn5+mDdvHnJycnDmzBnEx8fjr3/9K5ydnU0dntH169cPnp6emDt3Li5duoT169fj7NmzePbZZ00dmlH885//xM8//4zExETY2dlp/haWl5frtZ7W/5tlQPPmzcPixYsRFRUFBwcHvPrqqxg7dqypwzKKAwcOAABWrlyJlStXau37+eefLeKPtqVLTk7G0qVLERUVBbFYjIiICIsZdCgWi/Hpp5/i/fffR1RUFCQSCUaPHo233nrL1KGZhLW1NdauXYsFCxYgMjISXbp0wZo1ayzmbsP+/fuhVCrxwgsvaJUHBwdj69atequHy2sSERGZAd4SJyIiMgNM2ERERGaACZuIiMgMMGETERGZASZsIiIiM8CETUREZAaYsIlaoWHDhsHX11fzExAQgOHDh2PZsmWaOZ9PnDgBX19fQSsqqdVq7Nq1CyUlJYYOnYiaweewiVqhYcOGYezYsYiKigLQsJrS+fPnkZSUBE9PT2zatAkAcPv2bbi4uNxzsY7Tp0/jueeew6FDhyxmMgyihw2noyJqpezt7bUWX+jSpQu8vb0xYcIE/Otf/8KUKVMEL87A7/VEpsdb4kQWxN/fHyEhIUhPT9e5Jf79998jIiICffr0weDBg7FkyRLU1tbi+vXrmDp1KgBg+PDhWL16NYCG6WknTJiAPn36IDAwEJMnT0ZWVpamLl9fX3z11VeYOnUq+vTpg9GjR2P79u1a8ezatQvjx4/X7P/mm280+3755RfMmTMHwcHBCAsLQ2xsLG7dumXot4joocWETWRhevbsidzcXK2y0tJSzJ49G5MnT8a+ffuwfPlypKenY8OGDejYsSPWrl0LANi5cyeio6ORlZWFv//974iMjER6ejo2b94MAIiPj9c674oVKzB16lR88803ePTRR7F48WLcuHEDAJCeno4FCxbgmWeewe7duzFjxgy88847+PHHH1FdXY1p06ZBKpVi27Zt+Pzzz1FXV4eoqCiddeiJLAVviRNZmLZt22oGnjUqKipCXV0dOnToAC8vL3h5eeGzzz6Dvb09rK2tNWu8Ozs7w8HBARKJBIsWLcLkyZMBNCwp+eyzz+Kdd97ROu+ECRM0C+LExcVh586dyMrKgpeXF7744guMHz9e08/u7e2NqqoqqFQq7N27FzU1NUhKSoK1tTUA4IMPPkD//v3x3XffITw83KDvEdHDiAmbyMJUVVXB0dFRq8zPzw9jxozBSy+9hA4dOmDQoEEYOXJks+uc+/n5wdHREZ9++iny8vJQUFCA7OxsqFQqreO6du2q+Xfbtm0BAHV1dQCA3NxcPPXUU1rHN652lJCQgNLSUjz66KNa+2tqajTrThNZGiZsIgvz888/w9/fX6tMJBLhww8/xOzZs3HkyBH8+OOPePXVVzFx4kQsXrxY5xzHjx/HzJkzMXz4cAQHB2PChAm4evUqFi1apHWcjY2NzmsbB7DdbQlWiUQCHx8frFmzRmffn79sEFkK9mETWZCcnBxkZmbq3FI+d+4cEhMT4ePjgxkzZiA1NRWxsbGaQWAikUjr+C1btmDQoEH48MMPMX36dAwYMEDTNy10RHmPHj1w/vx5rbK4uDi89957eOSRR3D9+nW0a9cO3t7e8Pb2houLCxITE3X634ksBRM2UStVXV0NmUwGmUyGa9euYdeuXZg5cyZCQ0N1bkU7Ojriyy+/xAcffIDCwkJkZ2fj//7v/9CnTx8AgIODAwAgOzsblZWVcHZ2xsWLF3HmzBlcu3YNmzdvxhdffAEAggeFxcTEYPfu3di6dSsKCwuxY8cO7N27F8OGDcP48ePRvn17/P3vf8e5c+eQm5uLN998E2fPnsUjjzyix3eJyHzwljhRK7VhwwZs2LABQEPC9fLywnPPPYcXXnhBM5CrUdeuXfHxxx9j1apV2LRpEyQSCR577DHMmzcPAODj44Mnn3wSsbGxmDJlCubMmYNff/0VM2bMgLW1NXx9fZGUlITY2FicO3dOp++5KSNGjMDChQvx+eef4/3330eXLl2QnJyMsLAwAEBqaiqSkpIQFRUFkUiEoKAgfPHFF3BxcdHzO0VkHjjTGRERkRngLXEiIiIzwIRNRERkBpiwiYiIzAATNhERkRlgwiYiIjIDTNhERERmgAmbiIjIDDBhExERmQEmbCIiIjPw/z46yahSxqm+AAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "out = np.array([np.mean(m3_weighted_dist[kk]) for kk in range(13)])\n", + "fig = plt.figure(figsize=(7,4))\n", + "plt.axhline(np.mean(m3_dist), color='0.3', linestyle='dashed')\n", + "plt.axhline(np.mean(raw_dist), color='0.3', linestyle='dashed')\n", + "plt.plot(range(13), out, 'o-', ms=10, color='#6929c4')\n", + "plt.ylim([0.05,0.25])\n", + "for ax in fig.get_axes():\n", + " ax.label_outer()\n", + " ax.tick_params(labelsize=14)\n", + " \n", + "plt.xlabel('Distance', fontsize=15);\n", + "plt.ylabel('Expectation value', fontsize=15);\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/correcting_for_probabilities.ipynb b/examples/correcting_for_probabilities.ipynb new file mode 100644 index 00000000..3de8c9d4 --- /dev/null +++ b/examples/correcting_for_probabilities.ipynb @@ -0,0 +1,195 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "intimate-cookbook", + "metadata": {}, + "source": [ + "# Correcting GHZ probabilities on Melbourne\n", + "\n", + "Shows how to correct for really bad readout errors and transforming to true probability distribution." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "dietary-business", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from qiskit import *" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "composed-thumb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "# Matrix-free Measurement Mitigation (M3) version 0.4.1.dev1+1fabf99\n", + "# (C) Copyright IBM Quantum, 2021\n", + "# Paul Nation, Hwajung Kang, and Jay Gambetta\n", + "================================================================================\n" + ] + } + ], + "source": [ + "import mthree\n", + "mthree.about()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "natural-hunter", + "metadata": {}, + "outputs": [], + "source": [ + "IBMQ.load_account()\n", + "provider = IBMQ.get_provider(group='deployed')\n", + "backend = provider.backend.ibmq_16_melbourne" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "featured-translator", + "metadata": {}, + "outputs": [], + "source": [ + "qc = QuantumCircuit(5)\n", + "qc.h(2)\n", + "qc.cx(2,1)\n", + "qc.cx(1,0)\n", + "qc.cx(2,3)\n", + "qc.cx(3,4)\n", + "qc.measure_all()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "nominated-dominican", + "metadata": {}, + "outputs": [], + "source": [ + "trans_qc = transpile(qc, backend)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "computational-fabric", + "metadata": {}, + "outputs": [], + "source": [ + "raw_counts = backend.run(trans_qc, shots=2048).result().get_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "expanded-ability", + "metadata": {}, + "outputs": [], + "source": [ + "mit = mthree.M3Mitigation(backend)\n", + "mit.tensored_cals_from_system(range(qc.num_qubits))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fitted-median", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'method': 'direct',\n", + " 'time': 0.002025127410888672,\n", + " 'dimension': 32,\n", + " 'col_norms': array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "quasi, details = mit.apply_correction(raw_counts, range(qc.num_qubits), details=True)\n", + "details" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "physical-suite", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.visualization import plot_histogram" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "completed-accommodation", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAvcAAAFTCAYAAAC9GiPeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAABtj0lEQVR4nO3dd3gVVf7H8ffJvWkkoXcSSmihSQsighQRUdzFuogNEVEQG7qouBbE8lNc17KCou6uWQugq+vCigUUaUoLKEiR3nuHkJ6c3x9zczflBhLSbz6v55mH3LnznTlnZrj3O3PPnGOstYiIiIiISMUXUNYFEBERERGR4qHkXkRERETETyi5FxERERHxE0ruRURERET8hJJ7ERERERE/oeReRERERMRPuMu6AGWpdu3atmnTpmVdDBEREZFzWrly5RFrbR0f8+u63e6/Ae3RjVt/lwmsTU9PH9m1a9dDvhao1Ml906ZNiY+PL+tiiIiIiJyTMWanr/lut/tv9evXb1OnTp3jAQEBGsDIj2VmZprDhw+3PXDgwN+Awb6W0dWdiIiISMXWvk6dOqeU2Pu/gIAAW6dOnZM4v9L4XqYUyyMiIiIixS9AiX3l4TnW+ebwSu5FRERERPyEknsRERERET9RqR+oFREREfFHd71O15Jc/3tjWVmS65fzpzv3IiIiIlLi0tLSyroIlYKSexEREREpEY0aNerwxBNP1G/VqlXbsLCwLo8++miDqKio9mFhYZ2bN2/e7oMPPqietWzDhg07LFq0qArAW2+9VdMY03XlypUhAK+++mrtyy67rHkZVaNCUXIvIiIiIiXm888/r/nVV19tPnbs2M8xMTHJixYt2njq1Kmfx48fv2/UqFHNdu7cGQjQvXv30999910EwKJFiyIiIyNTsr0Ov+SSS06XZT0qCiX3IiIiIlJiRo8efbBFixZp4eHhdsSIEcebNm2a5nK5uOuuu443adIkZdGiRWEAvXv3Tli0aFEEwLJly8IfeuihA9leR/Tv3z+hLOtRUSi5FxEREZES06RJE29j+8mTJ9eKiYlpGxER0SkiIqLTli1bQg8fPuwGGDBgwOn4+PjwXbt2uTMzM80dd9xxLD4+Pnzjxo1Bp0+fdvXo0SOx7GpRcai3HBEREREpMcYYC7Bp06aghx9+uMl///vfTf37909wu93ExMS0tdYZf6t9+/YpISEhmS+//HK97t27n65Ro0Zm7dq109588806sbGxCS6Xq0zrUVHozr2IiIiIlLjTp08HGGOoX79+GsAbb7xRa8uWLaHZl+nevfvpuLi4ur179z4N0LNnz9NxcXF1e/Xqpfb2BaQ79yIiIiJ+pjz2Q9+1a9fku++++2Dv3r3bBAQE2Ouvv/5o586dc7Sj79279+kvv/yy5oABAxIA+vbte/rdd9+t169fP7W3LyCT9VNIZRQbG2vj4+PLuhgiIiIi52SMWWmtjc09f/Xq1Ts6dux4pCzKJGVj9erVtTt27NjU13tqliMiIiIi4ieU3IuIiIiI+Akl9yIiIiIifkLJvYiIiIiIn1ByLyIiIiLiJ5Tci4iIiIj4CSX3IiIiIiJ+Qsm9iIiIiIifUHIvIiIiAnzzzTe0bt2aFi1a8NJLL+W73IoVK3C5XHz22WfeeSdOnOCGG24gJiaGNm3asGTJEgBWr15Njx496NChA7///e85depUiddD8nr77bdr9uzZs2V+73/zzTfhTZs2bV+aZcrPX//611pdu3Ztfb7x7uIsjIiIiEhFlJGRwb333svcuXOJjIykW7duDB48mLZt2+ZZ7rHHHmPgwIE55j/44INcccUVfPbZZ6SmppKYmAjAyJEjeeWVV+jTpw//+Mc/+POf/8xzzz1X4vXZ2vqZriW5/uYbn1lZnOvbv3+/+6qrrmqxbdu2kIyMDJo3b5788ssv77788svPFMf677nnnmP33HPPsazXxpiuv/7669r27dunAFxxxRUJO3bsWFsc27rwwgtbDx069OjDDz9cJqMG6869iIiIVHrLly+nRYsWREdHExQUxNChQ5k5c2ae5d58802uv/566tat65136tQpFi5cyJ133glAUFAQ1atXB2Djxo307t0bgAEDBvD555+XfGUqoGrVqmW8//77248ePfrLyZMnf/njH/944A9/+EPLtLS0si5ahaPkXkRERCq9vXv3EhUV5X0dGRnJ3r178yzzxRdfMHr06Bzzt23bRp06dbjjjjvo3LkzI0eO5MwZ54Zz+/btmTVrFgD/+te/2L17dwnXpHxp1KhRh6eeeqpeq1at2oaGhnYeMmRIk927d7t79+7dMiwsrPPFF1/c6vDhw64qVarYjh07prhcLqy1uFwue+rUKdehQ4d8tjLZuHFjkDGm6xtvvFGrfv36F1StWrXTyy+/XGfBggVVWrVq1TYiIqLTsGHDGmctn72pS2xsbGuAbt26ta1SpUrn9957r8aXX34ZUa9evQuyll+8eHGVNm3atA0LC+t85ZVXRl911VXRDzzwQEOAw4cPu/r169eiRo0aHatWrdqpX79+LbZu3RoIcP/99zdauXJl+OOPP964SpUqnbPK8PPPP4dcfPHFLatVq9apadOm7f/2t7/VyNrWgQMHXJdeemmL8PDwzh06dGizdevW4KLscyX3IiIiUulZa/PMM8bkeD127FgmTZqEy+XKMT89PZ1Vq1Zxzz338PPPPxMWFuZts/+Pf/yDKVOm0LVrV06fPk1QUFDJVaKcmjVrVo3vv/9+0/r169d+99131QcOHNjyxRdf3HPkyJFfMjMzeemll7w/g7Rq1aptSEhIl1tuuaXFjTfeeKRRo0bpZ1v3smXLwrZt2/ZrXFzctqeeeirqueeea/DDDz9sWrNmzbovv/yyxuzZs8Nzx8THx28EWLFixfrExMSf77rrruPZ309OTjZDhgxpfvPNNx85duzYL0OHDj02Z86c6lnvZ2RkcPvttx/ZtWvXrzt37lwTEhKSOWrUqMYAb7755t6uXbsmvPjii7sSExN//uCDD3adOnUq4Morr2x14403Hjty5MgvH3300bZHHnmkcXx8fAjAyJEjm4SEhGTu27dv9T/+8Y/t06dPr12U/a029yIiIlLpRUZG5rirvmfPHho2bJhjmfj4eIYOHQrAkSNH+Oqrr3C73Vx00UVERkbSvXt3AG644QZvch8TE8OcOXMA2LRpE7Nnzy6N6pQro0ePPhQVFZUO0K1bt4TatWun9ezZMwng97///YkffvghImvZTZs2rU9MTDQffvhhjdTUVJPfOrO88MIL+6tUqWKvu+66U6GhoZk33njjsawLgm7duiWsXLmyylVXXZVQmPL+8MMPYenp6eaJJ544FBAQwO23337ir3/9q7ftf/369TOGDx9+Iuv1U089tf+KK67I9wHYTz75pFqjRo1SHnzwwaMAvXr1SrzyyitPTJ8+vUanTp32f/PNN9VXrFixvmrVqpndunVLHjJkyNElS5bkuSgpKCX3IiIiUul169aNzZs3s337dho1asSMGTOYNm1ajmW2b9/u/Xv48OH87ne/45prrgEgKiqKjRs30rp1a77//nvvg7iHDh2i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ERERXHjhhVx99dWsX7+er776itDQUD766CNq1qxJcHAw9913X46HZI8cOcKePXt45plnSryuIr4UpVma2+0mJCSE0NBQwsLCvPM//fRTIiIiCAkJoV69euzZs6dU6iIiOSm5F5FKx1p7XssEBASQkpLCmTNn+POf/4y1lo4dO5KZmQnAvHnzSE5O5vTp09SrVw9rLWlpaSQnJzNs2DDvemrXrk1mZiaNGzfOd/vp6em0bt36PGoncnZFbZYGsHr1apKSkjhz5ox33h133MHzzz9PcnIygwYN4qabbiqV+ohITkruRaTSiYmJ8baVB9i+fbu3zXyWWrVqsWHDBu/rrDbznTp1wuVyceeddwIwcuRI72BT7du3JygoCLfbzaRJk9i1a1cp1EakcIqrK9fcEhMTuf/++wEYPXo0y5cvL6kqiMhZKLkXkUpn2LBhnDx5koULF5KQkMDChQsL3Gb+ggsuICwsjK+//hqAzz77jCZNmgDkSH5eeeUV6tatW2p1Eimoonblaoyhc+fOVKlShVtvvTXHMk8++STgPDCemppaktUQkXy4y7oAIiKlLSQkhCeffJLLLrsMay19+/bl6quv5uabbwZg2rRpPP3003z++ecEBwfjcrl49913vfHvvvsuN9xwA5mZmVSvXp2ffvoJgOuuu459+/ZhjKFatWp888033PV63u2/N7YUKimSj6I0SwNnFOUuXbqwbt06YmNj6d69O/fffz+ffPIJt912G6+//jrdu3fHGFPsZReRc1NyLyKV0oQJE7x9zGeZNm2a9++AgAB+/fVXn7E33ngjN954Y57527Zty7vw/CIVU6TYxcTE8MEHH3hfF6ZZGkCXLl0AaNeuHd27d+fbb7/l/vvvZ9CgQd7mbt9++y0rVqwo6aqIiA9qliMiIlKJFKVZ2qFDh9i3bx8Ahw4dYuXKlVx00UUArFu3DnAeBh8zZgx/+MMfSrdiIgIouRcREalUsjdLq1GjBr169fI2S8tqmvb0009Tv379PF25rl+/nubNmxMaGkrjxo256KKLvO3sn3rqKYKCgqhSpQp16tTh73//e5nVUaQyU7McEZGzUJt58Ufn2yytb9++JCUl+Vznv//97+ItpIicF925FxERERHxE0ruRURERET8hJJ7OW/nO3z5iRMnCA8PJzQ0lJCQEPr06eONady4MaGhoYSGhuJ2uwkNDS21+oiISE53ve57EpHyS8m9nJeiDF9etWpVtmzZQlJSEseOHWPlypX87W9/A2DXrl0kJSWRlJREp06d6NGjR6nXTURERKSiUnIv56Uow5cHBARQv359wBmuPDMzM89gJ5mZmfzyyy88/vjjpVYnERERkYpOyb2cl6IOX56amkpoaCh16tShQ4cO3HnnnTlip0yZQnBwMAMGDCjBWoiISJZvvvmG1q1b06JFC1566aU871tr+enfD/DpCy244IILWLVqFQDJyclceOGFdOzYkXbt2uXoheeRRx4hJiaGCy64gGuvvZYTJ06UVnVEKi0l93Jeijp8eVBQEElJSezYsYNNmzbxxRdf5Fhu6tSpXHrppcVTWBEROauMjAzuvfdevv76a9avX8/06dNZv359jmX2bPiaU4c384c/bebdd9/lnnvuASA4OJh58+YxadIk0tLSmDRpkndQrAEDBrB27VrWrFlDy5Yt6d+/Py1a5Lw42L17N/369aNNmza0a9eON954w7vN1atX06NHDzp06MDvf/97Tp06VUp7RKTiUnIv5yUmJsY7zDgUfvjyLE2aNKFTp045BjtJTk5mw4YNPP300yVUehERyW758uW0aNGC6OhogoKCGDp0KDNnzsyxzM61M2nZbRjGGC666CJOnDjB/v37McYQGhrKvffeyxdffEFMTAxz585l/fr1XH755bjdzpA6QUFB7N+/n82bN9OjRw9iY2MJDAxk2LBh/OUvf2HDhg0sXbqUKVOmsHbtWjp27EinTp1YtWoV48eP59prr2Xs2LHUqFGD4OBgQkJCuO6667zl++STT7ydNYSFhfH++++X6j4UKS+U3Mt5Kcrw5Rs2bGDnzp2A03Rn1apVdOnSxRv3yiuvULVqVbp161aqdRIRqaz27t1LVFSU93VkZCR79+7NscyZk3sJq+57mSVLlnDo0CG6d+/OwIEDGTFiRJ6Lgw8//JBrr72WtLQ0/vGPfxAZGelN6Pfs2QNAREQEbdq04eWXX2bfvn1EREQwefJkRo0axYABA5g/fz6TJ08mJSWFbdu28eWXX3o7cxgzZgyPPvooSUlJPProozz00EMlsq9Eyjsl93JeijJ8+bp162jTpg2hoaE0bNiQrl278uyzz3rXHRcXx6BBg8qkXiIilZGvZpS5OzrgLMscOHCAG2+8kT179rB8+XKA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AjY4ONh+9NFHdt++fbZVq1b2ueees4GBgdbtdntjs1x//fU2MDDQBgcH227dupVI/d955x1bq1Yt7+vLL7+8UOffO++8Y6tWrWqDg4PzxCclJVljjG3atOlZz9+s/Zd9H2RfJvv5GxISYj/66CNvbH77LyoqyntOu1wuGxISUoS95PD1/7c0431JSUmxbrfb/vDDD/b06dM2JCTEzpw5M8cyzzzzjK1du7bNyMiw7733ng0LC8sRe8cdd9jAwEAL2M6dO1trra1Zs6adOHGitdbap59+2gYEBPjc/xdffHGOYzdq1CjboUMHa+3/zl/ANm7c2BtTo0YN72eQtc7nR9b540vdunXt6NGji7inSkZR97/L5bIul8vOnj3bBgcH28DAQDtz5swc+79Pnz7WGJPv8Tvbtq21tmvXrrZfv35Frquv83fka9b73ZV9KoyCxue3/dJSUvU/X0C8LQf5k6byPenOfRnZlnqUGq4q3teRgdUL3SxixIgRBAcH5xhEylrL119/DUCXLl0wxvhss/jQQw/RsmVLb5vF2NhY3G43DRo0ICMjA2stYWFheUaKrVmzZo6BToA8A51ER0eTnp5Onz59vA9SZWne5WZ2rPkcKPqdR193vi655BLv3ZiaNWvSqlUrn/Fbt25l06ZN3m1v376d8PBwVq9e7Y1PTEz09iIEzi8R6enpREVFee9cG2OYN2+e985169atMcbgdruJiYkhNTWVatWqeYdPb9CgAYcOHcq3ScOrr77KvHnzOHLkCMnJyfneOS2qovysDc4vH9m7S83erOeVV16hatWqJCYm5nv+5nfnPy0tzbuN//73vwB57vxnNQm59dZbMcbw7bff0qVLFyDnA70XXHABLperUHc+S/OB6KKc/3/4wx9IT09nwIAB3HDDDd4759nP/2effZZLL700z53zuLg4qlatyocffsicOXO49NJLWb16NbNmzcoxwmfW54iv/b9kyRIiIyO9x27Hjh1AzvO3Tp063HbbbTnqVNA2zOX9gcai/HIRFxdHcHAw1atXZ9CgQfTp04eIiAimTJmSY/+vXr2asLAwn/Hn2nZ5eubF1533kuwxLXvTypdeeinPdke+ZmnX23enELljs5TXTiFE8qPkvozYfHobyP7hcubMmTzvG2O8vdXcfvvtOdp8Z43Sl/uD6YJLH6F6vRhqNryAphdc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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot_histogram([raw_counts, quasi.nearest_probability_distribution()], figsize=(10,5),\n", + " legend=['raw', 'm3-mitigated'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dangerous-entity", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/m3_x8_stabilizer_example.ipynb b/examples/m3_x8_stabilizer_example.ipynb new file mode 100644 index 00000000..f090bcfc --- /dev/null +++ b/examples/m3_x8_stabilizer_example.ipynb @@ -0,0 +1,272 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# $\\langle XXXXXXXX\\rangle$ Stabilizer example\n", + " \n", + "Adapted from Ignis example by Chris Wood" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from qiskit import *\n", + "from qiskit.providers.aer import QasmSimulator, noise\n", + "\n", + "from qiskit.ignis.mitigation import (expectation_value, \n", + " expval_meas_mitigator_circuits,\n", + " ExpvalMeasMitigatorFitter)\n", + "\n", + "import mthree" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load systems and simulators" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IBMQ.load_account()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "pro= IBMQ.get_provider(project='internal-test')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":2: DeprecationWarning: The `backends` provider attribute is deprecated. Please use `provider.backend` (singular) instead. You can continue to use `provider.backends()` to retrieve all backends.\n", + " backend = pro.backends.ibmq_dublin\n" + ] + } + ], + "source": [ + "sim = QasmSimulator()\n", + "backend = pro.backends.ibmq_dublin" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Circuit Measure stabilizer\n", + "# Eight qubit stabilizer\n", + "qubits=[1, 4, 7, 10, 12, 2, 3, 5]\n", + "\n", + "qc = QuantumCircuit(8, 8)\n", + "qc.h(0)\n", + "qc.cx(0, 1)\n", + "qc.cx(1, 2)\n", + "qc.cx(2, 3)\n", + "qc.cx(3, 4)\n", + "qc.cx(0, 5)\n", + "qc.cx(5, 6)\n", + "qc.cx(6, 7)\n", + "qc.h(range(8))\n", + "qc.measure(range(8), range(8))\n", + "\n", + "shots = 8192\n", + "#Get ideal result and raw counts from backend\n", + "result_target = execute(qc, sim, shots=shots, initial_layout=qubits).result()\n", + "result_noise = execute(qc, backend, shots=shots, initial_layout=qubits).result()\n", + "counts_target = result_target.get_counts(0)\n", + "counts_noise = result_noise.get_counts(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Apply M3 correction" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "mit = mthree.M3Mitigation(backend)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "mit.tensored_cals_from_system(qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'method': 'direct',\n", + " 'time': 0.004311084747314453,\n", + " 'dimension': 256,\n", + " 'col_norms': array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1.])}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mit_counts, details = mit.apply_correction(counts_noise, qubits=qubits, details=True)\n", + "details" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Apply CTMP correction" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "circuits1, metadata1 = expval_meas_mitigator_circuits(len(qubits), method='tensored')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "job_cal1 = execute(circuits1, backend, shots=8192, initial_layout=qubits)\n", + "result_cal1 = job_cal1.result()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "ctmp_mitigator = ExpvalMeasMitigatorFitter(result_cal1, metadata1).fit()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tally all results" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ideal: 1.0\n", + "Raw: 0.497802734375\n", + "CTMP mitigated: 1.3377458081929379\n", + "M3 mitigated: 0.9543008693805328\n" + ] + } + ], + "source": [ + "print('Ideal:', expectation_value(counts_target)[0])\n", + "print('Raw:', expectation_value(counts_noise)[0])\n", + "print('CTMP mitigated:', expectation_value(counts_noise, meas_mitigator=ctmp_mitigator)[0])\n", + "print('M3 mitigated:', expectation_value(mit_counts)[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/mthree/__init__.py b/mthree/__init__.py new file mode 100644 index 00000000..285a01ef --- /dev/null +++ b/mthree/__init__.py @@ -0,0 +1,39 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +Mitigation classes +------------------ + +.. autosummary:: + :toctree: ../stubs/ + + M3Mitigation + +""" + +try: + from .version import version as __version__ +except ImportError: + __version__ = '0.0.0' + +from .mitigation import M3Mitigation + + +def about(): + """The M3 version info function. + """ + print('='*80) + print('# Matrix-free Measurement Mitigation (M3) version {}'.format(__version__)) + print('# (C) Copyright IBM Quantum, 2021') + print('# Paul Nation, Hwajung Kang, and Jay Gambetta') + print('='*80) diff --git a/mthree/classes.py b/mthree/classes.py new file mode 100644 index 00000000..db716c38 --- /dev/null +++ b/mthree/classes.py @@ -0,0 +1,108 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""mthree classes""" + +import math +from mthree.probability import quasi_to_probs +from mthree.expval import exp_val, exp_val_and_stddev +from mthree.exceptions import M3Error + + +class ProbDistribution(dict): + """A generic dict-like class for probability distributions. + """ + def __init__(self, data, shots=None): + """Initialize a probability distribution. + + Parameters: + data (dict): Input data. + shots (int): Number shots taken to form distribution. + """ + self.shots = shots + super().__init__(data) + + def expval(self): + """Compute expectation value from distribution. + + Returns: + float: Expectation value. + """ + return exp_val(self) + + def expval_and_stddev(self): + """Compute expectation value and standard deviation from distribution. + + Returns: + float: Expectation value. + float: Standard deviation. + """ + return exp_val_and_stddev(self) + + +class QuasiDistribution(dict): + """A dict-like class for representing quasi-probabilities. + """ + def __init__(self, data, shots=None, mitigation_overhead=None): + """Initialize a quasi-distribution. + + Parameters: + data (dict): Input data. + shots (int): Number shots taken to form quasi-distribution. + mitigation_overhead (float): Overhead from performing mitigation. + """ + self.shots = shots + self.mitigation_overhead = mitigation_overhead + super().__init__(data) + + def expval(self): + """Compute expectation value from distribution. + + Returns: + float: Expectation value. + """ + return exp_val(self) + + def expval_and_stddev(self): + """Compute expectation value and standard deviation estimate from distribution. + + Returns: + float: Expectation value. + float: Estimate of standard deviation upper-bound. + + Raises: + M3Error: Missing shots or mitigation_overhead information. + """ + if self.shots is None: + raise M3Error('Quasi-dist is missing shots information.') + if self.mitigation_overhead is None: + raise M3Error('Quasi-dist is missing mitigation overhead.') + return exp_val(self), math.sqrt(self.mitigation_overhead / self.shots) + + def nearest_probability_distribution(self, return_distance=False): + """Takes a quasiprobability distribution and maps + it to the closest probability distribution as defined by + the L2-norm. + + Parameters: + return_distance (bool): Return the L2 distance between distributions. + + Returns: + ProbDistribution: Nearest probability distribution. + float: Euclidean (L2) distance of distributions. + Notes: + Method from Smolin et al., Phys. Rev. Lett. 108, 070502 (2012). + """ + probs, dist = quasi_to_probs(self) + if return_distance: + return ProbDistribution(probs, self.shots), dist + return ProbDistribution(probs, self.shots) diff --git a/mthree/compute.pxd b/mthree/compute.pxd new file mode 100644 index 00000000..8db290cc --- /dev/null +++ b/mthree/compute.pxd @@ -0,0 +1,30 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +cdef unsigned int within_distance(unsigned int row, + unsigned int col, + const unsigned char * bitstrings, + unsigned int num_bits, + unsigned int distance) nogil + +cdef double compute_element(unsigned int row, + unsigned int col, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits) nogil + +cdef void compute_col_norms(double * col_norms, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits, + unsigned int num_elems, + unsigned int distance) nogil diff --git a/mthree/compute.pyx b/mthree/compute.pyx new file mode 100644 index 00000000..045df6ef --- /dev/null +++ b/mthree/compute.pyx @@ -0,0 +1,137 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +cimport cython +from cython.parallel cimport prange + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef inline unsigned int within_distance(unsigned int row, + unsigned int col, + const unsigned char * bitstrings, + unsigned int num_bits, + unsigned int distance) nogil: + """Computes the Hamming distance between two bitstrings. + + Parameters: + row (unsigned int): The row index. + col (unsigned int): The col index. + bitstrings (unsigned char *): Pointer to array of all bitstrings. + num_bits (unsigned int): The number of bits in a bitstring. + distance (unsigned int): The distance to calculate out to. + + Returns: + unsigned int: Are the bitstrings within given distance. + """ + + cdef size_t kk + cdef unsigned int temp_dist = 0 + cdef unsigned int row_start = row*num_bits + cdef unsigned int col_start = col*num_bits + + for kk in range(num_bits): + temp_dist += bitstrings[row_start+kk] != bitstrings[col_start+kk] + return temp_dist <= distance + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef inline double compute_element(unsigned int row, + unsigned int col, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits) nogil: + """Computes the matrix element specified by the input + bit strings from the supplied tensored cals data. + + Parameters: + row_arr (unsigned char *): Basis element giving row index. + col_arr (unsigned char *): Basis element giving col index. + cals (const double *): Tensored calibration data. + num_qubits (unsigned int): Number of qubits in arrays + + Returns: + double: Matrix element value. + """ + cdef double res = 1 + cdef size_t kk + cdef unsigned int offset + cdef unsigned int row_start = num_bits*row + cdef unsigned int col_start = num_bits*col + + for kk in range(num_bits): + offset = 2*bitstrings[row_start+kk]+bitstrings[col_start+kk] + res *= cals[4*kk+offset] + return res + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void compute_col_norms(double * col_norms, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits, + unsigned int num_elems, + unsigned int distance) nogil: + """Compute the matrix column norms for each bitstring. + + Parameters: + col_norms (double *): Pointer to double array in which to poulate norms. + bitstrings (unsigned char *): Pointer to array of all bitstrings. + num_bits (unsigned int): The number of bits in a bitstring. + num_elems (unsigned int): The number of bitstring elements. + distance (unsigned int): The distance to calculate out to. + """ + cdef size_t col, row + cdef double col_norm + cdef unsigned int MAX_DIST = 0 + + if distance == num_bits: + MAX_DIST = 1 + # Compute the column norm for each element + with nogil: + for col in prange(num_elems, schedule='static'): + col_norm = _inner_col_norm_loop(col, + bitstrings, + cals, + num_bits, + num_elems, + distance, + MAX_DIST) + col_norms[col] = col_norm + + +cdef double _inner_col_norm_loop(unsigned int col, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits, + unsigned int num_elems, + unsigned int distance, + unsigned int MAX_DIST) nogil: + """An inner-loop function for computing col_norms in parallel. + + This is needed to get around an issue with how Cython tries to do + OMP reductions. + + Parameters: + col (int): The column of interest. + col_norms (double *): Pointer to double array in which to poulate norms. + bitstrings (unsigned char *): Pointer to array of all bitstrings. + num_bits (unsigned int): The number of bits in a bitstring. + num_elems (unsigned int): The number of bitstring elements. + distance (unsigned int): The distance to calculate out to. + MAX_DIST (unsigned int): Are we doing max distance. + """ + cdef size_t row + cdef double col_norm = 0 + + for row in range(num_elems): + if MAX_DIST or within_distance(row, col, bitstrings, num_bits, distance): + col_norm += compute_element(row, col, bitstrings, cals, num_bits) + return col_norm diff --git a/mthree/converters.pxd b/mthree/converters.pxd new file mode 100644 index 00000000..2f20b1c5 --- /dev/null +++ b/mthree/converters.pxd @@ -0,0 +1,23 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +from libcpp.map cimport map +from libcpp.string cimport string + +cdef void counts_to_internal(map[string, double] * counts, + unsigned char * vec, + double * probs, + unsigned int num_bits, + double shots) + +cdef void internal_to_probs(map[string, double] * counts, + double * probs) diff --git a/mthree/converters.pyx b/mthree/converters.pyx new file mode 100644 index 00000000..5405ee67 --- /dev/null +++ b/mthree/converters.pyx @@ -0,0 +1,68 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +cimport cython +from libcpp.map cimport map +from libcpp.string cimport string +from cython.operator cimport dereference, postincrement + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void counts_to_internal(map[string, double] * counts_map, + unsigned char * vec, + double * probs, + unsigned int num_bits, + double shots): + """Converts a Qiskit counts object (or Python dict) into an array + of bitstrings and probabilities. + + Parameters: + counts (object): A Qiskit counts object or Python dict. + vec (unsigned char *): Pointer to array of bitstrings to populate. + probs (double *): Pointer to array of probabilities to populate. + num_bits (unsigned int): Number of bits in the bitstrings. + """ + cdef unsigned int idx, letter, start + cdef map[string, double].iterator end = counts_map.end() + cdef map[string, double].iterator it = counts_map.begin() + cdef string temp + idx = 0 + while it != end: + start = num_bits*idx + probs[idx] = dereference(it).second / shots + temp = dereference(it).first + for letter in range(num_bits): + vec[start+letter] = temp[letter]-48 + idx += 1 + postincrement(it) + + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void internal_to_probs(map[string, double] * counts_map, + double * probs): + """Converts internal arrays back into a Python dict. + + Parameters: + vec (unsigned char *): Pointer to array of bitstrings. + vec (dobule *): Pointer to array of probabilities. + num_elems (unsigned int): Number of elements. + num_bits (unsigned int): Number of bits in the bitstrings. + """ + cdef size_t idx = 0 + cdef map[string, double].iterator end = counts_map.end() + cdef map[string, double].iterator it = counts_map.begin() + + while it != end: + dereference(it).second = probs[idx] + idx += 1 + postincrement(it) diff --git a/mthree/exceptions.py b/mthree/exceptions.py new file mode 100644 index 00000000..4c9bf8c9 --- /dev/null +++ b/mthree/exceptions.py @@ -0,0 +1,26 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""mthree exceptions""" + + +class M3Error(Exception): + """Base class for errors raised by M3.""" + + def __init__(self, *message): + """Set the error message.""" + super().__init__(' '.join(message)) + self.message = ' '.join(message) + + def __str__(self): + """Return the message.""" + return repr(self.message) diff --git a/mthree/expval.pyx b/mthree/expval.pyx new file mode 100644 index 00000000..852ebaa5 --- /dev/null +++ b/mthree/expval.pyx @@ -0,0 +1,63 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""mthree expectation value""" +cimport cython +from libc.math cimport sqrt + + +@cython.boundscheck(False) +def exp_val(object quasi): + """Computes expectation value in computational basis. + + Parameters: + quasi (dict): Input quasi-probability distribution. + + Returns: + float: Expectation value. + """ + # Find normalization to probs + cdef double exp_val = 0 + cdef str key + cdef double val + cdef unsigned int one_count + for key, val in quasi.items(): + one_count = key.count('1') % 2 + exp_val += val * (-1 if one_count else 1) + return exp_val + +@cython.boundscheck(False) +def exp_val_and_stddev(object probs): + """Computes expectation value and standard deviation in computational basis + for a given probability distribution (not quasi-probs). + + Parameters: + probs (dict): Input probability distribution. + + Returns: + float: Expectation value. + float: Standard deviation. + """ + # Find normalization to probs + cdef double exp_val = 0 + cdef double stddev, exp2 = 0 + cdef str key + cdef double val + cdef unsigned int one_count + for key, val in probs.items(): + one_count = key.count('1') % 2 + exp_val += val * (-1 if one_count else 1) + exp2 += val + + stddev = sqrt((exp2 - exp_val*exp_val) / probs.shots) + + return exp_val, stddev diff --git a/mthree/hamming.pyx b/mthree/hamming.pyx new file mode 100644 index 00000000..2c5965ae --- /dev/null +++ b/mthree/hamming.pyx @@ -0,0 +1,64 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +cimport cython +import numpy as np + + +def hamming_ball(unsigned char[::1] arr, unsigned int pos, int distance): + """Compute all bitstrings up to a given Hamming distance + away from a target bitstring. + + Parameters: + arr (char array): Input bitstring. + pos (int): Index position. + distance (int): Maximum Hamming distance to consider + + Returns: + list: List of all bitstrings as arrays. + """ + cdef list out = [] + _hamming_core(arr, pos, distance, out) + return out + +@cython.boundscheck(False) +@cython.wraparound(False) +cdef void _hamming_core(unsigned char[::1] arr, unsigned int pos, int distance, list out): + """Compute all bitstrings up to a given Hamming distance + away from a target bitstring. + + Parameters: + arr (char array): Input bitstring. + pos (int): Index position. + distance (int): Maximum Hamming distance to consider + out (list): A empty list to store bitstrings to. + """ + cdef unsigned int length = arr.shape[0] + cdef int dist_offset + cdef unsigned char temp + cdef size_t kk + + if pos == length: + # Here is where you do things for each bitstring + out.append(np.asarray(arr.copy(), dtype=np.uint8)) + return + + if distance > 0: + temp = arr[pos] + for kk in range(2): + arr[pos] = kk + dist_offset = 0 + if temp != arr[pos]: + dist_offset = -1 + _hamming_core(arr, pos+1, distance + dist_offset, out) + arr[pos] = temp + else: + _hamming_core(arr, pos+1, distance, out) diff --git a/mthree/matrix.pyx b/mthree/matrix.pyx new file mode 100644 index 00000000..6e4740df --- /dev/null +++ b/mthree/matrix.pyx @@ -0,0 +1,183 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +cimport cython +from cython.parallel cimport prange +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free +from libcpp.map cimport map +from libcpp.string cimport string +from libcpp cimport bool + +from .converters cimport counts_to_internal +from .compute cimport compute_element, compute_col_norms, within_distance + +@cython.boundscheck(False) +cdef double matrix_element(unsigned int row, + unsigned int col, + const unsigned char * bitstrings, + const double * cals, + unsigned int num_bits, + unsigned int distance, + unsigned int MAX_DIST) nogil: + + cdef size_t kk + cdef double out = 0 + + if MAX_DIST or within_distance(row, col, bitstrings, num_bits, distance): + out = compute_element(row, col, bitstrings, cals, num_bits) + return out + +def bitstring_int(str string): + return int(string, 2) + +@cython.boundscheck(False) +@cython.cdivision(True) +def _reduced_cal_matrix(object counts, double[::1] cals, + unsigned int num_bits, unsigned int distance): + + cdef double shots = sum(counts.values()) + cdef map[string, double] counts_map = counts + cdef unsigned int num_elems = counts_map.size() + cdef unsigned int MAX_DIST + + MAX_DIST = distance == num_bits + cdef double[::1,:] W = np.zeros((num_elems, num_elems), order='F', dtype=float) + + cdef double[::1] col_norms = np.zeros(num_elems, dtype=float) + + cdef unsigned char * bitstrings = malloc(num_bits*num_elems*sizeof(unsigned char)) + cdef double * input_probs = malloc(num_elems*sizeof(double)) + counts_to_internal(&counts_map, bitstrings, input_probs, num_bits, shots) + + cdef size_t ii, jj + cdef double col_norm, _temp + cdef dict out_dict = counts_map + + with nogil: + for jj in prange(num_elems, schedule='static'): + omp_element_compute(jj, bitstrings, &cals[0], num_elems, num_bits, distance, + &W[0,0], &col_norms[0], MAX_DIST) + + free(bitstrings) + free(input_probs) + return np.asarray(W), out_dict, np.asarray(col_norms) + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void omp_element_compute(size_t jj, const unsigned char * bitstrings, + const double * cals_ptr, + unsigned int num_elems, + unsigned int num_bits, + unsigned int distance, + double * W_ptr, + double * col_norms_ptr, + unsigned int MAX_DIST) nogil: + """Computes the matrix elements for a single column + """ + cdef double _temp, col_norm = 0 + cdef size_t ii, col_idx + col_idx = jj*num_elems + for ii in range(num_elems): + _temp = matrix_element(ii, jj, bitstrings, cals_ptr, + num_bits, distance, MAX_DIST) + W_ptr[col_idx+ii] = _temp + col_norm += _temp + col_norms_ptr[jj] = col_norm + for ii in range(num_elems): + W_ptr[col_idx+ii] /= col_norm + +@cython.boundscheck(False) +def sdd_check(dict counts, double[::1] cals, + unsigned int num_bits, unsigned int distance): + """Determines if the sub-space A matrix is strictly + diagonally dominant or not. + + Parameters: + counts (dict): Input dict of counts. + cals (double ndarray): Calibrations. + num_bits (unsigned int): Number of bits in bit-strings. + distance (unsigned int): Distance to go out to. + + Returns: + int: Is matrix SDD or not. + """ + cdef double shots = sum(counts.values()) + cdef map[string, double] counts_map = counts + cdef unsigned int num_elems = counts_map.size() + cdef unsigned int MAX_DIST + + cdef size_t row + cdef unsigned int is_sdd = 1 + + if distance > num_bits: + raise ValueError('Distance ({}) cannot be larger than' + 'the number of bits ({}).'.format(distance, num_bits)) + + MAX_DIST = distance == num_bits + + # Assign memeory for bitstrings and input probabilities + cdef unsigned char * bitstrings = malloc(num_bits*num_elems*sizeof(unsigned char)) + cdef double * input_probs = malloc(num_elems*sizeof(double)) + # Assign memeory for column norms + cdef double * col_norms = malloc(num_elems*sizeof(double)) + + # Assign memeory sdd checks + cdef bool * row_sdd = malloc(num_elems*sizeof(bool)) + # Convert sorted counts dict into bistrings and input probability arrays + counts_to_internal(&counts_map, bitstrings, input_probs, num_bits, shots) + # Compute column norms + compute_col_norms(col_norms, bitstrings, &cals[0], num_bits, num_elems, distance) + + with nogil: + for row in prange(num_elems, schedule='static'): + omp_sdd_compute(row, bitstrings, &cals[0], col_norms, + row_sdd, num_bits, num_elems, distance, MAX_DIST) + + for row in range(num_elems): + if not row_sdd[row]: + is_sdd = 0 + break + + # Free stuff here + # --------------- + free(bitstrings) + free(input_probs) + free(col_norms) + free(row_sdd) + + return is_sdd + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void omp_sdd_compute(size_t row, + const unsigned char * bitstrings, + const double * cals, + const double * col_norms, + bool * row_sdd, + unsigned int num_bits, + unsigned int num_elems, + unsigned int distance, + unsigned int MAX_DIST) nogil: + + cdef size_t col + cdef double diag_elem, mat_elem, row_sum = 0 + + diag_elem = matrix_element(row, row, bitstrings, cals, num_bits, distance, MAX_DIST) + diag_elem /= col_norms[row] + for col in range(num_elems): + if col != row: + mat_elem = matrix_element(row, col, bitstrings, cals, num_bits, distance, MAX_DIST) + mat_elem /= col_norms[col] + row_sum += mat_elem + row_sdd[row] = row_sum < diag_elem diff --git a/mthree/matvec.pyx b/mthree/matvec.pyx new file mode 100644 index 00000000..bf31d7fe --- /dev/null +++ b/mthree/matvec.pyx @@ -0,0 +1,184 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +cimport cython +from cython.parallel cimport prange +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free +from libcpp cimport bool +from libcpp.map cimport map +from libcpp.string cimport string +from cython.operator cimport dereference, postincrement + +from mthree.compute cimport within_distance, compute_element, compute_col_norms + + +cdef class M3MatVec(): + cdef unsigned char * bitstrings + cdef double * col_norms + cdef bool MAX_DIST + cdef unsigned int distance + cdef public unsigned int num_elems + cdef public unsigned int num_bits + cdef double * cals + cdef public dict sorted_counts + + def __cinit__(self, object counts, double[::1] cals, int distance=-1): + + cdef double shots = sum(counts.values()) + cdef map[string, double] counts_map = counts + self.num_elems = counts_map.size() + self.num_bits = len(next(iter(counts))) + self.cals = &cals[0] + self.sorted_counts = counts_map + + if distance == -1: + distance = self.num_bits + + self.distance = distance + self.MAX_DIST = self.distance == self.num_bits + + self.bitstrings = malloc(self.num_bits*self.num_elems*sizeof(unsigned char)) + self.col_norms = malloc(self.num_elems*sizeof(double)) + + counts_to_bitstrings(&counts_map, self.bitstrings, self.num_bits) + + compute_col_norms(self.col_norms, self.bitstrings, self.cals, + self.num_bits, self.num_elems, distance) + + @cython.boundscheck(False) + def get_col_norms(self): + """ + Get the internally used column norms. + + Returns: + ndarray: Column norms. + """ + cdef size_t kk + cdef double[::1] out = np.empty(self.num_elems, dtype=float) + for kk in range(self.num_elems): + out[kk] = self.col_norms[kk] + return np.asarray(out, dtype=float) + + @cython.boundscheck(False) + @cython.cdivision(True) + def get_diagonal(self): + cdef size_t kk + cdef double temp_elem + cdef double[::1] out = np.empty(self.num_elems, dtype=float) + for kk in range(self.num_elems): + temp_elem = compute_element(kk, kk, self.bitstrings, + self.cals, self.num_bits) + temp_elem /= self.col_norms[kk] + out[kk] = temp_elem + return np.asarray(out, dtype=float) + + @cython.boundscheck(False) + def matvec(self, const double[::1] x): + cdef size_t row + if x.shape[0] != self.num_elems: + raise Exception('Incorrect length of input vector.') + cdef double[::1] out = np.empty(self.num_elems, dtype=float) + with nogil: + for row in prange(self.num_elems, schedule='static'): + omp_matvec(row, &x[0], &out[0], + self.bitstrings, self.col_norms, self.cals, + self.num_elems, self.num_bits, self.distance, + self.MAX_DIST) + return np.asarray(out, dtype=float) + + @cython.boundscheck(False) + def rmatvec(self, const double[::1] x): + cdef size_t col + if x.shape[0] != self.num_elems: + raise Exception('Incorrect length of input vector.') + cdef double[::1] out = np.empty(self.num_elems, dtype=float) + with nogil: + for col in prange(self.num_elems, schedule='static'): + omp_rmatvec(col, &x[0], &out[0], + self.bitstrings, self.col_norms, self.cals, + self.num_elems, self.num_bits, self.distance, + self.MAX_DIST) + return np.asarray(out, dtype=float) + + def __dealloc__(self): + if self.bitstrings is not NULL: + free(self.bitstrings) + if self.col_norms is not NULL: + free(self.col_norms) + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void omp_matvec(size_t row, + const double * x, + double * out, + const unsigned char * bitstrings, + const double * col_norms, + const double * cals, + unsigned int num_elems, + unsigned int num_bits, + unsigned int distance, + bool MAX_DIST) nogil: + cdef double temp_elem, row_sum = 0 + cdef size_t col + for col in range(num_elems): + if MAX_DIST or within_distance(row, col, bitstrings, + num_bits, distance): + temp_elem = compute_element(row, col, bitstrings, + cals, num_bits) + temp_elem /= col_norms[col] + row_sum += temp_elem * x[col] + out[row] = row_sum + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void omp_rmatvec(size_t col, + const double * x, + double * out, + const unsigned char * bitstrings, + const double * col_norms, + const double * cals, + unsigned int num_elems, + unsigned int num_bits, + unsigned int distance, + bool MAX_DIST) nogil: + cdef double temp_elem, row_sum = 0 + cdef size_t row + for row in range(num_elems): + if MAX_DIST or within_distance(row, col, bitstrings, + num_bits, distance): + temp_elem = compute_element(row, col, bitstrings, + cals, num_bits) + temp_elem /= col_norms[col] + row_sum += temp_elem * x[row] + out[col] = row_sum + + +@cython.boundscheck(False) +@cython.cdivision(True) +cdef void counts_to_bitstrings(map[string, double] * counts_map, + unsigned char * bitstrings, + unsigned int num_bits): + + cdef unsigned int idx, letter, start + cdef map[string, double].iterator end = counts_map.end() + cdef map[string, double].iterator it = counts_map.begin() + cdef string temp + idx = 0 + while it != end: + start = num_bits*idx + temp = dereference(it).first + for letter in range(num_bits): + bitstrings[start+letter] = temp[letter]-48 + idx += 1 + postincrement(it) diff --git a/mthree/mitigation.py b/mthree/mitigation.py new file mode 100644 index 00000000..4da87415 --- /dev/null +++ b/mthree/mitigation.py @@ -0,0 +1,504 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""Calibration data""" + +import warnings +from time import perf_counter + +import psutil +import numpy as np +import scipy.linalg as la +import scipy.sparse.linalg as spla +import orjson +from qiskit import QuantumCircuit, transpile + +from mthree.matrix import _reduced_cal_matrix, sdd_check +from mthree.utils import counts_to_vector, vector_to_quasiprobs +from mthree.norms import ainv_onenorm_est_lu, ainv_onenorm_est_iter +from mthree.matvec import M3MatVec +from mthree.exceptions import M3Error + + +def _tensor_meas_states(qubit, num_qubits): + """Construct |0> and |1> states + for marginal 1Q cals. + """ + qc0 = QuantumCircuit(num_qubits, 1) + qc0.measure(qubit, 0) + qc1 = QuantumCircuit(num_qubits, 1) + qc1.x(qubit) + qc1.measure(qubit, 0) + return [qc0, qc1] + + +def _marg_meas_states(num_qubits): + """Construct all zeros and all ones states + for marginal 1Q cals. + """ + qc0 = QuantumCircuit(num_qubits) + qc0.measure_all() + qc1 = QuantumCircuit(num_qubits) + qc1.x(range(num_qubits)) + qc1.measure_all() + return [qc0, qc1] + + +class M3Mitigation(): + """Main M3 calibration class.""" + def __init__(self, system, iter_threshold=4096): + """Main M3 calibration class. + + Parameters: + system (BaseBackend): Target backend. + iter_threshold (int): Sets the bitstring count at which iterative mode + is turned on (assuming reasonable error rates). + + Attributes: + system (BaseBackend): The target system. + single_qubit_cals (list): 1Q calibration matrices + """ + self.system = system + self.single_qubit_cals = None + self.num_qubits = system.configuration().num_qubits if system else None + self.iter_threshold = iter_threshold + self.cal_shots = None + self.cal_method = 'marginal' + self.rep_delay = None + + def _form_cals(self, qubits): + """Form the 1D cals array from tensored cals data + + Parameters: + qubits (array_like): The qubits to calibrate over. + + Returns: + ndarray: 1D Array of float cals data. + """ + qubits = np.asarray(qubits, dtype=int) + cals = np.zeros(4*qubits.shape[0], dtype=float) + + # Reverse index qubits for easier indexing later + for kk, qubit in enumerate(qubits[::-1]): + cals[4*kk:4*kk+4] = self.single_qubit_cals[qubit].ravel() + return cals + + def _check_sdd(self, counts, qubits, distance=None): + """Checks if reduced A-matrix is SDD or not + + Parameters: + counts (dict): Dictionary of counts. + qubits (array_like): List of qubits. + distance (int): Distance to compute over. + + Returns: + bool: True if A-matrix is SDD, else False + + Raises: + M3Error: Number of qubits supplied does not match bit-string length. + """ + # If distance is None, then assume max distance. + num_bits = len(qubits) + if distance is None: + distance = num_bits + + # check if len of bitstrings does not equal number of qubits passed. + bitstring_len = len(next(iter(counts))) + if bitstring_len != num_bits: + raise M3Error('Bitstring length ({}) does not match'.format(bitstring_len) + + ' number of qubits ({})'.format(num_bits)) + cals = self._form_cals(qubits) + return sdd_check(counts, cals, num_bits, distance) + + def tensored_cals_from_system(self, qubits=None, method='marginal', + shots=8192, rep_delay=None, counts_file=None): + """Grab calibration data from system. + + Parameters: + qubits (array_like): Qubits over which to correct calibration data. Default is all. + method (str): Type of calibration, 'marginal' (default) or 'independent'. + shots (int): Number of shots per circuit. Default is 8192. + rep_delay (float): Delay between circuits on IBM Quantum backends. + counts_file (str): Output path to write JSON calibration data to. + """ + warnings.warn("This method is deprecated, use 'cals_from_system' instead.") + self.cals_from_system(qubits=qubits, method=method, + shots=shots, rep_delay=rep_delay, + counts_file=counts_file) + + def cals_from_system(self, qubits=None, method='marginal', + shots=8192, rep_delay=None, counts_file=None): + """Grab calibration data from system. + + Parameters: + qubits (array_like): Qubits over which to correct calibration data. Default is all. + method (str): Type of calibration, 'marginal' (default) or 'independent'. + shots (int): Number of shots per circuit. Default is 8192. + rep_delay (float): Delay between circuits on IBM Quantum backends. + counts_file (str): Output path to write JSON calibration data to. + """ + if qubits is None: + qubits = range(self.num_qubits) + self.cal_method = method + self.rep_delay = rep_delay + self._grab_additional_cals(qubits, method, shots) + if counts_file: + with open(counts_file, 'wb') as fd: + fd.write(orjson.dumps(self.single_qubit_cals, + option=orjson.OPT_SERIALIZE_NUMPY)) + + def cals_from_file(self, counts_file): + """Generated the calibration data from a previous runs output + + counts_file (str): A string path to the saved counts file from an + earlier run. + """ + with open(counts_file, 'r') as fd: + self.single_qubit_cals = np.array(orjson.loads(fd.read())) + + def tensored_cals_from_file(self, counts_file): + """Generated the tensored calibration data from a previous runs output + + counts_file (str): A string path to the saved counts file from an + earlier run. + """ + warnings.warn("This method is deprecated, use 'cals_from_file' instead.") + self.cals_from_file(counts_file) + + def _grab_additional_cals(self, qubits, method='marginal', shots=8192, rep_delay=None): + """Grab missing calibration data from backend. + + Parameters: + qubits (array_like): List of measured qubits. + method (str): Type of calibration, 'marginal' (default) or 'independent'. + shots (int): Number of shots to take. + rep_delay (float): Delay between circuits on IBM Quantum backends. + + Raises: + M3Error: Faulty qubits found. + """ + if self.single_qubit_cals is None: + self.single_qubit_cals = [None]*self.num_qubits + if self.cal_shots is None: + self.cal_shots = shots + if self.rep_delay is None: + self.rep_delay = rep_delay + + if method not in ['marginal', 'independent']: + raise M3Error('Invalid calibration method.') + + num_cal_qubits = len(qubits) + if method == 'marginal': + circs = _marg_meas_states(num_cal_qubits) + trans_qcs = transpile(circs, self.system, + initial_layout=qubits, optimization_level=0) + job = self.system.run(trans_qcs, shots=self.cal_shots, rep_delay=self.rep_delay) + else: + circs = [] + for kk in qubits: + circs.extend(_tensor_meas_states(kk, self.num_qubits)) + + trans_qcs = transpile(circs, self.system, + initial_layout=qubits, optimization_level=0) + job = self.system.run(trans_qcs, shots=self.cal_shots, rep_delay=self.rep_delay) + counts = job.result().get_counts() + + # A list of qubits with bad meas cals + bad_list = [] + if method == 'independent': + for idx, qubit in enumerate(qubits): + self.single_qubit_cals[qubit] = np.zeros((2, 2), dtype=float) + # Counts 0 has all P00, P10 data, so do that here + prep0_counts = counts[2*idx] + P10 = prep0_counts.get('1', 0) / shots + P00 = 1-P10 + self.single_qubit_cals[qubit][:, 0] = [P00, P10] + # plus 1 here since zeros data at pos=0 + prep1_counts = counts[2*idx+1] + P01 = prep1_counts.get('0', 0) / shots + P11 = 1-P01 + self.single_qubit_cals[qubit][:, 1] = [P01, P11] + if P01 >= P00: + bad_list.append(qubit) + else: + prep0_counts = counts[0] + prep1_counts = counts[1] + for idx, qubit in enumerate(qubits): + self.single_qubit_cals[qubit] = np.zeros((2, 2), dtype=float) + count_vals = 0 + index = num_cal_qubits-idx-1 + for key, val in prep0_counts.items(): + if key[index] == '0': + count_vals += val + P00 = count_vals / shots + P10 = 1-P00 + self.single_qubit_cals[qubit][:, 0] = [P00, P10] + count_vals = 0 + for key, val in prep1_counts.items(): + if key[index] == '1': + count_vals += val + P11 = count_vals / shots + P01 = 1-P11 + self.single_qubit_cals[qubit][:, 1] = [P01, P11] + if P01 >= P00: + bad_list.append(qubit) + + if any(bad_list): + raise M3Error('Faulty qubits detected: {}'.format(bad_list)) + + def apply_correction(self, counts, qubits, distance=None, + method='auto', + max_iter=25, tol=1e-5, + return_mitigation_overhead=False, + details=False): + """Applies correction to given counts. + + Parameters: + counts (dict): Input counts dict. + qubits (array_like): Qubits on which measurements applied. + distance (int): Distance to correct for. Default=num_bits + method (str): Solution method: 'auto', 'iterative', 'direct'. + max_iter (int): Max. number of iterations, Default=25. + tol (float): Convergence tolerance of iterative method, Default=1e-5. + return_mitigation_overhead (bool): Returns the mitigation overhead, default=False. + details (bool): Return extra info, default=False. + + Returns: + QuasiDistribution: Dictionary of mitigated counts as probabilities. + + Raises: + M3Error: Bitstring length does not match number of qubits given. + """ + # This is needed because counts is a Counts object in Qiskit not a dict. + counts = dict(counts) + shots = sum(counts.values()) + + # If distance is None, then assume max distance. + num_bits = len(qubits) + num_elems = len(counts) + if distance is None: + distance = num_bits + + # check if len of bitstrings does not equal number of qubits passed. + bitstring_len = len(next(iter(counts))) + if bitstring_len != num_bits: + raise M3Error('Bitstring length ({}) does not match'.format(bitstring_len) + + ' number of qubits ({})'.format(num_bits)) + + # Check if no cals done yet + if self.single_qubit_cals is None: + warnings.warn('No calibration data. Calibrating: {}'.format(qubits)) + self._grab_additional_cals(qubits, method=self.cal_method) + + # Check if one or more new qubits need to be calibrated. + missing_qubits = [qq for qq in qubits if self.single_qubit_cals[qq] is None] + if any(missing_qubits): + warnings.warn('Computing missing calibrations for qubits: {}'.format(missing_qubits)) + self._grab_additional_cals(missing_qubits, method=self.cal_method) + + if method == 'auto': + current_free_mem = psutil.virtual_memory().available + # First check if direct method can be run + if num_elems <= self.iter_threshold \ + and ((num_elems**2+num_elems)*8/1024**3 < current_free_mem/1.5): + method = 'direct' + # If readout is not so good try direct if memory allows + elif np.min(self.readout_fidelity(qubits)) < 0.85 \ + and ((num_elems**2+num_elems)*8/1024**3 < current_free_mem/1.5): + method = 'direct' + else: + method = 'iterative' + + if method == 'direct': + st = perf_counter() + mit_counts, col_norms, gamma = self._direct_solver(counts, qubits, distance, + return_mitigation_overhead) + dur = perf_counter()-st + mit_counts.shots = shots + if gamma is not None: + mit_counts.mitigation_overhead = gamma * gamma + if details: + info = {'method': 'direct', 'time': dur, 'dimension': num_elems} + info['col_norms'] = col_norms + return mit_counts, info + return mit_counts + + elif method == 'iterative': + iter_count = np.zeros(1, dtype=int) + + def callback(_): + iter_count[0] += 1 + + if details: + st = perf_counter() + mit_counts, col_norms, gamma = self._matvec_solver(counts, + qubits, + distance, + tol, + max_iter, + 1, + callback, + return_mitigation_overhead) + dur = perf_counter()-st + mit_counts.shots = shots + if gamma is not None: + mit_counts.mitigation_overhead = gamma * gamma + info = {'method': 'iterative', 'time': dur, 'dimension': num_elems} + info['iterations'] = iter_count[0] + info['col_norms'] = col_norms + return mit_counts, info + # pylint: disable=unbalanced-tuple-unpacking + mit_counts, gamma = self._matvec_solver(counts, qubits, distance, tol, + max_iter, 0, None, + return_mitigation_overhead) + mit_counts.shots = shots + if gamma is not None: + mit_counts.mitigation_overhead = gamma * gamma + return mit_counts + + else: + raise M3Error('Invalid method: {}'.format(method)) + + def reduced_cal_matrix(self, counts, qubits, distance=None): + """Return the reduced calibration matrix used in the solution. + + Parameters: + counts (dict): Input counts dict. + qubits (array_like): Qubits on which measurements applied. + distance (int): Distance to correct for. Default=num_bits + + Returns: + ndarray: 2D array of reduced calibrations. + dict: Counts in order they are displayed in matrix. + + Raises: + M3Error: If bit-string length does not match passed number + of qubits. + """ + counts = dict(counts) + # If distance is None, then assume max distance. + num_bits = len(qubits) + if distance is None: + distance = num_bits + + # check if len of bitstrings does not equal number of qubits passed. + bitstring_len = len(next(iter(counts))) + if bitstring_len != num_bits: + raise M3Error('Bitstring length ({}) does not match'.format(bitstring_len) + + ' number of qubits ({})'.format(num_bits)) + + cals = self._form_cals(qubits) + A, counts, _ = _reduced_cal_matrix(counts, cals, num_bits, distance) + return A, counts + + def _direct_solver(self, counts, qubits, distance=None, + return_mitigation_overhead=False): + """Apply the mitigation using direct LU factorization. + + Parameters: + counts (dict): Input counts dict. + qubits (int): Qubits over which to calibrate. + distance (int): Distance to correct for. Default=num_bits + return_mitigation_overhead (bool): Returns the mitigation overhead, default=False. + + Returns: + QuasiDistribution: dict of Quasiprobabilites + """ + cals = self._form_cals(qubits) + num_bits = len(qubits) + A, sorted_counts, col_norms = _reduced_cal_matrix(counts, cals, num_bits, distance) + vec = counts_to_vector(sorted_counts) + LU = la.lu_factor(A, check_finite=False) + x = la.lu_solve(LU, vec, check_finite=False) + gamma = None + if return_mitigation_overhead: + gamma = ainv_onenorm_est_lu(A, LU) + out = vector_to_quasiprobs(x, sorted_counts) + return out, col_norms, gamma + + def _matvec_solver(self, counts, qubits, distance, tol=1e-5, max_iter=25, + details=0, callback=None, + return_mitigation_overhead=False): + """Compute solution using GMRES and Jacobi preconditioning. + + Parameters: + counts (dict): Input counts dict. + qubits (int): Qubits over which to calibrate. + tol (float): Tolerance to use. + max_iter (int): Maximum number of iterations to perform. + distance (int): Distance to correct for. Default=num_bits + details (bool): Return col norms. + callback (callable): Callback function to record iteration count. + return_mitigation_overhead (bool): Returns the mitigation overhead, default=False. + + Returns: + QuasiDistribution: dict of Quasiprobabilites + + Raises: + M3Error: Solver did not converge. + """ + cals = self._form_cals(qubits) + M = M3MatVec(dict(counts), cals, distance) + L = spla.LinearOperator((M.num_elems, M.num_elems), + matvec=M.matvec, rmatvec=M.rmatvec) + diags = M.get_diagonal() + + def precond_matvec(x): + out = x / diags + return out + + P = spla.LinearOperator((M.num_elems, M.num_elems), precond_matvec) + vec = counts_to_vector(M.sorted_counts) + out, error = spla.gmres(L, vec, tol=tol, atol=tol, maxiter=max_iter, + M=P, callback=callback) + if error: + raise M3Error('GMRES did not converge: {}'.format(error)) + + gamma = None + if return_mitigation_overhead: + gamma = ainv_onenorm_est_iter(M, tol=tol, max_iter=max_iter) + + quasi = vector_to_quasiprobs(out, M.sorted_counts) + if details: + return quasi, M.get_col_norms(), gamma + return quasi, gamma + + def readout_fidelity(self, qubits=None): + """Compute readout fidelity for calibrated qubits. + + Parameters: + qubits (array_like): Qubits to compute over, default is all. + + Returns: + list: List of qubit fidelities. + + Raises: + M3Error: Mitigator is not calibrated. + M3Error: Qubit indices out of range. + """ + if self.single_qubit_cals is None: + raise M3Error('Mitigator is not calibrated') + + if qubits is None: + qubits = range(self.num_qubits) + else: + outliers = [kk for kk in qubits if kk >= self.num_qubits] + if any(outliers): + raise M3Error('One or more qubit indices out of range: {}'.format(outliers)) + fids = [] + for kk in qubits: + qubit = self.single_qubit_cals[kk] + if qubit is not None: + fids.append(np.mean(qubit.diagonal())) + else: + fids.append(None) + return fids diff --git a/mthree/norms.py b/mthree/norms.py new file mode 100644 index 00000000..3c59f5b5 --- /dev/null +++ b/mthree/norms.py @@ -0,0 +1,179 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""mthree one-norm estimators""" + +import numpy as np +import scipy.linalg as la +import scipy.sparse.linalg as spla +from mthree.exceptions import M3Error + + +def ainv_onenorm_est_lu(A, LU=None): + """ + Estimates the one-norm of the inverse A**-1 of the input + matrix A using direct LU factorization. + + Parameters: + A (ndarray): Input square matrix. + LU (ndarray): Perfactored LU of A, if any. + + Returns: + float: Estimate of one-norm for A**-1. + + Notes: + This uses the modified Hager's method (Alg. 4.1) from + N. J. Higham, ACM Trans. Math. Software, Vol. 14, 381 (1988). + """ + dims = A.shape[0] + + # Starting vec + v = (1.0/dims)*np.ones(dims, dtype=float) + + # Factor A and A.T + if LU is None: + LU = la.lu_factor(A, check_finite=False) + LU_T = la.lu_factor(A.T, check_finite=False) + + # Initial solve + v = la.lu_solve(LU, v, check_finite=False) + gamma = la.norm(v, 1) + eta = np.sign(v) + x = la.lu_solve(LU_T, eta, check_finite=False) + + # loop over reasonable number of trials + k = 2 + while k < 6: + x_nrm = la.norm(x, np.inf) + idx = np.where(np.abs(x) == x_nrm)[0][0] + v = np.zeros(dims, dtype=float) + v[idx] = 1 + v = la.lu_solve(LU, v, check_finite=False) + + gamma_prime = gamma + gamma = la.norm(v, 1) + + if gamma <= gamma_prime or np.allclose(np.sign(v), eta): + break + + eta = np.sign(v) + x = la.lu_solve(LU_T, eta, check_finite=False) + if la.norm(x, np.inf) == x[idx]: + break + k += 1 + + # After loop do Higham's check for cancellations. + x = np.arange(1, dims+1) + x = (-1)**(x+1)*(1+(x-1)/(dims-1)) + + x = la.lu_solve(LU, x, check_finite=False) + + temp = 2*la.norm(x, 1)/(3*dims) + + if temp > gamma: + gamma = temp + + return gamma + + +def ainv_onenorm_est_iter(M, tol=1e-5, max_iter=25): + """ + Estimates the one-norm of the inverse A**-1 of the input + matrix A using itertive GMRES. + + Parameters: + M (M3MatVec): M3 matrix-vector multiplication container. + tol (float): Tolerance of iterative solver. + max_iter (int): Number of max iterations to perform. + + Returns: + float: Estimate of one-norm for A**-1. + + Notes: + This uses the modified Hager's method (Alg. 4.1) from + N. J. Higham, ACM Trans. Math. Software, Vol. 14, 381 (1988). + + Raises: + M3Error: Error in iterative solver. + """ + # Setup linear operator interfaces + L = spla.LinearOperator((M.num_elems, M.num_elems), + matvec=M.matvec) + + LT = spla.LinearOperator((M.num_elems, M.num_elems), + matvec=M.rmatvec) + + diags = M.get_diagonal() + + def precond_matvec(x): + out = x / diags + return out + + P = spla.LinearOperator((M.num_elems, M.num_elems), precond_matvec) + + dims = M.num_elems + + # Starting vec + v = (1.0/dims)*np.ones(dims, dtype=float) + + # Initial solve + v, error = spla.gmres(L, v, tol=tol, atol=tol, maxiter=max_iter, + M=P) + if error: + raise M3Error('Iterative solver error {}'.format(error)) + gamma = la.norm(v, 1) + eta = np.sign(v) + x, error = spla.gmres(LT, eta, tol=tol, atol=tol, maxiter=max_iter, + M=P) + if error: + raise M3Error('Iterative solver error {}'.format(error)) + # loop over reasonable number of trials + k = 2 + while k < 6: + x_nrm = la.norm(x, np.inf) + idx = np.where(np.abs(x) == x_nrm)[0][0] + v = np.zeros(dims, dtype=float) + v[idx] = 1 + v, error = spla.gmres(L, v, tol=tol, atol=tol, maxiter=max_iter, + M=P) + if error: + raise M3Error('Iterative solver error {}'.format(error)) + gamma_prime = gamma + gamma = la.norm(v, 1) + + if gamma <= gamma_prime or np.allclose(np.sign(v), eta, atol=tol): + break + + eta = np.sign(v) + x, error = spla.gmres(LT, eta, tol=tol, atol=tol, maxiter=max_iter, + M=P) + if error: + raise M3Error('Iterative solver error {}'.format(error)) + if la.norm(x, np.inf) == x[idx]: + break + k += 1 + + # After loop do Higham's check for cancellations. + x = np.arange(1, dims+1) + x = (-1)**(x+1)*(1+(x-1)/(dims-1)) + + x, error = spla.gmres(L, x, tol=tol, atol=tol, maxiter=max_iter, + M=P) + if error: + raise M3Error('Iterative solver error {}'.format(error)) + + temp = 2*la.norm(x, 1)/(3*dims) + + if temp > gamma: + gamma = temp + + return gamma diff --git a/mthree/probability.pyx b/mthree/probability.pyx new file mode 100644 index 00000000..9c8bd8c8 --- /dev/null +++ b/mthree/probability.pyx @@ -0,0 +1,44 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +cimport cython +from libc.math cimport sqrt + +@cython.boundscheck(False) +@cython.cdivision(True) +def quasi_to_probs(object quasiprobs): + """Takes a quasiprobability distribution and maps + it to the closest probability distribution as defined by + the L2-norm. + Parameters: + quasiprobs (QuasiDistribution): Input quasiprobabilities. + Returns: + dict: Nearest probability distribution + float: Distance between distributions + Notes: + Method from Smolin et al., Phys. Rev. Lett. 108, 070502 (2012). + """ + cdef dict sorted_probs = dict(sorted(quasiprobs.items(), key=lambda item: item[1])) + cdef unsigned int num_elems = len(sorted_probs) + cdef dict new_probs = {} + cdef double beta = 0 + cdef object key + cdef double val, temp, diff = 0 + for key, val in sorted_probs.items(): + temp = val+beta/num_elems + if temp < 0: + beta += val + num_elems -= 1 + diff += val*val + else: + diff += (beta/num_elems)*(beta/num_elems) + new_probs[key] = sorted_probs[key] + beta/num_elems + return new_probs, sqrt(diff) diff --git a/mthree/test/__init__.py b/mthree/test/__init__.py new file mode 100644 index 00000000..67cf3852 --- /dev/null +++ b/mthree/test/__init__.py @@ -0,0 +1,11 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. diff --git a/mthree/test/column_testing.pyx b/mthree/test/column_testing.pyx new file mode 100644 index 00000000..3bcd46ac --- /dev/null +++ b/mthree/test/column_testing.pyx @@ -0,0 +1,46 @@ +# This code is part of mthree. +# +# (C) Copyright IBM Quantum 2021. +# +# This code is for internal IBM Quantum use only. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +cimport cython +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free +from libcpp.map cimport map +from libcpp.string cimport string + +from mthree.compute cimport compute_col_norms +from mthree.converters cimport counts_to_internal + + +def _test_vector_column_norm(object counts, + double[::1] cals, + int distance): + """Test computing the column norm on a full vector + + Parameters: + col (unsigned char memoryview): Bitstring for column + cals (double memoryview): Input calibration data. + distance (int): Distance (weight) of errors to consider. + """ + cdef unsigned int num_bits = len(next(iter(counts))) + cdef double shots = sum(counts.values()) + cdef map[string, double] counts_map = counts + cdef unsigned int num_elems = counts_map.size() + + # Assign memeory for bitstrings and input probabilities + cdef unsigned char * bitstrings = malloc(num_bits*num_elems*sizeof(unsigned char)) + cdef double * input_probs = malloc(num_elems*sizeof(double)) + # Assign memeory for column norms + cdef double[::1] col_norms = np.zeros(num_elems, dtype=float) + + # Convert sorted counts dict into bistrings and input probability arrays + counts_to_internal(&counts_map, bitstrings, input_probs, num_bits, shots) + # Compute column norms + compute_col_norms(&col_norms[0], bitstrings, &cals[0], num_bits, num_elems, distance) + + free(bitstrings) + free(input_probs) + return np.asarray(col_norms) \ No newline at end of file diff --git a/mthree/test/converters_testing.pyx b/mthree/test/converters_testing.pyx new file mode 100644 index 00000000..802ed9df --- /dev/null +++ b/mthree/test/converters_testing.pyx @@ -0,0 +1,71 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# cython: c_string_type=unicode, c_string_encoding=UTF-8 +cimport cython +import numpy as np +from libc.stdlib cimport malloc, free +from libcpp.map cimport map +from libcpp.string cimport string + +from mthree.converters cimport counts_to_internal, internal_to_probs + + +def _test_counts_to_array(object counts): + + cdef double shots = sum(counts.values()) + cdef unsigned int num_bits = len(next(iter(counts))) + cdef map[string, double] counts_map = counts + cdef unsigned int num_elems = counts_map.size() + cdef size_t kk, ll + cdef list out + + # Assign memeory for bitstrings and input probabilities + cdef unsigned char * bitstrings = malloc(num_bits*num_elems*sizeof(unsigned char)) + cdef double * input_probs = malloc(num_elems*sizeof(double)) + + # Convert sorted counts dict into bistrings and input probability arrays + counts_to_internal(&counts_map, bitstrings, input_probs, num_bits, shots) + + out = ['']*num_elems + + for kk in range(num_elems): + for ll in range(num_bits): + out[kk] += str(bitstrings[kk*num_bits+ll]) + + #free data + free(bitstrings) + free(input_probs) + return out + + +def _test_counts_roundtrip(object counts): + + cdef double shots = sum(counts.values()) + cdef unsigned int num_bits = len(next(iter(counts))) + cdef map[string, double] counts_map = counts + cdef unsigned int num_elems = counts_map.size() + cdef size_t kk, ll + + # Assign memeory for bitstrings and input probabilities + cdef unsigned char * bitstrings = malloc(num_bits*num_elems*sizeof(unsigned char)) + cdef double * input_probs = malloc(num_elems*sizeof(double)) + + # Convert sorted counts dict into bistrings and input probability arrays + counts_to_internal(&counts_map, bitstrings, input_probs, num_bits, shots) + internal_to_probs(&counts_map, input_probs) + cdef dict out = counts_map + + #free data + free(bitstrings) + free(input_probs) + + return out diff --git a/mthree/test/test_columns.py b/mthree/test/test_columns.py new file mode 100644 index 00000000..de3c2233 --- /dev/null +++ b/mthree/test/test_columns.py @@ -0,0 +1,79 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test the converters""" +import numpy as np +from mthree.hamming import hamming_ball +from .column_testing import _test_vector_column_norm + + +mats = [np.array([[0.9954, 0.0682], + [0.0046, 0.9318]]), + np.array([[0.9494, 0.1236], + [0.0506, 0.8764]]), + np.array([[0.9778, 0.04], + [0.0222, 0.96]]), + np.array([[0.9718, 0.0726], + [0.0282, 0.9274]]), + np.array([[0.9832, 0.0568], + [0.0168, 0.9432]])] + +cals = np.array([0.9832, 0.0568, 0.0168, 0.9432, 0.9718, 0.0726, 0.0282, 0.9274, + 0.9778, 0.04, 0.0222, 0.96, 0.9494, 0.1236, 0.0506, 0.8764, + 0.9954, 0.0682, 0.0046, 0.9318]) + +FULL_MAT = np.kron(mats[1], mats[0]) +for ll in range(2, len(mats)): + FULL_MAT = np.kron(mats[ll], FULL_MAT) + + +def test_vector_colnorm_d0(): + """Distance 0 vector col_norm gives diagonal elements""" + + counts = {} + for kk in range(32): + counts[bin(kk)[2:].zfill(5)] = 1/32 + + out = _test_vector_column_norm(counts, cals, 0) + + for kk in range(32): + assert abs(out[kk] - FULL_MAT[kk, kk]) < 1e-15 + + +def test_vector_colnorm_d3(): + """Distance 3 vector col_norm verification""" + + counts = {} + for kk in range(32): + counts[bin(kk)[2:].zfill(5)] = 1/32 + + out = _test_vector_column_norm(counts, cals, 3) + + for kk in range(32): + arr = np.fromiter(bin(kk)[2:].zfill(5), np.uint8) + elems = hamming_ball(arr, 0, 3) + rows = np.asarray([np.sum(bits*2**np.arange(5)[::-1]) for bits in elems]) + assert abs(out[kk] - np.sum(FULL_MAT[rows, kk])) < 1e-15 + + +def test_vector_colnorm_d5(): + """Distance 5 vector col_norm gives unit norm for 5Q matrix""" + + counts = {} + for kk in range(32): + counts[bin(kk)[2:].zfill(5)] = 1/32 + + out = _test_vector_column_norm(counts, cals, 5) + + for kk in range(32): + assert abs(out[kk] - 1) < 1e-15 diff --git a/mthree/test/test_converters.py b/mthree/test/test_converters.py new file mode 100644 index 00000000..be9997fa --- /dev/null +++ b/mthree/test/test_converters.py @@ -0,0 +1,63 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test the converters""" +from mthree.matrix import bitstring_int +from .converters_testing import _test_counts_roundtrip, _test_counts_to_array + +COUNTS = {'00000': 520, + '00001': 10, + '10000': 21, + '10011': 1, + '10100': 3, + '10101': 4, + '10110': 2, + '10111': 23, + '11000': 3, + '11001': 4, + '11010': 1, + '11011': 17, + '11100': 8, + '11101': 64, + '11110': 36, + '11111': 374, + '00010': 33, + '00011': 4, + '00100': 4, + '00101': 2, + '00111': 5, + '01000': 11, + '01010': 2, + '01011': 1, + '01101': 4, + '01110': 4, + '01111': 31} + + +def test_counts_converted_properly(): + """Tests counts strings are converted properly""" + # The counts need to be sorted by int value as that is what + # the cpp_map is doing internally. + sorted_counts = dict(sorted(COUNTS.items(), + key=lambda item: bitstring_int(item[0]))) + ans_list = list(sorted_counts.keys()) + out_list = _test_counts_to_array(COUNTS) + assert ans_list == out_list + + +def test_roundtrip_convert(): + """Tests converts work roundtrip""" + shots = sum(COUNTS.values()) + out = _test_counts_roundtrip(COUNTS) + for key, val in COUNTS.items(): + assert abs(val/shots - out[key]) <= 1e-15 diff --git a/mthree/test/test_extra_cals.py b/mthree/test/test_extra_cals.py new file mode 100644 index 00000000..3a408cc9 --- /dev/null +++ b/mthree/test/test_extra_cals.py @@ -0,0 +1,87 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test is various methods agree""" + +import numpy as np +import orjson +from qiskit import QuantumCircuit, execute +from qiskit.test.mock import FakeAthens + +import mthree + + +def test_missing_qubit_cal(): + """Test if missing calibration is retrived at apply_correcton.""" + + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(1, 0) + qc.cx(2, 3) + qc.cx(3, 4) + qc.measure_all() + + backend = FakeAthens() + raw_counts = execute(qc, backend, shots=2048).result().get_counts() + + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(range(4)) + + assert mit.single_qubit_cals[4] is None + + _ = mit.apply_correction(raw_counts, range(5)) + + assert not any(mit.single_qubit_cals[kk] is None for kk in range(5)) + + +def test_missing_all_cals(): + """Test if calibrations get added if none set before.""" + + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(1, 0) + qc.cx(2, 3) + qc.cx(3, 4) + qc.measure_all() + + backend = FakeAthens() + raw_counts = execute(qc, backend, shots=2048).result().get_counts() + + mit = mthree.M3Mitigation(backend) + _ = mit.apply_correction(raw_counts, range(5)) + + assert not any(mit.single_qubit_cals[kk] is None for kk in range(5)) + + +def test_save_cals(tmp_path): + """Test if passing a calibration file saves the correct JSON.""" + backend = FakeAthens() + cal_file = tmp_path / "cal.json" + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(counts_file=cal_file) + with open(cal_file, 'r') as fd: + cals = np.array(orjson.loads(fd.read())) + assert np.array_equal(mit.single_qubit_cals, cals) + + +def test_load_cals(tmp_path): + """Test if loading a calibration JSON file correctly loads the cals.""" + cal_file = tmp_path / "cal.json" + backend = FakeAthens() + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(counts_file=cal_file) + new_mit = mthree.M3Mitigation(backend) + new_mit.cals_from_file(cal_file) + assert np.array_equal(mit.single_qubit_cals, new_mit.single_qubit_cals) diff --git a/mthree/test/test_full.py b/mthree/test/test_full.py new file mode 100644 index 00000000..991859e3 --- /dev/null +++ b/mthree/test/test_full.py @@ -0,0 +1,373 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test matrix elements""" +import numpy as np +import scipy.linalg as la + +from mthree import M3Mitigation +from mthree.matrix import bitstring_int + + +def test_full_problem(): + """Tests if matrix elements can be computed properly from the data""" + + # Compute using M3 + qubits = [1, 4, 7, 10, 12, 2, 3, 5] + mit = M3Mitigation(None) + mit.single_qubit_cals = CALS + mit_counts = mit.apply_correction(COUNTS, qubits, tol=1e-10, method='iterative') + + # Compute using LU solver + sorted_counts = dict(sorted(COUNTS.items(), key=lambda item: bitstring_int(item[0]))) + vec = counts_to_vector(sorted_counts) + + A = np.kron(mit.single_qubit_cals[qubits[1]], mit.single_qubit_cals[qubits[0]]) + for kk in range(2, len(qubits)): + A = np.kron(mit.single_qubit_cals[qubits[kk]], A) + + x = la.solve(A, vec) + lu_counts = vector_to_probs(x, sorted_counts) + + for key, val in lu_counts.items(): + assert abs(val - mit_counts[key]) < 1e-9 + + +def counts_to_vector(counts): + """ Return probability vector from counts dict. + + Parameters: + counts (dict): Input dict of counts. + + Returns: + ndarray: 1D array of probabilities. + """ + shots = sum(counts.values()) + vec = np.zeros(len(counts), dtype=float) + idx = 0 + for val in counts.values(): + vec[idx] = val / shots + idx += 1 + return vec + + +def vector_to_probs(vec, counts): + """ Return dict of probabilities. + + Parameters: + vec (ndarray): 1d vector of probabilites. + counts (dict): Dict of counts + + Returns: + dict: dict of probabilities + """ + out_counts = {} + idx = 0 + for key in counts: + out_counts[key] = vec[idx] + idx += 1 + return out_counts + + +COUNTS = {'00000000': 70, + '00000001': 33, + '00010000': 34, + '00000010': 30, + '00100000': 36, + '00000100': 20, + '01000000': 28, + '00001000': 31, + '10000000': 30, + '00010001': 34, + '00010010': 45, + '00010100': 56, + '00011000': 75, + '00100001': 50, + '00100010': 48, + '00100100': 30, + '00101000': 28, + '00000011': 46, + '00110000': 42, + '01000001': 59, + '01000010': 54, + '01000100': 42, + '01001000': 42, + '00000101': 30, + '01010000': 43, + '00000110': 47, + '01100000': 60, + '10000001': 48, + '10000010': 57, + '10000100': 30, + '10001000': 38, + '00001001': 33, + '10010000': 38, + '00001010': 33, + '10100000': 37, + '00001100': 36, + '11000000': 58, + '00010011': 22, + '00010101': 37, + '00010110': 35, + '00011001': 50, + '00011010': 38, + '00011100': 21, + '00100011': 37, + '00100101': 25, + '00100110': 34, + '00101001': 23, + '00101010': 38, + '00101100': 21, + '00110001': 34, + '00110010': 17, + '00110100': 23, + '00111000': 41, + '01000011': 28, + '01000101': 21, + '01000110': 23, + '01001001': 19, + '01001010': 13, + '01001100': 25, + '01010001': 29, + '01010010': 33, + '01010100': 26, + '01011000': 36, + '01100001': 40, + '01100010': 38, + '01100100': 37, + '01101000': 36, + '00000111': 26, + '01110000': 30, + '10000011': 24, + '10000101': 20, + '10000110': 20, + '10001001': 22, + '10001010': 18, + '10001100': 24, + '10010001': 23, + '10010010': 15, + '10010100': 17, + '10011000': 21, + '10100001': 32, + '10100010': 34, + '10100100': 23, + '10101000': 16, + '00001011': 23, + '10110000': 19, + '11000001': 24, + '11000010': 23, + '11000100': 30, + '11001000': 23, + '00001101': 31, + '11010000': 21, + '00001110': 30, + '11100000': 28, + '00010111': 47, + '00011011': 43, + '00011101': 53, + '00011110': 37, + '00100111': 40, + '00101011': 48, + '00101101': 39, + '00101110': 32, + '00110011': 32, + '00110101': 51, + '00110110': 44, + '00111001': 66, + '00111010': 49, + '00111100': 40, + '01000111': 47, + '01001011': 31, + '01001101': 33, + '01001110': 40, + '01010011': 38, + '01010101': 47, + '01010110': 40, + '01011001': 56, + '01011010': 38, + '01011100': 47, + '01100011': 45, + '01100101': 38, + '01100110': 31, + '01101001': 32, + '01101010': 38, + '01101100': 36, + '01110001': 35, + '01110010': 28, + '01110100': 49, + '01111000': 50, + '10000111': 36, + '10001011': 38, + '10001101': 37, + '10001110': 33, + '10010011': 25, + '10010101': 34, + '10010110': 35, + '10011001': 52, + '10011010': 41, + '10011100': 34, + '10100011': 45, + '10100101': 25, + '10100110': 34, + '10101001': 26, + '10101010': 19, + '10101100': 39, + '10110001': 21, + '10110010': 25, + '10110100': 31, + '10111000': 45, + '11000011': 41, + '11000101': 26, + '11000110': 39, + '11001001': 31, + '11001010': 29, + '11001100': 36, + '11010001': 25, + '11010010': 36, + '11010100': 39, + '11011000': 47, + '11100001': 53, + '11100010': 39, + '11100100': 35, + '11101000': 28, + '00001111': 45, + '11110000': 23, + '00011111': 36, + '00101111': 26, + '00110111': 26, + '00111011': 37, + '00111101': 23, + '00111110': 29, + '01001111': 16, + '01010111': 26, + '01011011': 31, + '01011101': 17, + '01011110': 23, + '01100111': 25, + '01101011': 25, + '01101101': 32, + '01101110': 26, + '01110011': 30, + '01110101': 26, + '01110110': 28, + '01111001': 30, + '01111010': 30, + '01111100': 31, + '10001111': 23, + '10010111': 22, + '10011011': 24, + '10011101': 21, + '10011110': 19, + '10100111': 18, + '10101011': 12, + '10101101': 14, + '10101110': 18, + '10110011': 26, + '10110101': 17, + '10110110': 20, + '10111001': 28, + '10111010': 19, + '10111100': 19, + '11000111': 16, + '11001011': 13, + '11001101': 20, + '11001110': 28, + '11010011': 14, + '11010101': 24, + '11010110': 24, + '11011001': 33, + '11011010': 28, + '11011100': 18, + '11100011': 36, + '11100101': 15, + '11100110': 15, + '11101001': 24, + '11101010': 26, + '11101100': 20, + '11110001': 28, + '11110010': 25, + '11110100': 27, + '11111000': 24, + '00111111': 40, + '01011111': 38, + '01101111': 30, + '01110111': 30, + '01111011': 50, + '01111101': 35, + '01111110': 32, + '10011111': 26, + '10101111': 27, + '10110111': 33, + '10111011': 46, + '10111101': 32, + '10111110': 29, + '11001111': 31, + '11010111': 35, + '11011011': 43, + '11011101': 36, + '11011110': 35, + '11100111': 30, + '11101011': 23, + '11101101': 38, + '11101110': 37, + '11110011': 30, + '11110101': 30, + '11110110': 38, + '11111001': 36, + '11111010': 44, + '11111100': 24, + '01111111': 27, + '10111111': 15, + '11011111': 17, + '11101111': 16, + '11110111': 24, + '11111011': 23, + '11111101': 17, + '11111110': 10, + '11111111': 19} + +CALS = [None, + np.array([[0.98299193, 0.01979335], + [0.01700807, 0.98020665]]), + np.array([[0.96917076, 0.03369085], + [0.03082924, 0.96630915]]), + np.array([[0.9858876, 0.02348826], + [0.0141124, 0.97651174]]), + np.array([[0.99496994, 0.02733885], + [0.00503006, 0.97266115]]), + np.array([[0.96395599, 0.18330204], + [0.03604401, 0.81669796]]), + None, + np.array([[0.98876682, 0.03722461], + [0.01123318, 0.96277539]]), + None, + None, + np.array([[0.99187792, 0.06334372], + [0.00812208, 0.93665628]]), + None, + np.array([[0.94568855, 0.07140989], + [0.05431145, 0.92859011]]), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None] diff --git a/mthree/test/test_matvec.py b/mthree/test/test_matvec.py new file mode 100644 index 00000000..44efda42 --- /dev/null +++ b/mthree/test/test_matvec.py @@ -0,0 +1,57 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""Test matrix elements""" +import numpy as np +import scipy.sparse.linalg as spla +from qiskit import QuantumCircuit, execute +from qiskit.test.mock import FakeAthens +import mthree +from mthree.matvec import M3MatVec + + +def test_matvec(): + """Check that matvec and rmatvec values are returned as expected""" + backend = FakeAthens() + + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(2, 3) + qc.cx(1, 0) + qc.cx(3, 4) + qc.measure_all() + + raw_counts = execute(qc, backend).result().get_counts() + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(range(5)) + + cals = mit._form_cals(range(5)) + M = M3MatVec(dict(raw_counts), cals, 5) + L = spla.LinearOperator((M.num_elems, M.num_elems), + matvec=M.matvec) + + LT = spla.LinearOperator((M.num_elems, M.num_elems), + matvec=M.rmatvec) + + A = mit.reduced_cal_matrix(raw_counts, range(5))[0] + vec = (-1)**np.arange(M.num_elems)*np.ones(M.num_elems, dtype=float) / M.num_elems + + v1 = L.dot(vec) + v2 = A.dot(vec) + + assert np.allclose(v1, v2, atol=1e-14) + + v3 = LT.dot(vec) + v4 = (A.T).dot(vec) + + assert np.allclose(v3, v4, atol=1e-14) diff --git a/mthree/test/test_methods.py b/mthree/test/test_methods.py new file mode 100644 index 00000000..4e392f08 --- /dev/null +++ b/mthree/test/test_methods.py @@ -0,0 +1,69 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test is various methods agree""" + +import numpy as np +from qiskit import QuantumCircuit, execute +from qiskit.test.mock import FakeAthens +import mthree + + +def test_methods_equality(): + """Make sure direct and iterative solvers agree with each other.""" + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(1, 0) + qc.cx(2, 3) + qc.cx(3, 4) + qc.measure_all() + + backend = FakeAthens() + raw_counts = execute(qc, backend, shots=2048).result().get_counts() + + mit = mthree.M3Mitigation(backend) + mit.cals_from_system() + + iter_q = mit.apply_correction(raw_counts, range(5), method='iterative') + direct_q = mit.apply_correction(raw_counts, range(5), method='direct') + + for key, val in direct_q.items(): + assert key in iter_q.keys() + assert np.abs(val-iter_q[key]) < 1e-5 + + +def test_set_iterative(): + """Make sure can overload auto setting""" + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(1, 0) + qc.cx(2, 3) + qc.cx(3, 4) + qc.measure_all() + + backend = FakeAthens() + raw_counts = execute(qc, backend, shots=4096).result().get_counts() + + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(shots=4096) + + _, details = mit.apply_correction(raw_counts, range(5), + method='iterative', + details=True) + assert details['method'] == 'iterative' + + _, details = mit.apply_correction(raw_counts, range(5), + details=True) + assert details['method'] == 'direct' diff --git a/mthree/test/test_probability.py b/mthree/test/test_probability.py new file mode 100644 index 00000000..a7c70c78 --- /dev/null +++ b/mthree/test/test_probability.py @@ -0,0 +1,29 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test conversion to probability distribution""" +import numpy as np +from mthree.classes import QuasiDistribution + + +def test_known_conversion(): + """Reproduce conversion from Smolin PRL""" + qprobs = {'0': 3/5, '1': 1/2, '2': 7/20, '3': 1/10, '4': -11/20} + closest, dist = QuasiDistribution(qprobs).nearest_probability_distribution( + return_distance=True) + ans = {'0': 9/20, '1': 7/20, '2': 1/5} + + for key, val in closest.items(): + assert abs(ans[key] - val) < 1e-14 + + assert abs(dist-np.sqrt(0.38)) < 1e-14 diff --git a/mthree/test/test_quasi_attr.py b/mthree/test/test_quasi_attr.py new file mode 100644 index 00000000..612b3dfa --- /dev/null +++ b/mthree/test/test_quasi_attr.py @@ -0,0 +1,59 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""Test matrix elements""" +from qiskit import QuantumCircuit, execute +from qiskit.test.mock import FakeMontreal +import mthree + + +def test_quasi_attr_set(): + """Test quasi-probs attributes are set""" + backend = FakeMontreal() + + N = 6 + qc = QuantumCircuit(N) + qc.x(range(0, N)) + qc.h(range(0, N)) + for kk in range(N//2, 0, -1): + qc.ch(kk, kk-1) + for kk in range(N//2, N-1): + qc.ch(kk, kk+1) + qc.measure_all() + + qubits = [1, 4, 7, 10, 12, 13] + + mit = mthree.M3Mitigation(backend) + mit.cals_from_system(qubits) + + raw_counts = execute(qc, backend, shots=1024, + initial_layout=qubits).result().get_counts() + quasi1 = mit.apply_correction(raw_counts, qubits, + return_mitigation_overhead=True, method='direct') + quasi2 = mit.apply_correction(raw_counts, qubits, + return_mitigation_overhead=True, method='iterative') + + quasi3 = mit.apply_correction(raw_counts, qubits, + return_mitigation_overhead=False, method='direct') + quasi4 = mit.apply_correction(raw_counts, qubits, + return_mitigation_overhead=False, method='iterative') + + shots = 1024 + assert quasi1.shots == shots + assert quasi2.shots == shots + assert quasi3.shots == shots + assert quasi4.shots == shots + + assert quasi1.mitigation_overhead is not None + assert quasi2.mitigation_overhead is not None + assert quasi3.mitigation_overhead is None + assert quasi4.mitigation_overhead is None diff --git a/mthree/test/test_reduced_matrix.py b/mthree/test/test_reduced_matrix.py new file mode 100644 index 00000000..1aa0afaa --- /dev/null +++ b/mthree/test/test_reduced_matrix.py @@ -0,0 +1,364 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test matrix elements""" +import numpy as np + +from mthree import M3Mitigation + + +def test_reduced_matrix(): + """Tests if matrix elements can be computed properly from the data""" + + # Compute using M3 + qubits = [1, 4, 7, 10, 12, 2, 3, 5] + mit = M3Mitigation(None) + mit.single_qubit_cals = CALS + M = mit.reduced_cal_matrix(COUNTS, qubits)[0] + # Compute using LU solver + A = np.kron(mit.single_qubit_cals[qubits[1]], mit.single_qubit_cals[qubits[0]]) + for kk in range(2, len(qubits)): + A = np.kron(mit.single_qubit_cals[qubits[kk]], A) + + assert np.linalg.norm(A-M, np.inf) < 1e-14 + + +def counts_to_vector(counts): + """ Return probability vector from counts dict. + + Parameters: + counts (dict): Input dict of counts. + + Returns: + ndarray: 1D array of probabilities. + """ + shots = sum(counts.values()) + num_bits = len(next(iter(counts))) + vec = np.zeros(2**num_bits, dtype=float) + idx = 0 + for val in counts.values(): + vec[idx] = val / shots + idx += 1 + return vec + + +def vector_to_probs(vec, counts): + """ Return dict of probabilities. + + Parameters: + vec (ndarray): 1d vector of probabilites. + counts (dict): Dict of counts + + Returns: + dict: dict of probabilities + """ + out_counts = {} + idx = 0 + for key in counts: + out_counts[key] = vec[idx] + idx += 1 + return out_counts + + +COUNTS = {'00000000': 70, + '00000001': 33, + '00010000': 34, + '00000010': 30, + '00100000': 36, + '00000100': 20, + '01000000': 28, + '00001000': 31, + '10000000': 30, + '00010001': 34, + '00010010': 45, + '00010100': 56, + '00011000': 75, + '00100001': 50, + '00100010': 48, + '00100100': 30, + '00101000': 28, + '00000011': 46, + '00110000': 42, + '01000001': 59, + '01000010': 54, + '01000100': 42, + '01001000': 42, + '00000101': 30, + '01010000': 43, + '00000110': 47, + '01100000': 60, + '10000001': 48, + '10000010': 57, + '10000100': 30, + '10001000': 38, + '00001001': 33, + '10010000': 38, + '00001010': 33, + '10100000': 37, + '00001100': 36, + '11000000': 58, + '00010011': 22, + '00010101': 37, + '00010110': 35, + '00011001': 50, + '00011010': 38, + '00011100': 21, + '00100011': 37, + '00100101': 25, + '00100110': 34, + '00101001': 23, + '00101010': 38, + '00101100': 21, + '00110001': 34, + '00110010': 17, + '00110100': 23, + '00111000': 41, + '01000011': 28, + '01000101': 21, + '01000110': 23, + '01001001': 19, + '01001010': 13, + '01001100': 25, + '01010001': 29, + '01010010': 33, + '01010100': 26, + '01011000': 36, + '01100001': 40, + '01100010': 38, + '01100100': 37, + '01101000': 36, + '00000111': 26, + '01110000': 30, + '10000011': 24, + '10000101': 20, + '10000110': 20, + '10001001': 22, + '10001010': 18, + '10001100': 24, + '10010001': 23, + '10010010': 15, + '10010100': 17, + '10011000': 21, + '10100001': 32, + '10100010': 34, + '10100100': 23, + '10101000': 16, + '00001011': 23, + '10110000': 19, + '11000001': 24, + '11000010': 23, + '11000100': 30, + '11001000': 23, + '00001101': 31, + '11010000': 21, + '00001110': 30, + '11100000': 28, + '00010111': 47, + '00011011': 43, + '00011101': 53, + '00011110': 37, + '00100111': 40, + '00101011': 48, + '00101101': 39, + '00101110': 32, + '00110011': 32, + '00110101': 51, + '00110110': 44, + '00111001': 66, + '00111010': 49, + '00111100': 40, + '01000111': 47, + '01001011': 31, + '01001101': 33, + '01001110': 40, + '01010011': 38, + '01010101': 47, + '01010110': 40, + '01011001': 56, + '01011010': 38, + '01011100': 47, + '01100011': 45, + '01100101': 38, + '01100110': 31, + '01101001': 32, + '01101010': 38, + '01101100': 36, + '01110001': 35, + '01110010': 28, + '01110100': 49, + '01111000': 50, + '10000111': 36, + '10001011': 38, + '10001101': 37, + '10001110': 33, + '10010011': 25, + '10010101': 34, + '10010110': 35, + '10011001': 52, + '10011010': 41, + '10011100': 34, + '10100011': 45, + '10100101': 25, + '10100110': 34, + '10101001': 26, + '10101010': 19, + '10101100': 39, + '10110001': 21, + '10110010': 25, + '10110100': 31, + '10111000': 45, + '11000011': 41, + '11000101': 26, + '11000110': 39, + '11001001': 31, + '11001010': 29, + '11001100': 36, + '11010001': 25, + '11010010': 36, + '11010100': 39, + '11011000': 47, + '11100001': 53, + '11100010': 39, + '11100100': 35, + '11101000': 28, + '00001111': 45, + '11110000': 23, + '00011111': 36, + '00101111': 26, + '00110111': 26, + '00111011': 37, + '00111101': 23, + '00111110': 29, + '01001111': 16, + '01010111': 26, + '01011011': 31, + '01011101': 17, + '01011110': 23, + '01100111': 25, + '01101011': 25, + '01101101': 32, + '01101110': 26, + '01110011': 30, + '01110101': 26, + '01110110': 28, + '01111001': 30, + '01111010': 30, + '01111100': 31, + '10001111': 23, + '10010111': 22, + '10011011': 24, + '10011101': 21, + '10011110': 19, + '10100111': 18, + '10101011': 12, + '10101101': 14, + '10101110': 18, + '10110011': 26, + '10110101': 17, + '10110110': 20, + '10111001': 28, + '10111010': 19, + '10111100': 19, + '11000111': 16, + '11001011': 13, + '11001101': 20, + '11001110': 28, + '11010011': 14, + '11010101': 24, + '11010110': 24, + '11011001': 33, + '11011010': 28, + '11011100': 18, + '11100011': 36, + '11100101': 15, + '11100110': 15, + '11101001': 24, + '11101010': 26, + '11101100': 20, + '11110001': 28, + '11110010': 25, + '11110100': 27, + '11111000': 24, + '00111111': 40, + '01011111': 38, + '01101111': 30, + '01110111': 30, + '01111011': 50, + '01111101': 35, + '01111110': 32, + '10011111': 26, + '10101111': 27, + '10110111': 33, + '10111011': 46, + '10111101': 32, + '10111110': 29, + '11001111': 31, + '11010111': 35, + '11011011': 43, + '11011101': 36, + '11011110': 35, + '11100111': 30, + '11101011': 23, + '11101101': 38, + '11101110': 37, + '11110011': 30, + '11110101': 30, + '11110110': 38, + '11111001': 36, + '11111010': 44, + '11111100': 24, + '01111111': 27, + '10111111': 15, + '11011111': 17, + '11101111': 16, + '11110111': 24, + '11111011': 23, + '11111101': 17, + '11111110': 10, + '11111111': 19} + +CALS = [None, + np.array([[0.98299193, 0.01979335], + [0.01700807, 0.98020665]]), + np.array([[0.96917076, 0.03369085], + [0.03082924, 0.96630915]]), + np.array([[0.9858876, 0.02348826], + [0.0141124, 0.97651174]]), + np.array([[0.99496994, 0.02733885], + [0.00503006, 0.97266115]]), + np.array([[0.96395599, 0.18330204], + [0.03604401, 0.81669796]]), + None, + np.array([[0.98876682, 0.03722461], + [0.01123318, 0.96277539]]), + None, + None, + np.array([[0.99187792, 0.06334372], + [0.00812208, 0.93665628]]), + None, + np.array([[0.94568855, 0.07140989], + [0.05431145, 0.92859011]]), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None] diff --git a/mthree/test/test_sdd.py b/mthree/test/test_sdd.py new file mode 100644 index 00000000..1ad2b6d8 --- /dev/null +++ b/mthree/test/test_sdd.py @@ -0,0 +1,91 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test is various methods agree""" + +import numpy as np +import mthree + + +def test_bad_A_matrix_sdd(): + """Test a bad A-matrix for SDD""" + + mit = mthree.M3Mitigation(None) + mit.single_qubit_cals = BAD_CALS + is_sdd = mit._check_sdd(COUNTS, range(5)) + assert not is_sdd + + +def test_goood_A_matrix_sdd(): + """Test a bad A-matrix for SDD""" + + mit = mthree.M3Mitigation(None) + mit.single_qubit_cals = GOOD_CALS + is_sdd = mit._check_sdd(COUNTS, range(5)) + assert is_sdd + + +BAD_CALS = [np.array([[0.99, 0.08288574], + [0.01, 0.91711426]]), + np.array([[0.91967773, 0.14404297], + [0.08032227, 0.85595703]]), + np.array([[0.9, 0.13195801], + [0.1, 0.86804199]]), + np.array([[0.85, 0.0703125], + [0.15, 0.9296875]]), + np.array([[0.9, 0.23425293], + [0.1, 0.76574707]])] + +GOOD_CALS = [np.array([[1, 0.05419922], + [0, 0.94580078]]), + np.array([[0.95532227, 0.06750488], + [0.04467773, 0.93249512]]), + np.array([[0.99047852, 0.03967285], + [0.00952148, 0.96032715]]), + np.array([[0.96643066, 0.09606934], + [0.03356934, 0.90393066]]), + np.array([[0.99255371, 0.06066895], + [0.00744629, 0.93933105]])] + +COUNTS = {'00000': 3591, + '00001': 7, + '10000': 77, + '10001': 2, + '10010': 2, + '10011': 14, + '10100': 5, + '10101': 22, + '10110': 29, + '10111': 305, + '11000': 17, + '11001': 10, + '11010': 8, + '11011': 128, + '11100': 69, + '11101': 196, + '11110': 199, + '11111': 2734, + '00010': 153, + '00011': 40, + '00100': 46, + '00101': 6, + '00110': 6, + '00111': 72, + '01000': 152, + '01001': 1, + '01010': 14, + '01011': 12, + '01100': 5, + '01101': 22, + '01110': 8, + '01111': 240} diff --git a/mthree/test/test_sim.py b/mthree/test/test_sim.py new file mode 100644 index 00000000..5bbb9dee --- /dev/null +++ b/mthree/test/test_sim.py @@ -0,0 +1,37 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module + +"""Test matrix elements""" +from qiskit import QuantumCircuit, execute +from qiskit.test.mock import FakeAthens +import mthree + + +def test_athens_sim(): + """A simple check that the full pipeline does not break""" + backend = FakeAthens() + + qc = QuantumCircuit(5) + qc.h(2) + qc.cx(2, 1) + qc.cx(2, 3) + qc.cx(1, 0) + qc.cx(3, 4) + qc.measure_all() + + raw_counts = execute(qc, backend).result().get_counts() + mit = mthree.M3Mitigation(backend) + mit.cals_from_system() + mit_counts = mit.apply_correction(raw_counts, qubits=range(5)) + + assert mit_counts is not None diff --git a/mthree/utils.py b/mthree/utils.py new file mode 100644 index 00000000..26e952bf --- /dev/null +++ b/mthree/utils.py @@ -0,0 +1,52 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +# pylint: disable=no-name-in-module +"""Utility functions""" +import numpy as np +from mthree.classes import QuasiDistribution + + +def counts_to_vector(counts): + """ Return probability vector from counts dict. + + Parameters: + counts (dict): Input dict of counts. + + Returns: + ndarray: 1D array of probabilities. + """ + num_bitstrings = len(counts) + shots = sum(counts.values()) + vec = np.zeros(num_bitstrings, dtype=float) + idx = 0 + for val in counts.values(): + vec[idx] = val / shots + idx += 1 + return vec + + +def vector_to_quasiprobs(vec, counts): + """ Return dict of quasi-probabilities. + + Parameters: + vec (ndarray): 1d vector of quasi-probabilites. + counts (dict): Dict of counts + + Returns: + QuasiDistribution: dict of quasi-probabilities + """ + out_counts = {} + idx = 0 + for key in counts: + out_counts[key] = vec[idx] + idx += 1 + return QuasiDistribution(out_counts) diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..514df4b9 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,10 @@ +scipy>=1.3 +qiskit>=0.24 +pytest +pylint +pycodestyle +Sphinx==3.3 +qiskit_sphinx_theme +jupyter-sphinx +nbsphinx +psutil \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..52494518 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +numpy>=1.17 +scipy>=1.3 +cython>=0.29 +qiskit==0.24.1 +psutil +orjson>=3.5 diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..84d0d30f --- /dev/null +++ b/setup.py @@ -0,0 +1,226 @@ +# This code is part of Mthree. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""mthree + +Matrix-free measurement mitigation +""" + +import os +import sys +import subprocess +import setuptools + +try: + import numpy as np +except ImportError: + subprocess.call([sys.executable, '-m', 'pip', 'install', 'numpy>=1.17']) + import numpy as np +try: + from Cython.Build import cythonize +except ImportError: + subprocess.call([sys.executable, '-m', 'pip', 'install', 'cython>=0.29']) + from Cython.Build import cythonize + + +MAJOR = 0 +MINOR = 9 +MICRO = 0 + +ISRELEASED = False +VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) + +REQUIREMENTS = ['numpy>=1.17', + 'scipy>=1.3', + 'cython>=0.29', + 'qiskit-terra>=0.16', + 'qiskit-ibmq-provider>=0.11', + 'psutil' + ] + +PACKAGES = setuptools.find_packages() +PACKAGE_DATA = {'mthree': ['*.pxd'], +} +DOCLINES = __doc__.split('\n') +DESCRIPTION = DOCLINES[0] +LONG_DESCRIPTION = "\n".join(DOCLINES[2:]) + +CYTHON_EXTS = ['compute', 'converters', 'hamming', 'matrix', 'probability', 'matvec'] + \ + ['expval', 'column_testing', 'converters_testing'] +CYTHON_MODULES = ['mthree']*7 + \ + ['mthree.test']*2 +CYTHON_SOURCE_DIRS = ['mthree']*7 + \ + ['mthree/test']*2 + +# Add openmp flags +OPTIONAL_FLAGS = [] +OPTIONAL_ARGS = [] +for _arg in sys.argv: + if _arg.startswith("--with-"): + _options = _arg.split("--with-")[1].split(",") + sys.argv.remove(_arg) + if "openmp" in _options: + if sys.platform == 'win32': + OPTIONAL_FLAGS = ['/openmp'] + else: + OPTIONAL_FLAGS = ['-fopenmp'] + OPTIONAL_ARGS = OPTIONAL_FLAGS + if "native" in _options: + OPTIONAL_FLAGS.append('-march=native') + +INCLUDE_DIRS = [np.get_include()] +# Extra link args +LINK_FLAGS = [] +# If on Win and not in MSYS2 (i.e. Visual studio compile) +if (sys.platform == 'win32' and os.environ.get('MSYSTEM') is None): + COMPILER_FLAGS = ['/O3'] +# Everything else +else: + COMPILER_FLAGS = ['-O3', '-ffast-math', '-std=c++17'] + if sys.platform == 'darwin': + # These are needed for compiling on OSX 10.14+ + COMPILER_FLAGS.append('-mmacosx-version-min=10.14') + LINK_FLAGS.append('-mmacosx-version-min=10.14') + + +EXT_MODULES = [] +# Add Cython Extensions +for idx, ext in enumerate(CYTHON_EXTS): + mod = setuptools.Extension(CYTHON_MODULES[idx] + '.' + ext, + sources=[CYTHON_SOURCE_DIRS[idx] + '/' + ext + '.pyx'], + include_dirs=INCLUDE_DIRS, + extra_compile_args=COMPILER_FLAGS+OPTIONAL_FLAGS, + extra_link_args=LINK_FLAGS+OPTIONAL_ARGS, + language='c++', + define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")]) + EXT_MODULES.append(mod) + + +def git_short_hash(): + try: + git_str = "+" + os.popen('git log -1 --format="%h"').read().strip() + except: # pylint: disable=bare-except + git_str = "" + else: + if git_str == '+': #fixes setuptools PEP issues with versioning + git_str = '' + return git_str + +FULLVERSION = VERSION +if not ISRELEASED: + FULLVERSION += '.dev'+str(MICRO)+git_short_hash() + +def write_version_py(filename='mthree/version.py'): + cnt = """\ +# THIS FILE IS GENERATED FROM MTHREE SETUP.PY +# pylint: disable=missing-module-docstring +short_version = '%(version)s' +version = '%(fullversion)s' +release = %(isrelease)s +""" + a = open(filename, 'w') + try: + a.write(cnt % {'version': VERSION, 'fullversion': + FULLVERSION, 'isrelease': str(ISRELEASED)}) + finally: + a.close() + +local_path = os.path.dirname(os.path.abspath(sys.argv[0])) +os.chdir(local_path) +sys.path.insert(0, local_path) +sys.path.insert(0, os.path.join(local_path, 'mthree')) # to retrive _version + +# always rewrite _version +if os.path.exists('mthree/version.py'): + os.remove('mthree/version.py') + +write_version_py() + + +# Add command for running pylint from setup.py +class PylintCommand(setuptools.Command): + """Run Pylint on all mthree Python source files.""" + description = 'Run Pylint on mthree Python source files' + user_options = [ + # The format is (long option, short option, description). + ('pylint-rcfile=', None, 'path to Pylint config file')] + + def initialize_options(self): + """Set default values for options.""" + # Each user option must be listed here with their default value. + self.pylint_rcfile = '' # pylint: disable=attribute-defined-outside-init + + def finalize_options(self): + """Post-process options.""" + if self.pylint_rcfile: + assert os.path.exists(self.pylint_rcfile), ( + 'Pylint config file %s does not exist.' % self.pylint_rcfile) + + def run(self): + """Run command.""" + command = ['pylint'] + if self.pylint_rcfile: + command.append('--rcfile=%s' % self.pylint_rcfile) + command.append(os.getcwd()+"/mthree") + subprocess.run(command, stderr=subprocess.STDOUT, check=False) + + +# Add command for running PEP8 tests from setup.py +class StyleCommand(setuptools.Command): + """Run pep8 from setup.""" + description = 'Run style from setup' + user_options = [ + # The format is (long option, short option, description). + ('abc', None, 'abc')] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + """Run command.""" + command = 'pycodestyle --max-line-length=100 mthree' + subprocess.run(command, shell=True, check=False, stderr=subprocess.STDOUT) + + +setuptools.setup( + name='mthree', + version=VERSION, + packages=PACKAGES, + description=DESCRIPTION, + long_description=LONG_DESCRIPTION, + url="", + author="Paul Nation", + author_email="paul.nation@ibm.com", + license="For internal IBM Quantum use only.", + classifiers=[ + "Environment :: Web Environment", + "License :: Other/Proprietary License", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Topic :: Scientific/Engineering", + ], + cmdclass={'lint': PylintCommand, 'style': StyleCommand}, + install_requires=REQUIREMENTS, + package_data=PACKAGE_DATA, + ext_modules=cythonize(EXT_MODULES, language_level=3), + include_package_data=True, + zip_safe=False +)