From df94d49207b1b7931ac1c88fb8ca8d82157546ad Mon Sep 17 00:00:00 2001 From: Filippo Miatto Date: Thu, 27 Jul 2023 07:31:43 -0700 Subject: [PATCH] release v0.5.0 (#265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Release 0.5.0 ### New features * Optimization callback functionalities has been improved. A dedicated `Callback` class is added which is able to access the optimizer, the cost function, the parameters as well as gradients, during the optimization. In addition, multiple callbacks can be specified. This opens up the endless possiblities of customizing the the optimization progress with schedulers, trackers, heuristics, tricks, etc. [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) * Tensorboard-based optimization tracking is added as a builtin `Callback` class: `TensorboardCallback`. It can automatically track costs as well as all trainable parameters during optimization in realtime. Tensorboard can be most conveniently viewed from VScode. [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) ```python import numpy as np from mrmustard.training import Optimizer, TensorboardCallback def cost_fn(): ... def as_dB(cost): delta = np.sqrt(np.log(1 / (abs(cost) ** 2)) / (2 * np.pi)) cost_dB = -10 * np.log10(delta**2) return cost_dB tb_cb = TensorboardCallback(cost_converter=as_dB, track_grads=True) opt = Optimizer(euclidean_lr = 0.001); opt.minimize(cost_fn, max_steps=200, by_optimizing=[...], callbacks=tb_cb) # Logs will be stored in `tb_cb.logdir` which defaults to `./tb_logdir/...` but can be customized. # VScode can be used to open the Tensorboard frontend for live monitoring. # Or, in command line: `tensorboard --logdir={tb_cb.logdir}` and open link in browser. ``` * Gaussian states support a `bargmann` method for returning the bargmann representation. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) * The `ket` method of `State` now supports new keyword arguments `max_prob` and `max_photons`. Use them to speed-up the filling of a ket array up to a certain probability or *total* photon number. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) ```python from mrmustard.lab import Gaussian # Fills the ket array up to 99% probability or up to the |0,3>, |1,2>, |2,1>, |3,0> subspace, whichever is reached first. # The array has the autocutoff shape, unless the cutoffs are specified explicitly. ket = Gaussian(2).ket(max_prob=0.99, max_photons=3) ``` * Gaussian transformations support a `bargmann` method for returning the bargmann representation. [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) * BSGate.U now supports method='vanilla' (default) and 'schwinger' (slower, but stable to any cutoff) [(#248)](https://github.com/XanaduAI/MrMustard/pull/248) ### Breaking Changes * The previous `callback` argument to `Optimizer.minimize` is now `callbacks` since we can now pass multiple callbacks to it. [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) * The `opt_history` attribute of `Optimizer` does not have the placeholder at the beginning anymore. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) ### Improvements * The math module now has a submodule `lattice` for constructing recurrence relation strategies in the Fock lattice. There are a few predefined strategies in `mrmustard.math.lattice.strategies`. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) * Gradients in the Fock lattice are now computed using the vector-jacobian product. This saves a lot of memory and speeds up the optimization process by roughly 4x. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) * Tests of the compact_fock module now use hypothesis. [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) * Faster implementation of the fock representation of `BSgate`, `Sgate` and `SqueezedVacuum`, ranging from 5x to 50x. [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) * More robust implementation of cutoffs for States. [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) * Dependencies and versioning are now managed using Poetry. [(#257)](https://github.com/XanaduAI/MrMustard/pull/257) ### Bug fixes * Fixed a bug that would make two progress bars appear during an optimization [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) * The displacement of the dual of an operation had the wrong sign [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) * When projecting a Gaussian state onto a Fock state, the upper limit of the autocutoff now respect the Fock projection. [(#246)](https://github.com/XanaduAI/MrMustard/pull/246) * Fixed a bug for the algorithms that allow faster PNR sampling from Gaussian circuits using density matrices. When the cutoff of the first detector is equal to 1, the resulting density matrix is now correct. ### Documentation ### Contributors [Filippo Miatto](https://github.com/ziofil), [Zeyue Niu](https://github.com/zeyueN), [Robbe De Prins](https://github.com/rdprins), [Gabriele Gullì](https://github.com/ggulli), [Richard A. Wolf](https://github.com/ryk-wolf) --------- Co-authored-by: Sebastián Duque Mesa <675763+sduquemesa@users.noreply.github.com> Co-authored-by: JacobHast Co-authored-by: elib20 <53090166+elib20@users.noreply.github.com> Co-authored-by: Luke Helt <31250931+heltluke@users.noreply.github.com> Co-authored-by: zeyueN <48225584+zeyueN@users.noreply.github.com> Co-authored-by: Robbe De Prins <52749580+rdprins@users.noreply.github.com> Co-authored-by: Robbe De Prins (UGent-imec) Co-authored-by: Yuan <16817699+sylviemonet@users.noreply.github.com> Co-authored-by: Ryk <47638463+ryk-wolf@users.noreply.github.com> Co-authored-by: Gabriele Gullì <120967042+ggulli@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 + .devcontainer/post-install.sh | 7 +- .github/CHANGELOG.md | 115 +- .github/workflows/builds.yml | 36 +- .github/workflows/tests.yml | 31 +- .github/workflows/upload.yml | 24 +- .readthedocs.yml | 13 +- Dockerfile | 50 - Makefile | 12 +- doc/code/training.rst | 1 + doc/code/training/callbacks.rst | 7 + doc/development/development_guide.rst | 8 +- doc/requirements.txt | 9 - mrmustard/__init__.py | 3 +- mrmustard/_version.py | 19 +- mrmustard/lab/abstract/state.py | 94 +- mrmustard/lab/abstract/transformation.py | 179 +- mrmustard/lab/circuit.py | 6 +- mrmustard/lab/detectors.py | 3 +- mrmustard/lab/gates.py | 149 +- mrmustard/lab/states.py | 13 +- mrmustard/math/lattice/__init__.py | 0 mrmustard/math/lattice/neighbors.py | 74 + mrmustard/math/lattice/paths.py | 81 + mrmustard/math/lattice/pivots.py | 55 + mrmustard/math/lattice/steps.py | 223 ++ mrmustard/math/lattice/strategies/__init__.py | 19 + .../math/lattice/strategies/beamsplitter.py | 204 + mrmustard/math/lattice/strategies/binomial.py | 160 + .../math/lattice/strategies/displacement.py | 139 + mrmustard/math/lattice/strategies/squeezer.py | 188 + mrmustard/math/lattice/strategies/vanilla.py | 117 + mrmustard/math/math_interface.py | 10 +- .../numba/compactFock_1leftoverMode_amps.py | 15 +- .../numba/compactFock_1leftoverMode_grad.py | 2 +- .../math/numba/compactFock_diagonal_amps.py | 2 +- .../math/numba/compactFock_diagonal_grad.py | 2 +- mrmustard/math/tensorflow.py | 90 +- mrmustard/physics/bargmann.py | 5 +- mrmustard/physics/fock.py | 232 +- mrmustard/training/__init__.py | 1 + mrmustard/training/callbacks.py | 286 ++ mrmustard/training/optimizer.py | 137 +- mrmustard/training/parametrized.py | 66 +- mrmustard/typing.py | 9 +- mrmustard/utils/wigner.py | 7 +- poetry.lock | 3445 +++++++++++++++++ pyproject.toml | 71 + requirements-dev.txt | 5 - requirements.txt | 9 - setup.py | 70 - tests/test_lab/test_circuit.py | 20 +- tests/test_lab/test_gates_fock.py | 151 +- tests/test_lab/test_state.py | 49 + tests/test_math/test_compactFock.py | 85 +- tests/test_math/test_interface.py | 13 +- tests/test_math/test_lattice.py | 29 + tests/test_math/test_special.py | 8 +- tests/test_physics/test_bargmann.py | 53 + tests/test_physics/test_fock/test_fock.py | 241 +- .../test_gaussian/test_gaussian_utils.py | 36 +- .../test_gaussian/test_symplectics.py | 41 +- tests/test_training/test_callbacks.py | 72 + tests/test_training/test_opt.py | 127 +- tests/test_training/test_parametrized.py | 22 + tests/test_utils/test_wigner.py | 15 +- 66 files changed, 6682 insertions(+), 785 deletions(-) delete mode 100644 Dockerfile create mode 100644 doc/code/training/callbacks.rst delete mode 100644 doc/requirements.txt create mode 100644 mrmustard/math/lattice/__init__.py create mode 100644 mrmustard/math/lattice/neighbors.py create mode 100644 mrmustard/math/lattice/paths.py create mode 100644 mrmustard/math/lattice/pivots.py create mode 100644 mrmustard/math/lattice/steps.py create mode 100644 mrmustard/math/lattice/strategies/__init__.py create mode 100644 mrmustard/math/lattice/strategies/beamsplitter.py create mode 100644 mrmustard/math/lattice/strategies/binomial.py create mode 100644 mrmustard/math/lattice/strategies/displacement.py create mode 100644 mrmustard/math/lattice/strategies/squeezer.py create mode 100644 mrmustard/math/lattice/strategies/vanilla.py create mode 100644 mrmustard/training/callbacks.py create mode 100644 poetry.lock create mode 100644 pyproject.toml delete mode 100644 requirements-dev.txt delete mode 100644 requirements.txt delete mode 100644 setup.py create mode 100644 tests/test_lab/test_state.py create mode 100644 tests/test_math/test_lattice.py create mode 100644 tests/test_physics/test_bargmann.py create mode 100644 tests/test_training/test_callbacks.py diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 12f6a982d..16064a59f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -36,6 +36,8 @@ RUN sh -c "$(wget -nv -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/mast # upgrade pip and install package manager RUN python -m pip install --no-cache-dir --upgrade pip +RUN pip install --no-cache-dir poetry==1.4.0 +RUN poetry config virtualenvs.create false ### TEAR DOWN IMAGE SETUP ### # switch back to dialog for any ad-hoc use of apt-get diff --git a/.devcontainer/post-install.sh b/.devcontainer/post-install.sh index c7cbf8aab..53bc587fa 100755 --- a/.devcontainer/post-install.sh +++ b/.devcontainer/post-install.sh @@ -1,8 +1,3 @@ #! /bin/zsh -pip install --no-cache-dir -r requirements.txt -pip install --no-cache-dir -r requirements-dev.txt -pip install --no-cache-dir -r doc/requirements.txt -pip install ray -pip install pylint -pip install -e . +poetry install --all-extras --with dev,doc diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 733a05e45..e137e8b9d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -1,3 +1,115 @@ +# Release 0.5.0 + +### New features + +* Optimization callback functionalities has been improved. A dedicated `Callback` class is added which + is able to access the optimizer, the cost function, the parameters as well as gradients, during the + optimization. In addition, multiple callbacks can be specified. This opens up the endless possiblities + of customizing the the optimization progress with schedulers, trackers, heuristics, tricks, etc. + [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) + +* Tensorboard-based optimization tracking is added as a builtin `Callback` class: `TensorboardCallback`. + It can automatically track costs as well as all trainable parameters during optimization in realtime. + Tensorboard can be most conveniently viewed from VScode. + [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) + + ```python + import numpy as np + from mrmustard.training import Optimizer, TensorboardCallback + + def cost_fn(): + ... + + def as_dB(cost): + delta = np.sqrt(np.log(1 / (abs(cost) ** 2)) / (2 * np.pi)) + cost_dB = -10 * np.log10(delta**2) + return cost_dB + + tb_cb = TensorboardCallback(cost_converter=as_dB, track_grads=True) + + opt = Optimizer(euclidean_lr = 0.001); + opt.minimize(cost_fn, max_steps=200, by_optimizing=[...], callbacks=tb_cb) + + # Logs will be stored in `tb_cb.logdir` which defaults to `./tb_logdir/...` but can be customized. + # VScode can be used to open the Tensorboard frontend for live monitoring. + # Or, in command line: `tensorboard --logdir={tb_cb.logdir}` and open link in browser. + ``` + +* Gaussian states support a `bargmann` method for returning the bargmann representation. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +* The `ket` method of `State` now supports new keyword arguments `max_prob` and `max_photons`. + Use them to speed-up the filling of a ket array up to a certain probability or *total* photon number. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + + ```python + from mrmustard.lab import Gaussian + + # Fills the ket array up to 99% probability or up to the |0,3>, |1,2>, |2,1>, |3,0> subspace, whichever is reached first. + # The array has the autocutoff shape, unless the cutoffs are specified explicitly. + ket = Gaussian(2).ket(max_prob=0.99, max_photons=3) + ``` + +* Gaussian transformations support a `bargmann` method for returning the bargmann representation. + [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) + +* BSGate.U now supports method='vanilla' (default) and 'schwinger' (slower, but stable to any cutoff) + [(#248)](https://github.com/XanaduAI/MrMustard/pull/248) + +### Breaking Changes + +* The previous `callback` argument to `Optimizer.minimize` is now `callbacks` since we can now pass + multiple callbacks to it. + [(#219)](https://github.com/XanaduAI/MrMustard/pull/219) + +* The `opt_history` attribute of `Optimizer` does not have the placeholder at the beginning anymore. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +### Improvements + +* The math module now has a submodule `lattice` for constructing recurrence relation strategies in the Fock lattice. + There are a few predefined strategies in `mrmustard.math.lattice.strategies`. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +* Gradients in the Fock lattice are now computed using the vector-jacobian product. + This saves a lot of memory and speeds up the optimization process by roughly 4x. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +* Tests of the compact_fock module now use hypothesis. + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +* Faster implementation of the fock representation of `BSgate`, `Sgate` and `SqueezedVacuum`, ranging from 5x to 50x. + [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) + +* More robust implementation of cutoffs for States. +[(#239)](https://github.com/XanaduAI/MrMustard/pull/239) + +* Dependencies and versioning are now managed using Poetry. +[(#257)](https://github.com/XanaduAI/MrMustard/pull/257) + +### Bug fixes + +* Fixed a bug that would make two progress bars appear during an optimization + [(#235)](https://github.com/XanaduAI/MrMustard/pull/235) + +* The displacement of the dual of an operation had the wrong sign + [(#239)](https://github.com/XanaduAI/MrMustard/pull/239) + +* When projecting a Gaussian state onto a Fock state, the upper limit of the autocutoff now respect the Fock projection. + [(#246)](https://github.com/XanaduAI/MrMustard/pull/246) + +* Fixed a bug for the algorithms that allow faster PNR sampling from Gaussian circuits using density matrices. When the +cutoff of the first detector is equal to 1, the resulting density matrix is now correct. + +### Documentation + +### Contributors +[Filippo Miatto](https://github.com/ziofil), [Zeyue Niu](https://github.com/zeyueN), +[Robbe De Prins](https://github.com/rdprins), [Gabriele Gullì](https://github.com/ggulli), +[Richard A. Wolf](https://github.com/ryk-wolf) + +--- + # Release 0.4.1 ### New features @@ -23,8 +135,9 @@ ### Contributors [Filippo Miatto](https://github.com/ziofil), [Sebastian Duque Mesa](https://github.com/sduquemesa) +--- -# Release 0.4.0 +# Release 0.4.0 (current release) ### New features diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index f92a611a9..90887d6ab 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -1,4 +1,4 @@ -name: builds +name: Build package on: push: branches: @@ -12,37 +12,37 @@ jobs: runs-on: ubuntu-latest env: HYPOTHESIS_PROFILE: ci - strategy: fail-fast: false matrix: python-version: ['3.9', '3.10'] + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.python-version }} + cancel-in-progress: true steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ github.token }} - - - uses: actions/checkout@v3 + - name: Checkout repo + uses: actions/checkout@v3 - - name: Set up Python + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Build and install Mr Mustard run: | - python -m pip install --upgrade pip wheel - python setup.py bdist_wheel + python -m pip install --no-cache-dir --upgrade pip + pip install --no-cache-dir poetry==1.4.0 + poetry config virtualenvs.create false + poetry build pip install dist/mrmustard*.whl + # Move to 'src' to properly test only installed package + # https://docs.pytest.org/en/7.1.x/explanation/goodpractices.html#tests-outside-application-code + mkdir src + mv mrmustard src - - name: Install test dependencies - run: | - pip install -r requirements.txt - pip install -r requirements-dev.txt - pip install wheel pytest pytest-cov pytest-mock hypothesis --upgrade + - name: Install only test dependencies + run: poetry install --no-root --extras "ray" --with dev - name: Run tests - run: | - python -m pytest tests -p no:warnings --tb=native + run: python -m pytest tests -p no:warnings --tb=native diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b081aae43..ad0ff8caf 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,35 +4,38 @@ on: branches: - develop pull_request: + paths: + - '.github/workflows/tests.yml' + - 'mrmustard/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - 'pytest.ini' jobs: pytest: runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: HYPOTHESIS_PROFILE: ci steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ github.token }} - - - uses: actions/checkout@v3 + - name: Checkout repo + uses: actions/checkout@v3 - - name: Setup python ${{ matrix.python-version }} + - name: Setup python uses: actions/setup-python@v4 with: python-version: '3.9' - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - pip install wheel pytest pytest-cov --upgrade - pip install .[ray] - # python setup.py bdist_wheel - # pip install dist/*.whl + python -m pip install --no-cache-dir --upgrade pip + pip install --no-cache-dir poetry==1.4.0 + poetry config virtualenvs.create false + poetry install --extras "ray" --with dev - name: Run tests run: python -m pytest tests --cov=mrmustard --cov-report=term-missing --cov-report=xml -p no:warnings --tb=native diff --git a/.github/workflows/upload.yml b/.github/workflows/upload.yml index e52e7ba79..2545e285c 100644 --- a/.github/workflows/upload.yml +++ b/.github/workflows/upload.yml @@ -10,7 +10,8 @@ jobs: HYPOTHESIS_PROFILE: ci steps: - - uses: actions/checkout@v3 + - name: Checkout repo + uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 @@ -19,21 +20,24 @@ jobs: - name: Build and install Mr Mustard run: | - python -m pip install --upgrade pip wheel - python setup.py bdist_wheel + python -m pip install --no-cache-dir --upgrade pip + pip install --no-cache-dir poetry==1.4.0 + poetry config virtualenvs.create false + poetry build pip install dist/mrmustard*.whl + # Move to 'src' to properly test only installed package + # https://docs.pytest.org/en/7.1.x/explanation/goodpractices.html#tests-outside-application-code + mkdir src + mv mrmustard src - - name: Install test dependencies - run: | - pip install -r requirements.txt - pip install wheel pytest pytest-cov pytest-mock hypothesis --upgrade + - name: Install only test dependencies + run: poetry install --no-root --extras "ray" --with dev - name: Run tests - run: | - python -m pytest tests -p no:warnings --tb=native + run: python -m pytest tests -p no:warnings --tb=native - name: Publish - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PIPY_TOKEN }} diff --git a/.readthedocs.yml b/.readthedocs.yml index 195e00930..a7dbfa275 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,6 +6,11 @@ build: os: ubuntu-22.04 tools: python: "3.9" + jobs: + post_install: + - pip install --no-cache-dir poetry==1.4.0 + - poetry config virtualenvs.create false + - poetry install --with doc # Build documentation in the docs/ directory with Sphinx sphinx: @@ -16,9 +21,5 @@ sphinx: # - pdf # Optionally declare the Python requirements required to build your docs -python: - install: - - requirements: doc/requirements.txt - - method: pip - path: . - system_packages: true +# python: +# install: diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index cf329f62f..000000000 --- a/Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -FROM python:3.10 - -# Configure apt for setup -ENV DEBIAN_FRONTEND=noninteractive - -WORKDIR /mrmustard -COPY . . - -RUN apt-get update && \ - apt-get -y install --no-install-recommends sudo \ - zsh \ - less \ - curl \ - wget \ - graphviz \ - fonts-powerline \ - locales \ - git \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -### GIT GLOBAL SETUP ### - -RUN git config --global core.excludesfile /.globalgitignore -RUN touch /.globalgitignore -RUN echo ".notebooks" >> /.globalgitignore -RUN echo "nohup.out" >> /.globalgitignore - -### ZSH TERMINAL SETUP ### - -# generate locale for zsh terminal agnoster theme -RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && /usr/sbin/locale-gen -RUN locale-gen en_US.UTF-8 -# set term to be bash instead of sh -ENV TERM xterm -ENV SHELL /bin/zsh -# install oh-my-zsh -RUN sh -c "$(wget -nv -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" - -### PYTHON DEPENDENCIES INTALLATION ### - -# upgrade pip and install package manager -RUN python -m pip install --no-cache-dir --upgrade pip -RUN pip install --no-cache-dir -r requirements.txt -RUN pip install --no-cache-dir -r requirements-dev.txt -RUN pip install --no-cache-dir ray -RUN pip install --no-cache-dir -e . - -### TEAR DOWN IMAGE SETUP ### -# switch back to dialog for any ad-hoc use of apt-get -ENV DEBIAN_FRONTEND=dialog diff --git a/Makefile b/Makefile index d20cad652..fcd55052a 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ COVERAGE := --cov=mrmustard --cov-report=html:coverage_html_report --cov-append help: @echo "Please use \`make ' where is one of" @echo " install to install Mr Mustard" + @echo " install-all to install Mr Mustard with all extras and optional dependencies" @echo " dist to package the source distribution" @echo " clean to delete all temporary, cache, and build files" @echo " clean-docs to delete all built documentation" @@ -18,11 +19,18 @@ install: ifndef PYTHON3 @echo "To install Mr Mustard you need to have Python 3 installed" endif - $(PYTHON) setup.py install + poetry install + +.PHONY: install-all +install-all: +ifndef PYTHON3 + @echo "To install Mr Mustard you need to have Python 3 installed" +endif + poetry install --all-extras --with dev,doc .PHONY: dist dist: - $(PYTHON) setup.py sdist + poetry build .PHONY : clean clean: diff --git a/doc/code/training.rst b/doc/code/training.rst index 1ab03e1c2..d65fb613a 100644 --- a/doc/code/training.rst +++ b/doc/code/training.rst @@ -8,6 +8,7 @@ mrmustard.training training/parameter training/parametrized training/trainer + training/callbacks .. currentmodule:: mrmustard.training diff --git a/doc/code/training/callbacks.rst b/doc/code/training/callbacks.rst new file mode 100644 index 000000000..ae216849f --- /dev/null +++ b/doc/code/training/callbacks.rst @@ -0,0 +1,7 @@ +callbacks +============ + +.. currentmodule:: mrmustard.training.callbacks + +.. automodapi:: mrmustard.training.callbacks + :no-heading: diff --git a/doc/development/development_guide.rst b/doc/development/development_guide.rst index b7ffbf419..9711859c9 100644 --- a/doc/development/development_guide.rst +++ b/doc/development/development_guide.rst @@ -66,11 +66,11 @@ Development environment ----------------------- Mr Mustard uses a ``pytest`` suite for testing and ``black`` for formatting. These -dependencies can be installed via ``pip``: +dependencies can be installed via ``poetry``: .. code-block:: bash - pip install -r requirements-dev.txt + poetry install --with dev Software tests -------------- @@ -175,11 +175,11 @@ Documentation ------------- Additional packages are required to build the documentation, as specified in -``doc/requirements.txt``. These packages can be installed using: +``pyproject.toml`` under the group ``doc``. These packages can be installed using: .. code-block:: bash - pip install -r doc/requirements.txt + poetry install --with doc from within the top-level directory. To then build the HTML documentation, run diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index 8ea6a7332..000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -sphinx -docutils -m2r2 -sphinx-autodoc-typehints -sphinx-copybutton -sphinx-automodapi -sphinxcontrib-bibtex -mistune==0.8.4 -xanadu-sphinx-theme==0.1.0 diff --git a/mrmustard/__init__.py b/mrmustard/__init__.py index a6556e73f..f8ed18e69 100644 --- a/mrmustard/__init__.py +++ b/mrmustard/__init__.py @@ -40,7 +40,7 @@ def __init__(self): self.AUTOCUTOFF_MIN_CUTOFF = 1 self.CIRCUIT_DECIMALS = 3 # use cutoff=5 for each mode when determining if two transformations in fock repr are equal - self.EQ_TRANSFORMATION_CUTOFF = 5 + self.EQ_TRANSFORMATION_CUTOFF = 3 # 3 is enough to include a full step of the rec relations self.EQ_TRANSFORMATION_RTOL_FOCK = 1e-3 self.EQ_TRANSFORMATION_RTOL_GAUSS = 1e-6 # for the detectors @@ -50,6 +50,7 @@ def __init__(self): self.PROGRESSBAR = True self._seed = np.random.randint(0, 2**31 - 1) self.rng = np.random.default_rng(self._seed) + self.DEFAULT_BS_METHOD = "vanilla" # can be 'vanilla' or 'schwinger' @property def SEED(self): diff --git a/mrmustard/_version.py b/mrmustard/_version.py index 4e4fa30c3..c9955a3aa 100644 --- a/mrmustard/_version.py +++ b/mrmustard/_version.py @@ -13,7 +13,22 @@ # limitations under the License. """Version information. - Version number (major.minor.patch[-label]) + +Version number retrieved from pyproject.toml file """ +from pathlib import Path +import tomli + + +def _get_project_root(): + """Compute and return root dir""" + return Path(__file__).parent.parent + + +def _get_project_version(): + """Parse 'pyproject.toml' and return current version""" + with open(f"{_get_project_root()}/pyproject.toml", mode="rb") as pyproject: + return tomli.load(pyproject)["tool"]["poetry"]["version"] + -__version__ = "0.4.1" +__version__ = str(_get_project_version()) diff --git a/mrmustard/lab/abstract/state.py b/mrmustard/lab/abstract/state.py index cc2945e30..8eb8c0e01 100644 --- a/mrmustard/lab/abstract/state.py +++ b/mrmustard/lab/abstract/state.py @@ -31,12 +31,14 @@ from mrmustard import settings from mrmustard.math import Math -from mrmustard.physics import fock, gaussian +from mrmustard.physics import bargmann, fock, gaussian from mrmustard.typing import ( + ComplexMatrix, + ComplexTensor, + ComplexVector, RealMatrix, - RealVector, RealTensor, - ComplexTensor, + RealVector, ) from mrmustard.utils import graphics @@ -47,7 +49,7 @@ # pylint: disable=too-many-instance-attributes -class State: +class State: # pylint: disable=too-many-public-methods r"""Base class for quantum states.""" def __init__( @@ -92,12 +94,15 @@ def __init__( self._norm = _norm if cov is not None and means is not None: self.is_gaussian = True + self.is_hilbert_vector = np.allclose(gaussian.purity(self.cov, settings.HBAR), 1.0) self.num_modes = cov.shape[-1] // 2 elif eigenvalues is not None and symplectic is not None: self.is_gaussian = True + self.is_hilbert_vector = np.allclose(eigenvalues, 2.0 / settings.HBAR) self.num_modes = symplectic.shape[-1] // 2 elif ket is not None or dm is not None: self.is_gaussian = False + self.is_hilbert_vector = ket is not None self.num_modes = len(ket.shape) if ket is not None else len(dm.shape) // 2 self._purity = 1.0 if ket is not None else None else: @@ -148,7 +153,7 @@ def is_mixed(self): @property def is_pure(self): r"""Returns ``True`` if the state is pure and ``False`` otherwise.""" - return True if self._ket is not None else np.isclose(self.purity, 1.0, atol=1e-6) + return np.isclose(self.purity, 1.0, atol=1e-6) @property def means(self) -> Optional[RealVector]: @@ -172,14 +177,22 @@ def number_stdev(self) -> RealVector: @property def cutoffs(self) -> List[int]: - r"""Returns the cutoff dimensions for each mode.""" - if self._cutoffs is not None: - return self._cutoffs # TODO: allow self._cutoffs = [N, None] - if self._ket is None and self._dm is None: - return fock.autocutoffs(self.cov, self.means, settings.AUTOCUTOFF_PROBABILITY) - return list( - self.fock.shape[: self.num_modes] - ) # NOTE: triggered only if the fock representation already exists + r"""Returns the Hilbert space dimension of each mode.""" + if self._cutoffs is None: + if self._ket is None and self._dm is None: + self._cutoffs = fock.autocutoffs( + self.cov, self.means, settings.AUTOCUTOFF_PROBABILITY + ) + else: + self._cutoffs = [ + int(c) + for c in ( + self._ket.shape + if self._ket is not None + else self._dm.shape[: self.num_modes] + ) + ] + return self._cutoffs @property def shape(self) -> List[int]: @@ -189,14 +202,14 @@ def shape(self) -> List[int]: the first two moments of the number operator. """ # NOTE: if we initialize State(dm=pure_dm), self.fock returns the dm, which does not have shape self.cutoffs - return self.cutoffs if self.is_pure else self.cutoffs + self.cutoffs + return self.cutoffs if self.is_hilbert_vector else self.cutoffs + self.cutoffs @property def fock(self) -> ComplexTensor: r"""Returns the Fock representation of the state.""" if self._dm is None and self._ket is None: _fock = fock.wigner_to_fock_state( - self.cov, self.means, shape=self.shape, return_dm=self.is_mixed + self.cov, self.means, shape=self.shape, return_dm=not self.is_hilbert_vector ) if self.is_mixed: self._dm = _fock @@ -227,7 +240,7 @@ def norm(self) -> float: r"""Returns the norm of the state.""" if self.is_gaussian: return self._norm - return fock.norm(self.fock, self._dm is not None) + return fock.norm(self.fock, not self.is_hilbert_vector) @property def probability(self) -> float: @@ -237,12 +250,21 @@ def probability(self) -> float: return norm**2 return norm - def ket(self, cutoffs: List[int] = None) -> Optional[ComplexTensor]: + def ket( + self, + cutoffs: List[int] = None, + max_prob: float = 1.0, + max_photons: int = None, + ) -> Optional[ComplexTensor]: r"""Returns the ket of the state in Fock representation or ``None`` if the state is mixed. Args: cutoffs List[int or None]: The cutoff dimensions for each mode. If a mode cutoff is ``None``, it's guessed automatically. + max_prob (float): The maximum probability of the state. Defaults to 1.0. + (used to stop the calculation of the amplitudes early) + max_photons (int): The maximum number of photons in the state, summing over all modes + (used to stop the calculation of the amplitudes early) Returns: Tensor: the ket @@ -255,16 +277,22 @@ def ket(self, cutoffs: List[int] = None) -> Optional[ComplexTensor]: else: cutoffs = [c if c is not None else self.cutoffs[i] for i, c in enumerate(cutoffs)] + # TODO: shouldn't we check if trainable instead? that's when we want to recompute fock if self.is_gaussian: self._ket = fock.wigner_to_fock_state( - self.cov, self.means, shape=cutoffs, return_dm=False + self.cov, + self.means, + shape=cutoffs, + return_dm=False, + max_prob=max_prob, + max_photons=max_photons, ) else: # only fock representation is available if self._ket is None: # if state is pure and has a density matrix, calculate the ket if self.is_pure: self._ket = fock.dm_to_ket(self._dm) - current_cutoffs = list(self._ket.shape[: self.num_modes]) + current_cutoffs = [int(s) for s in self._ket.shape] if cutoffs != current_cutoffs: paddings = [(0, max(0, new - old)) for new, old in zip(cutoffs, current_cutoffs)] if any(p != (0, 0) for p in paddings): @@ -295,7 +323,7 @@ def dm(self, cutoffs: Optional[List[int]] = None) -> ComplexTensor: else: if self.is_gaussian: self._dm = fock.wigner_to_fock_state( - self.cov, self.means, shape=cutoffs * 2, return_dm=True + self.cov, self.means, shape=cutoffs + cutoffs, return_dm=True ) elif cutoffs != (current_cutoffs := list(self._dm.shape[: self.num_modes])): paddings = [(0, max(0, new - old)) for new, old in zip(cutoffs, current_cutoffs)] @@ -498,6 +526,21 @@ def __getitem__(self, item) -> State: self._modes = item return self + def bargmann(self, numpy=False) -> Optional[tuple[ComplexMatrix, ComplexVector, complex]]: + r"""Returns the Bargmann representation of the state. + If numpy=True, returns the numpy arrays instead of the backend arrays. + """ + if self.is_gaussian: + if self.is_pure: + A, B, C = bargmann.wigner_to_bargmann_psi(self.cov, self.means) + else: + A, B, C = bargmann.wigner_to_bargmann_rho(self.cov, self.means) + else: + return None + if numpy: + return math.asnumpy(A), math.asnumpy(B), math.asnumpy(C) + return A, B, C + def get_modes(self, item) -> State: r"""Returns the state on the given modes.""" if isinstance(item, int): @@ -524,7 +567,7 @@ def get_modes(self, item) -> State: return State(dm=fock_partitioned, modes=item) # TODO: refactor - def __eq__(self, other) -> bool: + def __eq__(self, other) -> bool: # pylint: disable=too-many-return-statements r"""Returns whether the states are equal.""" if self.num_modes != other.num_modes: return False @@ -576,7 +619,9 @@ def __rmul__(self, other): warnings.warn( "scalar multiplication forces conversion to fock representation", UserWarning ) - return self.fock # trigger creation of fock representation + if self.is_pure: + return State(ket=self.ket() * other) + return State(dm=self.dm() * other) if self._dm is not None: return State(dm=self.dm() * other, modes=self.modes) if self._ket is not None: @@ -590,8 +635,9 @@ def __truediv__(self, other): """ if self.is_gaussian: warnings.warn("scalar division forces conversion to fock representation", UserWarning) - return self.fock - + if self.is_pure: + return State(ket=self.ket() / other) + return State(dm=self.dm() / other) if self._dm is not None: return State(dm=self.dm() / other, modes=self.modes) if self._ket is not None: diff --git a/mrmustard/lab/abstract/transformation.py b/mrmustard/lab/abstract/transformation.py index f8a1456dc..281791937 100644 --- a/mrmustard/lab/abstract/transformation.py +++ b/mrmustard/lab/abstract/transformation.py @@ -19,21 +19,13 @@ from __future__ import annotations -from typing import ( - Callable, - Iterable, - List, - Optional, - Sequence, - Tuple, - Union, -) +from typing import Callable, Iterable, List, Optional, Sequence, Tuple, Union import numpy as np from mrmustard import settings from mrmustard.math import Math -from mrmustard.physics import fock, gaussian +from mrmustard.physics import bargmann, fock, gaussian from mrmustard.training.parameter import Parameter from mrmustard.typing import RealMatrix, RealVector @@ -46,6 +38,23 @@ class Transformation: r"""Base class for all Transformations.""" is_unitary = True # whether the transformation is unitary (True by default) + def bargmann(self, numpy=False): + X, Y, d = self.XYd(allow_none=False) + if self.is_unitary: + A, B, C = bargmann.wigner_to_bargmann_U( + X if X is not None else math.identity(d.shape[-1], dtype=d.dtype), + d if d is not None else math.zeros(X.shape[-1], dtype=X.dtype), + ) + else: + A, B, C = bargmann.wigner_to_bargmann_Choi( + X if X is not None else math.identity(d.shape[-1], dtype=d.dtype), + Y if Y is not None else math.zeros((d.shape[-1], d.shape[-1]), dtype=d.dtype), + d if d is not None else math.zeros(X.shape[-1], dtype=X.dtype), + ) + if numpy: + return math.asnumpy(A), math.asnumpy(B), math.asnumpy(C) + return A, B, C + def primal(self, state: State) -> State: r"""Applies ``self`` (a ``Transformation``) to other (a ``State``) and returns the transformed state. @@ -86,7 +95,7 @@ def transform_gaussian(self, state: State, dual: bool) -> State: Returns: State: the transformed state """ - X, Y, d = self.XYd if not dual else self.XYd_dual + X, Y, d = self.XYd(allow_none=False) if not dual else self.XYd_dual(allow_none=False) cov, means = gaussian.CPTP(state.cov, state.means, X, Y, d, state.modes, self.modes) new_state = State( cov=cov, means=means, modes=state.modes, _norm=state.norm @@ -105,13 +114,15 @@ def transform_fock(self, state: State, dual: bool) -> State: """ op_idx = [state.modes.index(m) for m in self.modes] if self.is_unitary: - U = self.U(cutoffs=[state.cutoffs[i] for i in op_idx]) + # until we have output autocutoff we use the same input cutoff list + U = self.U(cutoffs=[state.cutoffs[i] for i in op_idx] * 2) U = math.dagger(U) if dual else U if state.is_pure: return State(ket=fock.apply_kraus_to_ket(U, state.ket(), op_idx), modes=state.modes) return State(dm=fock.apply_kraus_to_dm(U, state.dm(), op_idx), modes=state.modes) else: - choi = self.choi(cutoffs=[state.cutoffs[i] for i in op_idx]) + # until we have output autocutoff we use the same input cutoff list + choi = self.choi(cutoffs=[state.cutoffs[i] for i in op_idx] * 4) n = state.num_modes N0 = list(range(0, n)) N1 = list(range(n, 2 * n)) @@ -130,7 +141,7 @@ def transform_fock(self, state: State, dual: bool) -> State: def modes(self) -> Sequence[int]: """Returns the list of modes on which the transformation acts on.""" if self._modes in (None, []): - for elem in self.XYd: + for elem in self.XYd(allow_none=True): if elem is not None: self._modes = list(range(elem.shape[-1] // 2)) break @@ -181,59 +192,70 @@ def d_vector_dual(self) -> Optional[RealVector]: if (d := self.d_vector) is None: return None if (Xdual := self.X_matrix_dual) is None: - return d - return math.matmul(Xdual, d) + return -d + return -math.matmul(Xdual, d) - @property - def XYd(self) -> Tuple[Optional[RealMatrix], Optional[RealMatrix], Optional[RealVector]]: + def XYd( + self, allow_none: bool = True + ) -> Tuple[Optional[RealMatrix], Optional[RealMatrix], Optional[RealVector]]: r"""Returns the ```(X, Y, d)``` triple. Override in subclasses if computing ``X``, ``Y`` and ``d`` together is more efficient. """ - return self.X_matrix, self.Y_matrix, self.d_vector - - @property - def XYd_dual(self) -> Tuple[Optional[RealMatrix], Optional[RealMatrix], Optional[RealVector]]: + if allow_none: + return self.X_matrix, self.Y_matrix, self.d_vector + X = math.eye(2 * self.num_modes) if self.X_matrix is None else self.X_matrix + Y = math.zeros_like(X) if self.Y_matrix is None else self.Y_matrix + d = math.zeros_like(X[:, 0]) if self.d_vector is None else self.d_vector + return X, Y, d + + def XYd_dual( + self, allow_none: bool = True + ) -> tuple[Optional[RealMatrix], Optional[RealMatrix], Optional[RealVector]]: r"""Returns the ```(X, Y, d)``` triple of the dual of the current transformation. Override in subclasses if computing ``Xdual``, ``Ydual`` and ``ddual`` together is more efficient. """ - return self.X_matrix_dual, self.Y_matrix_dual, self.d_vector_dual - - @property - def is_phase_covariant(self) -> bool: - X, Y, d = self.XYd - if d is not None: - return False - if X is not None and not math.allclose(self.X, math.diag(math.diag_part(self.X))): - return False - if Y is not None and not math.allclose(self.Y, math.diag(math.diag_part(self.Y))): - return False - return True + if allow_none: + return self.X_matrix_dual, self.Y_matrix_dual, self.d_vector_dual + Xdual = math.eye(2 * self.num_modes) if self.X_matrix_dual is None else self.X_matrix_dual + Ydual = math.zeros_like(Xdual) if self.Y_matrix_dual is None else self.Y_matrix_dual + ddual = math.zeros_like(Xdual[:, 0]) if self.d_vector_dual is None else self.d_vector_dual + return Xdual, Ydual, ddual def U(self, cutoffs: Sequence[int]): r"""Returns the unitary representation of the transformation.""" if not self.is_unitary: return None - X, _, d = self.XYd - return fock.wigner_to_fock_U( - X if X is not None else math.eye(2 * self.num_modes), - d if d is not None else math.zeros((2 * self.num_modes,)), - shape=cutoffs * 2 if len(cutoffs) == self.num_modes else cutoffs, - ) + X, _, d = self.XYd(allow_none=False) + if len(cutoffs) == self.num_modes: + shape = tuple(cutoffs) * 2 + elif len(cutoffs) == 2 * self.num_modes: + shape = tuple(cutoffs) + + else: + raise ValueError( + f"Invalid number of cutoffs: {len(cutoffs)} (expected {self.num_modes} or {2*self.num_modes})" + ) + return fock.wigner_to_fock_U(X, d, shape=shape) def choi(self, cutoffs: Sequence[int]): r"""Returns the Choi representation of the transformation.""" + if len(cutoffs) == self.num_modes: + shape = tuple(cutoffs) * 4 + elif len(cutoffs) == 4 * self.num_modes: + shape = tuple(cutoffs) + else: + raise ValueError( + f"Invalid number of cutoffs: {len(cutoffs)} (expected {self.num_modes} or {4*self.num_modes})" + ) if self.is_unitary: - U = self.U(cutoffs) - return fock.U_to_choi(U) - X, Y, d = self.XYd - return fock.wigner_to_fock_Choi( - X if X is not None else math.eye(2 * self.num_modes), - Y if Y is not None else math.zeros((2 * self.num_modes, 2 * self.num_modes)), - d if d is not None else math.zeros((2 * self.num_modes,)), - shape=cutoffs * 4 if len(cutoffs) == self.num_modes else cutoffs, - ) + U = self.U(shape[: self.num_modes]) + Udual = self.U(shape[self.num_modes :]) + return fock.U_to_choi(U, Udual) + X, Y, d = self.XYd(allow_none=False) + + return fock.wigner_to_fock_Choi(X, Y, d, shape=shape) def __getitem__(self, items) -> Callable: r"""Sets the modes on which the transformation acts. @@ -300,7 +322,9 @@ def __lshift__(self, other: Union[State, Transformation]): return self.dual(other) if isinstance(other, Transformation): return self >> other # so that the dual is self.dual(other.dual(x)) - raise ValueError(f"{other} is not a valid state or transformation.") + raise ValueError( + f"{other} of type {other.__class__} is not a valid state or transformation." + ) # pylint: disable=too-many-branches,too-many-return-statements def __eq__(self, other): @@ -309,59 +333,14 @@ def __eq__(self, other): return False if not (self.is_gaussian and other.is_gaussian): return np.allclose( - self.choi(cutoffs=[settings.EQ_TRANSFORMATION_CUTOFF] * self.num_modes), - other.choi(cutoffs=[settings.EQ_TRANSFORMATION_CUTOFF] * self.num_modes), + self.choi(cutoffs=[settings.EQ_TRANSFORMATION_CUTOFF] * 4 * self.num_modes), + other.choi(cutoffs=[settings.EQ_TRANSFORMATION_CUTOFF] * 4 * self.num_modes), rtol=settings.EQ_TRANSFORMATION_RTOL_FOCK, ) - sX, sY, sd = self.XYd - oX, oY, od = other.XYd - if sX is None: - if oX is not None: - if not np.allclose( - oX, np.eye(oX.shape[0]), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if oX is None: - if sX is not None: - if not np.allclose( - sX, np.eye(sX.shape[0]), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if sX is not None and oX is not None: - if not np.allclose(sX, oX): - return False - if sY is None: - if oY is not None: - if not np.allclose( - oY, np.zeros_like(oY), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if oY is None: - if sY is not None: - if not np.allclose( - sY, np.zeros_like(sY), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if sY is not None and oY is not None: - if not np.allclose(sY, oY): - return False - if sd is None: - if od is not None: - if not np.allclose( - sd, np.zeros_like(sd), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if od is None: - if sd is not None: - if not np.allclose( - sd, np.zeros_like(sd), rtol=settings.EQ_TRANSFORMATION_RTOL_GAUSS - ): - return False - if sd is not None and od is not None: - if not np.allclose(sd, od): - return False - return True + sX, sY, sd = self.XYd(allow_none=False) + oX, oY, od = other.XYd(allow_none=False) + return np.allclose(sX, oX) and np.allclose(sY, oY) and np.allclose(sd, od) def __repr__(self): class_name = self.__class__.__name__ diff --git a/mrmustard/lab/circuit.py b/mrmustard/lab/circuit.py index dc34d2708..3b1c2040b 100644 --- a/mrmustard/lab/circuit.py +++ b/mrmustard/lab/circuit.py @@ -20,12 +20,12 @@ __all__ = ["Circuit"] -from mrmustard.typing import RealMatrix, RealVector from typing import List, Optional, Tuple from mrmustard import settings from mrmustard.lab.abstract import State, Transformation from mrmustard.training import Parametrized +from mrmustard.typing import RealMatrix, RealVector from mrmustard.utils.circdrawer import circuit_text from mrmustard.utils.xptensor import XPMatrix, XPVector @@ -62,9 +62,9 @@ def dual(self, state: State) -> State: state = op.dual(state) return state - @property def XYd( self, + allow_none: bool = True, ) -> Tuple[ RealMatrix, RealMatrix, RealVector ]: # NOTE: Overriding Transformation.XYd for efficiency @@ -72,7 +72,7 @@ def XYd( Y = XPMatrix(like_0=True) d = XPVector() for op in self._ops: - opx, opy, opd = op.XYd + opx, opy, opd = op.XYd(allow_none) opX = XPMatrix.from_xxpp(opx, modes=(op.modes, op.modes), like_1=True) opY = XPMatrix.from_xxpp(opy, modes=(op.modes, op.modes), like_0=True) opd = XPVector.from_xxpp(opd, modes=op.modes) diff --git a/mrmustard/lab/detectors.py b/mrmustard/lab/detectors.py index f6fb600ae..578f30d1d 100644 --- a/mrmustard/lab/detectors.py +++ b/mrmustard/lab/detectors.py @@ -16,8 +16,7 @@ This module implements the set of detector classes that perform measurements on quantum circuits. """ -from typing import List, Tuple, Union, Optional, Iterable - +from typing import Iterable, List, Optional, Tuple, Union from mrmustard import settings from mrmustard.math import Math diff --git a/mrmustard/lab/gates.py b/mrmustard/lab/gates.py index 586ce3fc8..f497e663c 100644 --- a/mrmustard/lab/gates.py +++ b/mrmustard/lab/gates.py @@ -18,13 +18,14 @@ This module defines gates and operations that can be applied to quantum modes to construct a quantum circuit. """ -from typing import Union, Optional, List, Tuple, Sequence -from mrmustard.typing import RealMatrix, ComplexMatrix +from typing import List, Optional, Sequence, Tuple, Union + from mrmustard import settings from mrmustard.lab.abstract import Transformation from mrmustard.math import Math -from mrmustard.physics import gaussian, fock +from mrmustard.physics import fock, gaussian from mrmustard.training import Parametrized +from mrmustard.typing import ComplexMatrix, RealMatrix math = Math() @@ -94,28 +95,45 @@ def d_vector(self): return gaussian.displacement(self.x.value, self.y.value, settings.HBAR) def U(self, cutoffs: Sequence[int]): - """Returns the unitary representation of the Displacement gate using the Laguerre - polynomials.""" + r"""Returns the unitary representation of the Displacement gate using + the Laguerre polynomials. + + Arguments: + cutoffs (Sequence[int]): the Hilbert space dimension cutoff for each mode + + Returns: + Raises: + ValueError: if the length of the cutoffs array is different from N and 2N + """ N = self.num_modes x = self.x.value * math.ones(N, dtype=self.x.value.dtype) y = self.y.value * math.ones(N, dtype=self.y.value.dtype) - r = math.sqrt(x * x + y * y) - phi = math.atan2(y, x) - - # calculate displacement unitary for each mode and concatenate with outer product - Ud = None - for idx, cutoff in enumerate(cutoffs): - if Ud is None: - Ud = fock.displacement(r[idx], phi[idx], cutoff) - else: - U_next = fock.displacement(r[idx], phi[idx], cutoff) - Ud = math.outer(Ud, U_next) + if len(cutoffs) == N: + shape = tuple(cutoffs) * 2 + elif len(cutoffs) == 2 * N: + shape = tuple(cutoffs) + else: + raise ValueError( + "len(cutoffs) should be either equal to the number of modes or twice the number of modes (for output-input)." + ) - return math.transpose( - Ud, - list(range(0, 2 * N, 2)) + list(range(1, 2 * N, 2)), - ) + if N > 1: + # calculate displacement unitary for each mode and concatenate with outer product + Ud = None + for idx, out_in in enumerate(zip(shape[:N], shape[N:])): + if Ud is None: + Ud = fock.displacement(x[idx], y[idx], shape=out_in) + else: + U_next = fock.displacement(x[idx], y[idx], shape=out_in) + Ud = math.outer(Ud, U_next) + + return math.transpose( + Ud, + list(range(0, 2 * N, 2)) + list(range(1, 2 * N, 2)), + ) + else: + return fock.displacement(x[0], y[0], shape=shape) class Sgate(Parametrized, Transformation): @@ -160,6 +178,43 @@ def __init__( self.is_gaussian = True self.short_name = "S" + def U(self, cutoffs: Sequence[int]): + r"""Returns the unitary representation of the Squeezing gate. + Args: + cutoffs (Sequence[int]): the Hilbert space dimension cutoff for each mode + + Returns: + array[complex]: the unitary matrix + """ + N = self.num_modes + if len(cutoffs) == N: + shape = tuple(cutoffs) * 2 + elif len(cutoffs) == 2 * N: + shape = tuple(cutoffs) + else: + raise ValueError( + "len(cutoffs) should be either equal to the number of modes or twice the number of modes (for output-input)." + ) + # this works both or scalar r/phi and vector r/phi: + r = self.r.value * math.ones(N, dtype=self.r.value.dtype) + phi = self.phi.value * math.ones(N, dtype=self.phi.value.dtype) + + if N > 1: + # calculate squeezing unitary for each mode and concatenate with outer product + Us = None + for idx, single_shape in enumerate(zip(shape[:N], shape[N:])): + if Us is None: + Us = fock.squeezer(r[idx], phi[idx], shape=single_shape) + else: + U_next = fock.squeezer(r[idx], phi[idx], shape=single_shape) + Us = math.outer(Us, U_next) + return math.transpose( + Us, + list(range(0, 2 * N, 2)) + list(range(1, 2 * N, 2)), + ) + else: + return fock.squeezer(r[0], phi[0], shape=shape) + @property def X_matrix(self): return gaussian.squeezing_symplectic(self.r.value, self.phi.value) @@ -203,13 +258,32 @@ def __init__( def X_matrix(self): return gaussian.rotation_symplectic(self.angle.value) - def U(self, cutoffs: Sequence[int]): + def U(self, cutoffs: Sequence[int], diag_only=False): + r"""Returns the unitary representation of the Rotation gate. + + Args: + cutoffs (Sequence[int]): cutoff dimension for each mode. + diag_only (bool): if True, only return the diagonal of the unitary matrix. + + Returns: + array[complex]: the unitary matrix + """ + if diag_only: + raise NotImplementedError("Rgate does not support diag_only=True yet") + N = self.num_modes + if len(cutoffs) == N: + shape = tuple(cutoffs) * 2 + elif len(cutoffs) == 2 * N: + shape = tuple(cutoffs) + else: + raise ValueError( + "len(cutoffs) should be either equal to the number of modes or twice the number of modes (for output-input)." + ) angles = self.angle.value * math.ones(self.num_modes, dtype=self.angle.value.dtype) - num_modes = len(cutoffs) # calculate rotation unitary for each mode and concatenate with outer product Ur = None - for idx, cutoff in enumerate(cutoffs): + for idx, cutoff in enumerate(shape[: self.num_modes]): theta = math.arange(cutoff) * angles[idx] if Ur is None: Ur = math.diag(math.make_complex(math.cos(theta), math.sin(theta))) @@ -220,7 +294,7 @@ def U(self, cutoffs: Sequence[int]): # return total unitary with indexes reordered according to MM convention return math.transpose( Ur, - list(range(0, 2 * num_modes, 2)) + list(range(1, 2 * num_modes, 2)), + list(range(0, 2 * self.num_modes, 2)) + list(range(1, 2 * self.num_modes, 2)), ) @@ -367,6 +441,33 @@ def __init__( self.is_gaussian = True self.short_name = "BS" + def U(self, cutoffs: Optional[List[int]], method=None): + r"""Returns the symplectic transformation matrix for the beam splitter. + + Args: + cutoffs (List[int]): the list of cutoff dimensions for each mode + in the order (out_0, out_1, in_0, in_1). + method (str): the method used to compute the unitary matrix. Options are: + * 'vanilla': uses the standard method + * 'schwinger': slower, but numerically stable + default is set in settings.DEFAULT_BS_METHOD (with 'vanilla' by default) + + Returns: + array[complex]: the unitary tensor of the beamsplitter + """ + if len(cutoffs) == 4: + shape = tuple(cutoffs) + elif len(cutoffs) == 2: + shape = tuple(cutoffs) + tuple(cutoffs) + else: + raise ValueError(f"Invalid len(cutoffs): {len(cutoffs)} (should be 2 or 4).") + return fock.beamsplitter( + self.theta.value, + self.phi.value, + shape=shape, + method=method or settings.DEFAULT_BS_METHOD, + ) + @property def X_matrix(self): return gaussian.beam_splitter_symplectic(self.theta.value, self.phi.value) diff --git a/mrmustard/lab/states.py b/mrmustard/lab/states.py index 7d08ff140..ea10e1d73 100644 --- a/mrmustard/lab/states.py +++ b/mrmustard/lab/states.py @@ -486,22 +486,29 @@ def __init__( def _preferred_projection(self, other: State, mode_indices: Sequence[int]): r"""Preferred method to perform a projection onto this state (rather than the default one). - E.g. ``ket << Fock(1, modes=[3])`` is equivalent to ``ket[:,:,:,1]`` if ``ket`` has 4 modes - E.g. ``dm << Fock(1, modes=[1])`` is equivalent to ``dm[:,1,:,1]`` if ``dm`` has 2 modes + E.g. ``ket << Fock([1], modes=[3])`` is equivalent to ``ket[:,:,:,1]`` if ``ket`` has 4 modes + E.g. ``dm << Fock([1], modes=[1])`` is equivalent to ``dm[:,1,:,1]`` if ``dm`` has 2 modes Args: other: the state to project onto this state mode_indices: the indices of the modes of other that we want to project onto self """ getitem = [] + cutoffs = [] used = 0 for i, _ in enumerate(other.modes): if i in mode_indices: getitem.append(self._n[used]) + cutoffs.append(self._n[used] + 1) used += 1 else: getitem.append(slice(None)) - output = other.fock[tuple(getitem)] if other.is_pure else other.fock[tuple(getitem) * 2] + cutoffs.append(other.cutoffs[i]) + output = ( + other.ket(cutoffs)[tuple(getitem)] + if other.is_hilbert_vector + else other.dm(cutoffs)[tuple(getitem) * 2] + ) if self._normalize: return fock.normalize(output, is_dm=other.is_mixed) return output diff --git a/mrmustard/math/lattice/__init__.py b/mrmustard/math/lattice/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/mrmustard/math/lattice/neighbors.py b/mrmustard/math/lattice/neighbors.py new file mode 100644 index 000000000..b9fe131dc --- /dev/null +++ b/mrmustard/math/lattice/neighbors.py @@ -0,0 +1,74 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""neighbours functions""" + +from typing import Iterator + +from numba import njit +from numba.cpython.unsafe.tuple import tuple_setitem + +################################################################################# +## All neighbours means all the indices that differ from the given pivot by ±1 ## +################################################################################# + + +@njit +def all_neighbors(pivot: tuple[int, ...]) -> Iterator[tuple[int, tuple[int, ...]]]: + r"""yields the indices of all the neighbours of the given index.""" + for j in range(len(pivot)): # pylint: disable=consider-using-enumerate + yield j, tuple_setitem(pivot, j, pivot[j] - 1) + yield j, tuple_setitem(pivot, j, pivot[j] + 1) + + +#################################################################################### +## Lower neighbours means all the indices that differ from the given index by -1 ## +#################################################################################### + + +@njit +def lower_neighbors(pivot: tuple[int, ...]) -> Iterator[tuple[int, tuple[int, ...]]]: + r"""yields the indices of the lower neighbours of the given index.""" + for j in range(len(pivot)): # pylint: disable=consider-using-enumerate + yield j, tuple_setitem(pivot, j, pivot[j] - 1) + + +#################################################################################### +## Upper neighbours means all the indices that differ from the given index by +1 ## +#################################################################################### + + +@njit +def upper_neighbors(pivot: tuple[int, ...]) -> Iterator[tuple[int, tuple[int, ...]]]: + r"""yields the indices of the lower neighbours of the given index.""" + for j in range(len(pivot)): + yield j, tuple_setitem(pivot, j, pivot[j] + 1) + + +#################################################################################################### +## bitstring neighbours are indices that differ from the given index by ±1 according to a bitstring +#################################################################################################### + + +@njit +def bitstring_neighbors( + pivot: tuple[int, ...], bitstring: tuple[int, ...] +) -> Iterator[tuple[int, tuple[int, ...]]]: + r"yields the indices of the bitstring neighbours of the given index" + for i, b in enumerate(bitstring): + if b: # b == 1 -> lower + yield i, tuple_setitem(pivot, i, pivot[i] - 1) + else: # b == 0 -> upper + yield i, tuple_setitem(pivot, i, pivot[i] + 1) diff --git a/mrmustard/math/lattice/paths.py b/mrmustard/math/lattice/paths.py new file mode 100644 index 000000000..4f3169a30 --- /dev/null +++ b/mrmustard/math/lattice/paths.py @@ -0,0 +1,81 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Path functions""" + +from numba import njit, typed, typeof, types +from numba.cpython.unsafe.tuple import tuple_setitem + +BINOMIAL_PATHS_PYTHON = {} + + +@njit +def _binomial_subspace_basis( + cutoffs: tuple[int, ...], + weight: int, + mode: int, + basis_element: tuple[int, ...], + basis: typed.List[tuple[int, ...]], +): + r"""Step of the recursive function to generate all indices + of a tensor with equal weight. + If cutoffs is an empty tuple, the the basis element is appended to the list. + Otherwise it loops over the values of the given mode, and it calls itself recursively + to construct the rest of the basis elements. + + Arguments: + cutoffs (tuple[int, ...]): the cutoffs of the tensor + weight (int): the weight of the subspace + mode (int): the mode to loop over + basis_element (tuple[int, ...]): the current basis element to construct + basis (list[tuple[int, ...]]): the list of basis elements to eventually append to + """ + if mode == len(cutoffs): + if weight == 0: # ran out of photons to distribute + basis.append(basis_element) + return + + for photons in range(cutoffs[mode]): # could be prange? + if weight - photons >= 0: + basis_element = tuple_setitem(basis_element, mode, photons) + _binomial_subspace_basis(cutoffs, weight - photons, mode + 1, basis_element, basis) + + +@njit +def binomial_subspace_basis(cutoffs: tuple[int, ...], weight: int): + r"""Returns all indices of a tensor with given weight. + + Arguments: + cutoffs (tuple[int, ...]): the cutoffs of the tensor + weight (int): the weight of the subspace + + Returns: + list[tuple[int, ...]]: the list of basis elements of the subspace + """ + basis = typed.List( + [cutoffs] + ) # this is just so that numba can infer the type, then we remove it + _binomial_subspace_basis(cutoffs, weight, 0, cutoffs, basis) + return basis[1:] # remove the dummy element + + +def BINOMIAL_PATHS_NUMBA_n(modes): + r"Creates a numba dictionary to store the paths and effectively cache them." + return typed.Dict.empty( + key_type=typeof(((0,) * modes, 0)), + value_type=types.ListType(typeof((0,) * modes)), + ) + + +BINOMIAL_PATHS_NUMBA = {modes: BINOMIAL_PATHS_NUMBA_n(modes) for modes in range(1, 100)} diff --git a/mrmustard/math/lattice/pivots.py b/mrmustard/math/lattice/pivots.py new file mode 100644 index 000000000..bc564f614 --- /dev/null +++ b/mrmustard/math/lattice/pivots.py @@ -0,0 +1,55 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from numba import njit +from numba.cpython.unsafe.tuple import tuple_setitem + + +@njit +def first_available_pivot(index: tuple[int, ...]) -> tuple[int, tuple[int, ...]]: + r"""returns the first available pivot for the given index. A pivot is a nearest neighbor + of the index. Here we pick the first available pivot. + + Arguments: + index: the index to get the first available pivot of. + + Returns: + the index that was decremented and the pivot + """ + for i, v in enumerate(index): + if v > 0: + return i, tuple_setitem(index, i, v - 1) + raise ValueError("Index is zero") + + +@njit +def smallest_pivot(index: tuple[int, ...]) -> tuple[int, tuple[int, ...]]: + r"""returns the pivot closest to a zero index. A pivot is a nearest neighbor + of the index. Here we pick the pivot with the smallest non-zero element. + + Arguments: + index: the index to get the smallest pivot of. + + Returns: + (int, tuple) the index of the element that was decremented and the pivot + """ + min_ = 2**64 - 1 + for i, v in enumerate(index): + if 0 < v < min_: + min_ = v + min_i = i + if min_ == 2**64 - 1: + raise ValueError("Index is zero") + return min_i, tuple_setitem(index, min_i, min_ - 1) diff --git a/mrmustard/math/lattice/steps.py b/mrmustard/math/lattice/steps.py new file mode 100644 index 000000000..573e04e5a --- /dev/null +++ b/mrmustard/math/lattice/steps.py @@ -0,0 +1,223 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Recurrencies for Fock-Bargmann amplitudes put together a strategy for +# enumerating the indices in a specific order and functions for calculating +# which neighbours to use in the calculation of the amplitude at a given index. +# In summary, they return the value of the amplitude at the given index by following +# a recipe made of two parts. The function to recompute A and b is determined by +# which neighbours are used. + +"""Fock-Bargmann recurrence relation steps for Gaussian states.""" + +import numpy as np +from numba import njit, prange, types +from numba.cpython.unsafe.tuple import tuple_setitem + +from mrmustard.math.lattice.neighbors import lower_neighbors +from mrmustard.math.lattice.pivots import first_available_pivot +from mrmustard.typing import ComplexMatrix, ComplexTensor, ComplexVector + +SQRT = np.sqrt(np.arange(100000)) + + +@njit +def vanilla_step( + G: ComplexTensor, + A: ComplexMatrix, + b: ComplexVector, + index: tuple[int, ...], +) -> complex: + r"""Fock-Bargmann recurrence relation step, vanilla version. + This function returns the amplitude of the Gaussian tensor G + at G[index]. It does not modify G. + The necessary pivot and neighbours must have already been computed, + as this step will read those values from G. + + Args: + G (array or dict): fock amplitudes data store that supports getitem[tuple[int, ...]] + A (array): A matrix of the Fock-Bargmann representation + b (array): B vector of the Fock-Bargmann representation + index (Sequence): index of the amplitude to calculate + Returns: + complex: the value of the amplitude at the given index + """ + # get pivot + i, pivot = first_available_pivot(index) + + # pivot contribution + value_at_index = b[i] * G[pivot] + + # neighbors contribution + for j, neighbor in lower_neighbors(pivot): + value_at_index += A[i, j] * SQRT[pivot[j]] * G[neighbor] + + return value_at_index / SQRT[index[i]] + + +@njit +def vanilla_step_jacobian( + G: ComplexTensor, + A: ComplexMatrix, + b: ComplexVector, + index: tuple[int, ...], + dGdA: ComplexTensor, + dGdB: ComplexTensor, +) -> tuple[ComplexTensor, ComplexTensor]: + r"""Jacobian contribution of a single Fock-Bargmann recurrence relation step, vanilla version. + It updates the dGdB and dGdA tensors at the given index. + + Args: + G (array or dict): fully computed store that supports __getitem__(index: tuple[int, ...]) + A (array): A matrix of the Fock-Bargmann representation + b (array): B vector of the Fock-Bargmann representation + c (complex): vacuum amplitude + index (Sequence): index at which to compute the jacobian + dGdB (array): gradient of G with respect to b (partially computed) + dGdA (array): gradient of G with respect to A (partially computed) + Returns: + tuple[array, array]: the dGdB and dGdA tensors updated at the given index + """ + # index -> pivot + i, pivot = first_available_pivot(index) + + # pivot contribution + dGdB[index] += b[i] * dGdB[pivot] / SQRT[index[i]] + dGdB[index + (i,)] += G[pivot] / SQRT[index[i]] + dGdA[index] += b[i] * dGdA[pivot] / SQRT[index[i]] + + # neighbors contribution + for j, neighbor in lower_neighbors(pivot): + dGdB[index] += A[i, j] * dGdB[neighbor] * SQRT[pivot[j]] / SQRT[index[i]] + dGdA[index] += A[i, j] * dGdA[neighbor] * SQRT[pivot[j]] / SQRT[index[i]] + dGdA[index + (i, j)] += G[neighbor] * SQRT[pivot[j]] / SQRT[index[i]] + + return dGdA, dGdB + + +@njit +def vanilla_step_grad( + G: ComplexTensor, + index: tuple[int, ...], + dA: ComplexMatrix, + db: ComplexVector, +) -> tuple[ComplexMatrix, ComplexVector]: + r"""Gradient with respect to A and b of a single Fock-Bargmann recurrence relation step, + vanilla version. dA and db can be used to update the dGdB and dGdA tensors at `index`, + or as part of the contraction with the gradient of the Gaussian tensor G. + Note that the gradient depends only on G and not on the values of A and b. + + Args: + G (array or dict): fully computed store that supports __getitem__(index: tuple[int, ...]) + index (Sequence): index of the amplitude to calculate the gradient of + dA (array): empty array to store the gradient of G[index] with respect to A + db (array): empty array to store the gradient of G[index] with respect to B + Returns: + tuple[array, array]: the updated dGdB and dGdA tensors + """ + for i in range(len(db)): # pylint: disable=consider-using-enumerate + pivot_i = tuple_setitem(index, i, index[i] - 1) + db[i] = SQRT[index[i]] * G[pivot_i] + dA[i, i] = 0.5 * SQRT[index[i] * pivot_i[i]] * G[tuple_setitem(pivot_i, i, pivot_i[i] - 1)] + for j in range(i + 1, len(db)): + dA[i, j] = SQRT[index[i] * pivot_i[j]] * G[tuple_setitem(pivot_i, j, pivot_i[j] - 1)] + + return dA, db + + +@njit +def vanilla_step_dict( + data: types.DictType, A: ComplexMatrix, b: ComplexVector, index: tuple[int, ...] +) -> complex: + r"""Fock-Bargmann recurrence relation step, vanilla version with numba dict. + This function calculates the index `index` of the Gaussian tensor `G`. + The appropriate pivot and neighbours must exist. + + Args: + data: dict(tuple[int,...], complex): fock amplitudes numba dict + A (array): A matrix of the Fock-Bargmann representation + b (array): b vector of the Fock-Bargmann representation + index (Sequence): index of the amplitude to calculate + Returns: + complex: the value of the amplitude at the given index + """ + # index -> pivot + i, pivot = first_available_pivot(index) + + # calculate value at index: pivot contribution + denom = SQRT[pivot[i] + 1] + value_at_index = b[i] / denom * data[pivot] + + # neighbors contribution + for j, neighbor in lower_neighbors(pivot): + value_at_index += A[i, j] / denom * SQRT[pivot[j]] * data.get(neighbor, 0.0 + 0.0j) + + return value_at_index + + +@njit +def binomial_step( + G: ComplexTensor, A: ComplexMatrix, b: ComplexVector, subspace_indices: list[tuple[int, ...]] +) -> tuple[ComplexTensor, float]: + r"""Computes a whole subspace of the ``G`` tensor at the indices in + ``subspace_indices`` (a subspace is such that `sum(index) = const`). + It updates the tensor ``G``. + It returns the updated tensor and the probability of the subspace. + + Args: + G (np.ndarray): Tensor filled up to the previous subspace + A (np.ndarray): A matrix of the Fock-Bargmann representation + b (np.ndarray): B vector of the Fock-Bargmann representation + subspace_indices (list[tuple[int, ...]]): list of indices to be updated + + Returns: + tuple[np.ndarray, float]: updated tensor and probability of the subspace + """ + norm = 0.0 + + for i in prange(len(subspace_indices)): + value = vanilla_step(G, A, b, subspace_indices[i]) + G[subspace_indices[i]] = value + norm = norm + np.abs(value) ** 2 + + return G, norm + + +@njit +def binomial_step_dict( + G: types.DictType, A: ComplexMatrix, b: ComplexVector, subspace_indices: list[tuple[int, ...]] +) -> tuple[types.DictType, float]: + r"""Computes a whole subspace of the ``G`` dict at the indices in + ``subspace_indices`` (a subspace is such that `sum(index) = const`). + It updates the dict ``G``. It returns the updated G dict + and the total probability of the subspace. + + Args: + G (types.DictType): Dictionary filled up to the previous subspace + A (np.ndarray): A matrix of the Fock-Bargmann representation + b (np.ndarray): B vector of the Fock-Bargmann representation + subspace_indices (list[tuple[int, ...]]): list of indices to be updated + + Returns: + tuple[types.DictType, float]: updated dictionary and probability of the subspace + """ + prob = 0.0 + + for i in prange(len(subspace_indices)): + value = vanilla_step_dict(G, A, b, subspace_indices[i]) + G[subspace_indices[i]] = value + prob = prob + np.abs(value) ** 2 + + return G, prob diff --git a/mrmustard/math/lattice/strategies/__init__.py b/mrmustard/math/lattice/strategies/__init__.py new file mode 100644 index 000000000..66a96b326 --- /dev/null +++ b/mrmustard/math/lattice/strategies/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .beamsplitter import * +from .binomial import * +from .displacement import * +from .squeezer import * +from .vanilla import * diff --git a/mrmustard/math/lattice/strategies/beamsplitter.py b/mrmustard/math/lattice/strategies/beamsplitter.py new file mode 100644 index 000000000..285ff9901 --- /dev/null +++ b/mrmustard/math/lattice/strategies/beamsplitter.py @@ -0,0 +1,204 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Recurrencies for Fock-Bargmann amplitudes put together a strategy for +# enumerating the indices in a specific order and functions for calculating +# which neighbours to use in the calculation of the amplitude at a given index. +# In summary, they return the value of the amplitude at the given index by following +# a recipe made of two parts. The function to recompute A and b is determined by +# which neighbours are used. + +"""Fock-Bargmann recurrence relation steps optimized for beamsplitter.""" + +import numpy as np +from numba import njit + +from mrmustard.math.lattice import steps +from mrmustard.typing import ComplexMatrix, ComplexTensor, ComplexVector + +SQRT = np.sqrt(np.arange(100000)) + +__all__ = ["beamsplitter", "beamsplitter_vjp", "beamsplitter_schwinger"] + + +@njit +def beamsplitter( + shape: tuple[int, int, int, int], theta: float, phi: float, dtype=np.complex128 +) -> ComplexTensor: # pragma: no cover + r"""Calculates the Fock representation of the beamsplitter. + It takes advantage of input-output particle conservation (m+n=p+q) + to avoid one for loop. Inspired from the original implementation in + the walrus by @ziofil. Here is how the parameters are used in the + code (see eq. 73-75 in https://arxiv.org/abs/2004.11002): + + A = [[0,V],[v^T,0]] # BS bargmann matrix + V = [[ct, -st expm], # BS unitary + [st exp, ct]] + + Args: + shape (tuple[int, int, int, int]): shape of the Fock representation + theta (float): beamsplitter angle + phi (float): beamsplitter phase + dtype (np.dtype): data type of the Fock representation + + Returns: + array (ComplexTensor): The Fock representation of the gate + """ + ct = np.cos(theta) + st = np.sin(theta) * np.exp(1j * phi) + stc = np.conj(st) + + M, N, P, Q = shape + G = np.zeros(shape, dtype=dtype) + G[0, 0, 0, 0] = 1.0 + + # rank 3 + for m in range(M): + for n in range(N - m): + p = m + n + if 0 < p < P: + G[m, n, p, 0] = ( + ct * SQRT[m] / SQRT[p] * G[m - 1, n, p - 1, 0] + + st * SQRT[n] / SQRT[p] * G[m, n - 1, p - 1, 0] + ) + + # rank 4 + for m in range(M): + for n in range(N): + for p in range(P): + q = m + n - p + if 0 < q < Q: + G[m, n, p, q] = ( + -stc * SQRT[m] / SQRT[q] * G[m - 1, n, p, q - 1] + + ct * SQRT[n] / SQRT[q] * G[m, n - 1, p, q - 1] + ) + return G + + +@njit +def beamsplitter_vjp( + G: ComplexTensor, + dLdG: ComplexTensor, + theta: float, + phi: float, +) -> tuple[ComplexMatrix, ComplexVector, complex]: # pragma: no cover + r"""Beamsplitter gradients with respect to theta and phi. + This function could return dL/dA, dL/db, dL/dc like its vanilla counterpart, + but it is more efficient to include this chain rule step in the numba function, + since we can. + + We use these derivatives of the BS unitary: + + dVdt = [[-st, -ct exp], + [ct exp, -st]] + dVdphi = [[0, -i ct expm], + [i ct exp, 0]] + + Args: + G (np.ndarray): Tensor result of the forward pass + dLdG (np.ndarray): gradient of the loss with respect to the output tensor + theta (float): beamsplitter angle + phi (float): beamsplitter phase + + Returns: + tuple[float, float]: dL/dtheta, dL/dphi + """ + M, N, P, Q = G.shape + + # init gradients + dA = np.zeros((4, 4), dtype=np.complex128) + db = np.zeros(4, dtype=np.complex128) + dLdA = np.zeros_like(dA) + dLdb = np.zeros_like(db) + + # rank 3 + for m in range(M): + for n in range(N - m): + p = m + n + if 0 < p < P: + dA, db = steps.vanilla_step_grad(G, (m, n, p, 0), dA, db) + dLdA += dA * dLdG[m, n, p, 0] + dLdb += db * dLdG[m, n, p, 0] + + # rank 4 + for m in range(M): + for n in range(N): + for p in range(P): + q = m + n - p + if 0 < q < Q: + dA, db = steps.vanilla_step_grad(G, (m, n, p, q), dA, db) + dLdA += dA * dLdG[m, n, p, q] + dLdb += db * dLdG[m, n, p, q] + + st = np.sin(theta) + ct = np.cos(theta) + e = np.exp(1j * phi) + em = np.exp(-1j * phi) + + # omitting bottom-left block because dLdA should be zero there + dLdtheta = 2 * np.real( + -st * dLdA[0, 2] - ct * em * dLdA[0, 3] + ct * e * dLdA[1, 2] - st * dLdA[1, 3] + ) + dLdphi = 2 * np.real(1j * st * em * dLdA[0, 3] + 1j * st * e * dLdA[1, 2]) + + return dLdtheta, dLdphi + + +def beamsplitter_schwinger(shape, theta, phi, max_N=None): + r"""Returns the Fock representation of the beamsplitter up to + the given cutoff for each of the two modes. + + This implementation is in pure python (so it's slower than the numba version), + but it's numerically stable up to arbitrary cutoffs. + + In this implementation we split the two-mode Fock basis into finite subsets spanned + by |m,n> with m+n=const, i.e. {|0,0>}, {|1,0>,|0,1>}, {|2,0>, |1,1>, |0,2>}, etc... + A beamsplitter acts unitariliy in each of these subspaces without mixing them with each other, + i.e. in this basis the beamsplitter would be a block-diagonal matrix. + This means we can construct the BS matrix by first calculating the BS unitaries + in each of these subspaces. + This can be done using the matrix exponential, which is numerically stable. + We couldn't do this in the original basis because it was infinite-dimensional + and we had to truncate it at some point. + + Arguments: + shape (int, int, int, int): The shape of the output tensor. Only shapes of the form (i,k,i,k) are supported. + theta (float): The angle of the beamsplitter. + phi (float): The phase of the beamsplitter. + max_N (int): The maximum total photon number to include in the calculation. + + Returns: + np.ndarray: The beamsplitter in the Fock basis. + """ + c1, c2, c3, c4 = shape + if c1 != c3 or c2 != c4: + raise ValueError("The Schwinger method only supports shapes of the form (i,k,i,k).") + # create output tensor + U = np.zeros(shape, dtype="complex128") + + # loop over subspaces of constant photon number N up to max_N + if max_N is None or max_N > c1 + c2 - 2: + max_N = c1 + c2 - 2 + for N in range(max_N + 1): + # construct the N+1 x N+1 unitary for this subspace + diag = np.exp(1j * phi) * np.sqrt(np.arange(N, 0, -1) * np.arange(1, N + 1, 1)) + iJy = np.diag(diag, k=-1) - np.diag(np.conj(diag), k=1) + E, V = np.linalg.eig(theta * iJy) + block = V @ np.diag(np.exp(E)) @ np.conj(V.T) + # insert the elements of the block into the output tensor + for i in range(max(0, N + 1 - c1), min(N + 1, c1)): + for j in range(max(0, N + 1 - c1), min(N + 1, c2)): + U[N - i, i, N - j, j] = block[i, j] + return U diff --git a/mrmustard/math/lattice/strategies/binomial.py b/mrmustard/math/lattice/strategies/binomial.py new file mode 100644 index 000000000..771675d1a --- /dev/null +++ b/mrmustard/math/lattice/strategies/binomial.py @@ -0,0 +1,160 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +" This module contains binomial strategies " + +from typing import Optional + +import numpy as np +from numba import njit, typed, types + +from mrmustard.math.lattice import paths, steps +from mrmustard.typing import ComplexMatrix, ComplexTensor, ComplexVector + +SQRT = np.sqrt(np.arange(100000)) + +__all__ = ["binomial", "binomial_dict", "binomial_numba"] + + +def binomial( + local_cutoffs: tuple[int, ...], + A: ComplexMatrix, + b: ComplexVector, + c: complex, + max_l2: float, + global_cutoff: int, +) -> ComplexTensor: + r"""Binomial strategy (fill ket by weight), python version with numba function/loop. + + Args: + local_cutoffs (tuple[int, ...]): local cutoffs of the tensor (used at least as shape) + A (np.ndarray): A matrix of the Fock-Bargmann representation + b (np.ndarray): B vector of the Fock-Bargmann representation + c (complex): vacuum amplitude + max_l2 (float): max L2 norm. If reached, the computation is stopped early. + global_cutoff (Optional[int]): global cutoff (max total photon number considered + 1). + + Returns: + G, prob (np.ndarray, float): Fock representation of the Gaussian tensor with shape ``shape`` and L2 norm + """ + # init output tensor + G = np.zeros(local_cutoffs, dtype=np.complex128) + + # write vacuum amplitude + G.flat[0] = c + norm = np.abs(c) ** 2 + + # iterate over subspaces by weight and stop if norm is large enough. Caches indices. + for photons in range(1, global_cutoff): + try: + indices = paths.BINOMIAL_PATHS_PYTHON[(local_cutoffs, photons)] + except KeyError: + indices = paths.binomial_subspace_basis(local_cutoffs, photons) + paths.BINOMIAL_PATHS_PYTHON[(local_cutoffs, photons)] = indices + G, subspace_norm = steps.binomial_step(G, A, b, indices) # numba parallelized function + norm += subspace_norm + try: + if norm > max_l2: + break + except TypeError: # max_l2 is None + pass + return G, norm + + +def binomial_dict( + local_cutoffs: tuple[int, ...], + A: ComplexMatrix, + b: ComplexVector, + c: complex, + max_prob: Optional[float] = None, + global_cutoff: Optional[int] = None, +) -> dict[tuple[int, ...], complex]: + r"""Factorial speedup strategy (fill ket by weight), python version with numba function/loop. + Uses a dictionary to store the output. + + Args: + local_cutoffs (tuple[int, ...]): local cutoffs of the tensor (used at least as shape) + A (np.ndarray): A matrix of the Fock-Bargmann representation + b (np.ndarray): B vector of the Fock-Bargmann representation + c (complex): vacuum amplitude + max_prob (float): max L2 norm. If reached, the computation is stopped early. + global_cutoff (Optional[int]): global cutoff (max total photon number considered). + If not given it is calculated from the local cutoffs. + + Returns: + dict[tuple[int, ...], complex]: Fock representation of the Gaussian tensor. + """ + if global_cutoff is None: + global_cutoff = sum(local_cutoffs) - len(local_cutoffs) + + # init numba output dict + G = typed.Dict.empty( + key_type=types.UniTuple(types.int64, len(local_cutoffs)), + value_type=types.complex128, + ) + + # write vacuum amplitude + G[(0,) * len(local_cutoffs)] = c + prob = np.abs(c) ** 2 + + # iterate over subspaces by weight and stop if norm is large enough. Caches indices. + for photons in range(1, global_cutoff): + try: + indices = paths.BINOMIAL_PATHS_PYTHON[(local_cutoffs, photons)] + except KeyError: + indices = paths.binomial_subspace_basis(local_cutoffs, photons) + paths.BINOMIAL_PATHS_PYTHON[(local_cutoffs, photons)] = indices + G, prob_subspace = steps.binomial_step_dict(G, A, b, indices) # numba parallelized function + prob += prob_subspace + try: + if prob > max_prob: + break + except TypeError: + pass + return G + + +@njit +def binomial_numba( + local_cutoffs: tuple[int, ...], + A: ComplexMatrix, + b: ComplexVector, + c: complex, + FP: dict[tuple[tuple[int, ...], int], list[tuple[int, ...]]], + max_prob: float = 0.999, + global_cutoff: Optional[int] = None, +) -> ComplexTensor: # pragma: no cover + r"""Binomial strategy (fill by weight), fully numba version.""" + if global_cutoff is None: + global_cutoff = sum(local_cutoffs) - len(local_cutoffs) + + # init output tensor + G = np.zeros(local_cutoffs, dtype=np.complex128) + + # write vacuum amplitude + G.flat[0] = c + prob = np.abs(c) ** 2 + + # iterate over all other indices in parallel and stop if norm is large enough + for photons in range(1, global_cutoff): + try: + indices = FP[(local_cutoffs, photons)] + except Exception: # pylint: disable=broad-except + indices = paths.binomial_subspace_basis(local_cutoffs, photons) + FP[(local_cutoffs, photons)] = indices + G, prob_subspace = steps.binomial_step(G, A, b, indices) + prob += prob_subspace + if prob > max_prob: + break + return G diff --git a/mrmustard/math/lattice/strategies/displacement.py b/mrmustard/math/lattice/strategies/displacement.py new file mode 100644 index 000000000..79c3568f8 --- /dev/null +++ b/mrmustard/math/lattice/strategies/displacement.py @@ -0,0 +1,139 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +" This module contains strategies for calculating the matrix elements of the displacement gate. " + +import numpy as np +from numba import jit + +__all__ = ["displacement", "laguerre", "grad_displacement", "jacobian_displacement"] + + +@jit(nopython=True) +def displacement(cutoffs, alpha, dtype=np.complex128): # pragma: no cover + r"""Calculates the matrix elements of the displacement gate using a recurrence relation. + Uses the log of the matrix elements to avoid numerical issues and then takes the exponential. + + Args: + alpha (complex): displacement magnitude and angle + cutoffs (tuple[int, int]): Fock ladder output-input cutoffs + dtype (data type): Specifies the data type used for the calculation + + Returns: + array[complex]: matrix representing the displacement operation. + """ + r = np.abs(alpha) + phi = np.angle(alpha) + N, M = cutoffs + flipped = False + if N < M: + N, M = M, N + flipped = True + + D = np.zeros((N, M), dtype=dtype) + rng = np.arange(max(*cutoffs)) + rng[0] = 1 + log_k_fac = np.cumsum(np.log(rng)) + for n_minus_m in range(N): + m_max = min(M, N - n_minus_m) + logL = np.log(laguerre(r**2.0, m_max, n_minus_m)) + for m in range(m_max): + n = n_minus_m + m + sign = 2 * (not (flipped and n > m and n_minus_m % 2)) - 1 + conj = 2 * (not (flipped and n > m)) - 1 + D[n, m] = sign * np.exp( + +0.5 * (log_k_fac[m] - log_k_fac[n]) + + n_minus_m * np.log(r) + - (r**2.0) / 2.0 + + conj * 1j * phi * n_minus_m + + logL[m] + ) + if n < M: + D[m, n] = (-1.0) ** n_minus_m * np.conj(D[n, m]) + return D if not flipped else np.transpose(D) + + +@jit(nopython=True, cache=True) +def laguerre(x, N, alpha, dtype=np.complex128): # pragma: no cover + r"""Returns the N first generalized Laguerre polynomials evaluated at x. + + Args: + x (float): point at which to evaluate the polynomials + N (int): maximum Laguerre polynomial to calculate + alpha (float): continuous parameter for the generalized Laguerre polynomials + """ + L = np.zeros(N, dtype=dtype) + L[0] = 1.0 + if N > 1: + for m in range(0, N - 1): + L[m + 1] = ((2 * m + 1 + alpha - x) * L[m] - (m + alpha) * L[m - 1]) / (m + 1) + return L + + +@jit(nopython=True) +def grad_displacement(T, r, phi): # pragma: no cover + r"""Calculates the gradient of the displacement gate with respect to the magnitude and angle of the displacement. + + Args: + T (array[complex]): array representing the gate + r (float): displacement magnitude + phi (float): displacement angle + + Returns: + tuple[array[complex], array[complex]]: The gradient of the displacement gate with respect to r and phi + """ + cutoff = T.shape[0] + dtype = T.dtype + ei = np.exp(1j * phi) + eic = np.exp(-1j * phi) + alpha = r * ei + alphac = r * eic + sqrt = np.sqrt(np.arange(cutoff, dtype=dtype)) + grad_r = np.zeros((cutoff, cutoff), dtype=dtype) + grad_phi = np.zeros((cutoff, cutoff), dtype=dtype) + + for m in range(cutoff): + for n in range(cutoff): + grad_r[m, n] = -r * T[m, n] + sqrt[m] * ei * T[m - 1, n] - sqrt[n] * eic * T[m, n - 1] + grad_phi[m, n] = ( + sqrt[m] * 1j * alpha * T[m - 1, n] + sqrt[n] * 1j * alphac * T[m, n - 1] + ) + + return grad_r, grad_phi + + +@jit(nopython=True) +def jacobian_displacement(D, alpha): # pragma: no cover + r"""Calculates the jacobian of the displacement gate with respect to the complex displacement + alpha and its conjugate. Both are needed for backprop, as the displacement gate is not a + holomorphic function, as the Fock amplitudes depend on both alpha and on its conjugate. + Each jacobian in this case has the same shape as the array D, as the displacement is a scalar. + + Args: + D (array[complex]): the D(alpha) gate in Fock representation. Batch dimensions are allowed. + alpha (complex): parameter of D(alpha) + + Returns: + 2 array[complex]: The jacobian of the displacement gate with respect to alpha and alphaconj + """ + shape = D.shape[-2:] + alphac = np.conj(alpha) + sqrt = np.sqrt(np.arange(shape[0] + shape[1], dtype=D.dtype)) + jac_alpha = np.zeros(D.shape, dtype=D.dtype) # i.e. dD_dalpha for all m,n + jac_alphac = np.zeros(D.shape, dtype=D.dtype) # i.e. dD_dalphac for all m,n + for m in range(shape[0]): + for n in range(shape[1]): + jac_alpha[m, n] = -0.5 * alphac * D[m, n] + sqrt[m] * D[m - 1, n] + jac_alphac[m, n] = -0.5 * alpha * D[m, n] - sqrt[n] * D[m, n - 1] + return jac_alpha, jac_alphac diff --git a/mrmustard/math/lattice/strategies/squeezer.py b/mrmustard/math/lattice/strategies/squeezer.py new file mode 100644 index 000000000..a39a7e649 --- /dev/null +++ b/mrmustard/math/lattice/strategies/squeezer.py @@ -0,0 +1,188 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +" This module contains strategies for calculating the matrix elements of the squeezing gate. " + +import numpy as np +from numba import njit + +from mrmustard.math.lattice import steps +from mrmustard.typing import ComplexTensor + +SQRT = np.sqrt(np.arange(100000)) + +__all__ = ["squeezer", "squeezer_vjp", "squeezed", "squeezed_vjp"] + + +@njit +def squeezer( + shape: tuple[int, int], r: float, theta: float, dtype=np.complex128 +): # pragma: no cover + r"""Calculates the matrix elements of the squeezing gate using a recurrence relation. + (See eq. 50-52 in https://arxiv.org/abs/2004.11002) + Args: + shape (tuple[int, int]): Fock cutoffs for the output and input indices. + r (float): squeezing magnitude + theta (float): squeezing angle + dtype (data type): data type used for the calculation. + + Returns: + array (ComplexMatrix): matrix representing the squeezing gate. + """ + M, N = shape + S = np.zeros(shape, dtype=dtype) + + eitheta_tanhr = np.exp(1j * theta) * np.tanh(r) + eitheta_tanhr_conj = np.conj(eitheta_tanhr) + sechr = 1.0 / np.cosh(r) + + S[0, 0] = np.sqrt(sechr) + for m in range(2, M, 2): + S[m, 0] = -SQRT[m - 1] / SQRT[m] * eitheta_tanhr * S[m - 2, 0] + + for m in range(M): + for n in range(2 - (m % 2), N, 2): + # for n in range(1, N): + if (m + n) % 2 == 0: + S[m, n] = ( + SQRT[n - 1] / SQRT[n] * eitheta_tanhr_conj * S[m, n - 2] + + SQRT[m] / SQRT[n] * sechr * S[m - 1, n - 1] + ) + return S + + +@njit +def squeezer_vjp( + G: ComplexTensor, + dLdG: ComplexTensor, + r: float, + phi: float, +) -> tuple[float, float]: # pragma: no cover + r"""Squeezing gradients with respect to r and theta. + This function could return dL/dA, dL/db, dL/dc like its vanilla counterpart, + but it is more efficient to include this chain rule step in the numba function, since we can. + + Args: + G (np.ndarray): Tensor result of the forward pass + dLdG (np.ndarray): gradient of the loss with respect to the output tensor + r (float): squeezing magnitude + phi (float): squeezing angle + + Returns: + tuple[float, float]: dL/dr, dL/phi + """ + M, N = G.shape + + # init gradients + dA = np.zeros((2, 2), dtype=np.complex128) # dGdA at an index (of G) + _ = np.zeros(2, dtype=np.complex128) + dLdA = np.zeros_like(dA) + + # first column + for m in range(2, M, 2): + dA, _ = steps.vanilla_step_grad(G, (m, 0), dA, _) + dLdA += dA * dLdG[m, 0] + + # rest of the matrix + for m in range(M): + for n in range(1, N): + if (m + n) % 2 == 0: + dA, _ = steps.vanilla_step_grad(G, (m, n), dA, _) + dLdA += dA * dLdG[m, n] + + dLdC = np.sum(G * dLdG) # np.sqrt(np.cosh(r)) cancels out with 1 / np.sqrt(np.cosh(r)) later + # chain rule + d_sech = -np.tanh(r) / np.cosh(r) + d_tanh = 1.0 / np.cosh(r) ** 2 + tanh = np.tanh(r) + exp = np.exp(1j * phi) + exp_conj = np.exp(-1j * phi) + + dLdr = 2 * np.real( + -dLdA[0, 0] * exp * d_tanh + + dLdA[0, 1] * d_sech + + dLdA[1, 1] * exp_conj * d_tanh + - np.conj(dLdC) * 0.5 * tanh # / np.sqrt(np.cosh(r)) + ) + dLdphi = 2 * np.real(-dLdA[0, 0] * 1j * exp * tanh - dLdA[1, 1] * 1j * exp_conj * tanh) + + return dLdr, dLdphi + + +@njit +def squeezed(cutoff: int, r: float, theta: float, dtype=np.complex128): # pragma: no cover + r"""Calculates the matrix elements of the single-mode squeezed state using recurrence relations. + + Args: + cutoff (int): Fock cutoff for the ket + r (float): squeezing magnitude + theta (float): squeezing angle + dtype (data type): data type used for the calculation. + + Returns: + array (ComplexMatrix): matrix representing the squeezing gate. + """ + S = np.zeros(cutoff, dtype=dtype) + eitheta_tanhr = np.exp(1j * theta) * np.tanh(r) + S[0] = np.sqrt(1.0 / np.cosh(r)) + + for m in range(2, cutoff, 2): + S[m] = SQRT[m - 1] / SQRT[m] * eitheta_tanhr * S[m - 2] + + return S + + +@njit +def squeezed_vjp( + G: ComplexTensor, + dLdG: ComplexTensor, + r: float, + phi: float, +) -> tuple[float, float]: # pragma: no cover + r"""Squeezed state gradients with respect to r and theta. + This function could return dL/dA, dL/db, dL/dc like its vanilla counterpart, + but it is more efficient to include this chain rule step in the numba function, since we can. + + Args: + G (np.ndarray): Tensor result of the forward pass + dLdG (np.ndarray): gradient of the loss with respect to the output tensor + r (float): squeezing magnitude + phi (float): squeezing angle + + Returns: + tuple[float, float]: dL/dr, dL/phi + """ + M = G.shape[0] + + # init gradients + dA = np.zeros((1, 1), dtype=np.complex128) + _ = np.zeros(1, dtype=np.complex128) + dLdA = np.zeros_like(dA) + + # first column + for m in range(2, M, 2): + dA, _ = steps.vanilla_step_grad(G, (m,), dA, _) + dLdA += dA * dLdG[m] + + # chain rule + tanh = np.tanh(r) + d_tanh = 1.0 / np.cosh(r) ** 2 + exp = np.exp(1j * phi) + + dLdC = np.sum(G * dLdG) # np.sqrt(np.cosh(r)) cancels out with 1 / np.sqrt(np.cosh(r)) later + + dLdr = 2 * np.real(-dLdA[0, 0] * exp * d_tanh - np.conj(dLdC) * 0.5 * tanh) + dLdphi = 2 * np.real(-dLdA[0, 0] * 1j * exp * tanh) + + return dLdr, dLdphi diff --git a/mrmustard/math/lattice/strategies/vanilla.py b/mrmustard/math/lattice/strategies/vanilla.py new file mode 100644 index 000000000..6943f98cf --- /dev/null +++ b/mrmustard/math/lattice/strategies/vanilla.py @@ -0,0 +1,117 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +from numba import njit + +from mrmustard.math.lattice import paths, steps +from mrmustard.typing import ComplexMatrix, ComplexTensor, ComplexVector + +SQRT = np.sqrt(np.arange(100000)) + +__all__ = ["vanilla", "vanilla_jacobian", "vanilla_vjp"] + + +@njit +def vanilla(shape: tuple[int, ...], A, b, c) -> ComplexTensor: # pragma: no cover + r"""Vanilla Fock-Bargmann strategy. Fills the tensor by iterating over all indices + in ndindex order. + + Args: + shape (tuple[int, ...]): shape of the output tensor + A (np.ndarray): A matrix of the Fock-Bargmann representation + b (np.ndarray): B vector of the Fock-Bargmann representation + c (complex): vacuum amplitude + + Returns: + np.ndarray: Fock representation of the Gaussian tensor with shape ``shape`` + """ + + # init output tensor + G = np.zeros(shape, dtype=np.complex128) + + # initialize path iterator + path = np.ndindex(shape) + + # write vacuum amplitude + G[next(path)] = c + + # iterate over the rest of the indices + for index in path: + G[index] = steps.vanilla_step(G, A, b, index) + return G + + +@njit +def vanilla_jacobian( + G, A, b, c +) -> tuple[ComplexTensor, ComplexTensor, ComplexTensor]: # pragma: no cover + r"""Vanilla Fock-Bargmann strategy gradient. Returns dG/dA, dG/db, dG/dc. + Notice that G is a holomorphic function of A, b, c. This means that there is only + one gradient to care about for each parameter (i.e. not dG/dA.conj() etc). + """ + + # init output tensors + dGdA = np.zeros(G.shape + A.shape, dtype=np.complex128) + dGdb = np.zeros(G.shape + b.shape, dtype=np.complex128) + dGdc = G / c + + # initialize path iterator + path = paths.ndindex_path(G.shape) + + # skip first index + next(path) + + # iterate over the rest of the indices + for index in path: + dGdA, dGdb = steps.vanilla_step_jacobian(G, A, b, index, dGdA, dGdb) + + return dGdA, dGdb, dGdc + + +@njit +def vanilla_vjp(G, c, dLdG) -> tuple[ComplexMatrix, ComplexVector, complex]: # pragma: no cover + r"""Vanilla Fock-Bargmann strategy gradient. Returns dL/dA, dL/db, dL/dc. + + Args: + G (np.ndarray): Tensor result of the forward pass + c (complex): vacuum amplitude + dLdG (np.ndarray): gradient of the loss with respect to the output tensor + + Returns: + tuple[np.ndarray, np.ndarray, complex]: dL/dA, dL/db, dL/dc + """ + D = G.ndim + + # init gradients + dA = np.zeros((D, D), dtype=np.complex128) # component of dL/dA + db = np.zeros(D, dtype=np.complex128) # component of dL/db + dLdA = np.zeros_like(dA) + dLdb = np.zeros_like(db) + + # initialize path iterator + path = np.ndindex(G.shape) + + # skip first index + next(path) + + # iterate over the rest of the indices + for index in path: + dA, db = steps.vanilla_step_grad(G, index, dA, db) + dLdA += dA * dLdG[index] + dLdb += db * dLdG[index] + + dLdc = np.sum(G * dLdG) / c + + return dLdA, dLdb, dLdc diff --git a/mrmustard/math/math_interface.py b/mrmustard/math/math_interface.py index fb074c009..986c9171b 100644 --- a/mrmustard/math/math_interface.py +++ b/mrmustard/math/math_interface.py @@ -15,19 +15,21 @@ """This module contains the :class:`Math` interface that every backend has to implement.""" from abc import ABC, abstractmethod -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple from functools import lru_cache from itertools import product +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple + import numpy as np from scipy.special import binom -from scipy.stats import unitary_group, ortho_group +from scipy.stats import ortho_group, unitary_group + from mrmustard import settings from mrmustard.typing import ( - Tensor, Matrix, Scalar, - Vector, + Tensor, Trainable, + Vector, ) diff --git a/mrmustard/math/numba/compactFock_1leftoverMode_amps.py b/mrmustard/math/numba/compactFock_1leftoverMode_amps.py index f6751f30a..959ef5466 100644 --- a/mrmustard/math/numba/compactFock_1leftoverMode_amps.py +++ b/mrmustard/math/numba/compactFock_1leftoverMode_amps.py @@ -3,21 +3,22 @@ This is done by applying the recursion relation in a selective manner. """ -import numpy as np import numba -from numba import njit, int64 +import numpy as np +from numba import int64, njit from numba.cpython.unsafe.tuple import tuple_setitem + from mrmustard.math.numba.compactFock_helperFunctions import ( SQRT, - repeat_twice, construct_dict_params, + repeat_twice, ) @njit def write_block( i, arr_write, write, arr_read_pivot, read_GB, G_in, GB, A, K_i, cutoff_leftoverMode -): +): # pragma: no cover """ Apply the recurrence relation to blocks of Fock amplitudes (of shape cutoff_leftoverMode x cutoff_leftoverMode) This is the coarse-grained version of applying the recurrence relation of mrmustard.math.numba.compactFock_diagonal_amps once. @@ -62,7 +63,9 @@ def write_block( @njit -def read_block(arr_write, idx_write, arr_read, idx_read_tail, cutoff_leftoverMode): +def read_block( + arr_write, idx_write, arr_read, idx_read_tail, cutoff_leftoverMode +): # pragma: no cover """ Read the blocks of Fock amplitudes (of shape cutoff_leftoverMode x cutoff_leftoverMode) that are required to apply the recurrence relation and write them to G_in @@ -258,7 +261,7 @@ def fock_representation_1leftoverMode_amps_NUMBA( for sum_params in range(sum(cutoffs_tail)): for params in dict_params[sum_params]: # diagonal pivots: aa,bb,cc,dd,... - if params[0] < cutoffs_tail[0] - 1: + if (cutoffs_tail[0] == 1) or (params[0] < cutoffs_tail[0] - 1): arr1 = use_diag_pivot( A, B, M - 1, cutoff_leftoverMode, cutoffs_tail, params, arr0, arr1 ) diff --git a/mrmustard/math/numba/compactFock_1leftoverMode_grad.py b/mrmustard/math/numba/compactFock_1leftoverMode_grad.py index 0bb14c6c5..d94db1a4e 100644 --- a/mrmustard/math/numba/compactFock_1leftoverMode_grad.py +++ b/mrmustard/math/numba/compactFock_1leftoverMode_grad.py @@ -655,7 +655,7 @@ def fock_representation_1leftoverMode_grad_NUMBA( for sum_params in range(sum(cutoffs_tail)): for params in dict_params[sum_params]: # diagonal pivots: aa,bb,cc,dd,... - if params[0] < cutoffs_tail[0] - 1: + if (cutoffs_tail[0] == 1) or (params[0] < cutoffs_tail[0] - 1): arr1_dA, arr1_dB = use_diag_pivot_grad( A, B, diff --git a/mrmustard/math/numba/compactFock_diagonal_amps.py b/mrmustard/math/numba/compactFock_diagonal_amps.py index d65e4ca58..d78df379a 100644 --- a/mrmustard/math/numba/compactFock_diagonal_amps.py +++ b/mrmustard/math/numba/compactFock_diagonal_amps.py @@ -142,7 +142,7 @@ def fock_representation_diagonal_amps_NUMBA( for sum_params in range(sum(cutoffs)): for params in dict_params[sum_params]: # diagonal pivots: aa,bb,cc,dd,... - if params[0] < cutoffs[0] - 1: + if (cutoffs[0] == 1) or (params[0] < cutoffs[0] - 1): arr1 = use_diag_pivot(A, B, M, cutoffs, params, arr0, arr1) # off-diagonal pivots: d=0: (a+1)a,bb,cc,dd,... | d=1: 00,(b+1)b,cc,dd | 00,00,(c+1)c,dd | ... for d in range(M): diff --git a/mrmustard/math/numba/compactFock_diagonal_grad.py b/mrmustard/math/numba/compactFock_diagonal_grad.py index 6b767b182..b3aab8fcd 100644 --- a/mrmustard/math/numba/compactFock_diagonal_grad.py +++ b/mrmustard/math/numba/compactFock_diagonal_grad.py @@ -254,7 +254,7 @@ def fock_representation_diagonal_grad_NUMBA( for sum_params in range(sum(cutoffs)): for params in dict_params[sum_params]: # diagonal pivots: aa,bb,cc,dd,... - if params[0] < cutoffs[0] - 1: + if (cutoffs[0] == 1) or (params[0] < cutoffs[0] - 1): arr1_dA, arr1_dB = use_diag_pivot_grad( A, B, M, cutoffs, params, arr0, arr1, arr0_dA, arr1_dA, arr0_dB, arr1_dB ) diff --git a/mrmustard/math/tensorflow.py b/mrmustard/math/tensorflow.py index 99caf41cd..5be6eba03 100644 --- a/mrmustard/math/tensorflow.py +++ b/mrmustard/math/tensorflow.py @@ -14,25 +14,23 @@ """This module contains the Tensorflow implementation of the :class:`Math` interface.""" -from typing import Callable, List, Sequence, Tuple, Union, Optional +from typing import Callable, List, Optional, Sequence, Tuple, Union import numpy as np import tensorflow as tf import tensorflow_probability as tfp -from thewalrus import hermite_multidimensional, grad_hermite_multidimensional - +from mrmustard import settings +from mrmustard.math.autocast import Autocast +from mrmustard.math.lattice import strategies from mrmustard.math.numba.compactFock_inputValidation import ( - hermite_multidimensional_diagonal, + grad_hermite_multidimensional_1leftoverMode, grad_hermite_multidimensional_diagonal, -) -from mrmustard.math.numba.compactFock_inputValidation import ( hermite_multidimensional_1leftoverMode, - grad_hermite_multidimensional_1leftoverMode, + hermite_multidimensional_diagonal, ) - -from mrmustard.math.autocast import Autocast from mrmustard.typing import Tensor, Trainable + from .math_interface import MathInterface @@ -364,10 +362,11 @@ def value_and_gradients( @tf.custom_gradient def hermite_renormalized( self, A: tf.Tensor, B: tf.Tensor, C: tf.Tensor, shape: Tuple[int] - ) -> tf.Tensor: # TODO this is not ready + ) -> tf.Tensor: r"""Renormalized multidimensional Hermite polynomial given by the "exponential" Taylor - series of :math:`exp(C + Bx - Ax^2)` at zero, where the series has :math:`sqrt(n!)` at the - denominator rather than :math:`n!`. Note the minus sign in front of ``A``. + series of :math:`exp(C + Bx + 1/2*Ax^2)` at zero, where the series has :math:`sqrt(n!)` + at the denominator rather than :math:`n!`. It computes all the amplitudes within the + tensor of given shape. Args: A: The A matrix. @@ -378,31 +377,62 @@ def hermite_renormalized( Returns: The renormalized Hermite polynomial of given shape. """ - if isinstance(shape, List) and len(shape) == 1: - shape = shape[0] + _A, _B, _C = self.asnumpy(A), self.asnumpy(B), self.asnumpy(C) + G = strategies.vanilla(tuple(shape), _A, _B, _C) + + def grad(dLdGconj): + dLdA, dLdB, dLdC = strategies.vanilla_vjp(G, _C, np.conj(dLdGconj)) + return self.conj(dLdA), self.conj(dLdB), self.conj(dLdC) - poly = hermite_multidimensional( - self.asnumpy(A), shape, self.asnumpy(B), self.asnumpy(C), True, True, True + return G, grad + + @tf.custom_gradient + def hermite_renormalized_binomial( + self, + A: tf.Tensor, + B: tf.Tensor, + C: tf.Tensor, + shape: Tuple[int], + max_l2: Optional[float], + global_cutoff: Optional[int], + ) -> tf.Tensor: + r"""Renormalized multidimensional Hermite polynomial given by the "exponential" Taylor + series of :math:`exp(C + Bx + 1/2*Ax^2)` at zero, where the series has :math:`sqrt(n!)` + at the denominator rather than :math:`n!`. The computation fills a tensor of given shape + up to a given L2 norm or global cutoff, whichever applies first. The max_l2 value, if + not provided, is set to the default value of the AUTOCUTOFF_PROBABILITY setting. + + Args: + A: The A matrix. + B: The B vector. + C: The C scalar. + shape: The shape of the final tensor (local cutoffs). + max_l2 (float): The maximum squared L2 norm of the tensor. + global_cutoff (optional int): The global cutoff. + + Returns: + The renormalized Hermite polynomial of given shape. + """ + _A, _B, _C = self.asnumpy(A), self.asnumpy(B), self.asnumpy(C) + G, _ = strategies.binomial( + tuple(shape), + _A, + _B, + _C, + max_l2=max_l2 or settings.AUTOCUTOFF_PROBABILITY, + global_cutoff=global_cutoff or sum(shape) - len(shape) + 1, ) - def grad(dLdpoly): - dpoly_dC, dpoly_dA, dpoly_dB = tf.numpy_function( - grad_hermite_multidimensional, [poly, A, B, C], [poly.dtype] * 3 - ) - ax = tuple(range(dLdpoly.ndim)) - dLdA = self.sum(dLdpoly[..., None, None] * self.conj(dpoly_dA), axes=ax) - dLdB = self.sum(dLdpoly[..., None] * self.conj(dpoly_dB), axes=ax) - dLdC = self.sum(dLdpoly * self.conj(dpoly_dC), axes=ax) - return dLdA, dLdB, dLdC + def grad(dLdGconj): + dLdA, dLdB, dLdC = strategies.vanilla_vjp(G, _C, np.conj(dLdGconj)) + return self.conj(dLdA), self.conj(dLdB), self.conj(dLdC) - return poly, grad + return G, grad def reorder_AB_bargmann(self, A: tf.Tensor, B: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]: r"""In mrmustard.math.numba.compactFock~ dimensions of the Fock representation are ordered like [mode0,mode0,mode1,mode1,...] while in mrmustard.physics.bargmann the ordering is [mode0,mode1,...,mode0,mode1,...]. Here we reorder A and B. - Moreover, the recurrence relation in mrmustard.math.numba.compactFock~ is defined such that A = -A compared to mrmustard.physics.bargmann. """ - A = -A ordering = np.arange(2 * A.shape[0] // 2).reshape(2, -1).T.flatten() A = tf.gather(A, ordering, axis=1) A = tf.gather(A, ordering) @@ -543,9 +573,9 @@ def boolean_mask(tensor: tf.Tensor, mask: tf.Tensor) -> Tensor: return tf.boolean_mask(tensor, mask) @staticmethod - def custom_gradient(func): + def custom_gradient(func, *args, **kwargs): """Decorator to define a function with a custom gradient.""" - return tf.custom_gradient(func) + return tf.custom_gradient(func, *args, **kwargs) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extras (not in the Interface) diff --git a/mrmustard/physics/bargmann.py b/mrmustard/physics/bargmann.py index 43b7738cb..f9513fe8f 100644 --- a/mrmustard/physics/bargmann.py +++ b/mrmustard/physics/bargmann.py @@ -18,9 +18,10 @@ This module contains functions for transforming to the Bargmann representation. """ import numpy as np -from mrmustard.physics.husimi import wigner_to_husimi, pq_to_aadag + from mrmustard import settings from mrmustard.math import Math +from mrmustard.physics.husimi import pq_to_aadag, wigner_to_husimi math = Math() @@ -51,10 +52,10 @@ def wigner_to_bargmann_rho(cov, means): here we define it as `A = [[A_11, A_10], [A_01, A_00]]`. For `B` we have `B = [B_0, B_1] -> B = [B_1, B_0]`. """ N = cov.shape[-1] // 2 - Q, beta = wigner_to_husimi(cov, means) A = math.matmul( cayley(pq_to_aadag(cov), c=0.5), math.Xmat(N) ) # X on the right, so the index order will be rho_{left,right}: + Q, beta = wigner_to_husimi(cov, means) B = math.solve(Q, beta) # no conjugate, so that the index order will be rho_{left,right} C = math.exp(-0.5 * math.sum(math.conj(beta) * B)) / math.sqrt(math.det(Q)) return A, B, C diff --git a/mrmustard/physics/fock.py b/mrmustard/physics/fock.py index 3eaa6f1c6..9fd1e049c 100644 --- a/mrmustard/physics/fock.py +++ b/mrmustard/physics/fock.py @@ -22,11 +22,11 @@ from typing import List, Optional, Sequence, Tuple import numpy as np -from numba import jit from mrmustard import settings from mrmustard.math import Math from mrmustard.math.caching import tensor_int_cache +from mrmustard.math.lattice import strategies from mrmustard.math.mmtensor import MMTensor from mrmustard.math.numba.compactFock_diagonal_amps import fock_representation_diagonal_amps from mrmustard.physics.bargmann import ( @@ -35,7 +35,7 @@ wigner_to_bargmann_rho, wigner_to_bargmann_U, ) -from mrmustard.typing import Matrix, Scalar, Tensor, Vector +from mrmustard.typing import ComplexTensor, Matrix, Scalar, Tensor, Vector math = Math() SQRT = np.sqrt(np.arange(1e6)) @@ -93,21 +93,27 @@ def wigner_to_fock_state( cov: Matrix, means: Vector, shape: Sequence[int], + max_prob: float = 1.0, + max_photons: Optional[int] = None, return_dm: bool = True, ) -> Tensor: r"""Returns the Fock representation of a Gaussian state. Use with caution: if the cov matrix is that of a mixed state, setting return_dm to False will produce nonsense. + If return_dm=False, we can apply max_prob and max_photons to stop the + computation of the Fock representation early, when those conditions are met. * If the state is pure it can return the state vector (ket) or the density matrix. - The index order is going to be ket_i where i is the only multimode index. + The index ordering is going to be [i's] in ket_i * If the state is mixed it can return the density matrix. - The index order is going to be dm_ij where j is the right multimode index and i is the left one. + The index order is going to be [i's,j's] in dm_ij Args: cov: the Wigner covariance matrix means: the Wigner means vector shape: the shape of the tensor + max_prob: the maximum probability of a the state (applies only if the ket is returned) + max_photons: the maximum number of photons in the state (applies only if the ket is returned) return_dm: whether to return the density matrix (otherwise it returns the ket) Returns: @@ -115,10 +121,16 @@ def wigner_to_fock_state( """ if return_dm: A, B, C = wigner_to_bargmann_rho(cov, means) - return math.hermite_renormalized(-A, B, C, shape=shape) - else: + return math.hermite_renormalized(A, B, C, shape=shape) + else: # here we can apply max prob and max photons A, B, C = wigner_to_bargmann_psi(cov, means) - return math.hermite_renormalized(-A, B, C, shape=shape) + if max_photons is None: + max_photons = sum(shape) - len(shape) + if max_prob < 1.0 or max_photons < sum(shape) - len(shape): + return math.hermite_renormalized_binomial( + A, B, C, shape=shape, max_l2=max_prob, global_cutoff=max_photons + 1 + ) + return math.hermite_renormalized(A, B, C, shape=tuple(shape)) def wigner_to_fock_U(X, d, shape): @@ -135,7 +147,7 @@ def wigner_to_fock_U(X, d, shape): Tensor: the fock representation of the unitary transformation """ A, B, C = wigner_to_bargmann_U(X, d) - return math.hermite_renormalized(-A, B, C, shape=shape) + return math.hermite_renormalized(A, B, C, shape=tuple(shape)) def wigner_to_fock_Choi(X, Y, d, shape): @@ -153,7 +165,7 @@ def wigner_to_fock_Choi(X, Y, d, shape): Tensor: the fock representation of the Choi matrix """ A, B, C = wigner_to_bargmann_Choi(X, Y, d) - return math.hermite_renormalized(-A, B, C, shape=shape) + return math.hermite_renormalized(A, B, C, shape=tuple(shape)) def ket_to_dm(ket: Tensor) -> Tensor: @@ -225,17 +237,18 @@ def dm_to_probs(dm: Tensor) -> Tensor: return math.all_diagonals(dm, real=True) -def U_to_choi(U: Tensor) -> Tensor: +def U_to_choi(U: Tensor, Udual: Optional[Tensor] = None) -> Tensor: r"""Converts a unitary transformation to a Choi tensor. Args: U: the unitary transformation + Udual: the dual unitary transformation (optional, will use conj U if not provided) Returns: Tensor: the Choi tensor. The index order is going to be :math:`[\mathrm{out}_l, \mathrm{in}_l, \mathrm{out}_r, \mathrm{in}_r]` where :math:`\mathrm{in}_l` and :math:`\mathrm{in}_r` are to be contracted with the left and right indices of the density matrix. """ - return math.outer(U, math.conj(U)) + return math.outer(U, Udual or math.conj(U)) def fidelity(state_a, state_b, a_ket: bool, b_ket: bool) -> Scalar: @@ -370,10 +383,11 @@ def apply_kraus_to_ket(kraus, ket, kraus_in_idx, kraus_out_idx=None): # check that there are no repeated indices in kraus_in_idx and kraus_out_idx (separately) validate_contraction_indices(kraus_in_idx, kraus_out_idx, ket.ndim, "kraus") - ket = MMTensor(ket, axis_labels=[f"left_{i}" for i in range(ket.ndim)]) + ket = MMTensor(ket, axis_labels=[f"in_left_{i}" for i in range(ket.ndim)]) kraus = MMTensor( kraus, - axis_labels=[f"out_left_{i}" for i in kraus_out_idx] + [f"left_{i}" for i in kraus_in_idx], + axis_labels=[f"out_left_{i}" for i in kraus_out_idx] + + [f"in_left_{i}" for i in kraus_in_idx], ) # contract the operator with the ket. @@ -440,42 +454,46 @@ def apply_kraus_to_dm(kraus, dm, kraus_in_idx, kraus_out_idx=None): return k_dm_k.transpose(left + right).tensor -def apply_choi_to_dm(choi, dm, choi_in_idx, choi_out_idx=None): +def apply_choi_to_dm( + choi: ComplexTensor, + dm: ComplexTensor, + choi_in_modes: Sequence[int], + choi_out_modes: Sequence[int] = None, +): r"""Applies a choi operator to a density matrix. It assumes that the density matrix is indexed as left_1, ..., left_n, right_1, ..., right_n. - The choi operator has indices that contract with the density matrix (choi_in_idx) and indices that are left over (choi_out_idx). - `choi` will contract choi_in_idx from the left and from the right with the density matrix. + The choi operator has indices that contract with the density matrix (choi_in_modes) and indices that are left over (choi_out_modes). + `choi` will contract choi_in_modes from the left and from the right with the density matrix. Args: choi (array): the choi operator to be applied dm (array): the density matrix to which the choi operator is applied - choi_in_idx (list of ints): the indices of the choi operator that contract with the density matrix - choi_out_idx (list of ints): the indices of the choi operator that re leftover + choi_in_modes (list of ints): the input modes of the choi operator that contract with the density matrix + choi_out_modes (list of ints): the output modes of the choi operator Returns: array: the resulting density matrix """ - if choi_out_idx is None: - choi_out_idx = choi_in_idx - - if not set(choi_in_idx).issubset(range(dm.ndim // 2)): + if choi_out_modes is None: + choi_out_modes = choi_in_modes + if not set(choi_in_modes).issubset(range(dm.ndim // 2)): raise ValueError("choi_in_idx should be a subset of the density matrix indices.") # check that there are no repeated indices in kraus_in_idx and kraus_out_idx (separately) - validate_contraction_indices(choi_in_idx, choi_out_idx, dm.ndim // 2, "choi") + validate_contraction_indices(choi_in_modes, choi_out_modes, dm.ndim // 2, "choi") dm = MMTensor( dm, - axis_labels=[f"left_{i}" for i in range(dm.ndim // 2)] - + [f"right_{i}" for i in range(dm.ndim // 2)], + axis_labels=[f"in_left_{i}" for i in range(dm.ndim // 2)] + + [f"in_right_{i}" for i in range(dm.ndim // 2)], ) choi = MMTensor( choi, - axis_labels=[f"out_left_{i}" for i in choi_out_idx] - + [f"left_{i}" for i in choi_in_idx] - + [f"out_right_{i}" for i in choi_out_idx] - + [f"right_{i}" for i in choi_in_idx], + axis_labels=[f"out_left_{i}" for i in choi_out_modes] + + [f"in_left_{i}" for i in choi_in_modes] + + [f"out_right_{i}" for i in choi_out_modes] + + [f"in_right_{i}" for i in choi_in_modes], ) # contract the choi matrix with the density matrix. @@ -670,10 +688,12 @@ def oscillator_eigenstate(q: Vector, cutoff: int) -> Tensor: prefactor = (omega_over_hbar / np.pi) ** (1 / 4) * math.sqrt(2 ** (-math.arange(0, cutoff))) # Renormalized physicist hermite polys: Hn / sqrt(n!) - R = np.array([[2 + 0j]]) # to get the physicist polys + R = -np.array([[2 + 0j]]) # to get the physicist polys def f_hermite_polys(xi): - poly = math.hermite_renormalized(R, 2 * math.astensor([xi], "complex128"), 1 + 0j, cutoff) + poly = math.hermite_renormalized( + R, 2 * math.astensor([xi], "complex128"), 1 + 0j, (cutoff,) + ) return math.cast(poly, "float64") hermite_polys = math.map_fn(f_hermite_polys, x_tensor) @@ -838,101 +858,87 @@ def sample_homodyne( return homodyne_sample, probability_sample -@jit(nopython=True) -def _displacement(r, phi, cutoff, dtype=np.complex128): # pragma: no cover - r"""Calculates the matrix elements of the displacement gate using a recurrence relation. - Uses the log of the matrix elements to avoid numerical issues and then takes the exponential. +@math.custom_gradient +def displacement(x, y, shape, tol=1e-15): + r"""creates a single mode displacement matrix""" + alpha = math.asnumpy(x) + 1j * math.asnumpy(y) - Args: - r (float): displacement magnitude - phi (float): displacement angle - cutoff (int): Fock ladder cutoff - dtype (data type): Specifies the data type used for the calculation + if np.sqrt(x * x + y * y) > tol: + gate = strategies.displacement(tuple(shape), alpha) + else: + gate = math.eye(max(shape), dtype="complex128")[: shape[0], : shape[1]] - Returns: - array[complex]: matrix representing the displacement operation. - """ - D = np.zeros((cutoff, cutoff), dtype=dtype) - rng = np.arange(cutoff) - rng[0] = 1 - log_k_fac = np.cumsum(np.log(rng)) - for n_minus_m in range(cutoff): - m_max = cutoff - n_minus_m - logL = np.log(_laguerre(r**2.0, m_max, n_minus_m)) - for m in range(m_max): - n = n_minus_m + m - D[n, m] = np.exp( - 0.5 * (log_k_fac[m] - log_k_fac[n]) - + n_minus_m * np.log(r) - - (r**2.0) / 2.0 - + 1j * phi * n_minus_m - + logL[m] - ) - D[m, n] = (-1.0) ** (n_minus_m) * np.conj(D[n, m]) - return D + def grad(dL_dDc): + dD_da, dD_dac = strategies.jacobian_displacement(math.asnumpy(gate), alpha) + dL_dac = np.sum(np.conj(dL_dDc) * dD_dac + dL_dDc * np.conj(dD_da)) + dLdx = 2 * np.real(dL_dac) + dLdy = 2 * np.imag(dL_dac) + return math.astensor(dLdx, dtype=x.dtype), math.astensor(dLdy, dtype=y.dtype) + return math.astensor(gate, dtype=gate.dtype.name), grad -@jit(nopython=True, cache=True) -def _laguerre(x, N, alpha, dtype=np.complex128): # pragma: no cover - r"""Returns the N first generalized Laguerre polynomials evaluated at x. + +@math.custom_gradient +def beamsplitter(theta: float, phi: float, shape: Sequence[int], method: str): + r"""Creates a beamsplitter tensor with given cutoffs using a numba-based fock lattice strategy. Args: - x (float): point at which to evaluate the polynomials - N (int): maximum Laguerre polynomial to calculate - alpha (float): continuous parameter for the generalized Laguerre polynomials + theta (float): transmittivity angle of the beamsplitter + phi (float): phase angle of the beamsplitter + cutoffs (int,int): cutoff dimensions of the two modes """ - L = np.zeros(N, dtype=dtype) - L[0] = 1.0 - if N > 1: - for m in range(0, N - 1): - L[m + 1] = ((2 * m + 1 + alpha - x) * L[m] - (m + alpha) * L[m - 1]) / (m + 1) - return L + if method == "vanilla": + bs_unitary = strategies.beamsplitter(shape, math.asnumpy(theta), math.asnumpy(phi)) + elif method == "schwinger": + bs_unitary = strategies.beamsplitter_schwinger( + shape, math.asnumpy(theta), math.asnumpy(phi) + ) + else: + raise ValueError( + f"Unknown beamsplitter method {method}. Options are 'vanilla' and 'schwinger'." + ) + def vjp(dLdGc): + dtheta, dphi = strategies.beamsplitter_vjp( + math.asnumpy(bs_unitary), + math.asnumpy(math.conj(dLdGc)), + math.asnumpy(theta), + math.asnumpy(phi), + ) + return math.astensor(dtheta, dtype=theta.dtype), math.astensor(dphi, dtype=phi.dtype) -@jit(nopython=True) -def _grad_displacement(T, r, phi): # pragma: no cover - r"""Calculates the gradients of the displacement gate with respect to the displacement magnitude and angle. + return math.astensor(bs_unitary, dtype=bs_unitary.dtype.name), vjp - Args: - T (array[complex]): array representing the gate - r (float): displacement magnitude - phi (float): displacement angle - Returns: - tuple[array[complex], array[complex]]: The gradient of the displacement gate with respect to r and phi - """ - cutoff = T.shape[0] - dtype = T.dtype - ei = np.exp(1j * phi) - eic = np.exp(-1j * phi) - alpha = r * ei - alphac = r * eic - sqrt = np.sqrt(np.arange(cutoff, dtype=dtype)) - grad_r = np.zeros((cutoff, cutoff), dtype=dtype) - grad_phi = np.zeros((cutoff, cutoff), dtype=dtype) - - for m in range(cutoff): - for n in range(cutoff): - grad_r[m, n] = -r * T[m, n] + sqrt[m] * ei * T[m - 1, n] - sqrt[n] * eic * T[m, n - 1] - grad_phi[m, n] = ( - sqrt[m] * 1j * alpha * T[m - 1, n] + sqrt[n] * 1j * alphac * T[m, n - 1] - ) +@math.custom_gradient +def squeezer(r, phi, shape): + r"""creates a single mode squeezer matrix using a numba-based fock lattice strategy""" + sq_unitary = strategies.squeezer(shape, math.asnumpy(r), math.asnumpy(phi)) + + def vjp(dLdGc): + dr, dphi = strategies.squeezer_vjp( + math.asnumpy(sq_unitary), + math.asnumpy(math.conj(dLdGc)), + math.asnumpy(r), + math.asnumpy(phi), + ) + return math.astensor(dr, dtype=r.dtype), math.astensor(dphi, phi.dtype) - return grad_r, grad_phi + return math.astensor(sq_unitary, dtype=sq_unitary.dtype.name), vjp @math.custom_gradient -def displacement(r, phi, cutoff, tol=1e-15): - """creates a single mode displacement matrix""" - if r > tol: - gate = _displacement(math.asnumpy(r), math.asnumpy(phi), cutoff) - else: - gate = math.eye(cutoff, dtype="complex128") - - def grad(dy): # pragma: no cover - Dr, Dphi = _grad_displacement(math.asnumpy(gate), math.asnumpy(r), math.asnumpy(phi)) - grad_r = math.real(math.sum(dy * math.conj(Dr))) - grad_phi = math.real(math.sum(dy * math.conj(Dphi))) - return grad_r, grad_phi, None +def squeezed(r, phi, shape): + r"""creates a single mode squeezed state using a numba-based fock lattice strategy""" + sq_ket = strategies.squeezed(shape, math.asnumpy(r), math.asnumpy(phi)) + + def vjp(dLdGc): + dr, dphi = strategies.squeezed_vjp( + math.asnumpy(sq_ket), + math.asnumpy(math.conj(dLdGc)), + math.asnumpy(r), + math.asnumpy(phi), + ) + return math.astensor(dr, dtype=r.dtype), math.astensor(dphi, phi.dtype) - return gate, grad + return math.astensor(sq_ket, dtype=sq_ket.dtype.name), vjp diff --git a/mrmustard/training/__init__.py b/mrmustard/training/__init__.py index b6492b490..8f13cda51 100644 --- a/mrmustard/training/__init__.py +++ b/mrmustard/training/__init__.py @@ -68,3 +68,4 @@ def cost_fn(): from .parametrized import Parametrized from .optimizer import Optimizer +from .callbacks import TensorboardCallback diff --git a/mrmustard/training/callbacks.py b/mrmustard/training/callbacks.py new file mode 100644 index 000000000..1c47c7ffd --- /dev/null +++ b/mrmustard/training/callbacks.py @@ -0,0 +1,286 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module contains the implementation of callback functionalities for optimizations. + +Callbacks allow users to have finer control over the optimization process by executing +predefined routines as optimization progresses. Even though the :meth:`Optimizer.minimize` accepts +`Callable` functions directly, the :class:`Callback` class modularizes the logic and makes it +easier for users to inherit from it and come up with their own custom callbacks. + +Things you can do with callbacks: + +* Logging custom metrics. +* Tracking parameters and costs with Tensorboard. +* Scheduling learning rates. +* Modifying the gradient update that gets applied. +* Updating cost_fn to alter the optimization landscape in our favour. +* Adding some RL into the optimizer. +* ... + +Builtin callbacks: + +* :class:`Callback`: The base class, to be used for building custom callbacks. +* :class:`TensorboardCallback`: Tracks costs, parameter values and gradients in Tensorboard. + +Examples: +========= + +.. code-block:: + + import numpy as np + from mrmustard.training import Optimizer, TensorboardCallback + + def cost_fn(): + ... + + def as_dB(cost): + delta = np.sqrt(np.log(1 / (abs(cost) ** 2)) / (2 * np.pi)) + cost_dB = -10 * np.log10(delta**2) + return cost_dB + + tb_cb = TensorboardCallback(cost_converter=as_dB, track_grads=True) + + def rolling_cost_cb(optimizer, cost, **kwargs): + return { + 'rolling_cost': np.mean(optimizer.opt_history[-10:] + [cost]), + } + + opt = Optimizer(euclidean_lr = 0.001); + opt.minimize(cost_fn, max_steps=200, by_optimizing=[...], callbacks=[tb_cb, rolling_cost_cb]) + + # VScode can be used to open the Tensorboard frontend for live monitoring. + + opt.callback_history['TensorboardCallback'] + opt.callback_history['rolling_cost_cb'] + +""" + +from dataclasses import dataclass +from datetime import datetime +import hashlib +from pathlib import Path +from typing import Callable, Optional, Mapping, Sequence, Union +import numpy as np +import tensorflow as tf +from mrmustard.math import Math + +math = Math() + + +@dataclass +class Callback: + """Base callback class for optimizers. Users can inherit from this class and define the + following custom logic: + + * `.trigger`: + Custom triggering condition, other than the regular schedule set by `step_per_call`. + * `.call`: + The main routine to be customized. + * `.update_cost_fn`: + The custom cost_fn updater, which is expected to return a new cost_fn callable to + replace the original one passed to the optimizer. + * `.update_grads`: + The custom grads modifyer, which is expected to return a list of parameter gradients + after modification, to be applied to the parameters. + * `.update_optimizer`: + The custom optimizer updater, which is expected to modify the optimizer inplace for + things like scheduling learning rates. + + """ + + #: Custom tag for a callback instance to be used as keys in `Optimizer.callback_history`. + #: Defaults to the class name. + tag: str = None + + #: Sets calling frequency of this callback. Defaults to once per optimization step. + #: Use higher values to reduce overhead. + steps_per_call: int = 1 + + def __post_init__(self): + self.tag = self.tag or self.__class__.__name__ + self.optimizer_step: int = 0 + self.callback_step: int = 0 + + def get_opt_step(self, optimizer, **kwargs): # pylint: disable=unused-argument + """Gets current step from optimizer.""" + self.optimizer_step = len(optimizer.opt_history) + return self.optimizer_step + + def _should_call(self, **kwargs) -> bool: + return (self.get_opt_step(**kwargs) % self.steps_per_call == 0) or self.trigger(**kwargs) + + def trigger(self, **kwargs) -> bool: # pylint: disable=unused-argument + """User implemented custom trigger conditions.""" + + def call(self, **kwargs) -> Optional[Mapping]: # pylint: disable=unused-argument + """User implemented main callback logic.""" + + def update_cost_fn(self, **kwargs) -> Optional[Callable]: # pylint: disable=unused-argument + """User implemented cost_fn modifier.""" + + def update_grads(self, **kwargs) -> Optional[Sequence]: # pylint: disable=unused-argument + """User implemented gradient modifier.""" + + def update_optimizer(self, optimizer, **kwargs): # pylint: disable=unused-argument + """User implemented optimizer update scheduler.""" + + def __call__( + self, + **kwargs, + ): + if self._should_call(**kwargs): + self.callback_step += 1 + callback_result = { + "optimizer_step": self.optimizer_step, + "callback_step": self.callback_step, + } + + callback_result.update(self.call(**kwargs) or {}) + + new_cost_fn = self.update_cost_fn(callback_result=callback_result, **kwargs) + if callable(new_cost_fn): + callback_result["cost_fn"] = new_cost_fn + + new_grads = self.update_grads(callback_result=callback_result, **kwargs) + if new_grads is not None: + callback_result["grads"] = new_grads + + # Modifies the optimizer inplace, e.g. its learning rates. + self.update_optimizer(callback_result=callback_result, **kwargs) + + return callback_result + return {} + + +@dataclass +class TensorboardCallback(Callback): # pylint: disable=too-many-instance-attributes + """Callback for enabling Tensorboard tracking of optimization progresses. + + Things tracked: + + * the cost + * the transformed cost, if a `cost_converter` is provided + * trainable parameter values + * trainable parameter gradients (if `track_grads` is `True`) + + To start the Tensorboard frontend, either: + + * use VSCode: F1 -> Tensorboard -> select your `root_logdir/experiment_tag`. + * use command line: `tensorboard --logdir=root_logdir/experiment_tag` and open link in browser. + + + """ + + #: The root logdir for tensorboard logging. + root_logdir: Union[str, Path] = "./tb_logdir" + + #: The tag for experiment subfolder to group similar optimizations together for easy comparisons. + #: Defaults to the hash of all trainable variables' names. + experiment_tag: Optional[str] = None + + #: Extra prefix to name the optimization experiment. + prefix: Optional[str] = None + + #: Transformation on cost for the purpose of better interpretation. + cost_converter: Optional[Callable] = None + + #: Whether to track gradients as well as the values for trainable parameters. + track_grads: bool = False + + #: Whether to return objectives in the callback results to be stored. + log_objectives: bool = True + + #: Whether to return parameter values in the callback results to be stored. + log_trainables: bool = False + + def __post_init__(self): + super().__post_init__() + self.root_logdir = Path(self.root_logdir) + + # Initialize only when first called to use optimization time rather than init time: + self.logdir = None + self.writter_logdir = None + self.tb_writer = None + + def init_writer(self, trainables): + """Initializes tb logdir folders and writer.""" + if (self.writter_logdir is None) or (self.optimizer_step <= self.steps_per_call): + trainable_key_hash = hashlib.sha256( + ",".join(trainables.keys()).encode("utf-8") + ).hexdigest() + self.experiment_tag = self.experiment_tag or f"experiment-{trainable_key_hash[:7]}" + self.logdir = self.root_logdir / self.experiment_tag + self.prefix = self.prefix or "optim" + existing_exp = [path for path in self.logdir.glob("*") if path.is_dir()] + optim_timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + + self.writter_logdir = self.logdir / ( + f"{self.prefix}-{len(existing_exp):03d}-{optim_timestamp}" + ) + self.tb_writer = tf.summary.create_file_writer(str(self.writter_logdir)) + self.tb_writer.set_as_default() + + def call( + self, + optimizer, + cost, + trainables, + **kwargs, + ): # pylint: disable=unused-argument,arguments-differ + """Logs costs and parameters to Tensorboard.""" + + self.init_writer(trainables=trainables) + obj_tag = "objectives" + + cost = np.array(cost).item() + + obj_scalars = { + f"{obj_tag}/cost": cost, + } + if self.cost_converter is not None: + obj_scalars[f"{obj_tag}/{self.cost_converter.__name__}(cost)"] = self.cost_converter( + cost + ) + + if "orig_cost" in optimizer.callback_history: + orig_cost = np.array(optimizer.callback_history["orig_cost"][-1]).item() + obj_scalars[f"{obj_tag}/orig_cost"] = orig_cost + if self.cost_converter is not None: + obj_scalars[ + f"{obj_tag}/{self.cost_converter.__name__}(orig_cost)" + ] = self.cost_converter(orig_cost) + + for k, v in obj_scalars.items(): + tf.summary.scalar(k, data=v, step=self.optimizer_step) + + for k, (x, dx) in trainables.items(): + x = np.array(x.value) + if self.track_grads: + dx = np.array(dx) + + tag = k if np.size(x) <= 1 else None + for ind, val in np.ndenumerate(x): + tag = tag or k + str(list(ind)).replace(" ", "") + tf.summary.scalar(tag + ":value", data=val, step=self.optimizer_step) + if self.track_grads: + tf.summary.scalar(tag + ":grad", data=dx[ind], step=self.optimizer_step) + tag = None + + result = obj_scalars if self.log_objectives else {} + + if self.log_trainables: + result.update(trainables) + + return result diff --git a/mrmustard/training/optimizer.py b/mrmustard/training/optimizer.py index 8ee5e0d19..4a49fc847 100644 --- a/mrmustard/training/optimizer.py +++ b/mrmustard/training/optimizer.py @@ -17,7 +17,8 @@ """ from itertools import chain, groupby -from typing import List, Callable, Sequence +from typing import List, Callable, Sequence, Union, Mapping, Dict +from mrmustard.training.callbacks import Callback from mrmustard.utils import graphics from mrmustard.logger import create_logger from mrmustard.math import Math @@ -55,7 +56,7 @@ def __init__( "orthogonal": orthogonal_lr, } self.opt_history: List[float] = [0] - self.callback_history: List = [] + self.callback_history: Dict[str, List] = {} self.log = create_logger(__name__) def minimize( @@ -63,7 +64,7 @@ def minimize( cost_fn: Callable, by_optimizing: Sequence[Trainable], max_steps: int = 1000, - callback: Callable = None, + callbacks: Union[Callable, Sequence[Callable], Mapping[str, Callable]] = None, ): r"""Minimizes the given cost function by optimizing circuits and/or detectors. @@ -74,32 +75,55 @@ def minimize( contain the parameters to optimize max_steps (int): the minimization keeps going until the loss is stable or max_steps are reached (if ``max_steps=0`` it will only stop when the loss is stable) - callback (Callable): a function that will be executed at each step of the optimization, which - takes as arguments the training step (int), the cost and the trainable parameters. - The return value is stored in self.callback_history. + callbacks (:class:`Callback`, `Callable`, or List/Dict of them): callback functions that + will be executed at each step of the optimization after backprop but before gradient + gets applied. It takes as arguments the optimizer itself, training step (int), the + cost value, the cost function, and the trainable parameters (values & grads) dict. + The optional returned dict for each step is stored in self.callback_history which + is a callback-name-keyed dict with each value a list of such callback result dicts. + Learn more about how to use callbacks to have finer control of the optimization + process in the :mod:`.callbacks` module. """ + callbacks = self._coerce_callbacks(callbacks) + try: - self._minimize(cost_fn, by_optimizing, max_steps, callback) + self._minimize(cost_fn, by_optimizing, max_steps, callbacks) except KeyboardInterrupt: # graceful exit self.log.info("Optimizer execution halted due to keyboard interruption.") raise self.OptimizerInterruptedError() from None - def _minimize(self, cost_fn, by_optimizing, max_steps, callback): + def _minimize(self, cost_fn, by_optimizing, max_steps, callbacks): # finding out which parameters are trainable from the ops trainable_params = self._get_trainable_params(by_optimizing) + cost_fn_modified = False + orig_cost_fn = cost_fn bar = graphics.Progressbar(max_steps) with bar: while not self.should_stop(max_steps): - cost, grads = self.compute_loss_and_gradients(cost_fn, trainable_params) - self.apply_gradients(trainable_params, grads) + cost, grads = self.compute_loss_and_gradients(cost_fn, trainable_params.values()) + + trainables = {tag: (x, dx) for (tag, x), dx in zip(trainable_params.items(), grads)} + + if cost_fn_modified: + self.callback_history["orig_cost"].append(orig_cost_fn()) + new_cost_fn, new_grads = self._run_callbacks( + callbacks=callbacks, + cost_fn=cost_fn, + cost=cost, + trainables=trainables, + ) + + self.apply_gradients(trainable_params.values(), new_grads or grads) self.opt_history.append(cost) bar.step(math.asnumpy(cost)) - if callback is not None: - self.callback_history.append( - callback(len(self.opt_history) - 1, cost, trainable_params) - ) + + if callable(new_cost_fn): + cost_fn = new_cost_fn + if not cost_fn_modified: + cost_fn_modified = True + self.callback_history["orig_cost"] = self.opt_history.copy() def apply_gradients(self, trainable_params, grads): """Apply gradients to variables. @@ -120,20 +144,33 @@ def apply_gradients(self, trainable_params, grads): update_method(grads_and_vars, param_lr) @staticmethod - def _get_trainable_params(trainable_items): - """Returns a list of trainable parameters from instances of Parametrized or - items that belong to the backend and are trainable + def _get_trainable_params(trainable_items, root_tag: str = "optimized"): + """Traverses all instances of Parametrized or trainable items that belong to the backend + and return a dict of trainables of the form `{tags: trainable_parameters}` where the `tags` + are traversal paths of collecting all parent tags for reaching each parameter. """ trainables = [] - for item in trainable_items: + for i, item in enumerate(trainable_items): + owner_tag = f"{root_tag}[{i}]" if isinstance(item, Parametrized): - trainables.append(item.trainable_parameters) + tag = f"{owner_tag}:{item.__class__.__qualname__}" + trainables.append(item.traverse_trainables(owner_tag=tag).items()) elif math.from_backend(item) and math.is_trainable(item): # the created parameter is wrapped into a list because the case above # returns a list, hence ensuring we have a list of lists - trainables.append([create_parameter(item, name="from_backend", is_trainable=True)]) - - return list(chain(*trainables)) + tag = f"{owner_tag}:{math.__class__.__name__}/{getattr(item, 'name', item.__class__.__name__)}" + trainables.append( + [ + ( + tag, + create_parameter( + item, name="from_backend", is_trainable=True, owner=tag + ), + ) + ] + ) + + return dict(chain(*trainables)) @staticmethod def _group_vars_and_grads_by_type(trainable_params, grads): @@ -186,6 +223,62 @@ def should_stop(self, max_steps: int) -> bool: return True return False + @staticmethod + def _coerce_callbacks(callbacks): + r"""Coerce callbacks into dict and validate them.""" + if callbacks is None: + callbacks = {} + elif callable(callbacks): + callbacks = { + callbacks.tag if isinstance(callbacks, Callback) else callbacks.__name__: callbacks + } + elif isinstance(callbacks, Sequence): + callbacks = { + cb.tag if isinstance(cb, Callback) else cb.__name__: cb for cb in callbacks + } + elif not isinstance(callbacks, Mapping): + raise TypeError( + f"Argument `callbacks` expected to be a callable or a list/dict of callables, got {type(callbacks)}." + ) + + if any(not callable(cb) for cb in callbacks.values()): + raise TypeError("Not all provided callbacks is callable.") + + return callbacks + + def _run_callbacks(self, callbacks, cost_fn, cost, trainables): + """Iteratively calls all callbacks and applies the necessary updates.""" + new_cost_fn, new_grads = None, None + + for cb_tag, cb in callbacks.items(): + if cb_tag not in self.callback_history: + self.callback_history[cb_tag] = [] + + cb_result = cb( + optimizer=self, + cost_fn=cost_fn if new_cost_fn is None else new_cost_fn, + cost=cost, + trainables=trainables, + ) + + if not isinstance(cb_result, (Mapping, type(None))): + raise TypeError( + f"The expected return type of callback functions is dict, got {type(cb_result)}." + ) + + new_cost_fn = cb_result.pop("cost_fn", None) + + if "grads" in cb_result: + new_grads = cb_result["grads"] + trainables = { + tag: (x, dx) for (tag, (x, _)), dx in zip(trainables.items(), new_grads) + } + + if cb_result is not None and cb_result: + self.callback_history[cb_tag].append(cb_result) + + return new_cost_fn, new_grads + class OptimizerInterruptedError(Exception): """A helper class to quietly stop execution without printing a traceback.""" diff --git a/mrmustard/training/parametrized.py b/mrmustard/training/parametrized.py index 176863243..e2a05578c 100644 --- a/mrmustard/training/parametrized.py +++ b/mrmustard/training/parametrized.py @@ -18,7 +18,7 @@ class constructor generate a backend Tensor and are assigned to fields of the class. """ -from typing import Any, Generator, List, Sequence, Tuple +from typing import Any, Generator, List, Sequence, Tuple, Mapping import numpy as np @@ -103,28 +103,82 @@ def trainable_parameters(self) -> Sequence[Trainable]: """Return a list of trainable parameters within the Parametrized object by recursively traversing the object's fields """ - return list(_traverse_parametrized(self.__dict__.values(), Trainable)) + return list(_traverse_parametrized(self.__dict__, Trainable)) @property def constant_parameters(self) -> List[Constant]: """Return a list of constant parameters within the Parametrized object by recursively traversing the object's fields """ - return list(_traverse_parametrized(self.__dict__.values(), Constant)) + return list(_traverse_parametrized(self.__dict__, Constant)) + + def traverse_trainables(self, owner_tag=None) -> Mapping[str, Trainable]: + """Return a dict of trainable parameters within the Parametrized object + by recursively traversing the object's fields. The key for each parameter + will be the path of tags for reaching it from the top level Parametrized. + """ + owner_tag = owner_tag or f"{self.__class__.__qualname__}" + return dict(_traverse_parametrized(self.__dict__, Trainable, owner_tag)) + + def traverse_constants(self, owner_tag=None) -> Mapping[str, Constant]: + """Return a dict of constant parameters within the Parametrized object + by recursively traversing the object's fields. The key for each parameter + will be the path of tags for reaching it from the top level Parametrized. + """ + owner_tag = owner_tag or f"{self.__class__.__qualname__}" + return dict(_traverse_parametrized(self.__dict__, Constant, owner_tag)) -def _traverse_parametrized(object_: Any, extract_type: Parameter) -> Generator: +def _traverse_parametrized_untagged(object_: Sequence, extract_type: Parameter) -> Generator: """This private method traverses recursively all the object's attributes for objects present in ``iterable`` which are instances of ``parameter_type`` or ``Parametrized`` returning a generator with objects of type ``extract_type``. """ - for obj in object_: if isinstance( - obj, (List, Tuple) + obj, (List, Tuple, Mapping) ): # pylint: disable=isinstance-second-argument-not-valid-type yield from _traverse_parametrized(obj, extract_type) elif isinstance(obj, Parametrized): yield from _traverse_parametrized(obj.__dict__.values(), extract_type) elif isinstance(obj, extract_type): yield obj + + +def _traverse_parametrized_tagged( + object_: Mapping, extract_type: Parameter, owner_tag: str = None +) -> Generator: + """This private method traverses recursively, while accumulating tags, all the object's + attributes for objects present in ``iterable`` which are instances of ``parameter_type`` + or ``Parametrized`` returning a generator of 2-tuples of the form (str, ``extract_type``). + """ + + delim = "/" + for k, obj in object_.items(): + obj_tag = f"{owner_tag}[{k}]" if isinstance(k, int) else f"{owner_tag}{delim}{k}" + if isinstance(obj, (Mapping, List, Tuple)): + yield from _traverse_parametrized(obj, extract_type, owner_tag=obj_tag) + elif isinstance(obj, Parametrized): + yield from _traverse_parametrized(obj.__dict__, extract_type, owner_tag=obj_tag) + elif isinstance(obj, extract_type): + yield obj_tag, obj + + +def _traverse_parametrized( + object_: Any, extract_type: Parameter, owner_tag: str = None +) -> Generator: + """The recursive parameter traversal to be used for both tagged and untagged collection + Depending on if the argument `owner_tag` is provided. + """ + + if owner_tag: + yield from _traverse_parametrized_tagged( + object_=dict(enumerate(object_)) if isinstance(object_, Sequence) else object_, + extract_type=extract_type, + owner_tag=owner_tag, + ) + else: + yield from _traverse_parametrized_untagged( + object_=list(object_.values()) if isinstance(object_, Mapping) else object_, + extract_type=extract_type, + ) diff --git a/mrmustard/typing.py b/mrmustard/typing.py index 6f374ff8a..9a8508a0f 100644 --- a/mrmustard/typing.py +++ b/mrmustard/typing.py @@ -33,7 +33,14 @@ "Tensor", "Trainable", ] -from typing import Iterator, Protocol, Tuple, TypeVar, Union, runtime_checkable +from typing import ( + Iterator, + Protocol, + Tuple, + TypeVar, + Union, + runtime_checkable, +) import numpy as np diff --git a/mrmustard/utils/wigner.py b/mrmustard/utils/wigner.py index f6162536a..4941b6d0b 100644 --- a/mrmustard/utils/wigner.py +++ b/mrmustard/utils/wigner.py @@ -14,8 +14,9 @@ """This module contains the calculation of the Wigner function.""" -from numba import njit import numpy as np +from numba import njit + from mrmustard import settings @@ -27,7 +28,7 @@ def wigner_discretized(rho, qvec, pvec, hbar=settings.HBAR): Args: rho (complex array): the density matrix of the state in Fock representation - xvec (array): array of discretized :math:`x` quadrature values + qvec (array): array of discretized :math:`q` quadrature values pvec (array): array of discretized :math:`p` quadrature values hbar (optional float): the value of `\hbar`, defaults to ``settings.HBAR``. @@ -40,7 +41,7 @@ def wigner_discretized(rho, qvec, pvec, hbar=settings.HBAR): P = np.outer(np.ones_like(qvec), pvec) cutoff = rho.shape[-1] - A = (Q + P * 1.0j) / (2 * np.sqrt(hbar / 2)) + A = (Q + P * 1.0j) / np.sqrt(2 * hbar) Wmat = np.zeros((2, cutoff) + A.shape, dtype=np.complex128) diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..df4e08254 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,3445 @@ +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. + +[[package]] +name = "absl-py" +version = "1.4.0" +description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "absl-py-1.4.0.tar.gz", hash = "sha256:d2c244d01048ba476e7c080bd2c6df5e141d211de80223460d5b3b8a2a58433d"}, + {file = "absl_py-1.4.0-py3-none-any.whl", hash = "sha256:0d3fe606adfa4f7db64792dd4c7aee4ee0c38ab75dfd353b7a83ed3e957fcb47"}, +] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + +[[package]] +name = "astroid" +version = "2.7.3" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = "~=3.6" +files = [ + {file = "astroid-2.7.3-py3-none-any.whl", hash = "sha256:dc1e8b28427d6bbef6b8842b18765ab58f558c42bb80540bd7648c98412af25e"}, + {file = "astroid-2.7.3.tar.gz", hash = "sha256:3b680ce0419b8a771aba6190139a3998d14b413852506d99aff8dc2bf65ee67c"}, +] + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +setuptools = ">=20.0" +wrapt = ">=1.11,<1.13" + +[[package]] +name = "astunparse" +version = "1.6.3" +description = "An AST unparser for Python" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, + {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, +] + +[package.dependencies] +six = ">=1.6.1,<2.0" +wheel = ">=0.23.0,<1.0" + +[[package]] +name = "atomicwrites" +version = "1.4.1" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "babel" +version = "2.12.1" +description = "Internationalization utilities" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, + {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, +] + +[[package]] +name = "black" +version = "23.7.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "cachetools" +version = "5.3.1" +description = "Extensible memoizing collections and decorators" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"}, + {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"}, +] + +[[package]] +name = "certifi" +version = "2023.5.7" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.4" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"}, + {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "cloudpickle" +version = "2.2.1" +description = "Extended pickling support for Python objects" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cloudpickle-2.2.1-py3-none-any.whl", hash = "sha256:61f594d1f4c295fa5cd9014ceb3a1fc4a70b0de1164b94fbc2d854ccba056f9f"}, + {file = "cloudpickle-2.2.1.tar.gz", hash = "sha256:d89684b8de9e34a2a43b3460fbca07d09d6e25ce858df4d5a44240403b6178f5"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + +[[package]] +name = "coverage" +version = "7.2.7" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, + {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, + {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, + {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, + {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, + {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, + {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, + {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, + {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, + {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, + {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, + {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, + {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, + {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, + {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, + {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, + {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, + {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, + {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, + {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, + {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, + {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, + {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, + {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, + {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, + {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, + {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, + {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, + {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, + {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, + {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, + {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, + {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, + {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, + {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, + {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cycler" +version = "0.11.0" +description = "Composable style cycles" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, + {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, +] + +[[package]] +name = "dask" +version = "2023.7.0" +description = "Parallel PyData with Task Scheduling" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "dask-2023.7.0-py3-none-any.whl", hash = "sha256:ceb10a806a8a6dca2d4623868687f9e166b4302f9a079e5a297e0780a2cd750d"}, + {file = "dask-2023.7.0.tar.gz", hash = "sha256:83212f085e9f59d6c724f32d4ce1dc1fed5405e868f5bfff701cc54912424c3d"}, +] + +[package.dependencies] +click = ">=8.0" +cloudpickle = ">=1.5.0" +fsspec = ">=2021.09.0" +importlib-metadata = ">=4.13.0" +packaging = ">=20.0" +partd = ">=1.2.0" +pyyaml = ">=5.3.1" +toolz = ">=0.10.0" + +[package.extras] +array = ["numpy (>=1.21)"] +complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)"] +dataframe = ["numpy (>=1.21)", "pandas (>=1.3)"] +diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] +distributed = ["distributed (==2023.7.0)"] +test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist"] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "dm-tree" +version = "0.1.8" +description = "Tree is a library for working with nested data structures." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "dm-tree-0.1.8.tar.gz", hash = "sha256:0fcaabbb14e7980377439e7140bd05552739ca5e515ecb3119f234acee4b9430"}, + {file = "dm_tree-0.1.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35cc164a79336bfcfafb47e5f297898359123bbd3330c1967f0c4994f9cf9f60"}, + {file = "dm_tree-0.1.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39070ba268c0491af9fe7a58644d99e8b4f2cde6e5884ba3380bddc84ed43d5f"}, + {file = "dm_tree-0.1.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2869228d9c619074de501a3c10dc7f07c75422f8fab36ecdcb859b6f1b1ec3ef"}, + {file = "dm_tree-0.1.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d20f2faa3672b52e5013f4077117bfb99c4cfc0b445d3bde1584c34032b57436"}, + {file = "dm_tree-0.1.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5483dca4d7eb1a0d65fe86d3b6a53ae717face83c1f17e0887b1a4a64ae5c410"}, + {file = "dm_tree-0.1.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d7c26e431fc93cc7e0cba867eb000db6a05f6f2b25af11ac4e9dada88fc5bca"}, + {file = "dm_tree-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d714371bb08839e4e5e29024fc95832d9affe129825ef38836b143028bd144"}, + {file = "dm_tree-0.1.8-cp310-cp310-win_amd64.whl", hash = "sha256:d40fa4106ca6edc66760246a08f500ec0c85ef55c762fb4a363f6ee739ba02ee"}, + {file = "dm_tree-0.1.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad16ceba90a56ec47cf45b21856d14962ac314787975ef786efb5e6e9ca75ec7"}, + {file = "dm_tree-0.1.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:803bfc53b4659f447ac694dbd04235f94a73ef7c1fd1e0df7c84ac41e0bc963b"}, + {file = "dm_tree-0.1.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:378cc8ad93c5fe3590f405a309980721f021c790ca1bdf9b15bb1d59daec57f5"}, + {file = "dm_tree-0.1.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1607ce49aa42f010d1e5e616d92ce899d66835d4d8bea49679582435285515de"}, + {file = "dm_tree-0.1.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:343a4a4ebaa127451ff971254a4be4084eb4bdc0b2513c32b46f6f728fd03f9e"}, + {file = "dm_tree-0.1.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa42a605d099ee7d41ba2b5fb75e21423951fd26e5d50583a00471238fb3021d"}, + {file = "dm_tree-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b7764de0d855338abefc6e3ee9fe40d301668310aa3baea3f778ff051f4393"}, + {file = "dm_tree-0.1.8-cp311-cp311-win_amd64.whl", hash = "sha256:a5d819c38c03f0bb5b3b3703c60e4b170355a0fc6b5819325bf3d4ceb3ae7e80"}, + {file = "dm_tree-0.1.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8c60a7eadab64c2278861f56bca320b2720f163dca9d7558103c3b77f2416571"}, + {file = "dm_tree-0.1.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af4b3d372f2477dcd89a6e717e4a575ca35ccc20cc4454a8a4b6f8838a00672d"}, + {file = "dm_tree-0.1.8-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de287fabc464b8734be251e46e06aa9aa1001f34198da2b6ce07bd197172b9cb"}, + {file = "dm_tree-0.1.8-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:054b461f8176f4bce7a21f7b1870f873a1ced3bdbe1282c816c550bb43c71fa6"}, + {file = "dm_tree-0.1.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f7915660f59c09068e428613c480150180df1060561fd0d1470684ae7007bd1"}, + {file = "dm_tree-0.1.8-cp37-cp37m-win_amd64.whl", hash = "sha256:b9f89a454e98806b44fe9d40ec9eee61f848388f7e79ac2371a55679bd5a3ac6"}, + {file = "dm_tree-0.1.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0e9620ccf06393eb6b613b5e366469304622d4ea96ae6540b28a33840e6c89cf"}, + {file = "dm_tree-0.1.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b095ba4f8ca1ba19350fd53cf1f8f3eb0bd406aa28af64a6dfc86707b32a810a"}, + {file = "dm_tree-0.1.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b9bd9b9ccb59409d33d51d84b7668010c04c2af7d4a371632874c1ca356cff3d"}, + {file = "dm_tree-0.1.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d3172394079a86c3a759179c65f64c48d1a42b89495fcf38976d11cc3bb952c"}, + {file = "dm_tree-0.1.8-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1612fcaecd79023dbc6a6ae48d51a80beb5c385d6f3f6d71688e57bc8d07de8"}, + {file = "dm_tree-0.1.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5c8c12e3fda754ef6af94161bacdaeda816d941995fac415d6855c6c386af68"}, + {file = "dm_tree-0.1.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:694c3654cfd2a81552c08ec66bb5c4a3d48fa292b9a181880fb081c36c5b9134"}, + {file = "dm_tree-0.1.8-cp38-cp38-win_amd64.whl", hash = "sha256:bb2d109f42190225112da899b9f3d46d0d5f26aef501c61e43529fe9322530b5"}, + {file = "dm_tree-0.1.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d16e1f2a073604cfcc09f7131ae8d534674f43c3aef4c25742eae295bc60d04f"}, + {file = "dm_tree-0.1.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:250b692fb75f45f02e2f58fbef9ab338904ef334b90557565621fa251df267cf"}, + {file = "dm_tree-0.1.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81fce77f22a302d7a5968aebdf4efafef4def7ce96528719a354e6990dcd49c7"}, + {file = "dm_tree-0.1.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7ac31b9aecccb2c6e1ab29706f6ded3eba0c2c69c770322c9c685929c3d6afb"}, + {file = "dm_tree-0.1.8-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe962015b2fe1282892b28ebe962faed53c7f98d942da9a4625cbf27baef913"}, + {file = "dm_tree-0.1.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c52cbf4f8b3dbd0beaedf44f69fa85eec5e9dede612e08035e06ada6ec9426"}, + {file = "dm_tree-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:181c35521d480d0365f39300542cb6cd7fd2b77351bb43d7acfda15aef63b317"}, + {file = "dm_tree-0.1.8-cp39-cp39-win_amd64.whl", hash = "sha256:8ed3564abed97c806db122c2d3e1a2b64c74a63debe9903aad795167cc301368"}, +] + +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + +[[package]] +name = "filelock" +version = "3.12.2" +description = "A platform independent file lock." +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, + {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, +] + +[package.extras] +docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "flatbuffers" +version = "23.5.26" +description = "The FlatBuffers serialization format for Python" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "flatbuffers-23.5.26-py2.py3-none-any.whl", hash = "sha256:c0ff356da363087b915fde4b8b45bdda73432fc17cddb3c8157472eab1422ad1"}, + {file = "flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89"}, +] + +[[package]] +name = "fonttools" +version = "4.40.0" +description = "Tools to manipulate font files" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b802dcbf9bcff74672f292b2466f6589ab8736ce4dcf36f48eb994c2847c4b30"}, + {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f6e3fa3da923063c286320e728ba2270e49c73386e3a711aa680f4b0747d692"}, + {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fdf60f8a5c6bcce7d024a33f7e4bc7921f5b74e8ea13bccd204f2c8b86f3470"}, + {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91784e21a1a085fac07c6a407564f4a77feb471b5954c9ee55a4f9165151f6c1"}, + {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05171f3c546f64d78569f10adc0de72561882352cac39ec7439af12304d8d8c0"}, + {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7449e5e306f3a930a8944c85d0cbc8429cba13503372a1a40f23124d6fb09b58"}, + {file = "fonttools-4.40.0-cp310-cp310-win32.whl", hash = "sha256:bae8c13abbc2511e9a855d2142c0ab01178dd66b1a665798f357da0d06253e0d"}, + {file = "fonttools-4.40.0-cp310-cp310-win_amd64.whl", hash = "sha256:425b74a608427499b0e45e433c34ddc350820b6f25b7c8761963a08145157a66"}, + {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:00ab569b2a3e591e00425023ade87e8fef90380c1dde61be7691cb524ca5f743"}, + {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18ea64ac43e94c9e0c23d7a9475f1026be0e25b10dda8f236fc956188761df97"}, + {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:022c4a16b412293e7f1ce21b8bab7a6f9d12c4ffdf171fdc67122baddb973069"}, + {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530c5d35109f3e0cea2535742d6a3bc99c0786cf0cbd7bb2dc9212387f0d908c"}, + {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5e00334c66f4e83535384cb5339526d01d02d77f142c23b2f97bd6a4f585497a"}, + {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb52c10fda31159c22c7ed85074e05f8b97da8773ea461706c273e31bcbea836"}, + {file = "fonttools-4.40.0-cp311-cp311-win32.whl", hash = "sha256:6a8d71b9a5c884c72741868e845c0e563c5d83dcaf10bb0ceeec3b4b2eb14c67"}, + {file = "fonttools-4.40.0-cp311-cp311-win_amd64.whl", hash = "sha256:15abb3d055c1b2dff9ce376b6c3db10777cb74b37b52b78f61657634fd348a0d"}, + {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14037c31138fbd21847ad5e5441dfdde003e0a8f3feb5812a1a21fd1c255ffbd"}, + {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:94c915f6716589f78bc00fbc14c5b8de65cfd11ee335d32504f1ef234524cb24"}, + {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37467cee0f32cada2ec08bc16c9c31f9b53ea54b2f5604bf25a1246b5f50593a"}, + {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56d4d85f5374b45b08d2f928517d1e313ea71b4847240398decd0ab3ebbca885"}, + {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8c4305b171b61040b1ee75d18f9baafe58bd3b798d1670078efe2c92436bfb63"}, + {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a954b90d1473c85a22ecf305761d9fd89da93bbd31dae86e7dea436ad2cb5dc9"}, + {file = "fonttools-4.40.0-cp38-cp38-win32.whl", hash = "sha256:1bc4c5b147be8dbc5df9cc8ac5e93ee914ad030fe2a201cc8f02f499db71011d"}, + {file = "fonttools-4.40.0-cp38-cp38-win_amd64.whl", hash = "sha256:8a917828dbfdb1cbe50cf40eeae6fbf9c41aef9e535649ed8f4982b2ef65c091"}, + {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:882983279bf39afe4e945109772c2ffad2be2c90983d6559af8b75c19845a80a"}, + {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c55f1b4109dbc3aeb496677b3e636d55ef46dc078c2a5e3f3db4e90f1c6d2907"}, + {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec468c022d09f1817c691cf884feb1030ef6f1e93e3ea6831b0d8144c06480d1"}, + {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d5adf4ba114f028fc3f5317a221fd8b0f4ef7a2e5524a2b1e0fd891b093791a"}, + {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa83b3f151bc63970f39b2b42a06097c5a22fd7ed9f7ba008e618de4503d3895"}, + {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97d95b8301b62bdece1af943b88bcb3680fd385f88346a4a899ee145913b414a"}, + {file = "fonttools-4.40.0-cp39-cp39-win32.whl", hash = "sha256:1a003608400dd1cca3e089e8c94973c6b51a4fb1ef00ff6d7641617b9242e637"}, + {file = "fonttools-4.40.0-cp39-cp39-win_amd64.whl", hash = "sha256:7961575221e3da0841c75da53833272c520000d76f7f71274dbf43370f8a1065"}, + {file = "fonttools-4.40.0-py3-none-any.whl", hash = "sha256:200729d12461e2038700d31f0d49ad5a7b55855dec7525074979a06b46f88505"}, + {file = "fonttools-4.40.0.tar.gz", hash = "sha256:337b6e83d7ee73c40ea62407f2ce03b07c3459e213b6f332b94a69923b9e1cb9"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.0.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "frozenlist" +version = "1.3.3" +description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, + {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, + {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, + {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, + {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, + {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, + {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, + {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, + {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, + {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, + {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, + {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, + {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, + {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, + {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, + {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, + {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, + {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, + {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, + {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, + {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, + {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, + {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, + {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, + {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, + {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, + {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, + {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, +] + +[[package]] +name = "fsspec" +version = "2023.6.0" +description = "File-system specification" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2023.6.0-py3-none-any.whl", hash = "sha256:1cbad1faef3e391fba6dc005ae9b5bdcbf43005c9167ce78c915549c352c869a"}, + {file = "fsspec-2023.6.0.tar.gz", hash = "sha256:d0b2f935446169753e7a5c5c55681c54ea91996cc67be93c39a154fb3a2742af"}, +] + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + +[[package]] +name = "gast" +version = "0.4.0" +description = "Python AST that abstracts the underlying Python version" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "gast-0.4.0-py3-none-any.whl", hash = "sha256:b7adcdd5adbebf1adf17378da5ba3f543684dbec47b1cda1f3997e573cd542c4"}, + {file = "gast-0.4.0.tar.gz", hash = "sha256:40feb7b8b8434785585ab224d1568b857edb18297e5a3047f1ba012bc83b42c1"}, +] + +[[package]] +name = "google-auth" +version = "2.17.3" +description = "Google Authentication Library" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +files = [ + {file = "google-auth-2.17.3.tar.gz", hash = "sha256:ce311e2bc58b130fddf316df57c9b3943c2a7b4f6ec31de9663a9333e4064efc"}, + {file = "google_auth-2.17.3-py2.py3-none-any.whl", hash = "sha256:f586b274d3eb7bd932ea424b1c702a30e0393a2e2bc4ca3eae8263ffd8be229f"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} +six = ">=1.9.0" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "requests (>=2.20.0,<3.0.0dev)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0dev)"] + +[[package]] +name = "google-auth-oauthlib" +version = "0.4.6" +description = "Google Authentication Library" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "google-auth-oauthlib-0.4.6.tar.gz", hash = "sha256:a90a072f6993f2c327067bf65270046384cda5a8ecb20b94ea9a687f1f233a7a"}, + {file = "google_auth_oauthlib-0.4.6-py2.py3-none-any.whl", hash = "sha256:3f2a6e802eebbb6fb736a370fbf3b055edcb6b52878bf2f26330b5e041316c73"}, +] + +[package.dependencies] +google-auth = ">=1.0.0" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click (>=6.0.0)"] + +[[package]] +name = "google-pasta" +version = "0.2.0" +description = "pasta is an AST-based Python refactoring library" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "google-pasta-0.2.0.tar.gz", hash = "sha256:c9f2c8dfc8f96d0d5808299920721be30c9eec37f2389f28904f454565c8a16e"}, + {file = "google_pasta-0.2.0-py2-none-any.whl", hash = "sha256:4612951da876b1a10fe3960d7226f0c7682cf901e16ac06e473b267a5afa8954"}, + {file = "google_pasta-0.2.0-py3-none-any.whl", hash = "sha256:b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "grpcio" +version = "1.49.1" +description = "HTTP/2-based RPC framework" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "grpcio-1.49.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:fd86040232e805b8e6378b2348c928490ee595b058ce9aaa27ed8e4b0f172b20"}, + {file = "grpcio-1.49.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6fd0c9cede9552bf00f8c5791d257d5bf3790d7057b26c59df08be5e7a1e021d"}, + {file = "grpcio-1.49.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:d0d402e158d4e84e49c158cb5204119d55e1baf363ee98d6cb5dce321c3a065d"}, + {file = "grpcio-1.49.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ceec743d42a627e64ea266059a62d214c5a3cdfcd0d7fe2b7a8e4e82527c7"}, + {file = "grpcio-1.49.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2106d9c16527f0a85e2eea6e6b91a74fc99579c60dd810d8690843ea02bc0f5f"}, + {file = "grpcio-1.49.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:52dd02b7e7868233c571b49bc38ebd347c3bb1ff8907bb0cb74cb5f00c790afc"}, + {file = "grpcio-1.49.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:120fecba2ec5d14b5a15d11063b39783fda8dc8d24addd83196acb6582cabd9b"}, + {file = "grpcio-1.49.1-cp310-cp310-win32.whl", hash = "sha256:f1a3b88e3c53c1a6e6bed635ec1bbb92201bb6a1f2db186179f7f3f244829788"}, + {file = "grpcio-1.49.1-cp310-cp310-win_amd64.whl", hash = "sha256:a7d0017b92d3850abea87c1bdec6ea41104e71c77bca44c3e17f175c6700af62"}, + {file = "grpcio-1.49.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:9fb17ff8c0d56099ac6ebfa84f670c5a62228d6b5c695cf21c02160c2ac1446b"}, + {file = "grpcio-1.49.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:075f2d06e3db6b48a2157a1bcd52d6cbdca980dd18988fe6afdb41795d51625f"}, + {file = "grpcio-1.49.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46d93a1b4572b461a227f1db6b8d35a88952db1c47e5fadcf8b8a2f0e1dd9201"}, + {file = "grpcio-1.49.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc79b2b37d779ac42341ddef40ad5bf0966a64af412c89fc2b062e3ddabb093f"}, + {file = "grpcio-1.49.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5f8b3a971c7820ea9878f3fd70086240a36aeee15d1b7e9ecbc2743b0e785568"}, + {file = "grpcio-1.49.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49b301740cf5bc8fed4fee4c877570189ae3951432d79fa8e524b09353659811"}, + {file = "grpcio-1.49.1-cp311-cp311-win32.whl", hash = "sha256:1c66a25afc6c71d357867b341da594a5587db5849b48f4b7d5908d236bb62ede"}, + {file = "grpcio-1.49.1-cp311-cp311-win_amd64.whl", hash = "sha256:6b6c3a95d27846f4145d6967899b3ab25fffc6ae99544415e1adcacef84842d2"}, + {file = "grpcio-1.49.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:1cc400c8a2173d1c042997d98a9563e12d9bb3fb6ad36b7f355bc77c7663b8af"}, + {file = "grpcio-1.49.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:34f736bd4d0deae90015c0e383885b431444fe6b6c591dea288173df20603146"}, + {file = "grpcio-1.49.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:196082b9c89ebf0961dcd77cb114bed8171964c8e3063b9da2fb33536a6938ed"}, + {file = "grpcio-1.49.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c9f89c42749890618cd3c2464e1fbf88446e3d2f67f1e334c8e5db2f3272bbd"}, + {file = "grpcio-1.49.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64419cb8a5b612cdb1550c2fd4acbb7d4fb263556cf4625f25522337e461509e"}, + {file = "grpcio-1.49.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8a5272061826e6164f96e3255405ef6f73b88fd3e8bef464c7d061af8585ac62"}, + {file = "grpcio-1.49.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ea9d0172445241ad7cb49577314e39d0af2c5267395b3561d7ced5d70458a9f3"}, + {file = "grpcio-1.49.1-cp37-cp37m-win32.whl", hash = "sha256:2070e87d95991473244c72d96d13596c751cb35558e11f5df5414981e7ed2492"}, + {file = "grpcio-1.49.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fcedcab49baaa9db4a2d240ac81f2d57eb0052b1c6a9501b46b8ae912720fbf"}, + {file = "grpcio-1.49.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:afbb3475cf7f4f7d380c2ca37ee826e51974f3e2665613996a91d6a58583a534"}, + {file = "grpcio-1.49.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a4f9ba141380abde6c3adc1727f21529137a2552002243fa87c41a07e528245c"}, + {file = "grpcio-1.49.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:cf0a1fb18a7204b9c44623dfbd1465b363236ce70c7a4ed30402f9f60d8b743b"}, + {file = "grpcio-1.49.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17bb6fe72784b630728c6cff9c9d10ccc3b6d04e85da6e0a7b27fb1d135fac62"}, + {file = "grpcio-1.49.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18305d5a082d1593b005a895c10041f833b16788e88b02bb81061f5ebcc465df"}, + {file = "grpcio-1.49.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b6a1b39e59ac5a3067794a0e498911cf2e37e4b19ee9e9977dc5e7051714f13f"}, + {file = "grpcio-1.49.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0e20d59aafc086b1cc68400463bddda6e41d3e5ed30851d1e2e0f6a2e7e342d3"}, + {file = "grpcio-1.49.1-cp38-cp38-win32.whl", hash = "sha256:e1e83233d4680863a421f3ee4a7a9b80d33cd27ee9ed7593bc93f6128302d3f2"}, + {file = "grpcio-1.49.1-cp38-cp38-win_amd64.whl", hash = "sha256:221d42c654d2a41fa31323216279c73ed17d92f533bc140a3390cc1bd78bf63c"}, + {file = "grpcio-1.49.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:fa9e6e61391e99708ac87fc3436f6b7b9c6b845dc4639b406e5e61901e1aacde"}, + {file = "grpcio-1.49.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9b449e966ef518ce9c860d21f8afe0b0f055220d95bc710301752ac1db96dd6a"}, + {file = "grpcio-1.49.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:aa34d2ad9f24e47fa9a3172801c676e4037d862247e39030165fe83821a7aafd"}, + {file = "grpcio-1.49.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5207f4eed1b775d264fcfe379d8541e1c43b878f2b63c0698f8f5c56c40f3d68"}, + {file = "grpcio-1.49.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b24a74651438d45619ac67004638856f76cc13d78b7478f2457754cbcb1c8ad"}, + {file = "grpcio-1.49.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fe763781669790dc8b9618e7e677c839c87eae6cf28b655ee1fa69ae04eea03f"}, + {file = "grpcio-1.49.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2f2ff7ba0f8f431f32d4b4bc3a3713426949d3533b08466c4ff1b2b475932ca8"}, + {file = "grpcio-1.49.1-cp39-cp39-win32.whl", hash = "sha256:08ff74aec8ff457a89b97152d36cb811dcc1d17cd5a92a65933524e363327394"}, + {file = "grpcio-1.49.1-cp39-cp39-win_amd64.whl", hash = "sha256:274ffbb39717918c514b35176510ae9be06e1d93121e84d50b350861dcb9a705"}, + {file = "grpcio-1.49.1.tar.gz", hash = "sha256:d4725fc9ec8e8822906ae26bb26f5546891aa7fbc3443de970cc556d43a5c99f"}, +] + +[package.dependencies] +six = ">=1.5.2" + +[package.extras] +protobuf = ["grpcio-tools (>=1.49.1)"] + +[[package]] +name = "grpcio" +version = "1.51.3" +description = "HTTP/2-based RPC framework" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "grpcio-1.51.3-cp310-cp310-linux_armv7l.whl", hash = "sha256:f601aaeae18dab81930fb8d4f916b0da21e89bb4b5f7367ef793f46b4a76b7b0"}, + {file = "grpcio-1.51.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:eef0450a4b5ed11feab639bf3eb1b6e23d0efa9b911bf7b06fb60e14f5f8a585"}, + {file = "grpcio-1.51.3-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:82b0ad8ac825d4bb31bff9f638557c045f4a6d824d84b21e893968286f88246b"}, + {file = "grpcio-1.51.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3667c06e37d6cd461afdd51cefe6537702f3d1dc5ff4cac07e88d8b4795dc16f"}, + {file = "grpcio-1.51.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3709048fe0aa23dda09b3e69849a12055790171dab9e399a72ea8f9dfbf9ac80"}, + {file = "grpcio-1.51.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:200d69857f9910f7458b39b9bcf83ee4a180591b40146ba9e49314e3a7419313"}, + {file = "grpcio-1.51.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cd9a5e68e79c5f031500e67793048a90209711e0854a9ddee8a3ce51728de4e5"}, + {file = "grpcio-1.51.3-cp310-cp310-win32.whl", hash = "sha256:6604f614016127ae10969176bbf12eb0e03d2fb3d643f050b3b69e160d144fb4"}, + {file = "grpcio-1.51.3-cp310-cp310-win_amd64.whl", hash = "sha256:e95c7ccd4c5807adef1602005513bf7c7d14e5a41daebcf9d8d30d8bf51b8f81"}, + {file = "grpcio-1.51.3-cp311-cp311-linux_armv7l.whl", hash = "sha256:5e77ee138100f0bb55cbd147840f87ee6241dbd25f09ea7cd8afe7efff323449"}, + {file = "grpcio-1.51.3-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:68a7514b754e38e8de9075f7bb4dee919919515ec68628c43a894027e40ddec4"}, + {file = "grpcio-1.51.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c1b9f8afa62ff265d86a4747a2990ec5a96e4efce5d5888f245a682d66eca47"}, + {file = "grpcio-1.51.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8de30f0b417744288cec65ec8cf84b8a57995cf7f1e84ccad2704d93f05d0aae"}, + {file = "grpcio-1.51.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b69c7adc7ed60da1cb1b502853db61f453fc745f940cbcc25eb97c99965d8f41"}, + {file = "grpcio-1.51.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d81528ffe0e973dc840ec73a4132fd18b8203ad129d7410155d951a0a7e4f5d0"}, + {file = "grpcio-1.51.3-cp311-cp311-win32.whl", hash = "sha256:040eb421613b57c696063abde405916dd830203c184c9000fc8c3b3b3c950325"}, + {file = "grpcio-1.51.3-cp311-cp311-win_amd64.whl", hash = "sha256:2a8e17286c4240137d933b8ca506465472248b4ce0fe46f3404459e708b65b68"}, + {file = "grpcio-1.51.3-cp37-cp37m-linux_armv7l.whl", hash = "sha256:d5cd1389669a847555df54177b911d9ff6f17345b2a6f19388707b7a9f724c88"}, + {file = "grpcio-1.51.3-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:be1bf35ce82cdbcac14e39d5102d8de4079a1c1a6a06b68e41fcd9ef64f9dd28"}, + {file = "grpcio-1.51.3-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:5eed34994c095e2bf7194ffac7381c6068b057ef1e69f8f08db77771350a7566"}, + {file = "grpcio-1.51.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9a7d88082b2a17ae7bd3c2354d13bab0453899e0851733f6afa6918373f476"}, + {file = "grpcio-1.51.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c8abbc5f837111e7bd619612eedc223c290b0903b952ce0c7b00840ea70f14"}, + {file = "grpcio-1.51.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:165b05af77e6aecb4210ae7663e25acf234ba78a7c1c157fa5f2efeb0d6ec53c"}, + {file = "grpcio-1.51.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54e36c2ee304ff15f2bfbdc43d2b56c63331c52d818c364e5b5214e5bc2ad9f6"}, + {file = "grpcio-1.51.3-cp37-cp37m-win32.whl", hash = "sha256:cd0daac21d9ef5e033a5100c1d3aa055bbed28bfcf070b12d8058045c4e821b1"}, + {file = "grpcio-1.51.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2fdd6333ce96435408565a9dbbd446212cd5d62e4d26f6a3c0feb1e3c35f1cc8"}, + {file = "grpcio-1.51.3-cp38-cp38-linux_armv7l.whl", hash = "sha256:54b0c29bdd9a3b1e1b61443ab152f060fc719f1c083127ab08d03fac5efd51be"}, + {file = "grpcio-1.51.3-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:ffaaf7e93fcb437356b5a4b23bf36e8a3d0221399ff77fd057e4bc77776a24be"}, + {file = "grpcio-1.51.3-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:eafbe7501a3268d05f2e450e1ddaffb950d842a8620c13ec328b501d25d2e2c3"}, + {file = "grpcio-1.51.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:881ecb34feabf31c6b3b9bbbddd1a5b57e69f805041e5a2c6c562a28574f71c4"}, + {file = "grpcio-1.51.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e860a3222139b41d430939bbec2ec9c3f6c740938bf7a04471a9a8caaa965a2e"}, + {file = "grpcio-1.51.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:49ede0528e9dac7e8a9fe30b16c73b630ddd9a576bf4b675eb6b0c53ee5ca00f"}, + {file = "grpcio-1.51.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6972b009638b40a448d10e1bc18e2223143b8a7aa20d7def0d78dd4af4126d12"}, + {file = "grpcio-1.51.3-cp38-cp38-win32.whl", hash = "sha256:5694448256e3cdfe5bd358f1574a3f2f51afa20cc834713c4b9788d60b7cc646"}, + {file = "grpcio-1.51.3-cp38-cp38-win_amd64.whl", hash = "sha256:3ea4341efe603b049e8c9a5f13c696ca37fcdf8a23ca35f650428ad3606381d9"}, + {file = "grpcio-1.51.3-cp39-cp39-linux_armv7l.whl", hash = "sha256:6c677581ce129f5fa228b8f418cee10bd28dd449f3a544ea73c8ba590ee49d0b"}, + {file = "grpcio-1.51.3-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:30e09b5e0531685e176f49679b6a3b190762cc225f4565e55a899f5e14b3aa62"}, + {file = "grpcio-1.51.3-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:c831f31336e81243f85b6daff3e5e8a123302ce0ea1f2726ad752fd7a59f3aee"}, + {file = "grpcio-1.51.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2cd2e4cefb724cab1ba2df4b7535a9980531b9ec51b4dbb5f137a1f3a3754ef0"}, + {file = "grpcio-1.51.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a0d0bf44438869d307f85a54f25a896ad6b4b0ca12370f76892ad732928d87"}, + {file = "grpcio-1.51.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c02abd55409bfb293371554adf6a4401197ec2133dd97727c01180889014ba4d"}, + {file = "grpcio-1.51.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2f8ff75e61e1227ba7a3f16b2eadbcc11d0a54096d52ab75a6b88cfbe56f55d1"}, + {file = "grpcio-1.51.3-cp39-cp39-win32.whl", hash = "sha256:6c99a73a6260bdf844b2e5ddad02dcd530310f80e1fa72c300fa19c1c7496962"}, + {file = "grpcio-1.51.3-cp39-cp39-win_amd64.whl", hash = "sha256:22bdfac4f7f27acdd4da359b5e7e1973dc74bf1ed406729b07d0759fde2f064b"}, + {file = "grpcio-1.51.3.tar.gz", hash = "sha256:be7b2265b7527bb12109a7727581e274170766d5b3c9258d4e466f4872522d7a"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.51.3)"] + +[[package]] +name = "h5py" +version = "3.9.0" +description = "Read and write HDF5 files from Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "h5py-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb7bdd5e601dd1739698af383be03f3dad0465fe67184ebd5afca770f50df9d6"}, + {file = "h5py-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:78e44686334cbbf2dd21d9df15823bc38663f27a3061f6a032c68a3e30c47bf7"}, + {file = "h5py-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f68b41efd110ce9af1cbe6fa8af9f4dcbadace6db972d30828b911949e28fadd"}, + {file = "h5py-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12aa556d540f11a2cae53ea7cfb94017353bd271fb3962e1296b342f6550d1b8"}, + {file = "h5py-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:d97409e17915798029e297a84124705c8080da901307ea58f29234e09b073ddc"}, + {file = "h5py-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:551e358db05a874a0f827b22e95b30092f2303edc4b91bb62ad2f10e0236e1a0"}, + {file = "h5py-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6822a814b9d8b8363ff102f76ea8d026f0ca25850bb579d85376029ee3e73b93"}, + {file = "h5py-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f01202cdea754ab4227dd27014bdbd561a4bbe4b631424fd812f7c2ce9c6ac"}, + {file = "h5py-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64acceaf6aff92af091a4b83f6dee3cf8d3061f924a6bb3a33eb6c4658a8348b"}, + {file = "h5py-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:804c7fb42a34c8ab3a3001901c977a5c24d2e9c586a0f3e7c0a389130b4276fc"}, + {file = "h5py-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8d9492391ff5c3c80ec30ae2fe82a3f0efd1e750833739c25b0d090e3be1b095"}, + {file = "h5py-3.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9da9e7e63376c32704e37ad4cea2dceae6964cee0d8515185b3ab9cbd6b947bc"}, + {file = "h5py-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4e20897c88759cbcbd38fb45b507adc91af3e0f67722aa302d71f02dd44d286"}, + {file = "h5py-3.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbf5225543ca35ce9f61c950b73899a82be7ba60d58340e76d0bd42bf659235a"}, + {file = "h5py-3.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:36408f8c62f50007d14e000f9f3acf77e103b9e932c114cbe52a3089e50ebf94"}, + {file = "h5py-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:23e74b878bbe1653ab34ca49b83cac85529cd0b36b9d625516c5830cc5ca2eac"}, + {file = "h5py-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f457089c5d524b7998e3649bc63240679b8fb0a3859ea53bbb06841f3d755f1"}, + {file = "h5py-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6284061f3214335e1eec883a6ee497dbe7a79f19e6a57fed2dd1f03acd5a8cb"}, + {file = "h5py-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7a745efd0d56076999b52e8da5fad5d30823bac98b59c68ae75588d09991a"}, + {file = "h5py-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:79bbca34696c6f9eeeb36a91776070c49a060b2879828e2c8fa6c58b8ed10dd1"}, + {file = "h5py-3.9.0.tar.gz", hash = "sha256:e604db6521c1e367c6bd7fad239c847f53cc46646f2d2651372d05ae5e95f817"}, +] + +[package.dependencies] +numpy = ">=1.17.3" + +[[package]] +name = "hypothesis" +version = "6.31.6" +description = "A library for property-based testing" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "hypothesis-6.31.6-py3-none-any.whl", hash = "sha256:fbd31da5174f3da8d062017302071967b239a1b397d0e3181a44d43346bc6def"}, + {file = "hypothesis-6.31.6.tar.gz", hash = "sha256:d54be6a80b160ad5ea4209b01a0d72e31d910510ed7142fa9907861911800771"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +sortedcontainers = ">=2.1.0,<3.0.0" + +[package.extras] +all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "django (>=2.2)", "dpcontracts (>=0.4)", "importlib-metadata (>=3.6)", "importlib-resources (>=3.3.0)", "lark-parser (>=0.6.5)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=0.25)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2021.5)"] +cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] +codemods = ["libcst (>=0.3.16)"] +dateutil = ["python-dateutil (>=1.4)"] +django = ["django (>=2.2)"] +dpcontracts = ["dpcontracts (>=0.4)"] +ghostwriter = ["black (>=19.10b0)"] +lark = ["lark-parser (>=0.6.5)"] +numpy = ["numpy (>=1.9.0)"] +pandas = ["pandas (>=0.25)"] +pytest = ["pytest (>=4.6)"] +pytz = ["pytz (>=2014.1)"] +redis = ["redis (>=3.0.0)"] +zoneinfo = ["backports.zoneinfo (>=0.2.1)", "importlib-resources (>=3.3.0)", "tzdata (>=2021.5)"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "joblib" +version = "1.3.1" +description = "Lightweight pipelining with Python functions" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "joblib-1.3.1-py3-none-any.whl", hash = "sha256:89cf0529520e01b3de7ac7b74a8102c90d16d54c64b5dd98cafcd14307fdf915"}, + {file = "joblib-1.3.1.tar.gz", hash = "sha256:1f937906df65329ba98013dc9692fe22a4c5e4a648112de500508b18a21b41e3"}, +] + +[[package]] +name = "jsonschema" +version = "4.18.2" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.18.2-py3-none-any.whl", hash = "sha256:159fdff1443b4c5ed900d4eeac6b928a3485f4aff5fba6edd1e25cd66bb46b39"}, + {file = "jsonschema-4.18.2.tar.gz", hash = "sha256:af3855bfa30e83b2200a5fe12ab5eb92460e4d3b8e4efd34094aa637f7272a87"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.6.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.6.1-py3-none-any.whl", hash = "sha256:3d2b82663aff01815f744bb5c7887e2121a63399b49b104a3c96145474d091d7"}, + {file = "jsonschema_specifications-2023.6.1.tar.gz", hash = "sha256:ca1c4dd059a9e7b34101cf5b3ab7ff1d18b139f35950d598d629837ef66e8f28"}, +] + +[package.dependencies] +referencing = ">=0.28.0" + +[[package]] +name = "keras" +version = "2.10.0" +description = "Deep learning for humans." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "keras-2.10.0-py2.py3-none-any.whl", hash = "sha256:26a6e2c2522e7468ddea22710a99b3290493768fc08a39e75d1173a0e3452fdf"}, +] + +[[package]] +name = "keras-preprocessing" +version = "1.1.2" +description = "Easy data preprocessing and data augmentation for deep learning models" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "Keras_Preprocessing-1.1.2-py2.py3-none-any.whl", hash = "sha256:7b82029b130ff61cc99b55f3bd27427df4838576838c5b2f65940e4fcec99a7b"}, + {file = "Keras_Preprocessing-1.1.2.tar.gz", hash = "sha256:add82567c50c8bc648c14195bf544a5ce7c1f76761536956c3d2978970179ef3"}, +] + +[package.dependencies] +numpy = ">=1.9.1" +six = ">=1.9.0" + +[package.extras] +image = ["Pillow (>=5.2.0)", "scipy (>=0.14)"] +pep8 = ["flake8"] +tests = ["Pillow", "keras", "pandas", "pytest", "pytest-cov", "pytest-xdist", "tensorflow"] + +[[package]] +name = "kiwisolver" +version = "1.4.4" +description = "A fast implementation of the Cassowary constraint solver" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, + {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, + {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, + {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, + {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, + {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, + {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, + {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, + {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, + {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, + {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, + {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, + {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, + {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, + {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, + {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, + {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, + {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, + {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, + {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, + {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, + {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, + {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, + {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, + {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, + {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, + {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, + {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, + {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, + {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, + {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, + {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, + {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, + {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, + {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, + {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, + {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, + {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, + {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, + {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, + {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, + {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, + {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, + {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, + {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, + {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, + {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, + {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, + {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, + {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, + {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, + {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, + {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, + {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, + {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, + {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, + {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, + {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, + {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, + {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, + {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, +] + +[[package]] +name = "latexcodec" +version = "2.0.1" +description = "A lexer and codec to work with LaTeX code in Python." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "latexcodec-2.0.1-py2.py3-none-any.whl", hash = "sha256:c277a193638dc7683c4c30f6684e3db728a06efb0dc9cf346db8bd0aa6c5d271"}, + {file = "latexcodec-2.0.1.tar.gz", hash = "sha256:2aa2551c373261cefe2ad3a8953a6d6533e68238d180eb4bb91d7964adb3fe9a"}, +] + +[package.dependencies] +six = ">=1.4.1" + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "libclang" +version = "16.0.0" +description = "Clang Python Bindings, mirrored from the official LLVM repo: https://github.com/llvm/llvm-project/tree/main/clang/bindings/python, to make the installation process easier." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "libclang-16.0.0-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:65258a6bb3e7dc31dc9b26f8d42f53c9d3b959643ade291fcd1aef4855303ca6"}, + {file = "libclang-16.0.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:af55a4aa86fdfe6b2ec68bc8cfe5fdac6c448d591ca7648be86ca17099b41ca8"}, + {file = "libclang-16.0.0-py2.py3-none-manylinux2010_x86_64.whl", hash = "sha256:a043138caaf2cb076ebb060c6281ec95612926645d425c691991fc9df00e8a24"}, + {file = "libclang-16.0.0-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:eb59652cb0559c0e71784ff4c8ba24c14644becc907b1446563ecfaa622d523b"}, + {file = "libclang-16.0.0-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:7b6686b67a0daa84b4c614bcc119578329fc4fbb52b919565b7376b507c4793b"}, + {file = "libclang-16.0.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2adce42ae652f312245b8f4eda6f30b4076fb61f7619f2dfd0a0c31dee4c32b9"}, + {file = "libclang-16.0.0-py2.py3-none-win_amd64.whl", hash = "sha256:ee20bf93e3dd330f71fc50cdbf13b92ced0aec8e540be64251db53502a9b33f7"}, + {file = "libclang-16.0.0-py2.py3-none-win_arm64.whl", hash = "sha256:bf4628fc4da7a1dd06a244f9b8e121c5ec68076a763c59d6b13cbb103acc935b"}, +] + +[[package]] +name = "llvmlite" +version = "0.39.1" +description = "lightweight wrapper around basic LLVM functionality" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "llvmlite-0.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6717c7a6e93c9d2c3d07c07113ec80ae24af45cde536b34363d4bcd9188091d9"}, + {file = "llvmlite-0.39.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ddab526c5a2c4ccb8c9ec4821fcea7606933dc53f510e2a6eebb45a418d3488a"}, + {file = "llvmlite-0.39.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3f331a323d0f0ada6b10d60182ef06c20a2f01be21699999d204c5750ffd0b4"}, + {file = "llvmlite-0.39.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c00ff204afa721b0bb9835b5bf1ba7fba210eefcec5552a9e05a63219ba0dc"}, + {file = "llvmlite-0.39.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16f56eb1eec3cda3a5c526bc3f63594fc24e0c8d219375afeb336f289764c6c7"}, + {file = "llvmlite-0.39.1-cp310-cp310-win32.whl", hash = "sha256:d0bfd18c324549c0fec2c5dc610fd024689de6f27c6cc67e4e24a07541d6e49b"}, + {file = "llvmlite-0.39.1-cp310-cp310-win_amd64.whl", hash = "sha256:7ebf1eb9badc2a397d4f6a6c8717447c81ac011db00064a00408bc83c923c0e4"}, + {file = "llvmlite-0.39.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6546bed4e02a1c3d53a22a0bced254b3b6894693318b16c16c8e43e29d6befb6"}, + {file = "llvmlite-0.39.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1578f5000fdce513712e99543c50e93758a954297575610f48cb1fd71b27c08a"}, + {file = "llvmlite-0.39.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3803f11ad5f6f6c3d2b545a303d68d9fabb1d50e06a8d6418e6fcd2d0df00959"}, + {file = "llvmlite-0.39.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50aea09a2b933dab7c9df92361b1844ad3145bfb8dd2deb9cd8b8917d59306fb"}, + {file = "llvmlite-0.39.1-cp37-cp37m-win32.whl", hash = "sha256:b1a0bbdb274fb683f993198775b957d29a6f07b45d184c571ef2a721ce4388cf"}, + {file = "llvmlite-0.39.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e172c73fccf7d6db4bd6f7de963dedded900d1a5c6778733241d878ba613980e"}, + {file = "llvmlite-0.39.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e31f4b799d530255aaf0566e3da2df5bfc35d3cd9d6d5a3dcc251663656c27b1"}, + {file = "llvmlite-0.39.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:62c0ea22e0b9dffb020601bb65cb11dd967a095a488be73f07d8867f4e327ca5"}, + {file = "llvmlite-0.39.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ffc84ade195abd4abcf0bd3b827b9140ae9ef90999429b9ea84d5df69c9058c"}, + {file = "llvmlite-0.39.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0f158e4708dda6367d21cf15afc58de4ebce979c7a1aa2f6b977aae737e2a54"}, + {file = "llvmlite-0.39.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22d36591cd5d02038912321d9ab8e4668e53ae2211da5523f454e992b5e13c36"}, + {file = "llvmlite-0.39.1-cp38-cp38-win32.whl", hash = "sha256:4c6ebace910410daf0bebda09c1859504fc2f33d122e9a971c4c349c89cca630"}, + {file = "llvmlite-0.39.1-cp38-cp38-win_amd64.whl", hash = "sha256:fb62fc7016b592435d3e3a8f680e3ea8897c3c9e62e6e6cc58011e7a4801439e"}, + {file = "llvmlite-0.39.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa9b26939ae553bf30a9f5c4c754db0fb2d2677327f2511e674aa2f5df941789"}, + {file = "llvmlite-0.39.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e4f212c018db951da3e1dc25c2651abc688221934739721f2dad5ff1dd5f90e7"}, + {file = "llvmlite-0.39.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39dc2160aed36e989610fc403487f11b8764b6650017ff367e45384dff88ffbf"}, + {file = "llvmlite-0.39.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ec3d70b3e507515936e475d9811305f52d049281eaa6c8273448a61c9b5b7e2"}, + {file = "llvmlite-0.39.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60f8dd1e76f47b3dbdee4b38d9189f3e020d22a173c00f930b52131001d801f9"}, + {file = "llvmlite-0.39.1-cp39-cp39-win32.whl", hash = "sha256:03aee0ccd81735696474dc4f8b6be60774892a2929d6c05d093d17392c237f32"}, + {file = "llvmlite-0.39.1-cp39-cp39-win_amd64.whl", hash = "sha256:3fc14e757bc07a919221f0cbaacb512704ce5774d7fcada793f1996d6bc75f2a"}, + {file = "llvmlite-0.39.1.tar.gz", hash = "sha256:b43abd7c82e805261c425d50335be9a6c4f84264e34d6d6e475207300005d572"}, +] + +[[package]] +name = "locket" +version = "1.0.0" +description = "File-based locks for Python on Linux and Windows" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "locket-1.0.0-py2.py3-none-any.whl", hash = "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3"}, + {file = "locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632"}, +] + +[[package]] +name = "m2r2" +version = "0.3.3.post2" +description = "Markdown and reStructuredText in a single file." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "m2r2-0.3.3.post2-py3-none-any.whl", hash = "sha256:86157721eb6eabcd54d4eea7195890cc58fa6188b8d0abea633383cfbb5e11e3"}, + {file = "m2r2-0.3.3.post2.tar.gz", hash = "sha256:e62bcb0e74b3ce19cda0737a0556b04cf4a43b785072fcef474558f2c1482ca8"}, +] + +[package.dependencies] +docutils = ">=0.19" +mistune = "0.8.4" + +[[package]] +name = "markdown" +version = "3.4.3" +description = "Python implementation of John Gruber's Markdown." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"}, + {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "matplotlib" +version = "3.5.0" +description = "Python plotting package" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "matplotlib-3.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4b018ea6f26424a0852eb60eb406420d9f0d34f65736ea7bbfbb104946a66d86"}, + {file = "matplotlib-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a07ff2565da72a7b384a9e000b15b6b8270d81370af8a3531a16f6fbcee023cc"}, + {file = "matplotlib-3.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2eea16883aa7724c95eea0eb473ab585c6cf66f0e28f7f13e63deb38f4fd6d0f"}, + {file = "matplotlib-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e020a42f3338823a393dd2f80e39a2c07b9f941dfe2c778eb104eeb33d60bb5"}, + {file = "matplotlib-3.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bac8eb1eccef540d7f4e844b6313d9f7722efd48c07e1b4bfec1056132127fd"}, + {file = "matplotlib-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7cb59ebd63a8ac4542ec1c61dd08724f82ec3aa7bb6b4b9e212d43c611ce3d"}, + {file = "matplotlib-3.5.0-cp310-cp310-win32.whl", hash = "sha256:6e0e6b2111165522ad336705499b1f968c34a9e84d05d498ee5af0b5697d1efe"}, + {file = "matplotlib-3.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:ff5d9fe518ad2de14ce82ab906b6ab5c2b0c7f4f984400ff8a7a905daa580a0a"}, + {file = "matplotlib-3.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:66b172610db0ececebebb09d146f54205f87c7b841454e408fba854764f91bdd"}, + {file = "matplotlib-3.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3d9ff16d749a9aa521bd7d86f0dbf256b2d2ac8ce31b19e4d2c86d2f2ff0b6"}, + {file = "matplotlib-3.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970aa97297537540369d05fe0fd1bb952593f9ab696c9b427c06990a83e2418b"}, + {file = "matplotlib-3.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:153a0cf6a6ff4f406a0600d2034710c49988bacc6313d193b32716f98a697580"}, + {file = "matplotlib-3.5.0-cp37-cp37m-win32.whl", hash = "sha256:6db02c5605f063b67780f4d5753476b6a4944343284aa4e93c5e8ff6e9ec7f76"}, + {file = "matplotlib-3.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:df0042cab69f4d246f4cb8fc297770ac4ae6ec2983f61836b04a117722037dcd"}, + {file = "matplotlib-3.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a7bf8b05c214d32fb7ca7c001fde70b9b426378e897b0adbf77b85ea3569d56a"}, + {file = "matplotlib-3.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0abf8b51cc6d3ba34d1b15b26e329f23879848a0cf1216954c1f432ffc7e1af7"}, + {file = "matplotlib-3.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:13930a0c9bec0fd25f43c448b047a21af1353328b946f044a8fc3be077c6b1a8"}, + {file = "matplotlib-3.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18f6e52386300db5cc4d1e9019ad9da2e80658bab018834d963ebb0aa5355095"}, + {file = "matplotlib-3.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba107add08e12600b072cf3c47aaa1ab85dd4d3c48107a5d3377d1bf80f8b235"}, + {file = "matplotlib-3.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2089b9014792dcc87bb1d620cde847913338abf7d957ef05587382b0cb76d44e"}, + {file = "matplotlib-3.5.0-cp38-cp38-win32.whl", hash = "sha256:f23fbf70d2e80f4e03a83fc1206a8306d9bc50482fee4239f10676ce7e470c83"}, + {file = "matplotlib-3.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:71a1851111f23f82fc43d2b6b2bfdd3f760579a664ebc939576fe21cc6133d01"}, + {file = "matplotlib-3.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d092b7ba63182d2dd427904e3eb58dd5c46ec67c5968de14a4b5007010a3a4cc"}, + {file = "matplotlib-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ac17a7e7b06ee426a4989f0b7f24ab1a592e39cdf56353a90f4e998bc0bf44d6"}, + {file = "matplotlib-3.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a5b62d1805cc83d755972033c05cea78a1e177a159fc84da5c9c4ab6303ccbd9"}, + {file = "matplotlib-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:666d717a4798eb9c5d3ae83fe80c7bc6ed696b93e879cb01cb24a74155c73612"}, + {file = "matplotlib-3.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65f877882b7ddede7090c7d87be27a0f4720fe7fc6fddd4409c06e1aa0f1ae8d"}, + {file = "matplotlib-3.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7baf23adb698d8c6ca7339c9dde00931bc47b2dd82fa912827fef9f93db77f5e"}, + {file = "matplotlib-3.5.0-cp39-cp39-win32.whl", hash = "sha256:b3b687e905da32e5f2e5f16efa713f5d1fcd9fb8b8c697895de35c91fedeb086"}, + {file = "matplotlib-3.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6cef5b31e27c31253c0f852b629a38d550ae66ec6850129c49d872f9ee428cb"}, + {file = "matplotlib-3.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0dcaf5648cecddc328e81a0421821a1f65a1d517b20746c94a1f0f5c36fb51a"}, + {file = "matplotlib-3.5.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b5e439d9e55d645f2a4dca63e2f66d68fe974c405053b132d61c7e98c25dfeb2"}, + {file = "matplotlib-3.5.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dc8c5c23e7056e126275dbf29efba817b3d94196690930d0968873ac3a94ab82"}, + {file = "matplotlib-3.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a0ea10faa3bab0714d3a19c7e0921279a68d57552414d6eceaea99f97d7735db"}, + {file = "matplotlib-3.5.0.tar.gz", hash = "sha256:38892a254420d95594285077276162a5e9e9c30b6da08bdc2a4d53331ad9a6fa"}, +] + +[package.dependencies] +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.0.1" +numpy = ">=1.17" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.2.1" +python-dateutil = ">=2.7" +setuptools-scm = ">=4" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] + +[[package]] +name = "mistune" +version = "0.8.4" +description = "The fastest markdown parser in pure Python" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, + {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +description = "Python library for arbitrary-precision floating-point arithmetic" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] + +[package.extras] +develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] +tests = ["pytest (>=4.6)"] + +[[package]] +name = "msgpack" +version = "1.0.5" +description = "MessagePack serializer" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:525228efd79bb831cf6830a732e2e80bc1b05436b086d4264814b4b2955b2fa9"}, + {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f8d8b3bf1ff2672567d6b5c725a1b347fe838b912772aa8ae2bf70338d5a198"}, + {file = "msgpack-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdc793c50be3f01106245a61b739328f7dccc2c648b501e237f0699fe1395b81"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cb47c21a8a65b165ce29f2bec852790cbc04936f502966768e4aae9fa763cb7"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e42b9594cc3bf4d838d67d6ed62b9e59e201862a25e9a157019e171fbe672dd3"}, + {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55b56a24893105dc52c1253649b60f475f36b3aa0fc66115bffafb624d7cb30b"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1967f6129fc50a43bfe0951c35acbb729be89a55d849fab7686004da85103f1c"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a97bf595a232c3ee6d57ddaadd5453d174a52594bf9c21d10407e2a2d9b3bd"}, + {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d25dd59bbbbb996eacf7be6b4ad082ed7eacc4e8f3d2df1ba43822da9bfa122a"}, + {file = "msgpack-1.0.5-cp310-cp310-win32.whl", hash = "sha256:382b2c77589331f2cb80b67cc058c00f225e19827dbc818d700f61513ab47bea"}, + {file = "msgpack-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:4867aa2df9e2a5fa5f76d7d5565d25ec76e84c106b55509e78c1ede0f152659a"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9f5ae84c5c8a857ec44dc180a8b0cc08238e021f57abdf51a8182e915e6299f0"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e6ca5d5699bcd89ae605c150aee83b5321f2115695e741b99618f4856c50898"}, + {file = "msgpack-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5494ea30d517a3576749cad32fa27f7585c65f5f38309c88c6d137877fa28a5a"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ab2f3331cb1b54165976a9d976cb251a83183631c88076613c6c780f0d6e45a"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28592e20bbb1620848256ebc105fc420436af59515793ed27d5c77a217477705"}, + {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe5c63197c55bce6385d9aee16c4d0641684628f63ace85f73571e65ad1c1e8d"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed40e926fa2f297e8a653c954b732f125ef97bdd4c889f243182299de27e2aa9"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b2de4c1c0538dcb7010902a2b97f4e00fc4ddf2c8cda9749af0e594d3b7fa3d7"}, + {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf22a83f973b50f9d38e55c6aade04c41ddda19b00c4ebc558930d78eecc64ed"}, + {file = "msgpack-1.0.5-cp311-cp311-win32.whl", hash = "sha256:c396e2cc213d12ce017b686e0f53497f94f8ba2b24799c25d913d46c08ec422c"}, + {file = "msgpack-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c4c68d87497f66f96d50142a2b73b97972130d93677ce930718f68828b382e2"}, + {file = "msgpack-1.0.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2b031c2e9b9af485d5e3c4520f4220d74f4d222a5b8dc8c1a3ab9448ca79c57"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f837b93669ce4336e24d08286c38761132bc7ab29782727f8557e1eb21b2080"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1d46dfe3832660f53b13b925d4e0fa1432b00f5f7210eb3ad3bb9a13c6204a6"}, + {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:366c9a7b9057e1547f4ad51d8facad8b406bab69c7d72c0eb6f529cf76d4b85f"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4c075728a1095efd0634a7dccb06204919a2f67d1893b6aa8e00497258bf926c"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:f933bbda5a3ee63b8834179096923b094b76f0c7a73c1cfe8f07ad608c58844b"}, + {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:36961b0568c36027c76e2ae3ca1132e35123dcec0706c4b7992683cc26c1320c"}, + {file = "msgpack-1.0.5-cp36-cp36m-win32.whl", hash = "sha256:b5ef2f015b95f912c2fcab19c36814963b5463f1fb9049846994b007962743e9"}, + {file = "msgpack-1.0.5-cp36-cp36m-win_amd64.whl", hash = "sha256:288e32b47e67f7b171f86b030e527e302c91bd3f40fd9033483f2cacc37f327a"}, + {file = "msgpack-1.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:137850656634abddfb88236008339fdaba3178f4751b28f270d2ebe77a563b6c"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c05a4a96585525916b109bb85f8cb6511db1c6f5b9d9cbcbc940dc6b4be944b"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a62ec00b636583e5cb6ad313bbed36bb7ead5fa3a3e38938503142c72cba4f"}, + {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef8108f8dedf204bb7b42994abf93882da1159728a2d4c5e82012edd92c9da9f"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1835c84d65f46900920b3708f5ba829fb19b1096c1800ad60bae8418652a951d"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e57916ef1bd0fee4f21c4600e9d1da352d8816b52a599c46460e93a6e9f17086"}, + {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:17358523b85973e5f242ad74aa4712b7ee560715562554aa2134d96e7aa4cbbf"}, + {file = "msgpack-1.0.5-cp37-cp37m-win32.whl", hash = "sha256:cb5aaa8c17760909ec6cb15e744c3ebc2ca8918e727216e79607b7bbce9c8f77"}, + {file = "msgpack-1.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:ab31e908d8424d55601ad7075e471b7d0140d4d3dd3272daf39c5c19d936bd82"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b72d0698f86e8d9ddf9442bdedec15b71df3598199ba33322d9711a19f08145c"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:379026812e49258016dd84ad79ac8446922234d498058ae1d415f04b522d5b2d"}, + {file = "msgpack-1.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:332360ff25469c346a1c5e47cbe2a725517919892eda5cfaffe6046656f0b7bb"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:476a8fe8fae289fdf273d6d2a6cb6e35b5a58541693e8f9f019bfe990a51e4ba"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9985b214f33311df47e274eb788a5893a761d025e2b92c723ba4c63936b69b1"}, + {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48296af57cdb1d885843afd73c4656be5c76c0c6328db3440c9601a98f303d87"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:addab7e2e1fcc04bd08e4eb631c2a90960c340e40dfc4a5e24d2ff0d5a3b3edb"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:916723458c25dfb77ff07f4c66aed34e47503b2eb3188b3adbec8d8aa6e00f48"}, + {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:821c7e677cc6acf0fd3f7ac664c98803827ae6de594a9f99563e48c5a2f27eb0"}, + {file = "msgpack-1.0.5-cp38-cp38-win32.whl", hash = "sha256:1c0f7c47f0087ffda62961d425e4407961a7ffd2aa004c81b9c07d9269512f6e"}, + {file = "msgpack-1.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:bae7de2026cbfe3782c8b78b0db9cbfc5455e079f1937cb0ab8d133496ac55e1"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:20c784e66b613c7f16f632e7b5e8a1651aa5702463d61394671ba07b2fc9e025"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:266fa4202c0eb94d26822d9bfd7af25d1e2c088927fe8de9033d929dd5ba24c5"}, + {file = "msgpack-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18334484eafc2b1aa47a6d42427da7fa8f2ab3d60b674120bce7a895a0a85bdd"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57e1f3528bd95cc44684beda696f74d3aaa8a5e58c816214b9046512240ef437"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:586d0d636f9a628ddc6a17bfd45aa5b5efaf1606d2b60fa5d87b8986326e933f"}, + {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a740fa0e4087a734455f0fc3abf5e746004c9da72fbd541e9b113013c8dc3282"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3055b0455e45810820db1f29d900bf39466df96ddca11dfa6d074fa47054376d"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a61215eac016f391129a013c9e46f3ab308db5f5ec9f25811e811f96962599a8"}, + {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:362d9655cd369b08fda06b6657a303eb7172d5279997abe094512e919cf74b11"}, + {file = "msgpack-1.0.5-cp39-cp39-win32.whl", hash = "sha256:ac9dd47af78cae935901a9a500104e2dea2e253207c924cc95de149606dc43cc"}, + {file = "msgpack-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:06f5174b5f8ed0ed919da0e62cbd4ffde676a374aba4020034da05fab67b9164"}, + {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "numba" +version = "0.56.4" +description = "compiling Python code using LLVM" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "numba-0.56.4-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9f62672145f8669ec08762895fe85f4cf0ead08ce3164667f2b94b2f62ab23c3"}, + {file = "numba-0.56.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c602d015478b7958408d788ba00a50272649c5186ea8baa6cf71d4a1c761bba1"}, + {file = "numba-0.56.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:85dbaed7a05ff96492b69a8900c5ba605551afb9b27774f7f10511095451137c"}, + {file = "numba-0.56.4-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f4cfc3a19d1e26448032049c79fc60331b104f694cf570a9e94f4e2c9d0932bb"}, + {file = "numba-0.56.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e08e203b163ace08bad500b0c16f6092b1eb34fd1fce4feaf31a67a3a5ecf3b"}, + {file = "numba-0.56.4-cp310-cp310-win32.whl", hash = "sha256:0611e6d3eebe4cb903f1a836ffdb2bda8d18482bcd0a0dcc56e79e2aa3fefef5"}, + {file = "numba-0.56.4-cp310-cp310-win_amd64.whl", hash = "sha256:fbfb45e7b297749029cb28694abf437a78695a100e7c2033983d69f0ba2698d4"}, + {file = "numba-0.56.4-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:3cb1a07a082a61df80a468f232e452d818f5ae254b40c26390054e4e868556e0"}, + {file = "numba-0.56.4-cp37-cp37m-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d69ad934e13c15684e7887100a8f5f0f61d7a8e57e0fd29d9993210089a5b531"}, + {file = "numba-0.56.4-cp37-cp37m-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:dbcc847bac2d225265d054993a7f910fda66e73d6662fe7156452cac0325b073"}, + {file = "numba-0.56.4-cp37-cp37m-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8a95ca9cc77ea4571081f6594e08bd272b66060634b8324e99cd1843020364f9"}, + {file = "numba-0.56.4-cp37-cp37m-win32.whl", hash = "sha256:fcdf84ba3ed8124eb7234adfbb8792f311991cbf8aed1cad4b1b1a7ee08380c1"}, + {file = "numba-0.56.4-cp37-cp37m-win_amd64.whl", hash = "sha256:42f9e1be942b215df7e6cc9948cf9c15bb8170acc8286c063a9e57994ef82fd1"}, + {file = "numba-0.56.4-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:553da2ce74e8862e18a72a209ed3b6d2924403bdd0fb341fa891c6455545ba7c"}, + {file = "numba-0.56.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4373da9757049db7c90591e9ec55a2e97b2b36ba7ae3bf9c956a513374077470"}, + {file = "numba-0.56.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3a993349b90569518739009d8f4b523dfedd7e0049e6838c0e17435c3e70dcc4"}, + {file = "numba-0.56.4-cp38-cp38-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:720886b852a2d62619ae3900fe71f1852c62db4f287d0c275a60219e1643fc04"}, + {file = "numba-0.56.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e64d338b504c9394a4a34942df4627e1e6cb07396ee3b49fe7b8d6420aa5104f"}, + {file = "numba-0.56.4-cp38-cp38-win32.whl", hash = "sha256:03fe94cd31e96185cce2fae005334a8cc712fc2ba7756e52dff8c9400718173f"}, + {file = "numba-0.56.4-cp38-cp38-win_amd64.whl", hash = "sha256:91f021145a8081f881996818474ef737800bcc613ffb1e618a655725a0f9e246"}, + {file = "numba-0.56.4-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:d0ae9270a7a5cc0ede63cd234b4ff1ce166c7a749b91dbbf45e0000c56d3eade"}, + {file = "numba-0.56.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c75e8a5f810ce80a0cfad6e74ee94f9fde9b40c81312949bf356b7304ef20740"}, + {file = "numba-0.56.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a12ef323c0f2101529d455cfde7f4135eaa147bad17afe10b48634f796d96abd"}, + {file = "numba-0.56.4-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:03634579d10a6129181129de293dd6b5eaabee86881369d24d63f8fe352dd6cb"}, + {file = "numba-0.56.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0240f9026b015e336069329839208ebd70ec34ae5bfbf402e4fcc8e06197528e"}, + {file = "numba-0.56.4-cp39-cp39-win32.whl", hash = "sha256:14dbbabf6ffcd96ee2ac827389afa59a70ffa9f089576500434c34abf9b054a4"}, + {file = "numba-0.56.4-cp39-cp39-win_amd64.whl", hash = "sha256:0da583c532cd72feefd8e551435747e0e0fbb3c0530357e6845fcc11e38d6aea"}, + {file = "numba-0.56.4.tar.gz", hash = "sha256:32d9fef412c81483d7efe0ceb6cf4d3310fde8b624a9cecca00f790573ac96ee"}, +] + +[package.dependencies] +llvmlite = ">=0.39.0dev0,<0.40" +numpy = ">=1.18,<1.24" +setuptools = "*" + +[[package]] +name = "numpy" +version = "1.23.5" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.23.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63"}, + {file = "numpy-1.23.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d"}, + {file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7903ba8ab592b82014713c491f6c5d3a1cde5b4a3bf116404e08f5b52f6daf43"}, + {file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e05b1c973a9f858c74367553e236f287e749465f773328c8ef31abe18f691e1"}, + {file = "numpy-1.23.5-cp310-cp310-win32.whl", hash = "sha256:522e26bbf6377e4d76403826ed689c295b0b238f46c28a7251ab94716da0b280"}, + {file = "numpy-1.23.5-cp310-cp310-win_amd64.whl", hash = "sha256:dbee87b469018961d1ad79b1a5d50c0ae850000b639bcb1b694e9981083243b6"}, + {file = "numpy-1.23.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ce571367b6dfe60af04e04a1834ca2dc5f46004ac1cc756fb95319f64c095a96"}, + {file = "numpy-1.23.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56e454c7833e94ec9769fa0f86e6ff8e42ee38ce0ce1fa4cbb747ea7e06d56aa"}, + {file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5039f55555e1eab31124a5768898c9e22c25a65c1e0037f4d7c495a45778c9f2"}, + {file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387"}, + {file = "numpy-1.23.5-cp311-cp311-win32.whl", hash = "sha256:b2a9ab7c279c91974f756c84c365a669a887efa287365a8e2c418f8b3ba73fb0"}, + {file = "numpy-1.23.5-cp311-cp311-win_amd64.whl", hash = "sha256:0cbe9848fad08baf71de1a39e12d1b6310f1d5b2d0ea4de051058e6e1076852d"}, + {file = "numpy-1.23.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f063b69b090c9d918f9df0a12116029e274daf0181df392839661c4c7ec9018a"}, + {file = "numpy-1.23.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0aaee12d8883552fadfc41e96b4c82ee7d794949e2a7c3b3a7201e968c7ecab9"}, + {file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92c8c1e89a1f5028a4c6d9e3ccbe311b6ba53694811269b992c0b224269e2398"}, + {file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d208a0f8729f3fb790ed18a003f3a57895b989b40ea4dce4717e9cf4af62c6bb"}, + {file = "numpy-1.23.5-cp38-cp38-win32.whl", hash = "sha256:06005a2ef6014e9956c09ba07654f9837d9e26696a0470e42beedadb78c11b07"}, + {file = "numpy-1.23.5-cp38-cp38-win_amd64.whl", hash = "sha256:ca51fcfcc5f9354c45f400059e88bc09215fb71a48d3768fb80e357f3b457e1e"}, + {file = "numpy-1.23.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8969bfd28e85c81f3f94eb4a66bc2cf1dbdc5c18efc320af34bffc54d6b1e38f"}, + {file = "numpy-1.23.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7ac231a08bb37f852849bbb387a20a57574a97cfc7b6cabb488a4fc8be176de"}, + {file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf837dc63ba5c06dc8797c398db1e223a466c7ece27a1f7b5232ba3466aafe3d"}, + {file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33161613d2269025873025b33e879825ec7b1d831317e68f4f2f0f84ed14c719"}, + {file = "numpy-1.23.5-cp39-cp39-win32.whl", hash = "sha256:af1da88f6bc3d2338ebbf0e22fe487821ea4d8e89053e25fa59d1d79786e7481"}, + {file = "numpy-1.23.5-cp39-cp39-win_amd64.whl", hash = "sha256:09b7847f7e83ca37c6e627682f145856de331049013853f344f37b0c9690e3df"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:abdde9f795cf292fb9651ed48185503a2ff29be87770c3b8e2a14b0cd7aa16f8"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9a909a8bae284d46bbfdefbdd4a262ba19d3bc9921b1e76126b1d21c3c34135"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:01dd17cbb340bf0fc23981e52e1d18a9d4050792e8fb8363cecbf066a84b827d"}, + {file = "numpy-1.23.5.tar.gz", hash = "sha256:1b1766d6f397c18153d40015ddfc79ddb715cabadc04d2d228d4e5a8bc4ded1a"}, +] + +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + +[[package]] +name = "opt-einsum" +version = "3.3.0" +description = "Optimizing numpys einsum function" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "opt_einsum-3.3.0-py3-none-any.whl", hash = "sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147"}, + {file = "opt_einsum-3.3.0.tar.gz", hash = "sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549"}, +] + +[package.dependencies] +numpy = ">=1.7" + +[package.extras] +docs = ["numpydoc", "sphinx (==1.2.3)", "sphinx-rtd-theme", "sphinxcontrib-napoleon"] +tests = ["pytest", "pytest-cov", "pytest-pep8"] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pandas" +version = "2.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] + +[[package]] +name = "partd" +version = "1.4.0" +description = "Appendable key-value storage" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "partd-1.4.0-py3-none-any.whl", hash = "sha256:7a63529348cf0dff14b986db641cd1b83c16b5cb9fc647c2851779db03282ef8"}, + {file = "partd-1.4.0.tar.gz", hash = "sha256:aa0ff35dbbcc807ae374db56332f4c1b39b46f67bf2975f5151e0b4186aed0d5"}, +] + +[package.dependencies] +locket = "*" +toolz = "*" + +[package.extras] +complete = ["blosc", "numpy (>=1.9.0)", "pandas (>=0.19.0)", "pyzmq"] + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, +] + +[[package]] +name = "pillow" +version = "10.0.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, + {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, + {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, + {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, + {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, + {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, + {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, + {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, + {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "platformdirs" +version = "3.8.1" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.8.1-py3-none-any.whl", hash = "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c"}, + {file = "platformdirs-3.8.1.tar.gz", hash = "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528"}, +] + +[package.extras] +docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] + +[[package]] +name = "pluggy" +version = "1.2.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "protobuf" +version = "3.19.6" +description = "Protocol Buffers" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "protobuf-3.19.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:010be24d5a44be7b0613750ab40bc8b8cedc796db468eae6c779b395f50d1fa1"}, + {file = "protobuf-3.19.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11478547958c2dfea921920617eb457bc26867b0d1aa065ab05f35080c5d9eb6"}, + {file = "protobuf-3.19.6-cp310-cp310-win32.whl", hash = "sha256:559670e006e3173308c9254d63facb2c03865818f22204037ab76f7a0ff70b5f"}, + {file = "protobuf-3.19.6-cp310-cp310-win_amd64.whl", hash = "sha256:347b393d4dd06fb93a77620781e11c058b3b0a5289262f094379ada2920a3730"}, + {file = "protobuf-3.19.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a8ce5ae0de28b51dff886fb922012dad885e66176663950cb2344c0439ecb473"}, + {file = "protobuf-3.19.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b0d02163c4e67279ddb6dc25e063db0130fc299aefabb5d481053509fae5c8"}, + {file = "protobuf-3.19.6-cp36-cp36m-win32.whl", hash = "sha256:30f5370d50295b246eaa0296533403961f7e64b03ea12265d6dfce3a391d8992"}, + {file = "protobuf-3.19.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0c0714b025ec057b5a7600cb66ce7c693815f897cfda6d6efb58201c472e3437"}, + {file = "protobuf-3.19.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5057c64052a1f1dd7d4450e9aac25af6bf36cfbfb3a1cd89d16393a036c49157"}, + {file = "protobuf-3.19.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:bb6776bd18f01ffe9920e78e03a8676530a5d6c5911934c6a1ac6eb78973ecb6"}, + {file = "protobuf-3.19.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84a04134866861b11556a82dd91ea6daf1f4925746b992f277b84013a7cc1229"}, + {file = "protobuf-3.19.6-cp37-cp37m-win32.whl", hash = "sha256:4bc98de3cdccfb5cd769620d5785b92c662b6bfad03a202b83799b6ed3fa1fa7"}, + {file = "protobuf-3.19.6-cp37-cp37m-win_amd64.whl", hash = "sha256:aa3b82ca1f24ab5326dcf4ea00fcbda703e986b22f3d27541654f749564d778b"}, + {file = "protobuf-3.19.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2b2d2913bcda0e0ec9a784d194bc490f5dc3d9d71d322d070b11a0ade32ff6ba"}, + {file = "protobuf-3.19.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d0b635cefebd7a8a0f92020562dead912f81f401af7e71f16bf9506ff3bdbb38"}, + {file = "protobuf-3.19.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a552af4dc34793803f4e735aabe97ffc45962dfd3a237bdde242bff5a3de684"}, + {file = "protobuf-3.19.6-cp38-cp38-win32.whl", hash = "sha256:0469bc66160180165e4e29de7f445e57a34ab68f49357392c5b2f54c656ab25e"}, + {file = "protobuf-3.19.6-cp38-cp38-win_amd64.whl", hash = "sha256:91d5f1e139ff92c37e0ff07f391101df77e55ebb97f46bbc1535298d72019462"}, + {file = "protobuf-3.19.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c0ccd3f940fe7f3b35a261b1dd1b4fc850c8fde9f74207015431f174be5976b3"}, + {file = "protobuf-3.19.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:30a15015d86b9c3b8d6bf78d5b8c7749f2512c29f168ca259c9d7727604d0e39"}, + {file = "protobuf-3.19.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:878b4cd080a21ddda6ac6d1e163403ec6eea2e206cf225982ae04567d39be7b0"}, + {file = "protobuf-3.19.6-cp39-cp39-win32.whl", hash = "sha256:5a0d7539a1b1fb7e76bf5faa0b44b30f812758e989e59c40f77a7dab320e79b9"}, + {file = "protobuf-3.19.6-cp39-cp39-win_amd64.whl", hash = "sha256:bbf5cea5048272e1c60d235c7bd12ce1b14b8a16e76917f371c718bd3005f045"}, + {file = "protobuf-3.19.6-py2.py3-none-any.whl", hash = "sha256:14082457dc02be946f60b15aad35e9f5c69e738f80ebbc0900a19bc83734a5a4"}, + {file = "protobuf-3.19.6.tar.gz", hash = "sha256:5f5540d57a43042389e87661c6eaa50f47c19c6176e8cf1c4f287aeefeccb5c4"}, +] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] + +[[package]] +name = "pyaml" +version = "23.7.0" +description = "PyYAML-based module to produce a bit more pretty and readable YAML-serialized data" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "pyaml-23.7.0-py3-none-any.whl", hash = "sha256:0a37018282545ccc31faecbe138fda4d89e236af04d691cfb5af00cd60089345"}, + {file = "pyaml-23.7.0.tar.gz", hash = "sha256:0c510bbb8938309400e0b1e47ac16fd90e56d652805a93417128786718f33546"}, +] + +[package.dependencies] +PyYAML = "*" + +[package.extras] +anchors = ["unidecode"] + +[[package]] +name = "pyarrow" +version = "12.0.1" +description = "Python library for Apache Arrow" +category = "main" +optional = true +python-versions = ">=3.7" +files = [ + {file = "pyarrow-12.0.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:6d288029a94a9bb5407ceebdd7110ba398a00412c5b0155ee9813a40d246c5df"}, + {file = "pyarrow-12.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345e1828efdbd9aa4d4de7d5676778aba384a2c3add896d995b23d368e60e5af"}, + {file = "pyarrow-12.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d6009fdf8986332b2169314da482baed47ac053311c8934ac6651e614deacd6"}, + {file = "pyarrow-12.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d3c4cbbf81e6dd23fe921bc91dc4619ea3b79bc58ef10bce0f49bdafb103daf"}, + {file = "pyarrow-12.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:cdacf515ec276709ac8042c7d9bd5be83b4f5f39c6c037a17a60d7ebfd92c890"}, + {file = "pyarrow-12.0.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:749be7fd2ff260683f9cc739cb862fb11be376de965a2a8ccbf2693b098db6c7"}, + {file = "pyarrow-12.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6895b5fb74289d055c43db3af0de6e16b07586c45763cb5e558d38b86a91e3a7"}, + {file = "pyarrow-12.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1887bdae17ec3b4c046fcf19951e71b6a619f39fa674f9881216173566c8f718"}, + {file = "pyarrow-12.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2c9cb8eeabbadf5fcfc3d1ddea616c7ce893db2ce4dcef0ac13b099ad7ca082"}, + {file = "pyarrow-12.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:ce4aebdf412bd0eeb800d8e47db854f9f9f7e2f5a0220440acf219ddfddd4f63"}, + {file = "pyarrow-12.0.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:e0d8730c7f6e893f6db5d5b86eda42c0a130842d101992b581e2138e4d5663d3"}, + {file = "pyarrow-12.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43364daec02f69fec89d2315f7fbfbeec956e0d991cbbef471681bd77875c40f"}, + {file = "pyarrow-12.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:051f9f5ccf585f12d7de836e50965b3c235542cc896959320d9776ab93f3b33d"}, + {file = "pyarrow-12.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:be2757e9275875d2a9c6e6052ac7957fbbfc7bc7370e4a036a9b893e96fedaba"}, + {file = "pyarrow-12.0.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:cf812306d66f40f69e684300f7af5111c11f6e0d89d6b733e05a3de44961529d"}, + {file = "pyarrow-12.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:459a1c0ed2d68671188b2118c63bac91eaef6fc150c77ddd8a583e3c795737bf"}, + {file = "pyarrow-12.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85e705e33eaf666bbe508a16fd5ba27ca061e177916b7a317ba5a51bee43384c"}, + {file = "pyarrow-12.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9120c3eb2b1f6f516a3b7a9714ed860882d9ef98c4b17edcdc91d95b7528db60"}, + {file = "pyarrow-12.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:c780f4dc40460015d80fcd6a6140de80b615349ed68ef9adb653fe351778c9b3"}, + {file = "pyarrow-12.0.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:a3c63124fc26bf5f95f508f5d04e1ece8cc23a8b0af2a1e6ab2b1ec3fdc91b24"}, + {file = "pyarrow-12.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b13329f79fa4472324f8d32dc1b1216616d09bd1e77cfb13104dec5463632c36"}, + {file = "pyarrow-12.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb656150d3d12ec1396f6dde542db1675a95c0cc8366d507347b0beed96e87ca"}, + {file = "pyarrow-12.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6251e38470da97a5b2e00de5c6a049149f7b2bd62f12fa5dbb9ac674119ba71a"}, + {file = "pyarrow-12.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:3de26da901216149ce086920547dfff5cd22818c9eab67ebc41e863a5883bac7"}, + {file = "pyarrow-12.0.1.tar.gz", hash = "sha256:cce317fc96e5b71107bf1f9f184d5e54e2bd14bbf3f9a3d62819961f0af86fec"}, +] + +[package.dependencies] +numpy = ">=1.16.6" + +[[package]] +name = "pyasn1" +version = "0.5.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, + {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.3.0" +description = "A collection of ASN.1-based protocols modules" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, + {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.6.0" + +[[package]] +name = "pybtex" +version = "0.24.0" +description = "A BibTeX-compatible bibliography processor in Python" +category = "dev" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" +files = [ + {file = "pybtex-0.24.0-py2.py3-none-any.whl", hash = "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f"}, + {file = "pybtex-0.24.0.tar.gz", hash = "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755"}, +] + +[package.dependencies] +latexcodec = ">=1.0.4" +PyYAML = ">=3.01" +six = "*" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "pybtex-docutils" +version = "1.0.2" +description = "A docutils backend for pybtex." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pybtex-docutils-1.0.2.tar.gz", hash = "sha256:43aa353b6d498fd5ac30f0073a98e332d061d34fe619d3d50d1761f8fd4aa016"}, + {file = "pybtex_docutils-1.0.2-py3-none-any.whl", hash = "sha256:6f9e3c25a37bcaac8c4f69513272706ec6253bb708a93d8b4b173f43915ba239"}, +] + +[package.dependencies] +docutils = ">=0.8" +pybtex = ">=0.16" + +[[package]] +name = "pygments" +version = "2.15.1" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, + {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pylint" +version = "2.10.0" +description = "python code static checker" +category = "dev" +optional = false +python-versions = "~=3.6" +files = [ + {file = "pylint-2.10.0-py3-none-any.whl", hash = "sha256:2d01c6de5ea20443e3f7ed8ae285f75b2d4da92e840f10118ddb7da18a1e09df"}, + {file = "pylint-2.10.0.tar.gz", hash = "sha256:dcf4a5dd7bc98c68790323f783d792423c1946e7a4a195e44d7b2c2d386f457d"}, +] + +[package.dependencies] +appdirs = ">=1.4.0" +astroid = ">=2.7.2,<2.8" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.7" +toml = ">=0.7.1" + +[[package]] +name = "pyparsing" +version = "3.1.0" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.0-py3-none-any.whl", hash = "sha256:d554a96d1a7d3ddaf7183104485bc19fd80543ad6ac5bdb6426719d766fb06c1"}, + {file = "pyparsing-3.1.0.tar.gz", hash = "sha256:edb662d6fe322d6e990b1594b5feaeadf806803359e3d4d42f11e295e588f0ea"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2023.3" +description = "World timezone definitions, modern and historical" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, +] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] + +[[package]] +name = "ray" +version = "2.5.0" +description = "Ray provides a simple, universal API for building distributed applications." +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "ray-2.5.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:d1bebc874e896880c1215f4c1a11697ada49fa1595d6d99d7c5b4dc03030df36"}, + {file = "ray-2.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0285df2d24cacc36ca64b7852178a9bf37e3fc88545752fc2b46c27396965c1"}, + {file = "ray-2.5.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:38935d46c2597c1d1f113e1c8f88e2716c67052c480de5b2a0265e0a1a5ce88f"}, + {file = "ray-2.5.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:d53a07c9a9dbc134945a26980f557e9ff0f591bf8cabed1a6ebf921768d1c8bd"}, + {file = "ray-2.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:ef26ba24461dad98365b48ef01e27e70bc9737f4cf4734115804153d7d9195dc"}, + {file = "ray-2.5.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d714175a5000ca91f82646a9b72521118bb6d2db5568e1b7ae9ceb64769716b6"}, + {file = "ray-2.5.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:0cde929e63497ed5f1c8626e5ccf7595ef6acaf1e7e270ad7c12f8e1c7695244"}, + {file = "ray-2.5.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:7e5512abf62c05c9ff90b1c89a4e0f2e45ee00e73f816eb8265e3ebd92fe4064"}, + {file = "ray-2.5.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3bf36beb213f89c0eb1ec5ac6ffddc8f53e616be745167f00ca017abd8672a2d"}, + {file = "ray-2.5.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:59c2448b07f45d9a9d8e594bb5337bd35a5fea04e42cb4211a3346c2c0d066b0"}, + {file = "ray-2.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:63008dd659d9ef25b0e20f0e1a285e8266e0af68b1178bca1b6ae43e49a68104"}, + {file = "ray-2.5.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:e9464e93d6b72e0da69b9c5ab0501cc40f2db14801e22c6b97fa4e8039647892"}, + {file = "ray-2.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7dc00fac119bfa1c2f8ac456d50a728346d6f2722fb7a21bf70841fc7476c285"}, + {file = "ray-2.5.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d76051519bd4ae39fda4a87536978cafdebf2843c1c29a9f734c503d8ea676cd"}, + {file = "ray-2.5.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:9a8e06dc5d4201129c28b6768a971c474b82a23935b2e40461ffc7f1c2f4942a"}, + {file = "ray-2.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:849014b62ca50ff106b7a5d41430346e2762b1c4c803673af076209925b8f912"}, + {file = "ray-2.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:a1b52c12a3349d8e37357df31438b6f1b12c7719ef41bdf5089fc7e78e8ab212"}, + {file = "ray-2.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25f3d50c27c4c4756259d093d152381c6604bb96684a0cf43c55ddcc2eb73f79"}, + {file = "ray-2.5.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1cb4f6ef9cfdb69d2ae582f357e977527944390e2f5cbbf51efd8252ed4c9a11"}, + {file = "ray-2.5.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:662cff303c086369a29283badcd7445b7f911874d8407b2c589b1ccbf6028d2e"}, + {file = "ray-2.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2cea10981dad7cfd187edf5e225a667eb114269afc5f2321b52113ef2d86123"}, +] + +[package.dependencies] +aiosignal = "*" +attrs = "*" +click = ">=7.0" +filelock = "*" +frozenlist = "*" +grpcio = [ + {version = ">=1.32.0,<=1.51.3", markers = "python_version < \"3.10\" and sys_platform != \"darwin\""}, + {version = ">=1.32.0,<=1.49.1", markers = "python_version < \"3.10\" and sys_platform == \"darwin\""}, + {version = ">=1.42.0,<=1.51.3", markers = "python_version >= \"3.10\" and sys_platform != \"darwin\""}, + {version = ">=1.42.0,<=1.49.1", markers = "python_version >= \"3.10\" and sys_platform == \"darwin\""}, +] +jsonschema = "*" +msgpack = ">=1.0.0,<2.0.0" +numpy = {version = ">=1.19.3", markers = "python_version >= \"3.9\""} +packaging = "*" +pandas = {version = "*", optional = true, markers = "extra == \"tune\""} +protobuf = ">=3.15.3,<3.19.5 || >3.19.5" +pyarrow = {version = ">=6.0.1", optional = true, markers = "extra == \"tune\""} +pyyaml = "*" +requests = "*" +tensorboardX = {version = ">=1.9", optional = true, markers = "extra == \"tune\""} + +[package.extras] +air = ["aiohttp (>=3.7)", "aiohttp-cors", "aiorwlock", "colorful", "fastapi", "fsspec", "gpustat (>=1.0.0)", "numpy (>=1.20)", "opencensus", "pandas", "pandas (>=1.3)", "prometheus-client (>=0.7.1)", "py-spy (>=0.2.0)", "pyarrow (>=6.0.1)", "pydantic", "requests", "smart-open", "starlette", "tensorboardX (>=1.9)", "uvicorn", "virtualenv (>=20.0.24,<20.21.1)"] +all = ["aiohttp (>=3.7)", "aiohttp-cors", "aiorwlock", "colorful", "dm-tree", "fastapi", "fsspec", "gpustat (>=1.0.0)", "gymnasium (==0.26.3)", "kubernetes", "lz4", "numpy (>=1.20)", "opencensus", "opentelemetry-api", "opentelemetry-exporter-otlp", "opentelemetry-sdk", "pandas", "pandas (>=1.3)", "prometheus-client (>=0.7.1)", "py-spy (>=0.2.0)", "pyarrow (>=6.0.1)", "pydantic", "pyyaml", "ray-cpp (==2.5.0)", "requests", "rich", "scikit-image", "scipy", "smart-open", "starlette", "tensorboardX (>=1.9)", "typer", "urllib3", "uvicorn", "virtualenv (>=20.0.24,<20.21.1)"] +cpp = ["ray-cpp (==2.5.0)"] +data = ["fsspec", "numpy (>=1.20)", "pandas (>=1.3)", "pyarrow (>=6.0.1)"] +default = ["aiohttp (>=3.7)", "aiohttp-cors", "colorful", "gpustat (>=1.0.0)", "opencensus", "prometheus-client (>=0.7.1)", "py-spy (>=0.2.0)", "pydantic", "requests", "smart-open", "virtualenv (>=20.0.24,<20.21.1)"] +k8s = ["kubernetes", "urllib3"] +observability = ["opentelemetry-api", "opentelemetry-exporter-otlp", "opentelemetry-sdk"] +rllib = ["dm-tree", "gymnasium (==0.26.3)", "lz4", "pandas", "pyarrow (>=6.0.1)", "pyyaml", "requests", "rich", "scikit-image", "scipy", "tensorboardX (>=1.9)", "typer"] +serve = ["aiohttp (>=3.7)", "aiohttp-cors", "aiorwlock", "colorful", "fastapi", "gpustat (>=1.0.0)", "opencensus", "prometheus-client (>=0.7.1)", "py-spy (>=0.2.0)", "pydantic", "requests", "smart-open", "starlette", "uvicorn", "virtualenv (>=20.0.24,<20.21.1)"] +train = ["pandas", "pyarrow (>=6.0.1)", "requests", "tensorboardX (>=1.9)"] +tune = ["pandas", "pyarrow (>=6.0.1)", "requests", "tensorboardX (>=1.9)"] + +[[package]] +name = "referencing" +version = "0.29.1" +description = "JSON Referencing + Python" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "referencing-0.29.1-py3-none-any.whl", hash = "sha256:d3c8f323ee1480095da44d55917cfb8278d73d6b4d5f677e3e40eb21314ac67f"}, + {file = "referencing-0.29.1.tar.gz", hash = "sha256:90cb53782d550ba28d2166ef3f55731f38397def8832baac5d45235f1995e35e"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-oauthlib" +version = "1.3.1" +description = "OAuthlib authentication support for Requests." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, + {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + +[[package]] +name = "rich" +version = "10.15.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" +optional = false +python-versions = ">=3.6.2,<4.0.0" +files = [ + {file = "rich-10.15.1-py3-none-any.whl", hash = "sha256:a59fb2721c52c5061ac65f318c0afb709e098b1ab6ce5813ea38982654c4b6ee"}, + {file = "rich-10.15.1.tar.gz", hash = "sha256:93d0ea3c35ecfd8703dbe52b76885e224ad8d68c7766c921c726b14b22a57b7d"}, +] + +[package.dependencies] +colorama = ">=0.4.0,<0.5.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + +[[package]] +name = "rpds-py" +version = "0.8.10" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.8.10-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93d06cccae15b3836247319eee7b6f1fdcd6c10dabb4e6d350d27bd0bdca2711"}, + {file = "rpds_py-0.8.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3816a890a6a9e9f1de250afa12ca71c9a7a62f2b715a29af6aaee3aea112c181"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7c6304b894546b5a6bdc0fe15761fa53fe87d28527a7142dae8de3c663853e1"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad3bfb44c8840fb4be719dc58e229f435e227fbfbe133dc33f34981ff622a8f8"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14f1c356712f66653b777ecd8819804781b23dbbac4eade4366b94944c9e78ad"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82bb361cae4d0a627006dadd69dc2f36b7ad5dc1367af9d02e296ec565248b5b"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e3c4f2a8e3da47f850d7ea0d7d56720f0f091d66add889056098c4b2fd576c"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15a90d0ac11b4499171067ae40a220d1ca3cb685ec0acc356d8f3800e07e4cb8"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:70bb9c8004b97b4ef7ae56a2aa56dfaa74734a0987c78e7e85f00004ab9bf2d0"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d64f9f88d5203274a002b54442cafc9c7a1abff2a238f3e767b70aadf919b451"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ccbbd276642788c4376fbe8d4e6c50f0fb4972ce09ecb051509062915891cbf0"}, + {file = "rpds_py-0.8.10-cp310-none-win32.whl", hash = "sha256:fafc0049add8043ad07ab5382ee80d80ed7e3699847f26c9a5cf4d3714d96a84"}, + {file = "rpds_py-0.8.10-cp310-none-win_amd64.whl", hash = "sha256:915031002c86a5add7c6fd4beb601b2415e8a1c956590a5f91d825858e92fe6e"}, + {file = "rpds_py-0.8.10-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:84eb541a44f7a18f07a6bfc48b95240739e93defe1fdfb4f2a295f37837945d7"}, + {file = "rpds_py-0.8.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f59996d0550894affaad8743e97b9b9c98f638b221fac12909210ec3d9294786"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9adb5664b78fcfcd830000416c8cc69853ef43cb084d645b3f1f0296edd9bae"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f96f3f98fbff7af29e9edf9a6584f3c1382e7788783d07ba3721790625caa43e"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:376b8de737401050bd12810003d207e824380be58810c031f10ec563ff6aef3d"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d1c2bc319428d50b3e0fa6b673ab8cc7fa2755a92898db3a594cbc4eeb6d1f7"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73a1e48430f418f0ac3dfd87860e4cc0d33ad6c0f589099a298cb53724db1169"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134ec8f14ca7dbc6d9ae34dac632cdd60939fe3734b5d287a69683c037c51acb"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4b519bac7c09444dd85280fd60f28c6dde4389c88dddf4279ba9b630aca3bbbe"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9cd57981d9fab04fc74438d82460f057a2419974d69a96b06a440822d693b3c0"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:69d089c026f6a8b9d64a06ff67dc3be196707b699d7f6ca930c25f00cf5e30d8"}, + {file = "rpds_py-0.8.10-cp311-none-win32.whl", hash = "sha256:220bdcad2d2936f674650d304e20ac480a3ce88a40fe56cd084b5780f1d104d9"}, + {file = "rpds_py-0.8.10-cp311-none-win_amd64.whl", hash = "sha256:6c6a0225b8501d881b32ebf3f5807a08ad3685b5eb5f0a6bfffd3a6e039b2055"}, + {file = "rpds_py-0.8.10-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:e3d0cd3dff0e7638a7b5390f3a53057c4e347f4ef122ee84ed93fc2fb7ea4aa2"}, + {file = "rpds_py-0.8.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d77dff3a5aa5eedcc3da0ebd10ff8e4969bc9541aa3333a8d41715b429e99f47"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41c89a366eae49ad9e65ed443a8f94aee762931a1e3723749d72aeac80f5ef2f"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3793c21494bad1373da517001d0849eea322e9a049a0e4789e50d8d1329df8e7"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:805a5f3f05d186c5d50de2e26f765ba7896d0cc1ac5b14ffc36fae36df5d2f10"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b01b39ad5411563031ea3977bbbc7324d82b088e802339e6296f082f78f6115c"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f1e860be21f3e83011116a65e7310486300e08d9a3028e73e8d13bb6c77292"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a13c8e56c46474cd5958d525ce6a9996727a83d9335684e41f5192c83deb6c58"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:93d99f957a300d7a4ced41615c45aeb0343bb8f067c42b770b505de67a132346"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:148b0b38d719c0760e31ce9285a9872972bdd7774969a4154f40c980e5beaca7"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3cc5e5b5514796f45f03a568981971b12a3570f3de2e76114f7dc18d4b60a3c4"}, + {file = "rpds_py-0.8.10-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e8e24b210a4deb5a7744971f8f77393005bae7f873568e37dfd9effe808be7f7"}, + {file = "rpds_py-0.8.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b41941583adce4242af003d2a8337b066ba6148ca435f295f31ac6d9e4ea2722"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c490204e16bca4f835dba8467869fe7295cdeaa096e4c5a7af97f3454a97991"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee45cd1d84beed6cbebc839fd85c2e70a3a1325c8cfd16b62c96e2ffb565eca"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a8ca409f1252e1220bf09c57290b76cae2f14723746215a1e0506472ebd7bdf"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96b293c0498c70162effb13100624c5863797d99df75f2f647438bd10cbf73e4"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4627520a02fccbd324b33c7a83e5d7906ec746e1083a9ac93c41ac7d15548c7"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e39d7ab0c18ac99955b36cd19f43926450baba21e3250f053e0704d6ffd76873"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ba9f1d1ebe4b63801977cec7401f2d41e888128ae40b5441270d43140efcad52"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:802f42200d8caf7f25bbb2a6464cbd83e69d600151b7e3b49f49a47fa56b0a38"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d19db6ba816e7f59fc806c690918da80a7d186f00247048cd833acdab9b4847b"}, + {file = "rpds_py-0.8.10-cp38-none-win32.whl", hash = "sha256:7947e6e2c2ad68b1c12ee797d15e5f8d0db36331200b0346871492784083b0c6"}, + {file = "rpds_py-0.8.10-cp38-none-win_amd64.whl", hash = "sha256:fa326b3505d5784436d9433b7980171ab2375535d93dd63fbcd20af2b5ca1bb6"}, + {file = "rpds_py-0.8.10-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7b38a9ac96eeb6613e7f312cd0014de64c3f07000e8bf0004ad6ec153bac46f8"}, + {file = "rpds_py-0.8.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d42e83ddbf3445e6514f0aff96dca511421ed0392d9977d3990d9f1ba6753c"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b21575031478609db6dbd1f0465e739fe0e7f424a8e7e87610a6c7f68b4eb16"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:574868858a7ff6011192c023a5289158ed20e3f3b94b54f97210a773f2f22921"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae40f4a70a1f40939d66ecbaf8e7edc144fded190c4a45898a8cfe19d8fc85ea"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f7ee4dc86db7af3bac6d2a2cedbecb8e57ce4ed081f6464510e537589f8b1e"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:695f642a3a5dbd4ad2ffbbacf784716ecd87f1b7a460843b9ddf965ccaeafff4"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f43ab4cb04bde6109eb2555528a64dfd8a265cc6a9920a67dcbde13ef53a46c8"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a11ab0d97be374efd04f640c04fe5c2d3dabc6dfb998954ea946ee3aec97056d"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:92cf5b3ee60eef41f41e1a2cabca466846fb22f37fc580ffbcb934d1bcab225a"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ceaac0c603bf5ac2f505a78b2dcab78d3e6b706be6596c8364b64cc613d208d2"}, + {file = "rpds_py-0.8.10-cp39-none-win32.whl", hash = "sha256:dd4f16e57c12c0ae17606c53d1b57d8d1c8792efe3f065a37cb3341340599d49"}, + {file = "rpds_py-0.8.10-cp39-none-win_amd64.whl", hash = "sha256:c03a435d26c3999c2a8642cecad5d1c4d10c961817536af52035f6f4ee2f5dd0"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0da53292edafecba5e1d8c1218f99babf2ed0bf1c791d83c0ab5c29b57223068"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d20a8ed227683401cc508e7be58cba90cc97f784ea8b039c8cd01111e6043e0"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97cab733d303252f7c2f7052bf021a3469d764fc2b65e6dbef5af3cbf89d4892"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c398fda6df361a30935ab4c4bccb7f7a3daef2964ca237f607c90e9f3fdf66f"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2eb4b08c45f8f8d8254cdbfacd3fc5d6b415d64487fb30d7380b0d0569837bf1"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7dfb1cbb895810fa2b892b68153c17716c6abaa22c7dc2b2f6dcf3364932a1c"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89c92b74e8bf6f53a6f4995fd52f4bd510c12f103ee62c99e22bc9e05d45583c"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9c0683cb35a9b5881b41bc01d5568ffc667910d9dbc632a1fba4e7d59e98773"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0eeb2731708207d0fe2619afe6c4dc8cb9798f7de052da891de5f19c0006c315"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:7495010b658ec5b52835f21d8c8b1a7e52e194c50f095d4223c0b96c3da704b1"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c72ebc22e70e04126158c46ba56b85372bc4d54d00d296be060b0db1671638a4"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2cd3045e7f6375dda64ed7db1c5136826facb0159ea982f77d9cf6125025bd34"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:2418cf17d653d24ffb8b75e81f9f60b7ba1b009a23298a433a4720b2a0a17017"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a2edf8173ac0c7a19da21bc68818be1321998528b5e3f748d6ee90c0ba2a1fd"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f29b8c55fd3a2bc48e485e37c4e2df3317f43b5cc6c4b6631c33726f52ffbb3"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a7d20c1cf8d7b3960c5072c265ec47b3f72a0c608a9a6ee0103189b4f28d531"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:521fc8861a86ae54359edf53a15a05fabc10593cea7b3357574132f8427a5e5a"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5c191713e98e7c28800233f039a32a42c1a4f9a001a8a0f2448b07391881036"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:083df0fafe199371206111583c686c985dddaf95ab3ee8e7b24f1fda54515d09"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ed41f3f49507936a6fe7003985ea2574daccfef999775525d79eb67344e23767"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:2614c2732bf45de5c7f9e9e54e18bc78693fa2f635ae58d2895b7965e470378c"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c60528671d9d467009a6ec284582179f6b88651e83367d0ab54cb739021cd7de"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ee744fca8d1ea822480a2a4e7c5f2e1950745477143668f0b523769426060f29"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a38b9f526d0d6cbdaa37808c400e3d9f9473ac4ff64d33d9163fd05d243dbd9b"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60e0e86e870350e03b3e25f9b1dd2c6cc72d2b5f24e070249418320a6f9097b7"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f53f55a8852f0e49b0fc76f2412045d6ad9d5772251dea8f55ea45021616e7d5"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c493365d3fad241d52f096e4995475a60a80f4eba4d3ff89b713bc65c2ca9615"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:300eb606e6b94a7a26f11c8cc8ee59e295c6649bd927f91e1dbd37a4c89430b6"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a665f6f1a87614d1c3039baf44109094926dedf785e346d8b0a728e9cabd27a"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:927d784648211447201d4c6f1babddb7971abad922b32257ab74de2f2750fad0"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c200b30dd573afa83847bed7e3041aa36a8145221bf0cfdfaa62d974d720805c"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:08166467258fd0240a1256fce272f689f2360227ee41c72aeea103e9e4f63d2b"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:996cc95830de9bc22b183661d95559ec6b3cd900ad7bc9154c4cbf5be0c9b734"}, + {file = "rpds_py-0.8.10.tar.gz", hash = "sha256:13e643ce8ad502a0263397362fb887594b49cf84bf518d6038c16f235f2bcea4"}, +] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +category = "main" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "scikit-learn" +version = "1.3.0" +description = "A set of python modules for machine learning and data mining" +category = "main" +optional = true +python-versions = ">=3.8" +files = [ + {file = "scikit-learn-1.3.0.tar.gz", hash = "sha256:8be549886f5eda46436b6e555b0e4873b4f10aa21c07df45c4bc1735afbccd7a"}, + {file = "scikit_learn-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:981287869e576d42c682cf7ca96af0c6ac544ed9316328fd0d9292795c742cf5"}, + {file = "scikit_learn-1.3.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:436aaaae2c916ad16631142488e4c82f4296af2404f480e031d866863425d2a2"}, + {file = "scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7e28d8fa47a0b30ae1bd7a079519dd852764e31708a7804da6cb6f8b36e3630"}, + {file = "scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae80c08834a473d08a204d966982a62e11c976228d306a2648c575e3ead12111"}, + {file = "scikit_learn-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:552fd1b6ee22900cf1780d7386a554bb96949e9a359999177cf30211e6b20df6"}, + {file = "scikit_learn-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79970a6d759eb00a62266a31e2637d07d2d28446fca8079cf9afa7c07b0427f8"}, + {file = "scikit_learn-1.3.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:850a00b559e636b23901aabbe79b73dc604b4e4248ba9e2d6e72f95063765603"}, + {file = "scikit_learn-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee04835fb016e8062ee9fe9074aef9b82e430504e420bff51e3e5fffe72750ca"}, + {file = "scikit_learn-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d953531f5d9f00c90c34fa3b7d7cfb43ecff4c605dac9e4255a20b114a27369"}, + {file = "scikit_learn-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:151ac2bf65ccf363664a689b8beafc9e6aae36263db114b4ca06fbbbf827444a"}, + {file = "scikit_learn-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a885a9edc9c0a341cab27ec4f8a6c58b35f3d449c9d2503a6fd23e06bbd4f6a"}, + {file = "scikit_learn-1.3.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:9877af9c6d1b15486e18a94101b742e9d0d2f343d35a634e337411ddb57783f3"}, + {file = "scikit_learn-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c470f53cea065ff3d588050955c492793bb50c19a92923490d18fcb637f6383a"}, + {file = "scikit_learn-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd6e2d7389542eae01077a1ee0318c4fec20c66c957f45c7aac0c6eb0fe3c612"}, + {file = "scikit_learn-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:3a11936adbc379a6061ea32fa03338d4ca7248d86dd507c81e13af428a5bc1db"}, + {file = "scikit_learn-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:998d38fcec96584deee1e79cd127469b3ad6fefd1ea6c2dfc54e8db367eb396b"}, + {file = "scikit_learn-1.3.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:ded35e810438a527e17623ac6deae3b360134345b7c598175ab7741720d7ffa7"}, + {file = "scikit_learn-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e8102d5036e28d08ab47166b48c8d5e5810704daecf3a476a4282d562be9a28"}, + {file = "scikit_learn-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7617164951c422747e7c32be4afa15d75ad8044f42e7d70d3e2e0429a50e6718"}, + {file = "scikit_learn-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:1d54fb9e6038284548072df22fd34777e434153f7ffac72c8596f2d6987110dd"}, +] + +[package.dependencies] +joblib = ">=1.1.1" +numpy = ">=1.17.3" +scipy = ">=1.5.0" +threadpoolctl = ">=2.0.0" + +[package.extras] +benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.10.1)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] +tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.16.2)"] + +[[package]] +name = "scikit-optimize" +version = "0.9.0" +description = "Sequential model-based optimization toolbox." +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "scikit-optimize-0.9.0.tar.gz", hash = "sha256:77d8c9e64947fc9f5cc05bbc6aed7b8a9907871ae26fe11997fd67be90f26008"}, + {file = "scikit_optimize-0.9.0-py2.py3-none-any.whl", hash = "sha256:5a439a18232381fad4bda78e914b616416720708e67f123498d14bd2842d861a"}, +] + +[package.dependencies] +joblib = ">=0.11" +numpy = ">=1.13.3" +pyaml = ">=16.9" +scikit-learn = ">=0.20.0" +scipy = ">=0.19.1" + +[package.extras] +plots = ["matplotlib (>=2.0.0)"] + +[[package]] +name = "scipy" +version = "1.8.0" +description = "SciPy: Scientific Library for Python" +category = "main" +optional = false +python-versions = ">=3.8,<3.11" +files = [ + {file = "scipy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87b01c7d5761e8a266a0fbdb9d88dcba0910d63c1c671bdb4d99d29f469e9e03"}, + {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ae3e327da323d82e918e593460e23babdce40d7ab21490ddf9fc06dec6b91a18"}, + {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:16e09ef68b352d73befa8bcaf3ebe25d3941fe1a58c82909d5589856e6bc8174"}, + {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c17a1878d00a5dd2797ccd73623ceca9d02375328f6218ee6d921e1325e61aff"}, + {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937d28722f13302febde29847bbe554b89073fbb924a30475e5ed7b028898b5f"}, + {file = "scipy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:8f4d059a97b29c91afad46b1737274cb282357a305a80bdd9e8adf3b0ca6a3f0"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4"}, + {file = "scipy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59"}, + {file = "scipy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:de2e80ee1d925984c2504812a310841c241791c5279352be4707cdcd7c255039"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:c2bae431d127bf0b1da81fc24e4bba0a84d058e3a96b9dd6475dfcb3c5e8761e"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:723b9f878095ed994756fa4ee3060c450e2db0139c5ba248ee3f9628bd64e735"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:011d4386b53b933142f58a652aa0f149c9b9242abd4f900b9f4ea5fbafc86b89"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f0cd9c0bd374ef834ee1e0f0999678d49dcc400ea6209113d81528958f97c7"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3720d0124aced49f6f2198a6900304411dbbeed12f56951d7c66ebef05e3df6"}, + {file = "scipy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:3d573228c10a3a8c32b9037be982e6440e411b443a6267b067cac72f690b8d56"}, + {file = "scipy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb7088e89cd751acf66195d2f00cf009a1ea113f3019664032d9075b1e727b6c"}, + {file = "scipy-1.8.0.tar.gz", hash = "sha256:31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd"}, +] + +[package.dependencies] +numpy = ">=1.17.3,<1.25.0" + +[[package]] +name = "setuptools" +version = "68.0.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, + {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "setuptools-scm" +version = "7.1.0" +description = "the blessed package to manage your versions by scm tags" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setuptools_scm-7.1.0-py3-none-any.whl", hash = "sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e"}, + {file = "setuptools_scm-7.1.0.tar.gz", hash = "sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27"}, +] + +[package.dependencies] +packaging = ">=20.0" +setuptools = "*" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +typing-extensions = "*" + +[package.extras] +test = ["pytest (>=6.2)", "virtualenv (>20)"] +toml = ["setuptools (>=42)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + +[[package]] +name = "sphinx" +version = "7.0.1" +description = "Python documentation generator" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Sphinx-7.0.1.tar.gz", hash = "sha256:61e025f788c5977d9412587e733733a289e2b9fdc2fef8868ddfbfc4ccfe881d"}, + {file = "sphinx-7.0.1-py3-none-any.whl", hash = "sha256:60c5e04756c1709a98845ed27a2eed7a556af3993afb66e77fec48189f742616"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.13" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "1.23.3" +description = "Type hints (PEP 484) support for the Sphinx autodoc extension" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinx_autodoc_typehints-1.23.3-py3-none-any.whl", hash = "sha256:ec913d93e915b4dae6a8758cd95baecc70ed77fcdfe050601fc6b12afd0fc059"}, + {file = "sphinx_autodoc_typehints-1.23.3.tar.gz", hash = "sha256:8fb8dfc4b010505c850f4ef395fc80222ebfd8fd1b40149f8862f2396f623760"}, +] + +[package.dependencies] +sphinx = ">=7.0.1" + +[package.extras] +docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)"] +numpy = ["nptyping (>=2.5)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.6.3)"] +type-comment = ["typed-ast (>=1.5.4)"] + +[[package]] +name = "sphinx-automodapi" +version = "0.15.0" +description = "Sphinx extension for auto-generating API documentation for entire modules" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-automodapi-0.15.0.tar.gz", hash = "sha256:fd5871e054df7f3e299dde959afffa849f4d01c6eac274c366b06472afcb06aa"}, + {file = "sphinx_automodapi-0.15.0-py3-none-any.whl", hash = "sha256:06848f261fb127b25d35f27c2c4fddb041e76498733da064504f8077cbd27bec"}, +] + +[package.dependencies] +sphinx = ">=2" + +[package.extras] +test = ["codecov", "coverage", "cython", "pytest", "pytest-cov"] + +[[package]] +name = "sphinx-copybutton" +version = "0.5.2" +description = "Add a copy button to each of your code cells." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, + {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, +] + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code-style = ["pre-commit (==2.12.1)"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] + +[[package]] +name = "sphinx-gallery" +version = "0.13.0" +description = "A `Sphinx `_ extension that builds an HTML gallery of examples from any set of Python scripts." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-gallery-0.13.0.tar.gz", hash = "sha256:4756f92e079128b08cbc7a57922cc904b3d442b1abfa73ec6471ad24f3c5b4b2"}, + {file = "sphinx_gallery-0.13.0-py3-none-any.whl", hash = "sha256:5bedfa4998b4158d5affc7d1df6796e4b1e834b16680001dac992af1304d8ed9"}, +] + +[package.dependencies] +sphinx = ">=4" + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-bibtex" +version = "2.5.0" +description = "Sphinx extension for BibTeX style citations." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinxcontrib-bibtex-2.5.0.tar.gz", hash = "sha256:71b42e5db0e2e284f243875326bf9936aa9a763282277d75048826fef5b00eaa"}, + {file = "sphinxcontrib_bibtex-2.5.0-py3-none-any.whl", hash = "sha256:748f726eaca6efff7731012103417ef130ecdcc09501b4d0c54283bf5f059f76"}, +] + +[package.dependencies] +docutils = ">=0.8" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +pybtex = ">=0.24" +pybtex-docutils = ">=1.0.0" +Sphinx = ">=2.1" + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sympy" +version = "1.12" +description = "Computer algebra system (CAS) in Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, +] + +[package.dependencies] +mpmath = ">=0.19" + +[[package]] +name = "tensorboard" +version = "2.10.1" +description = "TensorBoard lets you watch Tensors Flow" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "tensorboard-2.10.1-py3-none-any.whl", hash = "sha256:fb9222c1750e2fa35ef170d998a1e229f626eeced3004494a8849c88c15d8c1c"}, +] + +[package.dependencies] +absl-py = ">=0.4" +google-auth = ">=1.6.3,<3" +google-auth-oauthlib = ">=0.4.1,<0.5" +grpcio = ">=1.24.3" +markdown = ">=2.6.8" +numpy = ">=1.12.0" +protobuf = ">=3.9.2,<3.20" +requests = ">=2.21.0,<3" +setuptools = ">=41.0.0" +tensorboard-data-server = ">=0.6.0,<0.7.0" +tensorboard-plugin-wit = ">=1.6.0" +werkzeug = ">=1.0.1" +wheel = ">=0.26" + +[[package]] +name = "tensorboard-data-server" +version = "0.6.1" +description = "Fast data loading for TensorBoard" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "tensorboard_data_server-0.6.1-py3-none-any.whl", hash = "sha256:809fe9887682d35c1f7d1f54f0f40f98bb1f771b14265b453ca051e2ce58fca7"}, + {file = "tensorboard_data_server-0.6.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:fa8cef9be4fcae2f2363c88176638baf2da19c5ec90addb49b1cde05c95c88ee"}, + {file = "tensorboard_data_server-0.6.1-py3-none-manylinux2010_x86_64.whl", hash = "sha256:d8237580755e58eff68d1f3abefb5b1e39ae5c8b127cc40920f9c4fb33f4b98a"}, +] + +[[package]] +name = "tensorboard-plugin-wit" +version = "1.8.1" +description = "What-If Tool TensorBoard plugin." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "tensorboard_plugin_wit-1.8.1-py3-none-any.whl", hash = "sha256:ff26bdd583d155aa951ee3b152b3d0cffae8005dc697f72b44a8e8c2a77a8cbe"}, +] + +[[package]] +name = "tensorboardx" +version = "2.6" +description = "TensorBoardX lets you watch Tensors Flow without Tensorflow" +category = "main" +optional = true +python-versions = "*" +files = [ + {file = "tensorboardX-2.6-py2.py3-none-any.whl", hash = "sha256:24a7cd076488de1e9d15ef25371b8ebf90c4f8f622af2477c611198f03f4a606"}, + {file = "tensorboardX-2.6.tar.gz", hash = "sha256:d4c036964dd2deb075a1909832b276daa383eab3f9db519ad90b99f5aea06b0c"}, +] + +[package.dependencies] +numpy = "*" +packaging = "*" +protobuf = ">=3.8.0,<4" + +[[package]] +name = "tensorflow" +version = "2.10.0" +description = "TensorFlow is an open source machine learning framework for everyone." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tensorflow-2.10.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:60d5b4fbbb7a1304d96352372fa032e861e98bb3f23aced7ce53bc475a2df97d"}, + {file = "tensorflow-2.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1e898bc1df521af9a8bfe0e511124379a6414083234ec67c6ab212ad12b2f"}, + {file = "tensorflow-2.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e129114dc529e63af9c419b5917b3407d0d26a4c8b73e114f601a175a7eb0477"}, + {file = "tensorflow-2.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:0a3b58d90fadb5bdf81a964bea73bb89019a9d1e9ac12de75375c8f65e0d7570"}, + {file = "tensorflow-2.10.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:0701da16a3d6d34763cd9ced6467cee24c02c9abf0d1a48ba59ea5a8d0421cec"}, + {file = "tensorflow-2.10.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64cc999ae83ddd891083141d3e5d718e3d799501a1b56c544f2ca648a8396c3e"}, + {file = "tensorflow-2.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9f711c5ff04333355c83eb96ca2e1db57c9663c6fa01d68b5953a040a602a3c"}, + {file = "tensorflow-2.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9f4677e9ab7104e73710a94ff5d2ed4b335378dcd2ac7402a68c31802a680911"}, + {file = "tensorflow-2.10.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8773858cbf37aaad444b07605d29f5b2d8f7cd1ecbf1cce2777931b96884589c"}, + {file = "tensorflow-2.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5806d4645bce5eb415863d757b5f056364b9d1cfa2c34f711f69d46cac605eee"}, + {file = "tensorflow-2.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e85f89bc23c62d4243fad70bac902f00a234b33da8b91e2967eeef0f4b75b1e3"}, + {file = "tensorflow-2.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:d9b19b5120c0b393d9e2fc72561cfa3a454ef7f1ac649d8ad0dcc98817a086a4"}, + {file = "tensorflow-2.10.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:4b542af76d93c43e9d24dcb69888793831e434dc781c9533ee07f928fce84a15"}, + {file = "tensorflow-2.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588a1f34d9db51ea856aff07da9aa877c1d1d109336eee2c3bbb16dabd3f605"}, + {file = "tensorflow-2.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:487918f4074685e213ba247387faab34933df76939134008441cb9d3e2c95cab"}, + {file = "tensorflow-2.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:741a74278f471dc21991a6c7dc802d454d42fd39515900c6363b8c38a898fb0f"}, +] + +[package.dependencies] +absl-py = ">=1.0.0" +astunparse = ">=1.6.0" +flatbuffers = ">=2.0" +gast = ">=0.2.1,<=0.4.0" +google-pasta = ">=0.1.1" +grpcio = ">=1.24.3,<2.0" +h5py = ">=2.9.0" +keras = ">=2.10.0,<2.11" +keras-preprocessing = ">=1.1.1" +libclang = ">=13.0.0" +numpy = ">=1.20" +opt-einsum = ">=2.3.2" +packaging = "*" +protobuf = ">=3.9.2,<3.20" +setuptools = "*" +six = ">=1.12.0" +tensorboard = ">=2.10,<2.11" +tensorflow-estimator = ">=2.10.0,<2.11" +tensorflow-io-gcs-filesystem = ">=0.23.1" +termcolor = ">=1.1.0" +typing-extensions = ">=3.6.6" +wrapt = ">=1.11.0" + +[[package]] +name = "tensorflow-cpu-aws" +version = "2.10.0" +description = "TensorFlow is an open source machine learning framework for everyone." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tensorflow_cpu_aws-2.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b11a7004e078b17d1a472cd5a091a0efd14672294d98ab76b851ddc15faee92c"}, + {file = "tensorflow_cpu_aws-2.10.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8e76c48e75d0b353239fcb039c3abbfa8ee6fe2660badb6b094c59e222714e"}, + {file = "tensorflow_cpu_aws-2.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fe56d8506dae3891af6b62f26f16597e8416f9c6b788fe5dd98b602136f6cf6"}, + {file = "tensorflow_cpu_aws-2.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112fa013271dc3282f7c821b138126f2504892703d85d5686198eb348fa6f6d2"}, +] + +[package.dependencies] +absl-py = ">=1.0.0" +astunparse = ">=1.6.0" +flatbuffers = ">=2.0" +gast = ">=0.2.1,<=0.4.0" +google-pasta = ">=0.1.1" +grpcio = ">=1.24.3,<2.0" +h5py = ">=2.9.0" +keras = ">=2.10.0,<2.11" +keras-preprocessing = ">=1.1.1" +libclang = ">=13.0.0" +numpy = ">=1.20" +opt-einsum = ">=2.3.2" +packaging = "*" +protobuf = ">=3.9.2,<3.20" +setuptools = "*" +six = ">=1.12.0" +tensorboard = ">=2.10,<2.11" +tensorflow-estimator = ">=2.10.0,<2.11" +tensorflow-io-gcs-filesystem = ">=0.23.1" +termcolor = ">=1.1.0" +typing-extensions = ">=3.6.6" +wrapt = ">=1.11.0" + +[[package]] +name = "tensorflow-estimator" +version = "2.10.0" +description = "TensorFlow Estimator." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tensorflow_estimator-2.10.0-py2.py3-none-any.whl", hash = "sha256:f324ea17cd57f16e33bf188711d5077e6b2e5f5a12c328d6e01a07b23888edcd"}, +] + +[[package]] +name = "tensorflow-io-gcs-filesystem" +version = "0.32.0" +description = "TensorFlow IO" +category = "main" +optional = false +python-versions = ">=3.7, <3.12" +files = [ + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:74a7e25e83d4117a7ebb09a3f247553a5497393ab48c3ee0cf0d17b405026817"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:045d51bba586390d0545fcd8a18727d62b175eb142f6f4c6d719d39de40774cd"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db682e9a510c27dd35710ba5a2c62c371e25b727741b2fe3a920355fa501e947"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:7f15fd22e592661b10de317be2f42a0f84be7bfc5e6a565fcfcb04b60d625b78"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:336d9b3fe6b55aea149c4f6aa1fd6ffaf27d4e5c37e55a182340b47caba38846"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842f5f09cd756bdb3b4d0b5571b3a6f72fd534d42da938b9acf0ef462995eada"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:1ce80e1555d6ee88dda67feddf366cc8b30252b5837a7a17303df7b06a71fc2e"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05e65d3cb6c93a7929b384d86c6369c63cbbab8a770440a3d95e094878403f9f"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:21de7dcc06eb1e7de3c022b0072d90ba35ef886578149663437aa7a6fb5bf6b3"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:79fdd02103b8ae9f8b89af41f744c013fa1caaea709de19833917795e3063857"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5635df0bbe40f971dc1b946e3372744b0bdfda45c38ffcd28ef53a32bb8da4da"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:122be149e5f6a030f5c2901be0cc3cb07619232f7b03889e2cdf3da1c0d4f92f"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8214cdf85bea694160f9035ff395221c1e25e119784ccb4c104919b1f5dec84e"}, + {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28202492d904a6e280cf27560791e87ac1c7566000db82065d63a70c27008af2"}, +] + +[package.extras] +tensorflow = ["tensorflow (>=2.12.0,<2.13.0)"] +tensorflow-aarch64 = ["tensorflow-aarch64 (>=2.12.0,<2.13.0)"] +tensorflow-cpu = ["tensorflow-cpu (>=2.12.0,<2.13.0)"] +tensorflow-gpu = ["tensorflow-gpu (>=2.12.0,<2.13.0)"] +tensorflow-rocm = ["tensorflow-rocm (>=2.12.0,<2.13.0)"] + +[[package]] +name = "tensorflow-probability" +version = "0.18.0" +description = "Probabilistic modeling and statistical inference in TensorFlow" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "tensorflow_probability-0.18.0-py2.py3-none-any.whl", hash = "sha256:80d57e7792c78586f12255ab4a7c359b7e86bc06d487fd629119d9e650624a18"}, +] + +[package.dependencies] +absl-py = "*" +cloudpickle = ">=1.3" +decorator = "*" +dm-tree = "*" +gast = ">=0.3.2" +numpy = ">=1.13.3" +six = ">=1.10.0" + +[package.extras] +jax = ["jax", "jaxlib"] +tfds = ["tensorflow-datasets (>=2.2.0)"] + +[[package]] +name = "termcolor" +version = "2.3.0" +description = "ANSI color formatting for output in terminal" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, + {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "thewalrus" +version = "0.19.0" +description = "Open source library for hafnian calculation" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "thewalrus-0.19.0-py3-none-any.whl", hash = "sha256:07b6e2969bf5405a2df736c442b1500857438bbd2afc2053b8b600b8b0c67f97"}, + {file = "thewalrus-0.19.0.tar.gz", hash = "sha256:06ff07a14cd8cd4650d9c82b8bb8301ef9a58dcdd4bafb14841768ccf80c98b9"}, +] + +[package.dependencies] +dask = {version = "*", extras = ["delayed"]} +numba = ">=0.49.1" +numpy = ">=1.19.2" +scipy = ">=1.2.1" +sympy = ">=1.5.1" + +[[package]] +name = "threadpoolctl" +version = "3.1.0" +description = "threadpoolctl" +category = "main" +optional = true +python-versions = ">=3.6" +files = [ + {file = "threadpoolctl-3.1.0-py3-none-any.whl", hash = "sha256:8b99adda265feb6773280df41eece7b2e6561b772d21ffd52e372f999024907b"}, + {file = "threadpoolctl-3.1.0.tar.gz", hash = "sha256:a335baacfaa4400ae1f0d8e3a58d6674d2f8828e3716bb2802c44955ad391380"}, +] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "toolz" +version = "0.12.0" +description = "List processing tools and functional utilities" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, + {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, +] + +[[package]] +name = "tqdm" +version = "4.65.0" +description = "Fast, Extensible Progress Meter" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, + {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["py-make (>=0.1.0)", "twine", "wheel"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +category = "main" +optional = true +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "urllib3" +version = "2.0.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"}, + {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "werkzeug" +version = "2.3.6" +description = "The comprehensive WSGI web application library." +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Werkzeug-2.3.6-py3-none-any.whl", hash = "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890"}, + {file = "Werkzeug-2.3.6.tar.gz", hash = "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330"}, +] + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + +[[package]] +name = "wheel" +version = "0.40.0" +description = "A built-package format for Python" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"}, + {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)"] + +[[package]] +name = "wrapt" +version = "1.12.1" +description = "Module for decorators, wrappers and monkey patching." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, +] + +[[package]] +name = "xanadu-sphinx-theme" +version = "0.1.0" +description = "Sphinx theme for Xanadu open-source Python packages" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "xanadu-sphinx-theme-0.1.0.tar.gz", hash = "sha256:ce3c825cebf4b52a025330a907e95ab1a452e71f91c904fab7e38eccbe0d3eda"}, + {file = "xanadu_sphinx_theme-0.1.0-py3-none-any.whl", hash = "sha256:fedba15959e5abcdbf8f4ea34370ebf3bef32498eede9a7e7f14cc4ce0560b5b"}, +] + +[package.dependencies] +pillow = "*" +sphinx = "*" +sphinx-gallery = "*" + +[[package]] +name = "zipp" +version = "3.16.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.0-py3-none-any.whl", hash = "sha256:5dadc3ad0a1f825fe42ce1bce0f2fc5a13af2e6b2d386af5b0ff295bc0a287d3"}, + {file = "zipp-3.16.0.tar.gz", hash = "sha256:1876cb065531855bbe83b6c489dcf69ecc28f1068d8e95959fe8bbc77774c941"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[extras] +ray = ["ray", "scikit-optimize"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.9,<3.11" +content-hash = "4bc682389a785eeb023c5eae11a3800b7e79cc3405421797fcf1bc5d6b19ef89" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..1262f969a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,71 @@ +[tool.poetry] +name = "mrmustard" +version = "0.5.0" +description = "Differentiable quantum Gaussian circuits" +authors = ["Xanadu "] +license = "Apache License 2.0" +readme = "README.md" +include = ["pyproject.toml"] +classifiers = [ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: Apache Software License", + "Natural Language :: English", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Scientific/Engineering :: Physics", +] + +[tool.poetry.dependencies] +python = ">=3.9,<3.11" +numpy = "1.23.5" +scipy = "1.8.0" +numba = "0.56.4" +thewalrus = "0.19.0" +tensorflow = "<=2.10.1" +tensorflow-cpu-aws = { version = "2.10.0", markers = "platform_machine == 'aarch64' or platform_machine == 'arm64'" } +tensorflow-probability = "0.18.0" +rich = "10.15.1" +matplotlib = "3.5.0" +tqdm = "^4.65.0" +ray = { version = "2.5.0", extras = ["tune"], optional = true } +scikit-optimize = { version = "^0.9.0", optional = true } + +[tool.poetry.extras] +ray = ["ray", "scikit-optimize"] + +[tool.poetry.group.dev] +optional = true + +[tool.poetry.group.dev.dependencies] +pytest = "6.2.5" +pytest-cov ="3.0.0" +hypothesis = "6.31.6" +pylint = "2.10.0" +black = ">=22.1.0" + +[tool.poetry.group.doc] +optional = true + +[tool.poetry.group.doc.dependencies] +sphinx = "^7.0.1" +docutils = "^0.20.1" +m2r2 = "^0.3.3.post2" +sphinx-autodoc-typehints = "^1.23.3" +sphinx-copybutton = "^0.5.2" +sphinx-automodapi = "^0.15.0" +sphinxcontrib-bibtex = "^2.5.0" +mistune = "0.8.4" +xanadu-sphinx-theme = "0.1.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 5ec2222b6..000000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ -pytest==6.2.5 -pytest-cov==3.0.0 -hypothesis==6.31.6 -pylint==2.10.0 -black>=22.1.0 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 46cd82df7..000000000 --- a/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -numpy==1.23.5 -scipy==1.8.0 -numba==0.56.4 -thewalrus==0.19.0 -tensorflow==2.10.1; sys_platform != "darwin" -tensorflow_macos==2.10.0; sys_platform == "darwin" -tensorflow-probability==0.18.0 -rich==10.15.1 -matplotlib==3.5.0 diff --git a/setup.py b/setup.py deleted file mode 100644 index 77ae75209..000000000 --- a/setup.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2021 Xanadu Quantum Technologies Inc. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import platform - -from setuptools import find_packages, setup - -with open("mrmustard/_version.py") as f: - version = f.readlines()[-1].split()[-1].strip("\"'") - -requirements = [ - "numpy", - "scipy", - "numba", - "thewalrus>=0.17.0", - "tensorflow<=2.10.1" if platform.system() != "Darwin" else "tensorflow_macos<=2.10.0", - "tensorflow-probability<=0.18.0", - "rich", - "tqdm", - "matplotlib", -] - -extra_requirements = { - "ray": ["ray[tune]", "scikit-optimize"], -} - -info = { - "name": "mrmustard", - "version": version, - "description": "Differentiable quantum Gaussian circuits", - "url": "https://github.com/XanaduAI/mrmustard", - "author": "Xanadu", - "author_email": "filippo@xanadu.ai", - "license": "Apache License 2.0", - "packages": find_packages(where="."), - "install_requires": requirements, - "extras_require": extra_requirements, - "long_description": open("README.md", encoding="utf-8").read(), - "long_description_content_type": "text/markdown", -} - -classifiers = [ - "Development Status :: 4 - Beta", - "Environment :: Console", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: Apache Software License", - "Natural Language :: English", - "Operating System :: POSIX", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX :: Linux", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", - "Topic :: Scientific/Engineering :: Physics", -] - -setup(classifiers=classifiers, **(info)) diff --git a/tests/test_lab/test_circuit.py b/tests/test_lab/test_circuit.py index b8e9954db..c88068e38 100644 --- a/tests/test_lab/test_circuit.py +++ b/tests/test_lab/test_circuit.py @@ -12,14 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -import numpy as np -import pytest -from hypothesis import given, strategies as st, assume -from hypothesis.extra.numpy import arrays -from mrmustard.physics import gaussian + +from hypothesis import given + from mrmustard.lab import * -from mrmustard import settings -from tests import random +from tests.random import angle, medium_float, n_mode_pure_state, r def test_circuit_placement_SD(): @@ -53,3 +50,12 @@ def test_is_unitary(): assert Ggate(1).is_unitary assert (Ggate(1) >> Ggate(1)).is_unitary assert not (Ggate(2) >> Attenuator([0.1, 0.2])).is_unitary + + +@given( + r=r, phi1=angle, phi2=angle, x=medium_float, y=medium_float, G=n_mode_pure_state(num_modes=1) +) +def test_shift(r, phi1, phi2, x, y, G): + "test that the leftshift/rightshift operator works as expected" + circ = Sgate(r, phi1) >> Dgate(x, y) >> Rgate(phi2) + assert G == (circ << G) >> circ diff --git a/tests/test_lab/test_gates_fock.py b/tests/test_lab/test_gates_fock.py index 663732bdf..d9799ed73 100644 --- a/tests/test_lab/test_gates_fock.py +++ b/tests/test_lab/test_gates_fock.py @@ -17,6 +17,7 @@ from hypothesis import given from thewalrus.fock_gradients import ( beamsplitter, + displacement, mzgate, squeezing, two_mode_squeezing, @@ -35,6 +36,8 @@ Sgate, ) from mrmustard.lab.states import TMSV, Fock, SqueezedVacuum, State +from mrmustard.math import Math +from mrmustard.math.lattice import strategies from mrmustard.physics import fock from tests.random import ( angle, @@ -47,6 +50,8 @@ two_mode_unitary_gate, ) +math = Math() + @given(state=n_mode_pure_state(num_modes=1), x=medium_float, y=medium_float) def test_Dgate_1mode(state, x, y): @@ -97,7 +102,7 @@ def test_single_mode_fock_equals_gaussian_ket(gate): def test_single_mode_fock_equals_gaussian_ket_dm(gate): """Test same state is obtained via fock representation or phase space for single mode circuits.""" - cutoffs = [70] + cutoffs = (70,) gaussian_state = SqueezedVacuum(-0.1) fock_state = State(ket=gaussian_state.ket(cutoffs)) @@ -110,7 +115,7 @@ def test_single_mode_fock_equals_gaussian_ket_dm(gate): def test_two_mode_fock_equals_gaussian(gate): """Test same state is obtained via fock representation or phase space for two modes circuits.""" - cutoffs = [20, 20] + cutoffs = (20, 20) gaussian_state = TMSV(0.1) >> BSgate(np.pi / 2) >> Attenuator(0.5) fock_state = State(dm=gaussian_state.dm(cutoffs)) @@ -122,12 +127,12 @@ def test_two_mode_fock_equals_gaussian(gate): @pytest.mark.parametrize( "cutoffs,x,y", [ - [[5], 0.3, 0.5], - [[5], 0.0, 0.0], - [[2, 2], [0.1, 0.1], [0.25, -0.2]], - [[3, 3], [0.0, 0.0], [0.0, 0.0]], - [[2, 5, 1], [0.1, 5.0, 1.0], [-0.3, 0.1, 0.0]], - [[3, 3, 3, 3], [0.1, 0.2, 0.3, 0.4], [-0.5, -4, 3.1, 4.2]], + [[5, 5], 0.3, 0.5], + [[5, 5], 0.0, 0.0], + [[2, 2, 2, 2], [0.1, 0.1], [0.25, -0.2]], + [[3, 3, 3, 3], [0.0, 0.0], [0.0, 0.0]], + [[2, 5, 1, 2, 5, 1], [0.1, 5.0, 1.0], [-0.3, 0.1, 0.0]], + [[3, 3, 3, 3, 3, 3, 3, 3], [0.1, 0.2, 0.3, 0.4], [-0.5, -4, 3.1, 4.2]], ], ) def test_fock_representation_displacement(cutoffs, x, y): @@ -139,8 +144,80 @@ def test_fock_representation_displacement(cutoffs, x, y): # compare with the standard way of calculating # transformation unitaries using the Choi isomorphism - X = np.eye(2 * len(cutoffs)) - expected_Ud = fock.wigner_to_fock_U(X, dgate.XYd[-1], cutoffs * 2) + X, _, d = dgate.XYd(allow_none=False) + expected_Ud = fock.wigner_to_fock_U(X, d, cutoffs) + + assert np.allclose(Ud, expected_Ud, atol=1e-5) + + +@given(x1=medium_float, x2=medium_float, y1=medium_float, y2=medium_float) +def test_parallel_displacement(x1, x2, y1, y2): + """Tests that parallel Dgate returns the correct unitary.""" + U12 = Dgate([x1, x2], [y1, y2]).U([2, 7, 2, 7]) + U1 = Dgate(x1, y1).U([2, 2]) + U2 = Dgate(x2, y2).U([7, 7]) + assert np.allclose(U12, np.transpose(np.tensordot(U1, U2, [[], []]), [0, 2, 1, 3])) + + +def test_squeezer_grad_against_finite_differences(): + """tests fock squeezer gradient against finite differences""" + cutoffs = (5, 5) + r = math.new_variable(0.5, None, "r") + phi = math.new_variable(0.1, None, "phi") + delta = 1e-6 + dUdr = (Sgate(r + delta, phi).U(cutoffs) - Sgate(r - delta, phi).U(cutoffs)) / (2 * delta) + dUdphi = (Sgate(r, phi + delta).U(cutoffs) - Sgate(r, phi - delta).U(cutoffs)) / (2 * delta) + _, (gradr, gradphi) = math.value_and_gradients( + lambda: fock.squeezer(r, phi, shape=cutoffs), [r, phi] + ) + assert np.allclose(gradr, 2 * np.real(np.sum(dUdr))) + assert np.allclose(gradphi, 2 * np.real(np.sum(dUdphi))) + + +def test_displacement_grad(): + """tests fock displacement gradient against finite differences""" + cutoffs = [5, 5] + x = math.new_variable(0.1, None, "x") + y = math.new_variable(0.1, None, "y") + alpha = math.make_complex(x, y).numpy() + delta = 1e-6 + dUdx = (fock.displacement(x + delta, y, cutoffs) - fock.displacement(x - delta, y, cutoffs)) / ( + 2 * delta + ) + dUdy = (fock.displacement(x, y + delta, cutoffs) - fock.displacement(x, y - delta, cutoffs)) / ( + 2 * delta + ) + + D = fock.displacement(x, y, shape=cutoffs) + dD_da, dD_dac = strategies.jacobian_displacement(math.asnumpy(D), alpha) + assert np.allclose(dD_da + dD_dac, dUdx) + assert np.allclose(1j * (dD_da - dD_dac), dUdy) + + +def test_fock_representation_displacement_rectangular(): + """Tests that DGate returns the correct unitary.""" + x, y = 0.3, 0.5 + cutoffs = 5, 10 + # apply gate + dgate = Dgate(x, y) + Ud = dgate.U(cutoffs) + + # compare with tw implementation + expected_Ud = displacement(np.sqrt(x * x + y * y), np.arctan2(y, x), 10)[:5, :10] + + assert np.allclose(Ud, expected_Ud, atol=1e-5) + + +def test_fock_representation_displacement_rectangular2(): + """Tests that DGate returns the correct unitary.""" + x, y = 0.3, 0.5 + cutoffs = 10, 5 + # apply gate + dgate = Dgate(x, y) + Ud = dgate.U(cutoffs) + + # compare with tw implementation + expected_Ud = displacement(np.sqrt(x * x + y * y), np.arctan2(y, x), 10)[:10, :5] assert np.allclose(Ud, expected_Ud, atol=1e-5) @@ -149,28 +226,37 @@ def test_fock_representation_displacement(cutoffs, x, y): def test_fock_representation_squeezing(r, phi): S = Sgate(r=r, phi=phi) expected = squeezing(r=r, theta=phi, cutoff=20) - assert np.allclose(expected, S.U(cutoffs=[20]), atol=1e-5) + assert np.allclose(expected, S.U(cutoffs=[20, 20]), atol=1e-5) + + +@given(r1=r, phi1=angle, r2=r, phi2=angle) +def test_parallel_squeezing(r1, phi1, r2, phi2): + """Tests that two parallel squeezers return the correct unitary.""" + U12 = Sgate([r1, r2], [phi1, phi2]).U([5, 7, 5, 7]) + U1 = Sgate(r1, phi1).U([5, 5]) + U2 = Sgate(r2, phi2).U([7, 7]) + assert np.allclose(U12, np.transpose(np.tensordot(U1, U2, [[], []]), [0, 2, 1, 3])) @given(theta=angle, phi=angle) def test_fock_representation_beamsplitter(theta, phi): BS = BSgate(theta=theta, phi=phi) - expected = beamsplitter(theta=theta, phi=phi, cutoff=20) - assert np.allclose(expected, BS.U(cutoffs=[20, 20]), atol=1e-5) + expected = beamsplitter(theta=theta, phi=phi, cutoff=10) + assert np.allclose(expected, BS.U(cutoffs=[10, 10, 10, 10]), atol=1e-5) @given(r=r, phi=angle) def test_fock_representation_two_mode_squeezing(r, phi): S2 = S2gate(r=r, phi=phi) - expected = two_mode_squeezing(r=r, theta=phi, cutoff=20) - assert np.allclose(expected, S2.U(cutoffs=[20, 20]), atol=1e-5) + expected = two_mode_squeezing(r=r, theta=phi, cutoff=10) + assert np.allclose(expected, S2.U(cutoffs=[10, 10, 10, 10]), atol=1e-5) @given(phi_a=angle, phi_b=angle) def test_fock_representation_mzgate(phi_a, phi_b): MZ = MZgate(phi_a=phi_a, phi_b=phi_b, internal=False) - expected = mzgate(theta=phi_b, phi=phi_a, cutoff=20) - assert np.allclose(expected, MZ.U(cutoffs=[20, 20]), atol=1e-5) + expected = mzgate(theta=phi_b, phi=phi_a, cutoff=10) + assert np.allclose(expected, MZ.U(cutoffs=[10, 10, 10, 10]), atol=1e-5) @pytest.mark.parametrize( @@ -190,8 +276,8 @@ def test_fock_representation_rgate(cutoffs, angles, modes): # compare with the standard way of calculating # transformation unitaries using the Choi isomorphism - d = np.zeros(2 * len(cutoffs)) - expected_R = fock.wigner_to_fock_U(rgate.XYd[0], d, cutoffs * 2) + d = np.zeros(len(cutoffs) * 2) + expected_R = fock.wigner_to_fock_U(rgate.X_matrix, d, tuple(cutoffs + cutoffs)) assert np.allclose(R, expected_R, atol=1e-5) @@ -213,3 +299,30 @@ def test_raise_interferometer_error(): def test_choi_cutoffs(): output = State(dm=Coherent([1.0, 1.0]).dm([5, 8])) >> Attenuator(0.5, modes=[1]) assert output.cutoffs == [5, 8] # cutoffs are respected by the gate + + +def test_measure_with_fock(): + "tests that the autocutoff respects the fock projection cutoff" + cov = np.array( + [ + [1.08341848, 0.26536937, 0.0, 0.0], + [0.26536937, 1.05564949, 0.0, 0.0], + [0.0, 0.0, 0.98356475, -0.24724869], + [0.0, 0.0, -0.24724869, 1.00943755], + ] + ) + + state = State(means=np.zeros(4), cov=cov) + + n_detect = 2 + state_out = state << Fock([n_detect], modes=[1]) + assert np.allclose(state_out.ket(), np.array([0.00757899, 0.0])) + + +@given(theta=angle, phi=angle) +def test_schwinger_bs_equals_vanilla_bs_for_small_cutoffs(theta, phi): + """Tests that the Schwinger boson BS gate is equivalent to the vanilla BS gate for low cutoffs.""" + U_vanilla = BSgate(theta, phi).U([10, 10, 10, 10], method="vanilla") + U_schwinger = BSgate(theta, phi).U([10, 10, 10, 10], method="schwinger") + + assert np.allclose(U_vanilla, U_schwinger, atol=1e-6) diff --git a/tests/test_lab/test_state.py b/tests/test_lab/test_state.py new file mode 100644 index 000000000..47aeb6356 --- /dev/null +++ b/tests/test_lab/test_state.py @@ -0,0 +1,49 @@ +import numpy as np + +from mrmustard.lab import Attenuator, Gaussian + + +def test_addition(): + """Test that addition of Gaussians is correct""" + G0 = Gaussian(1, cutoffs=[10]) + G1 = Gaussian(1, cutoffs=[10]) + + mixed = G0 + G1 + + assert np.allclose(mixed.dm([10]), G0.dm([10]) + G1.dm([10])) + + +def test_multiplication_ket(): + """Test that multiplication of Gaussians is correct""" + G = Gaussian(1, cutoffs=[10]) + + scaled = 42.0 * G + + assert np.allclose(scaled.ket(G.shape), 42.0 * G.ket()) + + +def test_multiplication_dm(): + """Test that multiplication of Gaussians is correct""" + G = Gaussian(1) >> Attenuator(0.9) + + scaled = 42.0 * G + + assert np.allclose(scaled.dm(), 42.0 * G.dm()) + + +def test_division_ket(): + """Test that division of Gaussians is correct""" + G = Gaussian(1, cutoffs=[10]) + + scaled = G / 42.0 + + assert np.allclose(scaled.ket([10]), G.ket([10]) / 42.0) + + +def test_division_dm(): + """Test that division of Gaussians is correct""" + G = Gaussian(1) >> Attenuator(0.9) + + scaled = G / 42.0 + + assert np.allclose(scaled.dm(G.cutoffs), G.dm() / 42.0) diff --git a/tests/test_math/test_compactFock.py b/tests/test_math/test_compactFock.py index 2d9b0d828..26a11ce0c 100644 --- a/tests/test_math/test_compactFock.py +++ b/tests/test_math/test_compactFock.py @@ -15,6 +15,15 @@ math = Math() # use methods in math if you want them to be differentiable +def allowed_cutoffs(max_cutoffs): + r"""Generate all cutoffs from (1,)*M to max_cutoffs""" + res = [] + for idx in np.ndindex(max_cutoffs): + cutoffs = np.array(idx) + 1 + res.append(tuple(cutoffs)) + return res + + @st.composite def random_ABC(draw, M): r""" @@ -29,48 +38,50 @@ def random_ABC(draw, M): @given(random_ABC(M=3)) def test_compactFock_diagonal(A_B_G0): """Test getting Fock amplitudes if all modes are detected (math.hermite_renormalized_diagonal)""" - cutoffs = [7, 4, 8] - A, B, G0 = A_B_G0 # Create random state (M mode Gaussian state with displacement) - - # Vanilla MM - G_ref = math.hermite_renormalized( - math.conj(-A), math.conj(B), math.conj(G0), shape=list(cutoffs) * 2 - ).numpy() # note: shape=[C1,C2,C3,...,C1,C2,C3,...] - - # Extract diagonal amplitudes from vanilla MM - ref_diag = np.zeros(cutoffs, dtype=np.complex128) - for inds in np.ndindex(*cutoffs): - inds_expanded = list(inds) + list(inds) # a,b,c,a,b,c - ref_diag[inds] = G_ref[tuple(inds_expanded)] - - # New MM - G_diag = math.hermite_renormalized_diagonal(math.conj(-A), math.conj(B), math.conj(G0), cutoffs) - assert np.allclose(ref_diag, G_diag) + for cutoffs in allowed_cutoffs((7, 7, 7)): + A, B, G0 = A_B_G0 # Create random state (M mode Gaussian state with displacement) + + # Vanilla MM + G_ref = math.hermite_renormalized( + math.conj(-A), math.conj(B), math.conj(G0), shape=list(cutoffs) * 2 + ).numpy() # note: shape=[C1,C2,C3,...,C1,C2,C3,...] + + # Extract diagonal amplitudes from vanilla MM + ref_diag = np.zeros(cutoffs, dtype=np.complex128) + for inds in np.ndindex(*cutoffs): + inds_expanded = list(inds) + list(inds) # a,b,c,a,b,c + ref_diag[inds] = G_ref[tuple(inds_expanded)] + + # New MM + G_diag = math.hermite_renormalized_diagonal( + math.conj(-A), math.conj(B), math.conj(G0), cutoffs + ) + assert np.allclose(ref_diag, G_diag) @given(random_ABC(M=3)) def test_compactFock_1leftover(A_B_G0): """Test getting Fock amplitudes if all but the first mode are detected (math.hermite_renormalized_1leftoverMode)""" - cutoffs = [7, 4, 8] - A, B, G0 = A_B_G0 # Create random state (M mode Gaussian state with displacement) - - # New algorithm - G_leftover = math.hermite_renormalized_1leftoverMode( - math.conj(-A), math.conj(B), math.conj(G0), cutoffs - ) - - # Vanilla MM - G_ref = math.hermite_renormalized( - math.conj(-A), math.conj(B), math.conj(G0), shape=list(cutoffs) * 2 - ).numpy() # note: shape=[C1,C2,C3,...,C1,C2,C3,...] - - # Extract amplitudes of leftover mode from vanilla MM - ref_leftover = np.zeros([cutoffs[0]] * 2 + list(cutoffs)[1:], dtype=np.complex128) - for inds in np.ndindex(*cutoffs[1:]): - ref_leftover[tuple([slice(cutoffs[0]), slice(cutoffs[0])] + list(inds))] = G_ref[ - tuple([slice(cutoffs[0])] + list(inds) + [slice(cutoffs[0])] + list(inds)) - ] - assert np.allclose(ref_leftover, G_leftover) + for cutoffs in allowed_cutoffs((7, 7, 7)): + A, B, G0 = A_B_G0 # Create random state (M mode Gaussian state with displacement) + + # New algorithm + G_leftover = math.hermite_renormalized_1leftoverMode( + math.conj(-A), math.conj(B), math.conj(G0), cutoffs + ) + + # Vanilla MM + G_ref = math.hermite_renormalized( + math.conj(-A), math.conj(B), math.conj(G0), shape=list(cutoffs) * 2 + ).numpy() # note: shape=[C1,C2,C3,...,C1,C2,C3,...] + + # Extract amplitudes of leftover mode from vanilla MM + ref_leftover = np.zeros([cutoffs[0]] * 2 + list(cutoffs)[1:], dtype=np.complex128) + for inds in np.ndindex(*cutoffs[1:]): + ref_leftover[tuple([slice(cutoffs[0]), slice(cutoffs[0])] + list(inds))] = G_ref[ + tuple([slice(cutoffs[0])] + list(inds) + [slice(cutoffs[0])] + list(inds)) + ] + assert np.allclose(ref_leftover, G_leftover) def test_compactFock_diagonal_gradients(): diff --git a/tests/test_math/test_interface.py b/tests/test_math/test_interface.py index ad463f616..c3fbd63e4 100644 --- a/tests/test_math/test_interface.py +++ b/tests/test_math/test_interface.py @@ -16,9 +16,11 @@ Unit tests for the :class:`Math`. """ +import numpy as np import pytest -from mrmustard.math import Math + from mrmustard import settings +from mrmustard.math import Math try: import torch @@ -50,7 +52,14 @@ def test_error_for_wrong_backend(): backend = settings.BACKEND with pytest.raises(ValueError) as exception_info: settings.BACKEND = "unexisting_backend" - assert exception_info.value.args[0] == f"Backend must be either 'tensorflow' or 'torch'" + assert exception_info.value.args[0] == "Backend must be either 'tensorflow' or 'torch'" # set back to initial value to avoid side effects settings.BACKEND = backend + + +def test_hash_tensor(): + """Test hash of a tensor""" + math = Math() + tensor = math.astensor([1, 2, 3]) + assert np.allclose(*[math.hash_tensor(tensor) for _ in range(3)]) diff --git a/tests/test_math/test_lattice.py b/tests/test_math/test_lattice.py new file mode 100644 index 000000000..f7cb43a1f --- /dev/null +++ b/tests/test_math/test_lattice.py @@ -0,0 +1,29 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for the lattice module""" + +import numpy as np + +from mrmustard.lab import Gaussian + + +def test_vanilla_vs_binomial(): + """Test that the vanilla and binomial methods give the same result""" + G = Gaussian(2) + + ket_vanilla = G.ket(cutoffs=[10, 10])[:5, :5] + ket_binomial = G.ket(max_photons=10)[:5, :5] + + assert np.allclose(ket_vanilla, ket_binomial) diff --git a/tests/test_math/test_special.py b/tests/test_math/test_special.py index 6f08d450a..04916d3b8 100644 --- a/tests/test_math/test_special.py +++ b/tests/test_math/test_special.py @@ -16,6 +16,7 @@ import numpy as np from scipy.special import eval_hermite, factorial + from mrmustard.math import Math math = Math() @@ -26,9 +27,12 @@ def test_reduction_to_renorm_physicists_polys(): x = np.arange(-1, 1, 0.1) init = 1 n_max = 5 - A = np.ones([init, init], dtype=complex) + A = -np.ones([init, init], dtype=complex) vals = np.array( - [math.hermite_renormalized(2 * A, 2 * np.array([x0], dtype=complex), 1, n_max) for x0 in x] + [ + math.hermite_renormalized(2 * A, 2 * np.array([x0], dtype=complex), 1, (n_max,)) + for x0 in x + ] ).T expected = np.array([eval_hermite(i, x) / np.sqrt(factorial(i)) for i in range(len(vals))]) assert np.allclose(vals, expected) diff --git a/tests/test_physics/test_bargmann.py b/tests/test_physics/test_bargmann.py new file mode 100644 index 000000000..229536b96 --- /dev/null +++ b/tests/test_physics/test_bargmann.py @@ -0,0 +1,53 @@ +import numpy as np + +from mrmustard.lab import Attenuator, Dgate, Gaussian, Ggate +from mrmustard.physics.bargmann import ( + wigner_to_bargmann_Choi, + wigner_to_bargmann_psi, + wigner_to_bargmann_rho, + wigner_to_bargmann_U, +) + + +def test_wigner_to_bargmann_psi(): + """Test that the Bargmann representation of a ket is correct""" + G = Gaussian(2) >> Dgate(0.1, 0.2) + + for x, y in zip(G.bargmann(), wigner_to_bargmann_psi(G.cov, G.means)): + assert np.allclose(x, y) + + +def test_wigner_to_bargmann_rho(): + """Test that the Bargmann representation of a dm is correct""" + G = Gaussian(2) >> Dgate(0.1, 0.2) >> Attenuator(0.9) + + for x, y in zip(G.bargmann(), wigner_to_bargmann_rho(G.cov, G.means)): + assert np.allclose(x, y) + + +def test_wigner_to_bargmann_U(): + """Test that the Bargmann representation of a unitary is correct""" + G = Ggate(2) >> Dgate(0.1, 0.2) + X, _, d = G.XYd(allow_none=False) + for x, y in zip(G.bargmann(), wigner_to_bargmann_U(X, d)): + assert np.allclose(x, y) + + +def test_wigner_to_bargmann_choi(): + """Test that the Bargmann representation of a Choi matrix is correct""" + G = Ggate(2) >> Dgate(0.1, 0.2) >> Attenuator(0.9) + X, Y, d = G.XYd(allow_none=False) + for x, y in zip(G.bargmann(), wigner_to_bargmann_Choi(X, Y, d)): + assert np.allclose(x, y) + + +def test_bargmann_numpy_state(): + """Tests that the numpy option of the bargmann method of State works correctly""" + state = Gaussian(1) + assert all(isinstance(thing, np.ndarray) for thing in state.bargmann(numpy=True)) + + +def test_bargmann_numpy_transformation(): + """Tests that the numpy option of the bargmann method of State works correctly""" + transformation = Ggate(1) + assert all(isinstance(thing, np.ndarray) for thing in transformation.bargmann(numpy=True)) diff --git a/tests/test_physics/test_fock/test_fock.py b/tests/test_physics/test_fock/test_fock.py index 70e465653..8c673aee8 100644 --- a/tests/test_physics/test_fock/test_fock.py +++ b/tests/test_physics/test_fock/test_fock.py @@ -12,42 +12,30 @@ # See the License for the specific language governing permissions and # limitations under the License. -from hypothesis import settings, given, strategies as st -import pytest - import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st from scipy.special import factorial from thewalrus.quantum import total_photon_number_distribution + from mrmustard.lab import ( + TMSV, + Attenuator, + BSgate, Circuit, - Vacuum, + Coherent, + Fock, + Gaussian, + Ggate, S2gate, - BSgate, Sgate, - Rgate, - Dgate, - Ggate, - Interferometer, SqueezedVacuum, - TMSV, State, - Attenuator, - Fock, - Coherent, - Gaussian, -) -from mrmustard.physics.fock import ( - dm_to_ket, - ket_to_dm, - trace, - apply_choi_to_dm, - apply_choi_to_ket, - apply_kraus_to_dm, - apply_kraus_to_ket, - _grad_displacement, - _displacement, + Vacuum, ) - +from mrmustard.math.lattice.strategies import displacement, grad_displacement +from mrmustard.physics import fock # helper strategies st_angle = st.floats(min_value=0, max_value=2 * np.pi) @@ -176,30 +164,30 @@ def test_density_matrix(num_modes): [ Vacuum(num_modes=2), Fock([4, 3], modes=[0, 1]), - Coherent(x=[0.1, 0.2], y=[-0.4, 0.4], cutoffs=[25]), - Gaussian(num_modes=2, cutoffs=[35]), + Coherent(x=[0.1, 0.2], y=[-0.4, 0.4], cutoffs=[10, 10]), + Gaussian(num_modes=2, cutoffs=[35, 35]), ], ) def test_dm_to_ket(state): """Tests pure state density matrix conversion to ket""" dm = state.dm() - ket = dm_to_ket(dm) + ket = fock.dm_to_ket(dm) # check if ket is normalized - assert np.allclose(np.linalg.norm(ket), 1) + assert np.allclose(np.linalg.norm(ket), 1, atol=1e-4) # check kets are equivalent - assert np.allclose(ket, state.ket()) + assert np.allclose(ket, state.ket(), atol=1e-4) - dm_reconstructed = ket_to_dm(ket) + dm_reconstructed = fock.ket_to_dm(ket) # check ket leads to same dm assert np.allclose(dm, dm_reconstructed, atol=1e-15) def test_dm_to_ket_error(): - """Test dm_to_ket raises an error when state is mixed""" + """Test fock.dm_to_ket raises an error when state is mixed""" state = Coherent(x=0.1, y=-0.4, cutoffs=[15]) >> Attenuator(0.5) with pytest.raises(ValueError): - dm_to_ket(state) + fock.dm_to_ket(state) def test_fock_trace_mode1_dm(): @@ -238,30 +226,29 @@ def test_fock_trace_function(): """tests that the Fock state is correctly traced""" state = Vacuum(2) >> Ggate(2) >> Attenuator([0.1, 0.1]) dm = state.dm([3, 20]) - dm_traced = trace(dm, keep=[0]) + dm_traced = fock.trace(dm, keep=[0]) assert np.allclose(dm_traced, State(dm=dm).get_modes(0).dm(), atol=1e-5) def test_dm_choi(): """tests that choi op is correctly applied to a dm""" circ = Ggate(1) >> Attenuator([0.1]) - dm_out = apply_choi_to_dm(circ.choi([10]), Vacuum(1).dm([10]), [0], [0]) + dm_out = fock.apply_choi_to_dm(circ.choi([10, 10, 10, 10]), Vacuum(1).dm([10]), [0], [0]) dm_expected = (Vacuum(1) >> circ).dm([10]) assert np.allclose(dm_out, dm_expected, atol=1e-5) def test_single_mode_choi_application_order(): """Test dual operations output the correct mode ordering""" - s = Attenuator(1.0) << State(dm=SqueezedVacuum(1.0, np.pi / 2).dm([40])) - assert np.allclose(s.dm([10])[:10, :10], SqueezedVacuum(1.0, np.pi / 2).dm([10])) - # NOTE: the [:10,:10] part is not necessary once PR #184 is merged + s = Attenuator(1.0) << State(dm=SqueezedVacuum(1.0, np.pi / 2).dm([40])) # apply identity gate + assert np.allclose(s.dm([10]), SqueezedVacuum(1.0, np.pi / 2).dm([10])) def test_apply_kraus_to_ket_1mode(): """Test that Kraus operators are applied to a ket on the correct indices""" ket = np.random.normal(size=(2, 3, 4)) kraus = np.random.normal(size=(5, 3)) - ket_out = apply_kraus_to_ket(kraus, ket, [1], [1]) + ket_out = fock.apply_kraus_to_ket(kraus, ket, [1], [1]) assert ket_out.shape == (2, 5, 4) @@ -269,7 +256,7 @@ def test_apply_kraus_to_ket_2mode(): """Test that Kraus operators are applied to a ket on the correct indices""" ket = np.random.normal(size=(2, 3, 4)) kraus = np.random.normal(size=(5, 3, 4)) - ket_out = apply_kraus_to_ket(kraus, ket, [1, 2], [1]) + ket_out = fock.apply_kraus_to_ket(kraus, ket, [1, 2], [1]) assert ket_out.shape == (2, 5) @@ -277,7 +264,7 @@ def test_apply_kraus_to_ket_2mode_2(): """Test that Kraus operators are applied to a ket on the correct indices""" ket = np.random.normal(size=(2, 3)) kraus = np.random.normal(size=(5, 4, 3)) - ket_out = apply_kraus_to_ket(kraus, ket, [1], [1, 2]) + ket_out = fock.apply_kraus_to_ket(kraus, ket, [1], [1, 2]) assert ket_out.shape == (2, 5, 4) @@ -285,7 +272,7 @@ def test_apply_kraus_to_dm_1mode(): """Test that Kraus operators are applied to a dm on the correct indices""" dm = np.random.normal(size=(2, 3, 2, 3)) kraus = np.random.normal(size=(5, 3)) - dm_out = apply_kraus_to_dm(kraus, dm, [1], [1]) + dm_out = fock.apply_kraus_to_dm(kraus, dm, [1], [1]) assert dm_out.shape == (2, 5, 2, 5) @@ -293,7 +280,7 @@ def test_apply_kraus_to_dm_2mode(): """Test that Kraus operators are applied to a dm on the correct indices""" dm = np.random.normal(size=(2, 3, 4, 2, 3, 4)) kraus = np.random.normal(size=(5, 3, 4)) - dm_out = apply_kraus_to_dm(kraus, dm, [1, 2], [1]) + dm_out = fock.apply_kraus_to_dm(kraus, dm, [1, 2], [1]) assert dm_out.shape == (2, 5, 2, 5) @@ -301,7 +288,7 @@ def test_apply_kraus_to_dm_2mode_2(): """Test that Kraus operators are applied to a dm on the correct indices""" dm = np.random.normal(size=(2, 3, 4, 2, 3, 4)) kraus = np.random.normal(size=(5, 6, 3)) - dm_out = apply_kraus_to_dm(kraus, dm, [1], [3, 1]) + dm_out = fock.apply_kraus_to_dm(kraus, dm, [1], [3, 1]) assert dm_out.shape == (2, 6, 4, 5, 2, 6, 4, 5) @@ -309,7 +296,7 @@ def test_apply_choi_to_ket_1mode(): """Test that choi operators are applied to a ket on the correct indices""" ket = np.random.normal(size=(3, 5)) choi = np.random.normal(size=(4, 3, 4, 3)) # [out_l, in_l, out_r, in_r] - ket_out = apply_choi_to_ket(choi, ket, [0], [0]) + ket_out = fock.apply_choi_to_ket(choi, ket, [0], [0]) assert ket_out.shape == (4, 5, 4, 5) @@ -317,7 +304,7 @@ def test_apply_choi_to_ket_2mode(): """Test that choi operators are applied to a ket on the correct indices""" ket = np.random.normal(size=(3, 5)) choi = np.random.normal(size=(2, 3, 5, 2, 3, 5)) # [out_l, in_l, out_r, in_r] - ket_out = apply_choi_to_ket(choi, ket, [0, 1], [0]) + ket_out = fock.apply_choi_to_ket(choi, ket, [0, 1], [0]) assert ket_out.shape == (2, 2) @@ -325,82 +312,104 @@ def test_apply_choi_to_dm_1mode(): """Test that choi operators are applied to a dm on the correct indices""" dm = np.random.normal(size=(3, 5, 3, 5)) choi = np.random.normal(size=(4, 3, 4, 3)) # [out_l, in_l, out_r, in_r] - dm_out = apply_choi_to_dm(choi, dm, [0], [0]) + dm_out = fock.apply_choi_to_dm(choi, dm, [0], [0]) assert dm_out.shape == (4, 5, 4, 5) def test_apply_choi_to_dm_2mode(): """Test that choi operators are applied to a dm on the correct indices""" dm = np.random.normal(size=(4, 5, 4, 5)) - choi = np.random.normal(size=(2, 3, 5, 2, 3, 5)) # [out_l, in_l, out_r, in_r] - dm_out = apply_choi_to_dm(choi, dm, [1], [1, 2]) + choi = np.random.normal(size=(2, 3, 5, 2, 3, 5)) # [out_l_1,2, in_l_1, out_r_1,2, in_r_1] + dm_out = fock.apply_choi_to_dm(choi, dm, [1], [1, 2]) assert dm_out.shape == (4, 2, 3, 4, 2, 3) -class TestDisplacement: - def test_grad_displacement(self): - """Tests the value of the analytic gradient for the Dgate against finite differences""" - cutoff = 4 - r = 1.0 - theta = np.pi / 8 - T = _displacement(r, theta, cutoff) - Dr, Dtheta = _grad_displacement(T, r, theta) - - dr = 0.001 - dtheta = 0.001 - Drp = _displacement(r + dr, theta, cutoff) - Drm = _displacement(r - dr, theta, cutoff) - Dthetap = _displacement(r, theta + dtheta, cutoff) - Dthetam = _displacement(r, theta - dtheta, cutoff) - Drapprox = (Drp - Drm) / (2 * dr) - Dthetaapprox = (Dthetap - Dthetam) / (2 * dtheta) - assert np.allclose(Dr, Drapprox, atol=1e-5, rtol=0) - assert np.allclose(Dtheta, Dthetaapprox, atol=1e-5, rtol=0) - - def test_displacement_values(self): - """Tests the correct construction of the single mode displacement operation""" - cutoff = 5 - alpha = 0.3 + 0.5 * 1j - # This data is obtained by using qutip - # np.array(displace(40,alpha).data.todense())[0:5,0:5] - expected = np.array( +def test_displacement_grad(): + """Tests the value of the analytic gradient for the Dgate against finite differences""" + cutoff = 4 + r = 2.0 + theta = np.pi / 8 + T = displacement((cutoff, cutoff), r * np.exp(1j * theta)) + Dr, Dtheta = grad_displacement(T, r, theta) + + dr = 0.001 + dtheta = 0.001 + Drp = displacement((cutoff, cutoff), (r + dr) * np.exp(1j * theta)) + Drm = displacement((cutoff, cutoff), (r - dr) * np.exp(1j * theta)) + Dthetap = displacement((cutoff, cutoff), r * np.exp(1j * (theta + dtheta))) + Dthetam = displacement((cutoff, cutoff), r * np.exp(1j * (theta - dtheta))) + Drapprox = (Drp - Drm) / (2 * dr) + Dthetaapprox = (Dthetap - Dthetam) / (2 * dtheta) + assert np.allclose(Dr, Drapprox, atol=1e-5, rtol=0) + assert np.allclose(Dtheta, Dthetaapprox, atol=1e-5, rtol=0) + + +def test_displacement_values(): + """Tests the correct construction of the single mode displacement operation""" + cutoff = 5 + alpha = 0.3 + 0.5 * 1j + # This data is obtained by using qutip + # np.array(displace(40,alpha).data.todense())[0:5,0:5] + expected = np.array( + [ [ - [ - 0.84366482 + 0.00000000e00j, - -0.25309944 + 4.21832408e-01j, - -0.09544978 - 1.78968334e-01j, - 0.06819609 + 3.44424719e-03j, - -0.01109048 + 1.65323865e-02j, - ], - [ - 0.25309944 + 4.21832408e-01j, - 0.55681878 + 0.00000000e00j, - -0.29708743 + 4.95145724e-01j, - -0.14658716 - 2.74850926e-01j, - 0.12479885 + 6.30297236e-03j, - ], - [ - -0.09544978 + 1.78968334e-01j, - 0.29708743 + 4.95145724e-01j, - 0.31873657 + 0.00000000e00j, - -0.29777767 + 4.96296112e-01j, - -0.18306015 - 3.43237787e-01j, - ], - [ - -0.06819609 + 3.44424719e-03j, - -0.14658716 + 2.74850926e-01j, - 0.29777767 + 4.96296112e-01j, - 0.12389162 + 1.10385981e-17j, - -0.27646677 + 4.60777945e-01j, - ], - [ - -0.01109048 - 1.65323865e-02j, - -0.12479885 + 6.30297236e-03j, - -0.18306015 + 3.43237787e-01j, - 0.27646677 + 4.60777945e-01j, - -0.03277289 + 1.88440656e-17j, - ], - ] - ) - T = _displacement(np.abs(alpha), np.angle(alpha), cutoff) - assert np.allclose(T, expected, atol=1e-5, rtol=0) + 0.84366482 + 0.00000000e00j, + -0.25309944 + 4.21832408e-01j, + -0.09544978 - 1.78968334e-01j, + 0.06819609 + 3.44424719e-03j, + -0.01109048 + 1.65323865e-02j, + ], + [ + 0.25309944 + 4.21832408e-01j, + 0.55681878 + 0.00000000e00j, + -0.29708743 + 4.95145724e-01j, + -0.14658716 - 2.74850926e-01j, + 0.12479885 + 6.30297236e-03j, + ], + [ + -0.09544978 + 1.78968334e-01j, + 0.29708743 + 4.95145724e-01j, + 0.31873657 + 0.00000000e00j, + -0.29777767 + 4.96296112e-01j, + -0.18306015 - 3.43237787e-01j, + ], + [ + -0.06819609 + 3.44424719e-03j, + -0.14658716 + 2.74850926e-01j, + 0.29777767 + 4.96296112e-01j, + 0.12389162 + 1.10385981e-17j, + -0.27646677 + 4.60777945e-01j, + ], + [ + -0.01109048 - 1.65323865e-02j, + -0.12479885 + 6.30297236e-03j, + -0.18306015 + 3.43237787e-01j, + 0.27646677 + 4.60777945e-01j, + -0.03277289 + 1.88440656e-17j, + ], + ] + ) + D = displacement((cutoff, cutoff), alpha) + assert np.allclose(D, expected, atol=1e-5, rtol=0) + + +@given(x=st.floats(-1, 1), y=st.floats(-1, 1)) +def test_number_means(x, y): + assert np.allclose(State(ket=Coherent(x, y).ket([80])).number_means, x * x + y * y) + assert np.allclose(State(dm=Coherent(x, y).dm([80])).number_means, x * x + y * y) + + +@given(x=st.floats(-1, 1), y=st.floats(-1, 1)) +def test_number_variances_coh(x, y): + assert np.allclose(fock.number_variances(Coherent(x, y).ket([80]), False)[0], x * x + y * y) + assert np.allclose(fock.number_variances(Coherent(x, y).dm([80]), True)[0], x * x + y * y) + + +def test_number_variances_fock(): + assert np.allclose(fock.number_variances(Fock(n=1).ket(), False), 0) + assert np.allclose(fock.number_variances(Fock(n=1).dm(), True), 0) + + +def test_normalize_dm(): + dm = np.array([[0.2, 0], [0, 0.2]]) + assert np.allclose(fock.normalize(dm, True), np.array([[0.5, 0], [0, 0.5]])) diff --git a/tests/test_physics/test_gaussian/test_gaussian_utils.py b/tests/test_physics/test_gaussian/test_gaussian_utils.py index 1698f48a9..9b87c64c4 100644 --- a/tests/test_physics/test_gaussian/test_gaussian_utils.py +++ b/tests/test_physics/test_gaussian/test_gaussian_utils.py @@ -13,7 +13,7 @@ # limitations under the License. import numpy as np -from hypothesis import given, strategies as st + from mrmustard import * from mrmustard.physics import gaussian as gp @@ -53,10 +53,30 @@ def test_partition_cov_2modes(): def test_partition_cov_3modes(): pass # TODO - # arr = np.array([[1,2,3,4,5,6], - # [7,8,9,10,11,12], - # [13,14,15,16,17,18], - # [19,20,21,22,23,24], - # [25,26,27,28,29,30], - # [31,32,33,34,35,36]]) - # A,B,AB = gp.partition_cov(gp.math.astensor(arr), Amodes=[0,2]) + +def test_CPTP_with_none_X(): + cov, means = gp.CPTP( + cov=np.eye(2), + means=np.zeros(2), + X=None, + Y=np.zeros((2, 2)), + d=np.zeros(2), + state_modes=[0], + transf_modes=[0], + ) + assert np.allclose(cov, np.eye(2)) + assert np.allclose(means, np.zeros(2)) + + +def test_CPTP_with_none_XYd(): + cov, means = gp.CPTP( + cov=np.eye(2), + means=np.zeros(2), + X=None, + Y=None, + d=None, + state_modes=[0], + transf_modes=[0], + ) + assert np.allclose(cov, np.eye(2)) + assert np.allclose(means, np.zeros(2)) diff --git a/tests/test_physics/test_gaussian/test_symplectics.py b/tests/test_physics/test_gaussian/test_symplectics.py index 09fa2dff2..832f89cc3 100644 --- a/tests/test_physics/test_gaussian/test_symplectics.py +++ b/tests/test_physics/test_gaussian/test_symplectics.py @@ -12,28 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest -from hypothesis import given, strategies as st - -from thewalrus.symplectic import two_mode_squeezing, squeezing, rotation, beam_splitter, expand import numpy as np +from hypothesis import given +from hypothesis import strategies as st +from thewalrus.symplectic import beam_splitter, expand, rotation, squeezing, two_mode_squeezing -from mrmustard import settings -from mrmustard.lab.gates import ( - Sgate, +from mrmustard.lab import ( + Amplifier, + Attenuator, BSgate, - S2gate, - Rgate, - MZgate, - Pgate, + Coherent, CXgate, CZgate, Dgate, - Amplifier, - Attenuator, + MZgate, + Pgate, + Rgate, + S2gate, + Sgate, ) -from mrmustard.lab.states import Vacuum, TMSV, Thermal -from mrmustard.physics.gaussian import quadratic_phase, controlled_Z, controlled_X +from mrmustard.lab.states import TMSV, Thermal, Vacuum +from mrmustard.physics.gaussian import controlled_X, controlled_Z @given(r=st.floats(0, 2)) @@ -135,7 +134,7 @@ def test_BSgate(theta, phi): @given(r=st.floats(0, 1), phi=st.floats(0, 2 * np.pi)) def test_S2gate(r, phi): """Tests the S2gate is implemented correctly by applying it on one half of a maximally entangled state""" - r_choi = settings.CHOI_R + r_choi = np.arcsinh(1.0) S2 = S2gate(r=r, phi=phi) bell = (TMSV(r_choi) & TMSV(r_choi)).get_modes([0, 2, 1, 3]) cov = (bell[0, 1, 2, 3] >> S2[0, 1]).cov @@ -150,7 +149,7 @@ def test_S2gate(r, phi): @given(phi_ex=st.floats(0, 2 * np.pi), phi_in=st.floats(0, 2 * np.pi)) def test_MZgate_external_tms(phi_ex, phi_in): """Tests the MZgate is implemented correctly by applying it on one half of a maximally entangled state""" - r_choi = settings.CHOI_R + r_choi = np.arcsinh(1.0) bell = (TMSV(r_choi) & TMSV(r_choi)).get_modes([0, 2, 1, 3]) MZ = MZgate(phi_a=phi_ex, phi_b=phi_in, internal=False) cov = (bell[0, 1, 2, 3] >> MZ[0, 1]).cov @@ -173,7 +172,7 @@ def test_MZgate_external_tms(phi_ex, phi_in): @given(phi_a=st.floats(0, 2 * np.pi), phi_b=st.floats(0, 2 * np.pi)) def test_MZgate_internal_tms(phi_a, phi_b): """Tests the MZgate is implemented correctly by applying it on one half of a maximally entangled state""" - r_choi = settings.CHOI_R + r_choi = np.arcsinh(1.0) bell = (TMSV(r_choi) & TMSV(r_choi)).get_modes([0, 2, 1, 3]) MZ = MZgate(phi_a=phi_a, phi_b=phi_b, internal=True) cov = (bell[0, 1, 2, 3] >> MZ[0, 1]).cov @@ -207,3 +206,9 @@ def test_amplifier_attenuator_on_coherent_coherent(eta, x, y): assert Vacuum(1) >> Dgate(x, y) >> Amplifier(1 / eta) >> Attenuator(eta) == Thermal( ((1 / eta) - 1) * eta ) >> Dgate(x, y) + + +@given(x=st.floats(-2, 2), y=st.floats(-2, 2)) +def test_number_means(x, y): + """Tests that the number means of a displaced state are correct""" + assert np.allclose(Coherent(x, y).number_means, x * x + y * y) diff --git a/tests/test_training/test_callbacks.py b/tests/test_training/test_callbacks.py new file mode 100644 index 000000000..0091b9ff5 --- /dev/null +++ b/tests/test_training/test_callbacks.py @@ -0,0 +1,72 @@ +# Copyright 2022 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""callbacks tests""" + +import numpy as np +import tensorflow as tf + +from mrmustard import settings +from mrmustard.lab.circuit import Circuit +from mrmustard.lab.gates import ( + BSgate, + S2gate, +) +from mrmustard.lab.states import Vacuum +from mrmustard.math import Math +from mrmustard.training import Optimizer, TensorboardCallback + +math = Math() + + +def test_tensorboard_callback(tmp_path): + """Tests tensorboard callbacks on hong-ou-mandel optimization.""" + settings.SEED = 42 + i, k = 2, 3 + r = np.arcsinh(1.0) + s2_0, s2_1, bs = ( + S2gate(r=r, phi=0.0, phi_trainable=True)[0, 1], + S2gate(r=r, phi=0.0, phi_trainable=True)[2, 3], + BSgate( + theta=np.arccos(np.sqrt(k / (i + k))) + 0.1 * settings.rng.normal(), + phi=settings.rng.normal(), + theta_trainable=True, + phi_trainable=True, + )[1, 2], + ) + circ = Circuit([s2_0, s2_1, bs]) + state_in = Vacuum(num_modes=4) + cutoff = 1 + i + k + + free_var = math.new_variable([1.1, -0.2], None, "free_var") + + def cost_fn(): + return tf.abs( + (state_in >> circ).ket(cutoffs=[cutoff] * 4)[i, 1, i + k - 1, k] + ) ** 2 + tf.reduce_sum(free_var**2) + + tbcb = TensorboardCallback( + steps_per_call=2, + root_logdir=tmp_path, + cost_converter=np.log10, + track_grads=True, + ) + + opt = Optimizer(euclidean_lr=0.01) + opt.minimize(cost_fn, by_optimizing=[circ, free_var], max_steps=300, callbacks={"tb": tbcb}) + + assert np.allclose(np.cos(bs.theta.value) ** 2, k / (i + k), atol=1e-2) + assert tbcb.logdir.exists() + assert len(list(tbcb.writter_logdir.glob("events*"))) > 0 + assert len(opt.callback_history["tb"]) == (len(opt.opt_history) - 1) // tbcb.steps_per_call diff --git a/tests/test_training/test_opt.py b/tests/test_training/test_opt.py index 48b4bfbf9..9db5b0797 100644 --- a/tests/test_training/test_opt.py +++ b/tests/test_training/test_opt.py @@ -31,11 +31,12 @@ S2gate, Sgate, ) -from mrmustard.lab.states import DisplacedSqueezed, SqueezedVacuum, Vacuum +from mrmustard.lab.states import DisplacedSqueezed, Fock, Gaussian, SqueezedVacuum, Vacuum from mrmustard.math import Math from mrmustard.physics import fidelity from mrmustard.physics.gaussian import trace, von_neumann_entropy from mrmustard.training import Optimizer, Parametrized +from mrmustard.training.callbacks import Callback math = Math() @@ -43,7 +44,7 @@ @given(n=st.integers(0, 3)) def test_S2gate_coincidence_prob(n): """Testing the optimal probability of obtaining |n,n> from a two mode squeezed vacuum""" - settings.SEED = 42 + settings.SEED = 40 S = S2gate( r=abs(settings.rng.normal(loc=1.0, scale=0.1)), r_trainable=True, @@ -52,12 +53,24 @@ def test_S2gate_coincidence_prob(n): def cost_fn(): return -math.abs((Vacuum(2) >> S[0, 1]).ket(cutoffs=[n + 1, n + 1])[n, n]) ** 2 + def cb(optimizer, cost, trainables, **kwargs): # pylint: disable=unused-argument + return { + "cost": cost, + "lr": optimizer.learning_rate["euclidean"], + "num_trainables": len(trainables), + } + opt = Optimizer(euclidean_lr=0.01) - opt.minimize(cost_fn, by_optimizing=[S], max_steps=300) + opt.minimize(cost_fn, by_optimizing=[S], max_steps=300, callbacks=cb) expected = 1 / (n + 1) * (n / (n + 1)) ** n assert np.allclose(-cost_fn(), expected, atol=1e-5) + cb_result = opt.callback_history.get("cb") + assert {res["num_trainables"] for res in cb_result} == {1} + assert {res["lr"] for res in cb_result} == {0.01} + assert [res["cost"] for res in cb_result] == opt.opt_history[1:] + @given(i=st.integers(1, 5), k=st.integers(1, 5)) def test_hong_ou_mandel_optimizer(i, k): @@ -86,8 +99,15 @@ def cost_fn(): return math.abs((state_in >> circ).ket(cutoffs=[cutoff] * 4)[i, 1, i + k - 1, k]) ** 2 opt = Optimizer(euclidean_lr=0.01) - opt.minimize(cost_fn, by_optimizing=[circ], max_steps=300) + opt.minimize( + cost_fn, + by_optimizing=[circ], + max_steps=300, + callbacks=[Callback(tag="null_cb", steps_per_call=3)], + ) assert np.allclose(np.cos(bs.theta.value) ** 2, k / (i + k), atol=1e-2) + assert "null_cb" in opt.callback_history + assert len(opt.callback_history["null_cb"]) == (len(opt.opt_history) - 1) // 3 def test_learning_two_mode_squeezing(): @@ -95,8 +115,8 @@ def test_learning_two_mode_squeezing(): settings.SEED = 42 ops = [ Sgate( - r=abs(settings.rng.normal(size=(2))), - phi=settings.rng.normal(size=(2)), + r=abs(settings.rng.normal(size=2)), + phi=settings.rng.normal(size=2), r_trainable=True, phi_trainable=True, ), @@ -126,7 +146,7 @@ def test_learning_two_mode_Ggate(): G = Ggate(num_modes=2, symplectic_trainable=True) def cost_fn(): - amps = (Vacuum(2) >> G).ket(cutoffs=[2, 2]) + amps = (Vacuum(2) >> G).ket(cutoffs=[2, 2], max_prob=0.9999) return -math.abs(amps[1, 1]) ** 2 + math.abs(amps[0, 1]) ** 2 opt = Optimizer(symplectic_lr=0.5, euclidean_lr=0.01) @@ -140,8 +160,8 @@ def test_learning_two_mode_Interferometer(): settings.SEED = 42 ops = [ Sgate( - r=settings.rng.normal(size=(2)) ** 2, - phi=settings.rng.normal(size=(2)), + r=settings.rng.normal(size=2) ** 2, + phi=settings.rng.normal(size=2), r_trainable=True, phi_trainable=True, ), @@ -165,8 +185,8 @@ def test_learning_two_mode_RealInterferometer(): settings.SEED = 2 ops = [ Sgate( - r=settings.rng.normal(size=(2)) ** 2, - phi=settings.rng.normal(size=(2)), + r=settings.rng.normal(size=2) ** 2, + phi=settings.rng.normal(size=2), r_trainable=True, phi_trainable=True, ), @@ -223,7 +243,7 @@ def test_learning_four_mode_Interferometer(): >> BSgate(settings.rng.normal(scale=0.01), modes=[1, 2]) >> BSgate(settings.rng.normal(scale=0.01), modes=[0, 3]) ) - X = math.cast(perturbed.XYd[0], "complex128") + X = math.cast(perturbed.XYd()[0], "complex128") perturbed_U = X[:4, :4] + 1j * X[4:, :4] ops = [ @@ -263,7 +283,7 @@ def test_learning_four_mode_RealInterferometer(): >> BSgate(settings.rng.normal(scale=0.01), modes=[1, 2]) >> BSgate(settings.rng.normal(scale=0.01), modes=[0, 3]) ) - perturbed_O = pertubed.XYd[0][:4, :4] + perturbed_O = pertubed.XYd()[0][:4, :4] ops = [ Sgate( @@ -386,12 +406,87 @@ def test_dgate_optimization(): settings.SEED = 24 dgate = Dgate(x_trainable=True, y_trainable=True) - target_state = DisplacedSqueezed(r=0.0, x=1.0, y=1.0) + target_state = DisplacedSqueezed(r=0.0, x=0.1, y=0.2).ket(cutoffs=[40]) def cost_fn(): state_out = Vacuum(1) >> dgate - - return 1 - fidelity(state_out, target_state) + return -math.abs(math.sum(math.conj(state_out.ket([40])) * target_state)) ** 2 opt = Optimizer() opt.minimize(cost_fn, by_optimizing=[dgate]) + + assert np.allclose(dgate.x.value, 0.1, atol=0.01) + assert np.allclose(dgate.y.value, 0.2, atol=0.01) + + +def test_sgate_optimization(): + """Test that Sgate is optimized correctly.""" + settings.SEED = 25 + + sgate = Sgate(r=0.2, phi=0.1, r_trainable=True, phi_trainable=True) + target_state = SqueezedVacuum(r=0.1, phi=0.2).ket(cutoffs=[40]) + + def cost_fn(): + state_out = Vacuum(1) >> sgate + + return -math.abs(math.sum(math.conj(state_out.ket([40])) * target_state)) ** 2 + + opt = Optimizer() + opt.minimize(cost_fn, by_optimizing=[sgate]) + + assert np.allclose(sgate.r.value, 0.1, atol=0.01) + assert np.allclose(sgate.phi.value, 0.2, atol=0.01) + + +def test_bsgate_optimization(): + """Test that Sgate is optimized correctly.""" + settings.SEED = 25 + + G = Gaussian(2) + + bsgate = BSgate(0.05, 0.1, theta_trainable=True, phi_trainable=True) + target_state = (G >> BSgate(0.1, 0.2)).ket(cutoffs=[40, 40]) + + def cost_fn(): + state_out = G >> bsgate + + return -math.abs(math.sum(math.conj(state_out.ket([40, 40])) * target_state)) ** 2 + + opt = Optimizer() + opt.minimize(cost_fn, by_optimizing=[bsgate]) + + assert np.allclose(bsgate.theta.value, 0.1, atol=0.01) + assert np.allclose(bsgate.phi.value, 0.2, atol=0.01) + + +def test_squeezing_grad_from_fock(): + """Test that the gradient of a squeezing gate is computed from the fock representation.""" + squeezing = Sgate(r=1, r_trainable=True) + + def cost_fn(): + return -(Fock(2) >> squeezing << Vacuum(1)) + + opt = Optimizer(euclidean_lr=0.05) + opt.minimize(cost_fn, by_optimizing=[squeezing], max_steps=100) + + +def test_displacement_grad_from_fock(): + """Test that the gradient of a displacement gate is computed from the fock representation.""" + disp = Dgate(x=1.0, y=1.0, x_trainable=True, y_trainable=True) + + def cost_fn(): + return -(Fock(2) >> disp << Vacuum(1)) + + opt = Optimizer(euclidean_lr=0.05) + opt.minimize(cost_fn, by_optimizing=[disp], max_steps=100) + + +def test_bsgate_grad_from_fock(): + """Test that the gradient of a beamsplitter gate is computed from the fock representation.""" + sq = SqueezedVacuum(r=1.0, r_trainable=True) + + def cost_fn(): + return -((sq & Fock(1)) >> BSgate(0.5) << (Vacuum(1) & Fock(1))) + + opt = Optimizer(euclidean_lr=0.05) + opt.minimize(cost_fn, by_optimizing=[sq], max_steps=100) diff --git a/tests/test_training/test_parametrized.py b/tests/test_training/test_parametrized.py index 171dc4685..55ca3f7b4 100644 --- a/tests/test_training/test_parametrized.py +++ b/tests/test_training/test_parametrized.py @@ -115,6 +115,18 @@ def test_get_parameters(): assert len(constant_params) == 2 assert all(isinstance(param, Constant) for param in constant_params) + trainable_params = parametrized.traverse_trainables(owner_tag="foo") + assert len(trainable_params) == 4 + assert all(isinstance(param, Trainable) for param in trainable_params.values()) + assert all(tag.startswith("foo") for tag in trainable_params) + assert all(tag.split("/")[1] in kwargs for tag in trainable_params) + + constant_params = parametrized.traverse_constants() + assert len(constant_params) == 2 + assert all(isinstance(param, Constant) for param in constant_params.values()) + assert all(tag.startswith("Parametrized") for tag in constant_params) + assert all(tag.split("/")[1] in kwargs for tag in constant_params) + def test_get_nested_parameters(): """Test that nested Parametrized objects (e.g. a circuit) return all the trainable @@ -137,3 +149,13 @@ def test_get_nested_parameters(): assert (s2.phi in trainables) and (bs.theta in trainables) assert (s2.r in constants) and (bs.phi in constants) + + trainables = circ.traverse_trainables() + constants = circ.traverse_constants("Device") + assert len(trainables) == 2 + assert len(constants) == 2 + assert all(tag.startswith("Circuit/_ops[") for tag in trainables) + assert all(tag.startswith("Device/_ops[") for tag in constants) + + assert (s2.phi in trainables.values()) and (bs.theta in trainables.values()) + assert (s2.r in constants.values()) and (bs.phi in constants.values()) diff --git a/tests/test_utils/test_wigner.py b/tests/test_utils/test_wigner.py index 8ade9e656..60395d3b8 100644 --- a/tests/test_utils/test_wigner.py +++ b/tests/test_utils/test_wigner.py @@ -14,20 +14,21 @@ """This module contains test for the calculation of the discretized Wigner function.""" -import pytest import numpy as np +import pytest from scipy.stats import multivariate_normal -from mrmustard.utils.wigner import wigner_discretized + +from mrmustard import settings from mrmustard.lab import ( - Vacuum, Coherent, - SqueezedVacuum, - Thermal, DisplacedSqueezed, - Gaussian, Fock, + Gaussian, + SqueezedVacuum, + Thermal, + Vacuum, ) -from mrmustard import settings +from mrmustard.utils.wigner import wigner_discretized def multivariate_normal_pdf(qvec, pvec, means, cov):