diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a8a43dfd..12c6b78f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python 3.9 - uses: actions/setup-python@v4.7.1 + uses: actions/setup-python@v5.1.0 with: python-version: 3.9 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 85c35645..2b3157eb 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python 3.9 - uses: actions/setup-python@v4.7.1 + uses: actions/setup-python@v5.1.0 with: python-version: 3.9 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 49f4f9b0..057c062d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python 3.9 - uses: actions/setup-python@v4.7.1 + uses: actions/setup-python@v5.1.0 with: python-version: 3.9 diff --git a/.gitignore b/.gitignore index ca0dca44..4b891006 100644 --- a/.gitignore +++ b/.gitignore @@ -133,3 +133,6 @@ dmypy.json # Pyre type checker .pyre/ .DS_Store + +# Data folders +data/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3e8f321a..e1cb2566 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 24.3.0 hooks: - id: black entry: black . @@ -33,13 +33,13 @@ repos: pass_filenames: false - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.9.0 hooks: - id: mypy exclude: '(^examples|^docs)/.*' - repo: https://github.com/python-poetry/poetry - rev: 1.7.0 + rev: 1.8.0 hooks: - id: poetry-check - id: poetry-export diff --git a/.readthedocs.yml b/.readthedocs.yml index 7c3a951b..a426e9ef 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,9 +6,9 @@ build: python: "3.9" sphinx: - configuration: docs/conf.py + configuration: docs/source/conf.py python: install: - - requirements: docs/requirements.txt + - requirements: docs/source/requirements.txt - requirements: requirements.txt diff --git a/LICENSE.md b/LICENSE.md index 03c9dd0f..387a9345 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Aleksandr Berezutskii +Copyright (c) 2024 Aleksandr Berezutskii Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 30ff8c2f..d92c46cf 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [![codecov](https://codecov.io/gh/quicophy/mdopt/branch/main/graph/badge.svg?token=4G7VWYX0S2)](https://codecov.io/gh/quicophy/mdopt) -[![tests](https://github.com/quicophy/mdopt/actions/workflows/tests.yml/badge.svg)](https://github.com/quicophy/mdopt/actions/workflows/tests.yml) +[![tests](https://github.com/quicophy/mdopt/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/quicophy/mdopt/actions/workflows/tests.yml) [![Documentation Status](https://readthedocs.org/projects/mdopt/badge/?version=latest)](https://mdopt.readthedocs.io/en/latest/?badge=latest) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/quicophy/mdopt/main.svg)](https://results.pre-commit.ci/latest/github/quicophy/mdopt/main) [![lint](https://github.com/quicophy/mdopt/actions/workflows/lint.yml/badge.svg)](https://github.com/quicophy/mdopt/actions/workflows/lint.yml) -[![mypy](https://github.com/quicophy/mdopt/actions/workflows/mypy.yml/badge.svg)](https://github.com/quicophy/mdopt/actions/workflows/mypy.yml) +[![mypy](https://github.com/quicophy/mdopt/actions/workflows/mypy.yml/badge.svg?branch=main)](https://github.com/quicophy/mdopt/actions/workflows/mypy.yml) [![Unitary Fund](https://img.shields.io/badge/Supported%20By-Unitary%20Fund-brightgreen.svg?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACgAAAASCAYAAAApH5ymAAAAt0lEQVRIic2WUQ6AIAiGsXmC7n9Gr1Dzwcb%2BUAjN8b%2B0BNwXApbKRRcF1nGmN5y0Jon7WWO%2B6pgJLhtynzUHKTMNrNo4ZPPldikW10f7qYBEMoTmJ73z2NFHcJkAvbLUpVYmvwIigKeRsjdQEtagZ2%2F0DzsHG2h9iICrRwh2qObbGPIfMDPCMjHNQawpbc71bBZhsrpNYs3qqCFmO%2FgBjHTEqKm7eIdMg9p7PCvma%2Fz%2FwQAMfRHRDTlhQGoOLve1AAAAAElFTkSuQmCC)](http://unitary.fund) [![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/) diff --git a/docs/README.rst b/docs/README.rst deleted file mode 100644 index 079fa563..00000000 --- a/docs/README.rst +++ /dev/null @@ -1,45 +0,0 @@ - - -.. image:: https://codecov.io/gh/quicophy/mdopt/branch/main/graph/badge.svg?token=4G7VWYX0S2 - :target: https://codecov.io/gh/quicophy/mdopt - :alt: codecov - - -.. image:: https://github.com/quicophy/mdopt/actions/workflows/tests.yml/badge.svg - :target: https://github.com/quicophy/mdopt/actions/workflows/tests.yml - :alt: tests - - -.. image:: https://readthedocs.org/projects/mdopt/badge/?version=latest - :target: https://mdopt.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - - -.. image:: https://img.shields.io/badge/License-MIT-blue.svg - :target: https://lbesson.mit-license.org/ - :alt: MIT license - - -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Code style: black - - -mdopt -===== - -mdopt is a python package built on top of numpy for discrete optimisation in the tensor-network (specifically, MPS-MPO) language. The code is hosted on github, so please feel free to submit issues and pull requests. - -Installation ------------- - -Use the package manager `pip `_ to install mdopt. - -.. code-block:: bash - - pip install mdopt - -Usage ------ - -For usage, see the examples folder. diff --git a/docs/contractor.rst b/docs/contractor.rst deleted file mode 100644 index e8181c7e..00000000 --- a/docs/contractor.rst +++ /dev/null @@ -1,11 +0,0 @@ -Contractor module -======================== - - -The Contractor submodule ----------------------------------- - -.. automodule:: mdopt.contractor.contractor - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/examples.rst b/docs/examples.rst deleted file mode 100644 index 98a957a8..00000000 --- a/docs/examples.rst +++ /dev/null @@ -1,9 +0,0 @@ -examples ------------ - -.. toctree:: - :maxdepth: 4 - - examples/main_component/main_component.ipynb - examples/decoding/classical.ipynb - examples/decoding/quantum.ipynb diff --git a/docs/examples/__init__.py b/docs/examples/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/examples/decoding/__init__.py b/docs/examples/decoding/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/examples/decoding/classical.ipynb b/docs/examples/decoding/classical.ipynb deleted file mode 100644 index c9bda623..00000000 --- a/docs/examples/decoding/classical.ipynb +++ /dev/null @@ -1,250 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this experiment, we decode a classical linear error correcting code.\n", - "First, we build the MPS containing the superposition of all codewords.\n", - "Then, we demostrate simple decoding of a classical LDPC code using Dephasing DMRG --\n", - "our own built-in DMRG-like optimisation algorithm to solve the main component problem --\n", - "the problem of finding a computational basis state cotributing the most to a given state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qecstruct as qec\n", - "from mdopt.optimiser.utils import (\n", - " ConstraintString,\n", - " IDENTITY,\n", - " SWAP,\n", - " XOR_BULK,\n", - " XOR_LEFT,\n", - " XOR_RIGHT,\n", - ")\n", - "from examples.decoding.decoding import (\n", - " linear_code_constraint_sites,\n", - " linear_code_prepare_message,\n", - " linear_code_codewords,\n", - ")\n", - "from examples.decoding.decoding import (\n", - " apply_bias_channel,\n", - " apply_constraints,\n", - " decode,\n", - ")\n", - "from mdopt.mps.utils import create_simple_product_state, create_custom_product_state\n", - "from mdopt.utils.utils import mpo_to_matrix" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Fixing a random seed\n", - "SEED = 123\n", - "\n", - "tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", - "\n", - "# Defining the parameters of a classical LDPC code.\n", - "NUM_BITS, NUM_CHECKS = 10, 6\n", - "CHECK_DEGREE, BIT_DEGREE = 5, 3\n", - "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", - " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", - "\n", - "# Constructing the code as a qecstruct object.\n", - "example_code = qec.random_regular_code(\n", - " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", - ")\n", - "\n", - "# Preparing the initial state.\n", - "state = create_simple_product_state(NUM_BITS, which=\"+\")\n", - "state_dense = state.dense(flatten=True)\n", - "\n", - "# Getting the sites where each string of constraints should be applied.\n", - "code_constraint_sites = linear_code_constraint_sites(example_code)\n", - "\n", - "print(\"\")\n", - "print(\"Checking the codeword superposition state:\")\n", - "print(\"\")\n", - "\n", - "# Preparing the codeword superposition state by the MPS-MPO evolution.\n", - "state = apply_constraints(state, code_constraint_sites, tensors)\n", - "\n", - "# Preparing the codeword superposition state in the dense form.\n", - "for j in range(NUM_CHECKS):\n", - "\n", - " # Preparing the MPO.\n", - " constraint_string = ConstraintString(tensors, code_constraint_sites[j])\n", - " constraint_mpo = constraint_string.mpo()\n", - "\n", - " # Finding the starting site of the MPS to build a correct dense-form operator.\n", - " START_SITE = min(constraint_string.flat())\n", - "\n", - " # Preparing the dense-form operator.\n", - " identities_l = [IDENTITY for _ in range(START_SITE)]\n", - " identities_r = [\n", - " IDENTITY for _ in range(NUM_BITS - len(constraint_mpo) - START_SITE)\n", - " ]\n", - " full_mpo = identities_l + constraint_mpo + identities_r\n", - " mpo_dense = mpo_to_matrix(full_mpo, interlace=False, group=True)\n", - "\n", - " # Doing the contraction in dense form.\n", - " state_dense = mpo_dense @ state_dense\n", - "\n", - "# Tolerance under which we round tensor elements to zero.\n", - "TOL = 1e-12\n", - "mps_dense = state.dense(flatten=True)\n", - "mps_dense[np.abs(mps_dense) < TOL] = 0\n", - "\n", - "# Retreiving codewords.\n", - "cwords = linear_code_codewords(example_code)\n", - "cwords_to_compare_mps = np.flatnonzero(mps_dense)\n", - "cwords_to_compare_dense = np.flatnonzero(state_dense)\n", - "\n", - "print()\n", - "print(\"Codewords from the generator matrix:\")\n", - "print(cwords)\n", - "print(\"Codewords from the dense-form simulation:\")\n", - "print(cwords_to_compare_mps)\n", - "print(\"Codewords from the MPS-form simulation:\")\n", - "print(cwords_to_compare_dense)\n", - "print(\"\")\n", - "print(\n", - " \"All lists of codewords match:\",\n", - " np.logical_and(\n", - " np.array_equal(cwords, cwords_to_compare_mps),\n", - " np.array_equal(cwords_to_compare_mps, cwords_to_compare_dense),\n", - " ),\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"\")\n", - "print(\"Retreiving a perturbed codeword:\")\n", - "print(\"\")\n", - "\n", - "# Defining the parameters of a classical LDPC code.\n", - "NUM_BITS, NUM_CHECKS = 16, 12\n", - "CHECK_DEGREE, BIT_DEGREE = 4, 3\n", - "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", - " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", - "\n", - "# Defining the bias channel parameter and the error probability.\n", - "PROB_ERROR = 0.15\n", - "PROB_CHANNEL = PROB_ERROR\n", - "\n", - "# Maximum bond dimension for contractor/DMRG.\n", - "CHI_MAX_CONTRACTOR = 1e4\n", - "CHI_MAX_DMRG = 1e4\n", - "# Number of DMRG sweeps.\n", - "NUM_RUNS = 1\n", - "\n", - "# Constructing the code as a qecstruct object.\n", - "example_code = qec.random_regular_code(\n", - " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", - ")\n", - "\n", - "# Getting the sites where each string of constraints should be applied.\n", - "code_constraint_sites = linear_code_constraint_sites(example_code)\n", - "\n", - "# Building an initial and a perturbed codeword.\n", - "INITIAL_CODEWORD, PERTURBED_CODEWORD = linear_code_prepare_message(\n", - " example_code, PROB_ERROR, error_model=qec.BinarySymmetricChannel, seed=SEED\n", - ")\n", - "print(\"The initial codeword is\", INITIAL_CODEWORD)\n", - "print(\"The perturbed codeword is\", PERTURBED_CODEWORD)\n", - "print(\"\")\n", - "\n", - "# Building the corresponding matrix product states.\n", - "initial_codeword_state = create_custom_product_state(\n", - " INITIAL_CODEWORD, form=\"Right-canonical\"\n", - ")\n", - "perturbed_codeword_state = create_custom_product_state(\n", - " PERTURBED_CODEWORD, form=\"Right-canonical\"\n", - ")\n", - "\n", - "# Passing the perturbed codeword state through the bias channel.\n", - "perturbed_codeword_state = apply_bias_channel(\n", - " basis_mps=perturbed_codeword_state,\n", - " basis_string=PERTURBED_CODEWORD,\n", - " prob_channel=PROB_CHANNEL,\n", - ")\n", - "\n", - "print(\"Applying constraints:\")\n", - "print(\"\")\n", - "# Applying the parity constraints defined by the code.\n", - "perturbed_codeword_state = apply_constraints(\n", - " perturbed_codeword_state,\n", - " code_constraint_sites,\n", - " tensors,\n", - " chi_max=CHI_MAX_CONTRACTOR,\n", - " renormalise=True,\n", - " strategy=\"naive\",\n", - " silent=False,\n", - ")\n", - "\n", - "print(\"\")\n", - "print(\"Decoding:\")\n", - "print(\"\")\n", - "# Decoding the perturbed codeword.\n", - "dmrg_container, success = decode(\n", - " message=perturbed_codeword_state,\n", - " codeword=initial_codeword_state,\n", - " code=example_code,\n", - " num_runs=NUM_RUNS,\n", - " chi_max_dmrg=CHI_MAX_DMRG,\n", - " cut=1e-10,\n", - " silent=False,\n", - ")\n", - "print(\"\")\n", - "print(\n", - " \"The overlap of the density MPO main component and the initial codeword state: \",\n", - " success,\n", - ")\n", - "print(\n", - " \"__________________________________________________________________________________________\"\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "mdopt-ZdbamFdU-py3.9", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.2" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "cd00668ec6929851fcf19d7aebdf8f5927f35d0f54b527f252ebcdaf64fd8c43" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/docs/examples/decoding/decoding.py b/docs/examples/decoding/decoding.py deleted file mode 100644 index e31a1108..00000000 --- a/docs/examples/decoding/decoding.py +++ /dev/null @@ -1,623 +0,0 @@ -""" -Below, we define some decoding-specific functions over the MPS/MPO entities -we encounter during the decoding process as well as the functions we use -to generate and operate over both classical and quantum error correcting codes. -""" - -from functools import reduce -from typing import cast, Union, Optional, List, Tuple - -import numpy as np -from tqdm import tqdm -import qecstruct as qec -from more_itertools import powerset - -from mdopt.mps.explicit import ExplicitMPS -from mdopt.mps.canonical import CanonicalMPS -from mdopt.mps.utils import find_orth_centre, inner_product, create_simple_product_state -from mdopt.contractor.contractor import apply_one_site_operator, mps_mpo_contract -from mdopt.optimiser.dephasing_dmrg import DephasingDMRG -from mdopt.optimiser.utils import ConstraintString - - -def bias_channel(p_bias: np.float32 = np.float32(0.5), which: str = "0") -> np.ndarray: - """ - Here, we define bias channel -- an operator which will bias us towards the initial message - while decoding by ranking the bitstrings according to Hamming distance from the latter. - This function returns a one-site bias channel MPO which - acts on one-qubit computational basis states as follows: - |0> -> √(1-p)|0> + √p|1>, - |1> -> √(1-p)|1> + √p|0>, - Note, that this operation is unitary, which means that it preserves the canonical form. - - Parameters - ---------- - p_bias : np.float32 - Probability of the channel. - which : str - "0" or "1", depending on which one-qubit basis state we are acting on. - - Returns - ------- - b_ch : np.ndarray - The corresponding one-site MPO. - """ - - if not 0 <= p_bias <= 1: - raise ValueError( - f"The channel parameter `p_bias` should be a probability, " - f"given {p_bias}." - ) - if which not in ["0", "1", "+"]: - raise ValueError("Invalid one-qubit basis state given.") - - if which == "0": - b_channel = np.array( - [ - [np.sqrt(1 - p_bias), np.sqrt(p_bias)], - [np.sqrt(p_bias), -np.sqrt(1 - p_bias)], - ] - ) - if which == "1": - b_channel = np.array( - [ - [-np.sqrt(1 - p_bias), np.sqrt(p_bias)], - [np.sqrt(p_bias), np.sqrt(1 - p_bias)], - ] - ) - if which == "+": - b_channel = np.array( - [ - [1.0, 0.0], - [0.0, 1.0], - ] - ) - - return b_channel - - -def apply_bias_channel( - basis_mps: Union[ExplicitMPS, CanonicalMPS], - basis_string: str, - prob_channel: np.float32 = np.float32(0.5), -) -> Union[ExplicitMPS, CanonicalMPS]: - """ - The function which applies a bias channel to a computational-basis-state MPS. - - Parameters - ---------- - basis_mps : Union[ExplicitMPS, CanonicalMPS] - The computational-basis-state MPS, e.g., ``|010010>``. - basis_string : str - The string of "0", "1" and "+" which corresponds to ``basis_mps``. - prob_channel : np.float32 - The bias channel probability. - - - Returns - ------- - biased_mps : CanonicalMPS - The resulting MPS. - """ - - if len(basis_mps) != len(basis_string): - raise ValueError( - f"The lengths of `basis_mps` and `codeword_string` should be equal, but given the " - f"MPS of length {len(basis_mps)} and the string of length {len(basis_string)}." - ) - - biased_mps_tensors = [] - for i, mps_tensor in enumerate(basis_mps.tensors): - biased_mps_tensors.append( - apply_one_site_operator( - tensor=mps_tensor, - operator=bias_channel(prob_channel, which=basis_string[i]), - ) - ) - - if isinstance(basis_mps, ExplicitMPS): - return ExplicitMPS( - tensors=biased_mps_tensors, - singular_values=basis_mps.singular_values, - tolerance=basis_mps.tolerance, - chi_max=basis_mps.chi_max, - ) - - if isinstance(basis_mps, CanonicalMPS): - return CanonicalMPS( - tensors=biased_mps_tensors, - orth_centre=basis_mps.orth_centre, - tolerance=basis_mps.tolerance, - chi_max=basis_mps.chi_max, - ) - - -# Below, we define some utility functions to operate with data structures from `qecstruct` -- -# an error-correction library we are using in this example. - - -def bin_vec_to_dense(vector: "qec.sparse.BinaryVector") -> np.ndarray: - """ - Given a vector (1D array) in the ``qecstruct.sparse.BinaryVector`` format - (native to ``qecstruct``), returns its dense representation. - - Parameters - ---------- - vector : qec.sparse.BinaryVector - The vector we want to densify. - - Returns - ------- - array : np.ndarray - The dense representation. - """ - - array = np.zeros(vector.len(), dtype=int) - for pos in vector: - array[pos] = 1 - return array - - -def linear_code_checks(code: "qec.LinearCode") -> List[List[int]]: - """ - Given a linear code, returns a list of its checks, where each check - is represented as a list of indices of the bits touched by it. - - Parameters - ---------- - code : qec.LinearCode - Linear code object. - - Returns - ------- - checks : List[List[int]] - List of checks. - """ - - parity_matrix = code.par_mat() - array = np.zeros((parity_matrix.num_rows(), parity_matrix.num_columns()), dtype=int) - for row, cols in enumerate(parity_matrix.rows()): - for col in cols: - array[row, col] = 1 - return [list(np.nonzero(row)[0]) for row in array] - - -def linear_code_constraint_sites(code: "qec.LinearCode") -> List[List[List[int]]]: - """ - Returns the list of MPS sites where the logical constraints should be applied. - - Parameters - ---------- - code : qec.LinearCode - Linear code object. - - Returns - ------- - strings : List[List[List[int]]] - List of MPS sites. - """ - - sites_all = linear_code_checks(code) - check_degree = len(sites_all[0]) - constraints_strings = [] - - for sites in sites_all: - # Retreiving the sites indices where we apply the "bulk"/"boundary" XOR tensors. - xor_left_sites = [sites[0]] - xor_bulk_sites = [sites[i] for i in range(1, check_degree - 1)] - xor_right_sites = [sites[-1]] - - # Retreiving the sites indices where we apply the SWAP tensors. - swap_sites = list(range(sites[0] + 1, sites[-1])) - for k in range(1, check_degree - 1): - swap_sites.remove(sites[k]) - - constraints_strings.append( - [xor_left_sites, xor_bulk_sites, swap_sites, xor_right_sites] - ) - - return cast(List[List[List[int]]], constraints_strings) - - -def linear_code_codewords(code: "qec.LinearCode") -> np.ndarray: - """ - Returns the list of codewords of a linear code. Codewords are returned - as integers in most-significant-bit-first convention. - - Parameters - ---------- - code : qec.LinearCode - Linear code object. - - Returns - ------- - codewords : np.ndarray - The codewords. - """ - - codewords = [] - - gen_mat = code.gen_mat() - rows_bin = gen_mat.rows() - rows_dense = [bin_vec_to_dense(row_bin) for row_bin in rows_bin] - rows_int = [row.dot(1 << np.arange(row.size)[::-1]) for row in rows_dense] - - # Append the all-zeros codeword which is always a codeword. - codewords.append(0) - - # Append the rows of the generator matrix. - for basis_codeword in rows_int: - codewords.append(basis_codeword) - - # Append all linear combinations. - for generators in powerset(rows_int): - if len(generators) > 1: - codewords.append(reduce(np.bitwise_xor, generators)) - - return np.sort(np.array(codewords)) - - -def css_code_checks(code: qec.CssCode) -> Tuple[List[int]]: - """ - Given a quantum CSS code, returns a list of its checks, where each check - is represented as a list of indices of the bits adjacent to it. - - Parameters - ---------- - code : qec.CssCode - The CSS code object. - - Returns - ------- - checks : Tuple[List[List[int]] - A tuple of two lists, where the first one corresponds to X checks and - the second one -- to Z checks. - """ - - parity_matrix_x = code.x_stabs_binary() - array_x = np.zeros( - (parity_matrix_x.num_rows(), parity_matrix_x.num_columns()), dtype=int - ) - for row, cols in enumerate(parity_matrix_x.rows()): - for col in cols: - array_x[row, col] = 1 - - parity_matrix_z = code.z_stabs_binary() - array_z = np.zeros( - (parity_matrix_z.num_rows(), parity_matrix_z.num_columns()), dtype=int - ) - for row, cols in enumerate(parity_matrix_z.rows()): - for col in cols: - array_z[row, col] = 1 - - checks_x = [ - 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() - for row in array_x - ] - checks_x = [list(check_x) for check_x in checks_x] - checks_z = [ - 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() + 1 - for row in array_z - ] - checks_z = [list(check_z) for check_z in checks_z] - - return checks_x, checks_z - - -def css_code_constraint_sites(code: qec.CssCode) -> Tuple[List[int]]: - """ - Returns the list of MPS sites where the logical constraints should be applied. - - Parameters - ---------- - code : qec.CssCode - CSS code object. - - Returns - ------- - strings : Tuple[List[int]] - List of MPS sites. - """ - - sites_x, sites_z = css_code_checks(code) - - constraints_strings_x = [] - constraints_strings_z = [] - - for sites in sites_x: - xor_left_sites_x = [sites[0]] - xor_bulk_sites_x = [sites[i] for i in range(1, len(sites) - 1)] - xor_right_sites_x = [sites[-1]] - - swap_sites_x = list(range(sites[0] + 1, sites[-1])) - for k in range(1, len(sites) - 1): - swap_sites_x.remove(sites[k]) - - constraints_strings_x.append( - [xor_left_sites_x, xor_bulk_sites_x, swap_sites_x, xor_right_sites_x] - ) - - for sites in sites_z: - xor_left_sites_z = [sites[0]] - xor_bulk_sites_z = [sites[i] for i in range(1, len(sites) - 1)] - xor_right_sites_z = [sites[-1]] - - swap_sites_z = list(range(sites[0] + 1, sites[-1])) - for k in range(1, len(sites) - 1): - swap_sites_z.remove(sites[k]) - - constraints_strings_z.append( - [xor_left_sites_z, xor_bulk_sites_z, swap_sites_z, xor_right_sites_z] - ) - - return constraints_strings_x, constraints_strings_z - - -def css_code_logicals(code: qec.CssCode): - """ - Returns the list of MPS sites where the logical constraints should be applied. - - Parameters - ---------- - code : qec.CssCode - The CSS code object. - - Returns - ------- - logicals : Tuple[List[int]] - List of logical operators, first X, then Z. - """ - - log_matrix_x = code.z_logicals_binary() - array_x = np.zeros((log_matrix_x.num_rows(), log_matrix_x.num_columns()), dtype=int) - for row, cols in enumerate(log_matrix_x.rows()): - for col in cols: - array_x[row, col] = 1 - - log_matrix_z = code.x_logicals_binary() - array_z = np.zeros((log_matrix_z.num_rows(), log_matrix_z.num_columns()), dtype=int) - for row, cols in enumerate(log_matrix_z.rows()): - for col in cols: - array_z[row, col] = 1 - - x_logicals = [ - 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() + 1 - for row in array_x - ] - x_logicals = [list(x_logical) for x_logical in x_logicals] - z_logicals = [ - 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() - for row in array_z - ] - z_logicals = [list(z_logical) for z_logical in z_logicals] - - return z_logicals[0], x_logicals[0] - - -def css_code_logicals_sites(code: qec.CssCode) -> Tuple[List[int]]: - """ - Returns the list of MPS sites where the logical operators should be applied. - - Parameters - ---------- - code : qec.CssCode - CSS code object. - - Returns - ------- - strings : Tuple[List[int]] - List of MPS sites. - """ - - sites_x, sites_z = css_code_logicals(code) - - copy_site_x = [0] - copy_site_z = [1] - - xor_right_site_x = [sites_x[-1]] - xor_right_site_z = [sites_z[-1]] - - xor_bulk_sites_x = [sites_x[i] for i in range(len(sites_x) - 1)] - xor_bulk_sites_z = [sites_z[i] for i in range(len(sites_z) - 1)] - - swap_sites_x = list(range(copy_site_x[0] + 1, xor_right_site_x[0])) - swap_sites_x = [site for site in swap_sites_x if site not in xor_bulk_sites_x] - swap_sites_z = list(range(copy_site_z[0] + 1, xor_right_site_z[0])) - swap_sites_z = [site for site in swap_sites_z if site not in xor_bulk_sites_z] - - string_x = [copy_site_x, xor_bulk_sites_x, swap_sites_x, xor_right_site_x] - string_z = [copy_site_z, xor_bulk_sites_z, swap_sites_z, xor_right_site_z] - - return string_x, string_z - - -def linear_code_prepare_message( - code: "qec.LinearCode", - prob_error: np.float32 = np.float32(0.5), - error_model: "qec.noise_model" = qec.BinarySymmetricChannel, - seed: Optional[int] = None, -) -> Tuple[str, str]: - """ - This function prepares a message in the form of a random codeword - and its perturbed version after applying an error model. - - Parameters - ---------- - code : qec.LinearCode - Linear code object. - prob_error : np.float32 - Error probability of the error model. - error_model : qec.noise_model - The error model used to flip bits of a random codeword. - seed : Optional[int] - Random seed. - - Returns - ------- - initial_codeword : str - The bitstring of the initial codeword. - perturbed_codeword : str - The bitstring of the perturbed codeword. - """ - - num_bits = len(code) - initial_codeword = code.random_codeword(qec.Rng(seed)) - perturbed_codeword = initial_codeword + error_model(prob_error).sample( - num_bits, qec.Rng(seed) - ) - initial_codeword = "".join(str(bit) for bit in bin_vec_to_dense(initial_codeword)) - perturbed_codeword = "".join( - str(bit) for bit in bin_vec_to_dense(perturbed_codeword) - ) - - return initial_codeword, perturbed_codeword - - -# The functions below are used to apply constraints to a codeword MPS and perform actual decoding. - - -def apply_constraints( - mps: Union[ExplicitMPS, CanonicalMPS], - strings: List[List[int]], - logical_tensors: List[np.ndarray], - chi_max: int = int(1e4), - renormalise: bool = False, - strategy: str = "naive", - silent: bool = False, -) -> CanonicalMPS: - """ - This function applies logical constraints to an MPS. - - Parameters - ---------- - mps : Union[ExplicitMPS, CanonicalMPS] - The MPS to which the logical constraints are being applied. - strings : List[List[int]] - The list of arguments for :class:`ConstraintString`. - logical_tensors : List[np.ndarray] - List of logical tensors for :class:`ConstraintString`. - chi_max : int - Maximum bond dimension to keep in the contractor. - renormalise : bool - Whether to renormalise the singular values at each MPS bond involved in contraction. - strategy : str - The contractor strategy. - silent : bool - Whether to show the progress bar or not. - - Returns - ------- - mps : CanonicalMPS - The resulting MPS. - """ - - if strategy == "naive": - for string in tqdm(strings, disable=silent): - # Preparing the MPO. - string = ConstraintString(logical_tensors, string) - mpo = string.mpo() - - # Finding the starting site for the MPS to perform contraction. - start_site = min(string.flat()) - - # Preparing the MPS for contraction. - if isinstance(mps, ExplicitMPS): - mps = mps.mixed_canonical(orth_centre=start_site) - - if isinstance(mps, CanonicalMPS): - if mps.orth_centre is None: - orth_centres, flags_left, flags_right = find_orth_centre( - mps, return_orth_flags=True - ) - - # Managing possible issues with multiple orthogonality centres - # arising if we do not renormalise while contracting. - if orth_centres and len(orth_centres) == 1: - mps.orth_centre = orth_centres[0] - # Convention. - if all(flags_left) and all(flags_right): - mps.orth_centre = 0 - elif flags_left in ([True] + [False] * (mps.num_sites - 1)): - if flags_right == [not flag for flag in flags_left]: - mps.orth_centre = mps.num_sites - 1 - elif flags_left in ([True] * (mps.num_sites - 1) + [False]): - if flags_right == [not flag for flag in flags_left]: - mps.orth_centre = 0 - elif all(flags_right): - mps.orth_centre = 0 - elif all(flags_left): - mps.orth_centre = mps.num_sites - 1 - - mps = cast( - Union[ExplicitMPS, CanonicalMPS], - mps.move_orth_centre(final_pos=start_site), - ) - - # Doing the contraction. - mps = mps_mpo_contract( - mps, - mpo, - start_site, - renormalise=renormalise, - chi_max=chi_max, - inplace=False, - ) - - return cast(CanonicalMPS, mps) - - -def decode( - message: Union[ExplicitMPS, CanonicalMPS], - codeword: Union[ExplicitMPS, CanonicalMPS], - code: "qec.LinearCode", - num_runs: int = int(1), - chi_max_dmrg: int = int(1e4), - cut: np.float32 = np.float32(1e-12), - silent: bool = False, -) -> Tuple[DephasingDMRG, np.float32]: - """ - This function performs actual decoding of a message given a code and - the DMRG truncation parameters. - Returns the overlap between the decoded message given the initial message. - - Parameters - ---------- - message : Union[ExplicitMPS, CanonicalMPS] - The message MPS. - codeword : Union[ExplicitMPS, CanonicalMPS] - The codeword MPS. - code : qec.LinearCode - Linear code object. - num_runs : int - Number of DMRG sweeps. - chi_max_dmrg : int - Maximum bond dimension to keep in the DMRG algorithm. - cut : np.float32 - The lower boundary of the spectrum in the DMRG algorithm. - All the singular values smaller than that will be discarded. - - Returns - ------- - engine : DephasingDMRG - The container class for the Deohasing DMRG algorithm, see :class:`mdopt.optimiser.DMRG`. - overlap : np.float32 - The overlap between the decoded message and a given codeword, - computed as the following inner product ||. - """ - - # Creating an all-plus state to start the DMRG with. - num_bits = len(code) - mps_dmrg_start = create_simple_product_state(num_bits, which="+") - engine = DephasingDMRG( - mps_dmrg_start, - message, - chi_max=chi_max_dmrg, - cut=cut, - mode="LA", - silent=silent, - ) - engine.run(num_runs) - mps_dmrg_final = engine.mps.right_canonical() - overlap = abs(inner_product(mps_dmrg_final, codeword)) - - return engine, overlap diff --git a/docs/examples/decoding/quantum.ipynb b/docs/examples/decoding/quantum.ipynb deleted file mode 100644 index a60e1686..00000000 --- a/docs/examples/decoding/quantum.ipynb +++ /dev/null @@ -1,410 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this experiment, we decode Shor's nine-qubit quantum error correcting code.\n", - "We show decoding of the Shor's nine-qubit code using Dephasing DMRG, which is our own built-in DMRG-like optimisation algorithm to solve the main component problem which in its turn is the problem of finding a computational basis state cotributing the most to a given state." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qecstruct as qec\n", - "from mdopt.mps.utils import marginalise, create_custom_product_state\n", - "from mdopt.contractor.contractor import mps_mpo_contract\n", - "from mdopt.optimiser.utils import (\n", - " SWAP,\n", - " COPY_LEFT,\n", - " XOR_BULK,\n", - " XOR_LEFT,\n", - " XOR_RIGHT,\n", - ")\n", - "from examples.decoding.decoding import (\n", - " css_code_checks,\n", - " css_code_logicals,\n", - " css_code_logicals_sites,\n", - " css_code_constraint_sites,\n", - ")\n", - "from examples.decoding.decoding import (\n", - " apply_constraints,\n", - " apply_bias_channel,\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first import the code from `qecstruct` and take a look at it." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "X stabilizers:\n", - "[0, 1, 2, 3, 4, 5]\n", - "[3, 4, 5, 6, 7, 8]\n", - "Z stabilizers:\n", - "[0, 1]\n", - "[1, 2]\n", - "[3, 4]\n", - "[4, 5]\n", - "[6, 7]\n", - "[7, 8]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "code = qec.shor_code()\n", - "code" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This quantum error correcting code is defined on 9 physical qubits and has 2 logical operators. This means we will need $9*2 + 2 = 20$ sites in our MPS." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "num_sites = 2 * len(code) + code.num_x_logicals() + code.num_z_logicals()\n", - "num_logicals = code.num_x_logicals() + code.num_z_logicals()\n", - "assert num_sites == 20\n", - "assert num_logicals == 2" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us define the initial state. First of all we will check that no error implies no correction. This means starting from the all-zeros state followed by decoding will return all-zeros state for the logical operators (the final logical operator will be identity operator)." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "error = \"000000000010000111\"\n", - "string_state = \"++\" + error\n", - "error_state = create_custom_product_state(string=string_state, form=\"Right-canonical\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here, we get the sites where the checks will be applied. We will need to construct MPOs using this data." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "X checks:\n", - "[2, 4, 6, 8, 10, 12]\n", - "[8, 10, 12, 14, 16, 18]\n", - "Z checks:\n", - "[3, 5]\n", - "[5, 7]\n", - "[9, 11]\n", - "[11, 13]\n", - "[15, 17]\n", - "[17, 19]\n" - ] - } - ], - "source": [ - "checks_x, checks_z = css_code_checks(code)\n", - "print(\"X checks:\")\n", - "for check in checks_x:\n", - " print(check)\n", - "print(\"Z checks:\")\n", - "for check in checks_z:\n", - " print(check)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These lists mention only the sites where we will apply the XOR constraints. However, the MPOs will also consist of other tensors, such as SWAPs (wire crossings) and boundary XOR constraints. In what follows we define the list of these auxiliary tensors and the corresponding sites where they reside." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Full X-check lists of sites:\n", - "[[2], [4, 6, 8, 10], [3, 5, 7, 9, 11], [12]]\n", - "[[8], [10, 12, 14, 16], [9, 11, 13, 15, 17], [18]]\n", - "Full Z-check lists of sites:\n", - "[[3], [], [4], [5]]\n", - "[[5], [], [6], [7]]\n", - "[[9], [], [10], [11]]\n", - "[[11], [], [12], [13]]\n", - "[[15], [], [16], [17]]\n", - "[[17], [], [18], [19]]\n" - ] - } - ], - "source": [ - "csscode_constraint_sites = css_code_constraint_sites(code)\n", - "print(\"Full X-check lists of sites:\")\n", - "for string in csscode_constraint_sites[0]:\n", - " print(string)\n", - "print(\"Full Z-check lists of sites:\")\n", - "for string in csscode_constraint_sites[1]:\n", - " print(string)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now take a look at the logical operators." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 2]\n", - "\n", - "[0, 3, 6]\n", - "\n" - ] - } - ], - "source": [ - "print(code.x_logicals_binary())\n", - "print(code.z_logicals_binary())" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We need to again translate it to our MPO language by changing the indices since we add the logical-operator sites to the end of the MPS." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 4, 6]\n", - "[3, 9, 15]\n" - ] - } - ], - "source": [ - "print(css_code_logicals(code)[0])\n", - "print(css_code_logicals(code)[1])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now goes the same operation of adding sites where auxiliary tensors go." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[0], [2, 4], [1, 3, 5], [6]]\n", - "[[1], [3, 9], [2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14], [15]]\n" - ] - } - ], - "source": [ - "print(css_code_logicals_sites(code)[0])\n", - "print(css_code_logicals_sites(code)[1])" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "tensors_constraints = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", - "tensors_logicals = [COPY_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", - "constraint_sites_logicals = css_code_logicals_sites(code)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now the fun part, contracting the logical MPOs." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "renormalise = True\n", - "error_state = apply_bias_channel(\n", - " basis_mps=error_state, basis_string=string_state, prob_channel=0.1\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 2/2 [00:00<00:00, 324.99it/s]\n", - "100%|██████████| 6/6 [00:00<00:00, 1956.45it/s]\n", - "100%|██████████| 2/2 [00:00<00:00, 483.58it/s]\n" - ] - } - ], - "source": [ - "error_state = apply_constraints(\n", - " error_state,\n", - " csscode_constraint_sites[0],\n", - " tensors_constraints,\n", - " renormalise=renormalise,\n", - ")\n", - "error_state = apply_constraints(\n", - " error_state,\n", - " csscode_constraint_sites[1],\n", - " tensors_constraints,\n", - " renormalise=renormalise,\n", - ")\n", - "error_state = apply_constraints(\n", - " error_state,\n", - " constraint_sites_logicals,\n", - " tensors_logicals,\n", - " renormalise=renormalise,\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Marginalise over the message bits to get the logical operator MPS." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0.00110897 0.00278983 0.00142582 0.00358692]\n" - ] - } - ], - "source": [ - "sites_to_marginalise = list(range(num_logicals, len(error_state)))\n", - "logical = marginalise(mps=error_state, sites_to_marginalise=sites_to_marginalise)\n", - "print(logical.dense(flatten=True))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "mdopt-ZdbamFdU-py3.11", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.2" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "64c06a7280c9749d5771a76ca6109d7df6b2615ddb3b9b0828f83fb315c7f8a2" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/docs/examples/ising/__init__.py b/docs/examples/ising/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/examples/ising/ground_state.ipynb b/docs/examples/ising/ground_state.ipynb deleted file mode 100644 index 1ef973b5..00000000 --- a/docs/examples/ising/ground_state.ipynb +++ /dev/null @@ -1,273 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this experiment we will use our DMRG optimiser to find the ground state\n", - "of an open-bounded transverse field Ising chain. The Hamiltonian reads:\n", - "$$\n", - "H = - \\sum_{i=1}^{N-1} Z_i Z_{i+1} - h * \\sum_{i=1}^{N} X_i.\n", - "$$\n", - "Here, the magnetic field is in the units of the nearest-neighbour ZZ-interaction.\n", - "We find the ground state of this Hamiltonian and compute some observables." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "from opt_einsum import contract\n", - "from tqdm import tqdm\n", - "from scipy.sparse.linalg import eigsh\n", - "\n", - "from ising import IsingExact, IsingMPO\n", - "from mdopt.mps.utils import create_simple_product_state\n", - "from mdopt.optimiser.dmrg import DMRG as dmrg" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first check we build the right MPO. We do this by virtue of constructing a 3-site MPO and then changing it into the Hamiltonian." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Checking the exact and the MPO Hamiltonians being the same: True\n" - ] - } - ], - "source": [ - "NUM_SITES = 3\n", - "H_MAGNETIC = 1.0\n", - "ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", - "ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", - "ham_mpo = ising_mpo.hamiltonian_mpo()\n", - "m = contract(\n", - " \"zabc, adef, dygh -> begcfh\",\n", - " ham_mpo[0],\n", - " ham_mpo[1],\n", - " ham_mpo[2],\n", - " optimize=[(0, 1), (0, 1)],\n", - ").reshape((8, 8))\n", - "\n", - "print(\n", - " \"Checking the exact and the MPO Hamiltonians being the same:\",\n", - " (ising_exact.hamiltonian_dense() == m).all(),\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Then, we solve the model by both exact diagonalisation and DMRG. Afterwards, we need to check that the ground states are the same up to a phase." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DMRG running:\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 10/10 [00:23<00:00, 2.33s/it]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Eigensolver running.\n", - "The ground states are the same: True\n" - ] - } - ], - "source": [ - "NUM_SITES = 10\n", - "H_MAGNETIC = 1.0\n", - "NUM_DMRG_RUNS = 10\n", - "CHI_MAX = 128\n", - "CUT = 1e-12\n", - "MODE = \"SA\"\n", - "TOL = 1e-7\n", - "ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", - "ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", - "ham_mpo = ising_mpo.hamiltonian_mpo()\n", - "ham_sparse = ising_exact.hamiltonian_sparse()\n", - "\n", - "mps_start = create_simple_product_state(NUM_SITES, which=\"+\")\n", - "\n", - "print(\"DMRG running:\")\n", - "print(\"\")\n", - "engine = dmrg(mps_start, ham_mpo, chi_max=CHI_MAX, cut=CUT, mode=MODE)\n", - "engine.run(NUM_DMRG_RUNS)\n", - "print(\"\")\n", - "ground_state_mps = engine.mps\n", - "print(\"Eigensolver running.\")\n", - "ground_state_exact = eigsh(ham_sparse, k=2, tol=TOL)[1][:, 0]\n", - "print(\n", - " \"The ground states are the same:\",\n", - " np.isclose(abs(ground_state_mps.dense()), abs(ground_state_exact)).all(),\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we would like to compare the magnetisation plots from exact diagonalisation and DMRG. The plots should coincide exactly." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 20/20 [08:05<00:00, 24.25s/it]\n" - ] - } - ], - "source": [ - "transverse_magnetic_field_space = np.linspace(0.2, 2.0, 20)\n", - "mag_z_exact = []\n", - "mag_x_exact = []\n", - "mag_z_dmrg = []\n", - "mag_x_dmrg = []\n", - "for magnetic_field in tqdm(transverse_magnetic_field_space):\n", - " ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=magnetic_field)\n", - " ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=magnetic_field)\n", - " ham_mpo = ising_mpo.hamiltonian_mpo()\n", - " ham_sparse = ising_exact.hamiltonian_sparse()\n", - " mps_start = create_simple_product_state(num_sites=NUM_SITES, which=\"+\")\n", - " engine = dmrg(mps_start, ham_mpo, chi_max=CHI_MAX, cut=CUT, mode=MODE, silent=True)\n", - " engine.run(NUM_DMRG_RUNS)\n", - " ground_state_mps = engine.mps\n", - " ground_state_exact = eigsh(ham_sparse, k=2, tol=TOL)[1][:, 0]\n", - "\n", - " mag_z_exact.append(ising_exact.average_chain_z_magnetisation(ground_state_exact))\n", - " mag_x_exact.append(ising_exact.average_chain_x_magnetisation(ground_state_exact))\n", - "\n", - " mag_z_dmrg.append(ising_mpo.average_chain_z_magnetisation(ground_state_mps))\n", - " mag_x_dmrg.append(ising_mpo.average_chain_x_magnetisation(ground_state_mps))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can take a look at the plots!" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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Blaza3/0zTffSJLOnj2rs2fPqkGDBpZ9999/v1q0aKFFixYpLCxMJSUlat++vQoKCi7m4+1tcz5XIoo8AAAA4CpnMplsfmzySnTgwAGNGzdOixYt0urVqzVkyBB98cUXcnFx0ZkzZ5SWlqZFixapZ8+ekqSvvvrK6viOHTvqvffe09mzZ8uczfPw8FBxce1/d9FWrK4JAAAAoN7Iz89Xenq61ef06dMqLi7WE088obi4OA0bNkxLlizRrl279NZbb0mSAgIC1LhxYy1cuFD79+/Xhg0bFB8fb9X3gAEDFBISon79+unrr7/WwYMH9a9//UvJycmSpJYtW+rQoUNKTU3V6dOnlZ+fX+vXXxUUeQAAAADqjcTERIWGhlp9evToob/85S/65Zdf9I9//EOSFBoaqoULF+rll1/Wzp075eLiolWrVmnbtm1q3769xo0bpzfffNOqbw8PD61bt05BQUG655571KFDB73++utydb34WOnDDz+sPn366I477lDTpk31wQcf1Pr1V4XJMAyjrpO42pjNZvn5+Sk7O1u+vr51nQ4AAACuIhcuXNChQ4cUEREhLy+vuk7nqlDRmNdEbcBMHgAAAAA4EYo8AAAAAHAiFHkAAAAA4EQo8gAAAADAiVDkAQAAAIATocgDAAAAACdCkQcAAAAAToQiDwAAAACcCEUeAAAAADgRijwAAAAAcCIUeQAAAADqhaFDh8pkMslkMsnd3V3BwcG66667tHjxYpWUlFjiWrZsKZPJpFWrVpXq44YbbpDJZNLSpUtLxZtMJvn4+KhDhw567733Sh1rGIYWLVqkrl27ytfXVw0bNtQNN9yg5557Tvv376+Ra7YHRR4AAACAeqNPnz46efKkDh8+rP/+97+644479Nxzz+m+++5TUVGRJS48PFxLliyxOvbbb79Venq6GjRoUKrf6dOn6+TJk9qzZ4+eeOIJjRw5Uv/9738t+w3D0OOPP65nn31W99xzj9atW6cffvhB77//vry8vPTqq6/W3EXbyK2uEwAAAACAqvL09FRISIgkqVmzZrrpppt0yy23qFevXlq6dKlGjBghSRo4cKDmzp2ro0ePKjw8XJK0ePFiDRw4UMuXLy/Vb6NGjSz9Tpw4UbNmzdL69et19913S5JWr16tVatW6d///rceeOABy3HXXHONbrnlFhmGUaPXbQtm8gAAAABcVJBb/qfwgg2x5yuPdaA777xTnTp10scff2xpCw4OVlxcnJYtWyZJysvL0+rVq/Xkk09W2FdJSYn+9a9/6ddff5WHh4el/YMPPlCbNm2sCrzLmUwmB1yJYzCTBwAAAOCi18LK33dtb2ngh79vvxkpFeaVHduihzTs89+33+4g5Z2xjnkl2/48y9C2bVvt2rXLqu3JJ5/U888/r5deekkfffSRWrduraioqDKPnzhxol5++WXl5+erqKhIgYGBlllBSfrpp5/Upk0bq2PGjh1r+e6ev7+/jh075tBrshczeQAAAADqPcMwSs2m3XvvvcrJydGWLVu0ePHiCmfxXnjhBaWmpmrDhg2KiYnR3LlzFRkZWeE5X3rpJaWmpiohIUE5OTkOuQ5HYCYPAAAAwEUvnih/n8nVevuFClaTNP1hLmnsbvtzqqJ9+/YpIiLCqs3NzU2DBg3S1KlTlZKSojVr1pR7fJMmTRQZGanIyEh9+OGH6tChg6Kjo9WuXTtJ0rXXXqu0tDSrY5o2baqmTZsqKCjI8RdUDVfFTN78+fPVsmVLeXl5KSYmRlu3bi039vbbb7csn3r5595777XEXL5066VPnz59auNSAAAAgJrj0aD8j7uXDbHelcc60IYNG7R79249/PDDpfY9+eST2rx5s/r27auAgIAq9RceHq7+/ftr8uTJlrYBAwYoLS1N//73vx2Wd01x+pm81atXKz4+XgsWLFBMTIzefvttxcXFKS0trcyK++OPP1ZBQYFl+8yZM+rUqZP+9Kc/WcX16dPHaklWT0/PmrsIAAAAAJKk/Px8paenq7i4WBkZGUpMTNTMmTN13333afDgwaXir7/+ep0+fVo+Pj42nee5555T+/bt9f333ys6OlqPPfaYPv74Yz322GOaPHmy4uLiFBwcrF9++UWrV6+Wq6tr5Z3WEqefyZszZ45GjhypYcOGqV27dlqwYIF8fHy0ePHiMuMDAwMVEhJi+axfv14+Pj6lirxLS7de+lT1XwUAAAAA2C8xMVGhoaFq2bKl+vTpo40bN2revHn697//XW6h1bhxY3l7e5e5rzzt2rVT7969lZCQIOni6pmrV6/W22+/rbVr16pXr15q06aNnnzySYWHh+urr76q9rU5ism4kl7o4GAFBQXy8fHRRx99pH79+lnahwwZoqysrCpNtXbo0EFdu3bVwoULLW1Dhw7VJ598Ig8PDwUEBOjOO+/Uq6++qsaNG5fZR35+vvLz8y3bZrNZ4eHhys7Olq+vr/0XCAAAANjowoULOnTokCIiIuTl5VX5Aai2isbcbDbLz8/PobWBU8/knT59WsXFxQoODrZqDw4OVnp6eqXHb926VXv27LFaOlW6+Kjm8uXLlZSUpDfeeEObN2/W3XffreLi4jL7mTlzpvz8/CyfSy9jBAAAAABHc/rv5FXH+++/rw4dOqhLly5W7Y899pjl5w4dOqhjx45q3bq1Nm3apF69epXqZ/LkyYqPj7dsX5rJAwAAAABHc+qZvCZNmsjV1VUZGRlW7RkZGQoJCanw2NzcXK1atUrDhw+v9DytWrVSkyZNtH9/2cvIenp6ytfX1+oDAAAAADXBqYs8Dw8Pde7cWUlJSZa2kpISJSUlqWvXrhUe++GHHyo/P19PPPFEpec5duyYzpw5o9DQ0GrnDAAAAADV4dRFniTFx8dr0aJFWrZsmfbt26fRo0crNzdXw4YNkyQNHjzY6v0Xl7z//vvq169fqcVUcnJy9MILL+jbb7/V4cOHlZSUpL59+yoyMlJxcXG1ck0AAAAAUB6n/05e//79derUKSUkJCg9PV1RUVFKTEy0LMZy5MgRubhY17ppaWn66quvtG7dulL9ubq6ateuXVq2bJmysrIUFham3r17a8aMGbwrDwAAAPWGEy+yf8Wp7bF26lcoXKlqYplUAAAAoCqKi4v1008/KSgoqNxXgMGxzpw5o8zMTF133XWl3uVXE7WB08/kAQAAAPidq6ur/P39lZmZKUny8fGRyWSq46yck2EYysvLU2Zmpvz9/ct9WbujUeQBAAAAV5lLK81fKvRQs/z9/Std3d+RKPIAAACAq4zJZFJoaKiCgoJUWFhY1+k4NXd391qbwbuEIg8AAAC4Srm6utZ6AYKa5/SvUAAAAACAqwlFHgAAAAA4EYo8AAAAAHAiFHkAAAAA4EQo8gAAAADAiVDkAQAAAIATocgDAAAAACdCkQcAAAAAToQiDwAAAACcCEUeAAAAADgRijwAAAAAcCIUeQAAAADgRCjyAAAAAMCJUOQBAAAAgBOhyAMAAAAAJ0KRBwAAAABOhCIPAAAAAJwIRR4AAAAAOBGKPAAAAABwIhR5AAAAAOBEKPIAAAAAwIlQ5AEAAACAE3FYkbd9+3ZHdQUAAAAAsJPDirwuXbooPj7eqm3t2rWO6h4AAAAAUAUOK/I6dOggX19fDRs2zNL28ssvO6p7AAAAAEAVOKzIM5lMeuWVV9SpUyc98sgjKiwslGEYjuoeAAAAAFAFbo7qyNfXV5I0duxYBQQE6IEHHtD58+cd1T0AAAAAoAocVuRt2rTJ8vOQIUPk6+ur4cOHO6p7AAAAAEAVmAw7n6k0m81asmSJ0tPTFRERoaioKLVv314+Pj6OztHpmM1m+fn5KTs72zIDCgAAAODqUxO1gd0zeQ899JB27typm2++Wf/5z3+UlpYmSWrdurU6deqk1atXOyRBAAAAAEDV2V3kJScna9OmTbr55pslSfn5+dq9e7dSU1O1c+dOhyUIAAAAAKg6u1fX7Nixo9zcfq8RPT09FR0drREjRujdd991SHKOMn/+fLVs2VJeXl6KiYnR1q1by41dunSpTCaT1cfLy8sqxjAMJSQkKDQ0VN7e3oqNjdXPP/9c05cBAAAAAJWyu8ibNWuWEhISlJ+f78h8HG716tWKj4/X1KlTtX37dnXq1ElxcXHKzMws9xhfX1+dPHnS8vnll1+s9s+aNUvz5s3TggULlJKSogYNGiguLk4XLlyo6csBAAAAgArZXeS1bNlSZrNZ7dq104svvqhPP/1UR48edWRuDjFnzhyNHDlSw4YNU7t27bRgwQL5+Pho8eLF5R5jMpkUEhJi+QQHB1v2GYaht99+Wy+//LL69u2rjh07avny5Tpx4oQ++eSTWrgiAAAAACif3UXeww8/rMOHD6t79+765ptvNGTIELVs2VJNmzZV7969HZmj3QoKCrRt2zbFxsZa2lxcXBQbG6vk5ORyj8vJyVGLFi0UHh6uvn37au/evZZ9hw4dUnp6ulWffn5+iomJKbfP/Px8mc1mqw8AAAAA1AS7F17Zs2ePkpOT1alTJ0vb4cOHtWPHDu3atcshyVXX6dOnVVxcbDUTJ0nBwcH68ccfyzymTZs2Wrx4sTp27Kjs7GzNnj1b3bp10969e9W8eXOlp6db+vhjn5f2/dHMmTM1bdo0B1wRAAAAAFTM7iLv5ptvVm5urlVby5Yt1bJlSz344IPVTqyudO3aVV27drVsd+vWTddff73+8Y9/aMaMGXb1OXnyZMXHx1u2zWazwsPDq50rAAAAAPyR3Y9rPvfcc3rllVeUlZXlwHQcq0mTJnJ1dVVGRoZVe0ZGhkJCQqrUh7u7u2688Ubt379fkizH2dKnp6enfH19rT4AAAAAUBPsLvIeeeQRffHFF7r22ms1atQovf/++9q+fbsKCgocmV+1eHh4qHPnzkpKSrK0lZSUKCkpyWq2riLFxcXavXu3QkNDJUkREREKCQmx6tNsNislJaXKfQIAAABATbH7cc1Dhw5p586dlpefv/baazp8+LDc3NzUpk2bK+Z7efHx8RoyZIiio6PVpUsXvf3228rNzdWwYcMkSYMHD1azZs00c+ZMSdL06dN1yy23KDIyUllZWXrzzTf1yy+/aMSIEZIurrw5duxYvfrqq7r22msVERGhKVOmKCwsTP369aurywQAAAAASdUo8lq0aKEWLVrogQcesLSdO3dOqampV0yBJ0n9+/fXqVOnlJCQoPT0dEVFRSkxMdGycMqRI0fk4vL7hOavv/6qkSNHKj09XQEBAercubO++eYbtWvXzhIzYcIE5ebmatSoUcrKylKPHj2UmJhY6qXpAAAAAFDbTIZhGHWdxNXGbDbLz89P2dnZfD8PAAAAuIrVRG1g93fyAAAAAABXHoo8AAAAAHAiFHkAAAAA4EQo8gAAAADAidi9uqYkJSUlKSkpSZmZmSopKbHat3jx4molBgAAAACwnd1F3rRp0zR9+nRFR0crNDRUJpPJkXkBAAAAAOxgd5G3YMECLV26VIMGDXJkPgAAAACAarD7O3kFBQXq1q2bI3MBAAAAAFST3UXeiBEjtHLlSkfmAgAAAACoJrsf17xw4YIWLlyoL774Qh07dpS7u7vV/jlz5lQ7OQAAAACAbewu8nbt2qWoqChJ0p49e6z2sQgLAAAAANQNu4u8jRs3OjIPAAAAAIAD8DJ0AAAAAHAi1XoZelZWlt5//33t27dPktSuXTsNHz5cfn5+DkkOAAAAAGAbu2fyvv/+e7Vu3Vpz587V2bNndfbsWc2dO1etW7fW9u3bHZkjAAAAAKCKTIZhGPYc2LNnT0VGRmrRokVyc7s4IVhUVKQRI0bo4MGD2rJli0MTdSZms1l+fn7Kzs6Wr69vXacDAAAAoI7URG1gd5Hn7e2tHTt2qG3btlbtP/zwg6Kjo5WXl+eQBJ0RRR4AAAAAqWZqA7sf1/T19dWRI0dKtR89elSNGjWqVlIAAAAAAPvYXeT1799fw4cP1+rVq3X06FEdPXpUq1at0ogRIzRgwABH5ggAAAAAqCK7V9ecPXu2TCaTBg8erKKiIkmSu7u7Ro8erddff91hCQIAAAAAqs7u7+RdkpeXpwMHDkiSWrduLR8fH4ck5sz4Th4AAAAAqWZqg2q9J0+SfHx81KFDB0fkAgAAAACoJpuKvPj4eM2YMUMNGjRQfHx8hbFz5sypVmIAAAAAANvZVOTt2LFDhYWFlp/LYzKZqpcVAAAAAMAuNhV5GzdutPy8bNkyNW/eXC4u1gt0Goaho0ePOiY7AAAAAIBN7H6FQkREhE6fPl2q/ezZs4qIiKhWUgAAAAAA+9hd5JW3KGdOTo68vLzsTggAAAAAYD+bV9e8tOCKyWRSQkKC1SsTiouLlZKSoqioKIclCAAAAACoOpuLvEsLrhiGod27d8vDw8Oyz8PDQ506ddL48eMdlyEAAAAAoMpsLvIuLb4ybNgwvfPOO7zMGwAAAACuIHa/DH3JkiWOzAMAAAAA4AB2F3mX/PDDDzpy5IgKCgqs2h944IHqdg0AAAAAsJHdRd7Bgwf14IMPavfu3TKZTJbVNi+9CL24uNgxGQIAAAAAqszuVyg899xzioiIUGZmpnx8fLR3715t2bJF0dHR2rRpkwNTBAAAAABUld0zecnJydqwYYOaNGkiFxcXubi4qEePHpo5c6aeffZZyyqcAAAAAIDaY/dMXnFxsRo1aiRJatKkiU6cOCFJatGihdLS0hyTnYPMnz9fLVu2lJeXl2JiYrR169ZyYxctWqSePXsqICBAAQEBio2NLRU/dOhQmUwmq0+fPn1q+jIAAAAAoFJ2F3nt27fXzp07JUkxMTGaNWuWvv76a02fPl2tWrVyWILVtXr1asXHx2vq1Knavn27OnXqpLi4OGVmZpYZv2nTJg0YMEAbN25UcnKywsPD1bt3bx0/ftwqrk+fPjp58qTl88EHH9TG5QAAAABAhUzGpRVTbPS///1Pubm5euihh7R//37dd999+umnn9S4cWOtXr1ad955p6NztUtMTIxuvvlm/fWvf5UklZSUKDw8XM8884wmTZpU6fHFxcUKCAjQX//6Vw0ePFjSxZm8rKwsffLJJ3blZDab5efnp+zsbN4zCAAAAFzFaqI2sPs7eXFxcZafIyMj9eOPP+rs2bMKCAiwrLBZ1woKCrRt2zZNnjzZ0ubi4qLY2FglJydXqY+8vDwVFhYqMDDQqn3Tpk0KCgpSQECA7rzzTr366qtq3LhxmX3k5+crPz/fsm02m+24GgAAAAConN2Pa54/f155eXmW7V9++UXLly/X+vXrHZKYI5w+fVrFxcUKDg62ag8ODlZ6enqV+pg4caLCwsIUGxtraevTp4+WL1+upKQkvfHGG9q8ebPuvvvucl8bMXPmTPn5+Vk+4eHh9l8UAAAAAFTA7pm8vn376qGHHtJTTz2lrKwsdenSRR4eHjp9+rTmzJmj0aNHOzLPOvH6669r1apV2rRpk7y8vCztjz32mOXnDh06qGPHjmrdurU2bdqkXr16lepn8uTJio+Pt2ybzWYKPQAAAAA1wu6ZvO3bt6tnz56SpI8++kghISGW2bx58+Y5LMHqaNKkiVxdXZWRkWHVnpGRoZCQkAqPnT17tl5//XWtW7dOHTt2rDC2VatWatKkifbv31/mfk9PT/n6+lp9AAAAAKAm2F3k5eXlWV6hsG7dOj300ENycXHRLbfcol9++cVhCVaHh4eHOnfurKSkJEtbSUmJkpKS1LVr13KPmzVrlmbMmKHExERFR0dXep5jx47pzJkzCg0NdUjeAAAAAGAvu4u8yMhIffLJJzp69Kj+97//qXfv3pKkzMzMK2qmKj4+XosWLdKyZcu0b98+jR49Wrm5uRo2bJgkafDgwVYLs7zxxhuaMmWKFi9erJYtWyo9PV3p6enKycmRJOXk5OiFF17Qt99+q8OHDyspKUl9+/ZVZGSk1WI0AAAAAFAX7P5OXkJCgh5//HGNGzdOvXr1ssyMrVu3TjfeeKPDEqyu/v3769SpU0pISFB6erqioqKUmJhoWYzlyJEjcnH5vdb9+9//roKCAj3yyCNW/UydOlWvvPKKXF1dtWvXLi1btkxZWVkKCwtT7969NWPGDHl6etbqtQEAAADAH9n9njxJSk9P18mTJ9WpUydLobR161b5+vqqbdu2DkvS2fCePAAAAADSFfaePEkKCQkptYBJly5dqpUQAAAAAMB+NhV58fHxmjFjhho0aGD1SoCyzJkzp1qJAQAAAABsZ1ORt2PHDhUWFlp+Lo/JZKpeVgAAAAAAu9hU5G3cuNHy87Jly9S8eXOrRUskyTAMHT161DHZAQAAAABsYvcrFCIiInT69OlS7WfPnlVERES1kgIAAAAA2MfuIq+8RTlzcnLk5eVld0IAAAAAAPvZvLrmpQVXTCaTEhIS5OPjY9lXXFyslJQURUVFOSxBAAAAAEDV2VzkXVpwxTAM7d69Wx4eHpZ9Hh4e6tSpk8aPH++4DAEAAAAAVWZzkXdp8ZVhw4bpnXfe4WXeAAAAAHAFsftl6EuWLHFkHgAAAAAAB7B74RVJ+vLLL/XEE0+oa9euOn78uCTp//7v//TVV185JDkAAAAAgG3sLvL+9a9/KS4uTt7e3tqxY4fy8/MlSdnZ2XrttdccliAAAAAAoOrsLvJeffVVLViwQIsWLZK7u7ulvXv37tq+fbtDkgMAAAAA2MbuIi8tLU233nprqXY/Pz9lZWVVJycAAAAAgJ3sLvJCQkK0f//+Uu1fffWVWrVqVa2kAAAAAAD2sbvIGzlypJ577jmlpKTIZDLpxIkTWrFihcaPH6/Ro0c7MkcAAAAAQBXZ/QqFSZMmqaSkRL169VJeXp5uvfVWeXp6avz48XrmmWccmSMAAAAAoIpMhmEY1emgoKBA+/fvV05Ojtq1a6eGDRs6KjenZTab5efnp+zsbF4mDwAAAFzFaqI2sHsm7xIPDw+1a9fOEbkAAAAAAKqpWkVeUlKSkpKSlJmZqZKSEqt9ixcvrlZiAAAAAADb2V3kTZs2TdOnT1d0dLRCQ0NlMpkcmRcAAAAAwA52F3kLFizQ0qVLNWjQIEfmAwAAAACoBrtfoVBQUKBu3bo5MhcAAAAAQDXZXeSNGDFCK1eudGQuAAAAAIBqsvtxzQsXLmjhwoX64osv1LFjR7m7u1vtnzNnTrWTAwAAAADYxu4ib9euXYqKipIk7dmzx1H5AAAAAACqwe4ib+PGjY7MAwAAAADgAHYXefHx8WW2m0wmeXl5KTIyUn379lVgYKDdyQEAAAAAbGMyDMOw58A77rhD27dvV3Fxsdq0aSNJ+umnn+Tq6qq2bdsqLS1NJpNJX331ldq1a+fQpOs7s9ksPz8/ZWdny9fXt67TAQAAAFBHaqI2sHt1zb59+yo2NlYnTpzQtm3btG3bNh07dkx33XWXBgwYoOPHj+vWW2/VuHHjHJIoAAAAAKByds/kNWvWTOvXry81S7d371717t1bx48f1/bt29W7d2+dPn3aIck6C2byAAAAAEhX2Exedna2MjMzS7WfOnVKZrNZkuTv76+CggL7swMAAAAA2KRaj2s++eSTWrNmjY4dO6Zjx45pzZo1Gj58uPr16ydJ2rp1q6677jpH5QoAAAAAqITdj2vm5ORo3LhxWr58uYqKiiRJbm5uGjJkiObOnasGDRooNTVVkizv08NFPK4JAAAAQKqZ2sDuIu+SnJwcHTx4UJLUqlUrNWzY0CGJOTOKPAAAAADSFfadvEsaNmyojh07qmPHjldsgTd//ny1bNlSXl5eiomJ0datWyuM//DDD9W2bVt5eXmpQ4cOWrt2rdV+wzCUkJCg0NBQeXt7KzY2Vj///HNNXgIAAAAAVEm1i7wffvhBiYmJ+vTTT60+V4rVq1crPj5eU6dO1fbt29WpUyfFxcWVuWiMJH3zzTcaMGCAhg8frh07dqhfv37q16+f9uzZY4mZNWuW5s2bpwULFiglJUUNGjRQXFycLly4UFuXBQAAAABlsvtxzYMHD+rBBx/U7t27ZTKZdKkbk8kkSSouLnZcltUQExOjm2++WX/9618lSSUlJQoPD9czzzyjSZMmlYrv37+/cnNz9dlnn1nabrnlFkVFRWnBggUyDENhYWF6/vnnNX78eEkXVxoNDg7W0qVL9dhjj1WaE49rAgAAAJBqpjZws/fA5557ThEREUpKSlJERIS2bt2qM2fO6Pnnn9fs2bMdklx1FRQUaNu2bZo8ebKlzcXFRbGxsUpOTi7zmOTkZMXHx1u1xcXF6ZNPPpEkHTp0SOnp6YqNjbXs9/PzU0xMjJKTk8ss8vLz85Wfn2/ZvvSKieyZ18nwLD2Z+rWiNNk01rKdZIyQu4rKzHeb2mmcaYJl+3PjaTVSbpmxP6i1njJNsWz/y4hXU50tM/aAmmuoZli2V2iyrlF6mbHHFaT+xhuW7cV6RdfplzJjz8hfD2iu5R8FFphmqqPKftQ1V96KNebr0j9DvO0yRzHaU2ZsiVzUveQ9y/brLn/V7dpeZqwk3Wb8Q4VylyRNNS1UnL4tN/YevSuzLj6KPEFL9YBpc7mxD+stZSpQkvSMPtCjWldu7BOaqSOmUEnSCONfGqz/lBs7Qq/oJ1PLi8cZn2mUPio39mm9qN2mi6vaPmKs17NaUW7seD2vraYOkqT7jM2aoCXlxk7RGG02RUuSehnfaqoWlBv7qkZpnambJKm7sUMz9U65sbM1RJ+a7pAkRRt7NUdvlhv7Vw3QP01xkqQbjP36u14tN/Y9PaTlpgckSa2No1qiKeXGrtC9+ofpT5KkZkaGPtDEcmP/pVi9Y3pCktTY+FVrNK7c2M91q94wPSlJamDk6b/6c7mxSYrRNNNoSZKrUayNGl5u7JVwjzio5hpq+n38VxiTFF7BPWKAaZZl+z1jaoX3iAdNb1u25xt/UYcK7hF3m/5u2Z5tzFaXcu4RxXLRHabFlu1XjXd1q7aVGStJvbRIhaaL94gpxj90l8r+M0OS7tVfdc508R4x3liqB7Sp3NhH9JYyTY0lSWOMldwjxD2CewT3iMtxj7joartHmPNLyo23l91FXnJysjZs2KAmTZrIxcVFLi4u6tGjh2bOnKlnn31WO3bscGSedjl9+rSKi4sVHBxs1R4cHKwff/yxzGPS09PLjE9PT7fsv9RWXswfzZw5U9OmTSvV7qc8+cpUqt29+LyyCwst2408c+VpKvvm7FGcZxXb0DNXfqayb86eJXnKLvg9tkEFsd4leTIX/H5OH488+bmUHftrSZ7OXRbrXUFsvuGunPzfY70qiHUxSpRX8PuMsLd7nvxdy44tMlx0vvD3WE/3C/IrJ1aS8vKLVfDb08rulcTmXCjSud/+cHR1uyA/t4piC2X+LdZUSWxufoGyjd9+PSqJzbss1nC9ID/38mMv5OdbYosric0vyFd2ycXYItf8qse65MvPo/zYwstiCyqJLS7MV3bxxdgLlcSWFJ7/PdaULz/P8mONwguW2DxTQYWxKrqg7KKLsf6VxJoui/VQofy8yo91KTpviS2uJNbtst/3riquMPZKuEd4/SG2ot/3v9oQm2+4K/vC77GeldwjrGLd88r9vVxkuFjFurufr/D3vflCoS695dW1kthzFwqVrd9+7dzOV/h7+fJY7hHcI7hHXMQ9ouxY7hFXzz3CpGqtg1n2eex9XDMgIEDbt29XRESEWrdurffee0933HGHDhw4oA4dOigvL8/RudrsxIkTatasmb755ht17drV0j5hwgRt3rxZKSkppY7x8PDQsmXLNGDAAEvb3/72N02bNk0ZGRn65ptv1L17d504cUKhoaGWmEcffVQmk0mrV68u1WdZM3nh4eHas+1LNSpjsZoSdx8VNwyzbLtnHZDK+WUqcfNWcaNml8UelIyy/zXAcPVSkW9zy7Zb9mGZSsq+6Ruunir2Db8s9heZSn6/+V16LFeSDBd3Ffm1+D0H81Gp+PfrvZzJxVVF/hGWbddzx2QquiBTGcWuTC4q8m+lS6dyPXdcpqLzZfYrSUUBkZafXc6dlKmw7N9ghgwV+beSTBeLPNfcDJkKzpU3xCryi5Dh4vpbbKZcCszW/V12YKFvC8n14r/sueSdlkt+Vrn5FvpeI7l6XIw9f0auF34t/9oaNZfh5nUx9sJZuZ4v+19OJamoYTMZ7t6/xWbJ9fzpCmLDZLj7XIzNz5Zr3qnyYxuEyPC4+P+rqeCc3HIzyo0t9glSiafvb7G5css9WUFsU5V4+l2MLcyTW86J8mO9G6vEK+BibNF5uZ07XkFsoEq8An+LvSC3c8fKj/UKUIl34982CuRuPlJubImnn4p9mv62UST37MPlx3r4qrhB0G8bxXLPPlRBbEMVNwi5uGEYF3/flxd7hdwjiiq4R1jF/uEe4WY+KlM59wjDZH2PcKvo973JRYX+rSybrueOy6WCe0ThZfcI15yTcinnHiHpYr+X3SNcCs6VH+sXIVVwj7CKvewe4co94rdY7hEXN7hHWGK5R1yM5R7xW6zz3yPO5eSofeeeV8bjmu3bt9fOnTsVERGhmJgYzZo1Sx4eHlq4cKFatWpVeQe1oEmTJnJ1dVVGhvX/RBkZGQoJCSnzmJCQkArjL/03IyPDqsjLyMgo932Anp6e8vT0LNUeHtmxar+QTTtVHmOJ7WhDbHsbYm+oemyTtlWPbdym6rGB19oQ29qGHGz4/7VJROUxFrasNttQUotKo36PvcaG2OaVRv0e26zSqN9jQyuN+j02uNKo32ODqh4b2tSG2CZVjJUUElj12OComokNsiG2vt0jml5vQ6wN9wibYm24nzS14feyLbHcIy6L5R5hcyz3iN9iuUf8Hss9or7eIy59lcuR7F5d8+WXX1ZJycV/6Zk+fboOHTqknj17au3atZo3b57DEqwODw8Pde7cWUlJSZa2kpISJSUlWc3sXa5r165W8ZK0fv16S3xERIRCQkKsYsxms1JSUsrtEwAAAABqi90zeXFxcZafIyMj9eOPP+rs2bMKCAiwepSvrsXHx2vIkCGKjo5Wly5d9Pbbbys3N1fDhg2TJA0ePFjNmjXTzJkzJV1cUOa2227TW2+9pXvvvVerVq3S999/r4ULF0q6+Jji2LFj9eqrr+raa69VRESEpkyZorCwMPXr16+uLhMAAAAAJFWjyJOkCxcuaNeuXcrMzLTM6l3ywAMPVCsxR+nfv79OnTqlhIQEpaenKyoqSomJiZaFU44cOSIXl98nNLt166aVK1fq5Zdf1osvvqhrr71Wn3zyidq3//2RhAkTJig3N1ejRo1SVlaWevToocTERHl5edX69QEAAADA5exeeCUxMVGDBg3SmTNnSndqMl0x78m7EvGePAAAAABSzdQGdn8n75lnntGjjz6qkydPqqSkxOpDgQcAAAAAdcPuIi8jI0Px8fGl3hcHAAAAAKg7dhd5jzzyiDZt2uTAVAAAAAAA1WX3d/Ly8vL0pz/9SU2bNlWHDh3k7u5utf/ZZ591SILOiO/kAQAAAJBqpjawe3XNDz74QOvWrZOXl5c2bdpk9doEk8lEkQcAAAAAdcDuIu+ll17StGnTNGnSJKtXEAAAAAAA6o7d1VlBQYH69+9PgQcAAAAAVxC7K7QhQ4Zo9erVjswFAAAAAFBNdj+uWVxcrFmzZul///ufOnbsWGrhlTlz5lQ7OQAAAACAbewu8nbv3q0bb7xRkrRnzx6rfZcvwgIAAAAAqD12F3kbN250ZB4AAAAAAAdg1RQAAAAAcCIUeQAAAADgRCjyAAAAAMCJUOQBAAAAgBOhyAMAAAAAJ0KRBwAAAABOxKZXKMTHx1c5lpehAwAAAEDts6nI27FjR5XieBk6AAAAANQNm4o8XoAOAAAAAFc2m4q8svzwww86cuSICgoKLG0mk0n3339/dbsGAAAAANjI7iLv4MGDevDBB7V7926ZTCYZhiHp90c1i4uLHZMhAAAAAKDK7F5d87nnnlNERIQyMzPl4+OjvXv3asuWLYqOjtamTZscmCIAAAAAoKrsnslLTk7Whg0b1KRJE7m4uMjFxUU9evTQzJkz9eyzz1Z5kRYAAAAAgOPYPZNXXFysRo0aSZKaNGmiEydOSJJatGihtLQ0x2QHAAAAALCJ3TN57du3186dOxUREaGYmBjNmjVLHh4eWrhwoVq1auXIHAEAAAAAVWR3kffyyy8rNzdXkjR9+nTdd9996tmzpxo3bqzVq1c7LEEAAAAAQNWZjEvLYjrA2bNnFRAQwMvQK2E2m+Xn56fs7Gz5+vrWdToAAAAA6khN1AbVfk/e5QIDAx3ZHQAAAADARtUq8pKSkpSUlKTMzEyVlJRY7Vu8eHG1EgMAAAAA2M7uIm/atGmaPn26oqOjFRoayiOaAAAAAHAFsLvIW7BggZYuXapBgwY5Mh8AAAAAQDXY/Z68goICdevWzZG5AAAAAACqye4ib8SIEVq5cqUjcwEAAAAAVJPdj2teuHBBCxcu1BdffKGOHTvK3d3dav+cOXOqnRwAAAAAwDZ2z+Tt2rVLUVFRcnFx0Z49e7Rjxw7LJzU11YEp2ufs2bMaOHCgfH195e/vr+HDhysnJ6fC+GeeeUZt2rSRt7e3rrnmGj377LPKzs62ijOZTKU+q1atqunLAQAAAIAqsXsmb+PGjY7Mw+EGDhyokydPav369SosLNSwYcM0atSoch8xPXHihE6cOKHZs2erXbt2+uWXX/TUU0/pxIkT+uijj6xilyxZoj59+li2/f39a/JSAAAAAKDKTIZhGHWdhKPt27dP7dq103fffafo6GhJUmJiou655x4dO3ZMYWFhVernww8/1BNPPKHc3Fy5uV2sh00mk9asWaN+/frZnV9NvNUeAAAAQP1TE7WBTTN58fHxmjFjhho0aKD4+PgKY+vyO3nJycny9/e3FHiSFBsbKxcXF6WkpOjBBx+sUj+XBvpSgXfJ008/rREjRqhVq1Z66qmnNGzYsArfE5ifn6/8/HzLttlstvGKAAAAAKBqbCryduzYocLCQsvP5anrF6Onp6crKCjIqs3NzU2BgYFKT0+vUh+nT5/WjBkzNGrUKKv26dOn684775SPj4/WrVunP//5z8rJydGzzz5bbl8zZ87UtGnTbL8QAAAAALBRvXpcc9KkSXrjjTcqjNm3b58+/vhjLVu2TGlpaVb7goKCNG3aNI0ePbrCPsxms+666y4FBgbq008/LbVy6OUSEhK0ZMkSHT16tNyYsmbywsPDeVwTAAAAuMrV+eOade3555/X0KFDK4xp1aqVQkJClJmZadVeVFSks2fPKiQkpMLjz507pz59+qhRo0Zas2ZNhQWeJMXExGjGjBnKz8+Xp6dnmTGenp7l7gMAAAAAR7L5O3lVVRPfyWvatKmaNm1aaVzXrl2VlZWlbdu2qXPnzpKkDRs2qKSkRDExMeUeZzabFRcXJ09PT3366afy8vKq9FypqakKCAigiAMAAABwRbD5O3mX2759u4qKitSmTRtJ0k8//SRXV1dLYVVXrr/+evXp00cjR47UggULVFhYqDFjxuixxx6zrKx5/Phx9erVS8uXL1eXLl1kNpvVu3dv5eXl6f/9v/8ns9lsWSCladOmcnV11X/+8x9lZGTolltukZeXl9avX6/XXntN48ePr8vLBQAAAAALm4q8y9+NN2fOHDVq1EjLli1TQECAJOnXX3/VsGHD1LNnT8dmaYcVK1ZozJgx6tWrl1xcXPTwww9r3rx5lv2FhYVKS0tTXl6epIsFa0pKiiQpMjLSqq9Dhw6pZcuWcnd31/z58zVu3DgZhqHIyEjNmTNHI0eOrL0LAwAAAIAK2L3wSrNmzbRu3TrdcMMNVu179uxR7969deLECYck6Ix4Tx4AAAAAqWZqA5fqJHPq1KlS7adOndK5c+eqlRQAAAAAwD52F3kPPvighg0bpo8//ljHjh3TsWPH9K9//UvDhw/XQw895MgcAQAAAABVZPcrFBYsWKDx48fr8ccfV2FhoQzDkLu7u4YPH64333zTkTkCAAAAAKqo2i9Dz83N1YEDByRJrVu3VoMGDRySmDPjO3kAAAAApCvsZejTp0+vcH9CQoK9XQMAAAAA7GR3kbdmzRqr7cLCQh06dEhubm5q3bo1RR4AAAAA1AG7i7w/vhhdujjVOHToUD344IPVSgoAAAAAYB+7V9csi6+vr6ZNm6YpU6Y4slsAAAAAQBU5tMiTpOzsbGVnZzu6WwAAAABAFdj9uOa8efOstg3D0MmTJ/V///d/uvvuu6udGAAAAADAdnYXeXPnzrXadnFxUdOmTTVkyBBNnjy52okBAAAAAGxnd5F36NAhR+YBAAAAAHAAu7+Td+TIEZX3HvUjR47YnRAAAAAAwH52F3kRERE6depUqfYzZ84oIiKiWkkBAAAAAOxjd5FnGIZMJlOp9pycHHl5eVUrKQAAAACAfWz+Tl58fLwkyWQyacqUKfLx8bHsKy4uVkpKiqKiohyWIAAAAACg6mwu8nbs2CHp4kze7t275eHhYdnn4eGhTp06afz48Y7LEAAAAABQZTYXeRs3bpQkDRs2TO+88458fX0dnhQAAAAAwD52v0JhyZIljswDAAAAAOAANhV58fHxmjFjhho0aGD5bl555syZU63EAAAAAAC2s6nI27FjhwoLCy0/AwAAAACuLCajvDeao8aYzWb5+fkpOzub7zQCAAAAV7GaqA3s/k5eeY9rmkwmeXl5KTIyUn379lVgYKDdyQEAAAAAbGP3TN4dd9yh7du3q7i4WG3atJEk/fTTT3J1dVXbtm2VlpYmk8mkr776Su3atXNo0vUdM3kAAAAApJqpDVzsPbBv376KjY3ViRMntG3bNm3btk3Hjh3TXXfdpQEDBuj48eO69dZbNW7cOIckCgAAAAConN0zec2aNdP69etLzdLt3btXvXv31vHjx7V9+3b17t1bp0+fdkiyzoKZPAAAAADSFTaTl52drczMzFLtp06dktlsliT5+/uroKDA/uwAAAAAADap1uOaTz75pNasWaNjx47p2LFjWrNmjYYPH65+/fpJkrZu3arrrrvOUbkCAAAAACph9+OaOTk5GjdunJYvX66ioiJJkpubm4YMGaK5c+eqQYMGSk1NlSRFRUU5Kl+nwOOaAAAAAKSaqQ2q/Z68nJwcHTx4UJLUqlUrNWzY0CGJOTOKPAAAAADSFfaevEsaNmyojh07OiIXAAAAAEA1VavIS0pKUlJSkjIzM1VSUmK1b/HixdVKDAAAAABgO7uLvGnTpmn69OmKjo5WaGioTCaTI/MCAAAAANjB7iJvwYIFWrp0qQYNGuTIfAAAAAAA1WD3KxQKCgrUrVs3R+biUGfPntXAgQPl6+srf39/DR8+XDk5ORUec/vtt8tkMll9nnrqKauYI0eO6N5775WPj4+CgoL0wgsvWFYXBQAAAIC6ZneRN2LECK1cudKRuTjUwIEDtXfvXq1fv16fffaZtmzZolGjRlV63MiRI3Xy5EnLZ9asWZZ9xcXFuvfee1VQUKBvvvlGy5Yt09KlS5WQkFCTlwIAAAAAVWb345oXLlzQwoUL9cUXX6hjx45yd3e32j9nzpxqJ2evffv2KTExUd99952io6MlSe+++67uuecezZ49W2FhYeUe6+Pjo5CQkDL3rVu3Tj/88IO++OILBQcHKyoqSjNmzNDEiRP1yiuvyMPDo0auBwAAAACqyu6ZvF27dikqKkouLi7as2ePduzYYflcegl6XUlOTpa/v7+lwJOk2NhYubi4KCUlpcJjV6xYoSZNmqh9+/aaPHmy8vLyrPrt0KGDgoODLW1xcXEym83au3ev4y8EAAAAAGxk90zexo0bHZmHQ6WnpysoKMiqzc3NTYGBgUpPTy/3uMcff1wtWrRQWFiYdu3apYkTJyotLU0ff/yxpd/LCzxJlu2K+s3Pz1d+fr5l22w223xNAAAAAFAV1X4Zem2aNGmS3njjjQpj9u3bZ3f/l39nr0OHDgoNDVWvXr104MABtW7d2u5+Z86cqWnTptl9PAAAAABUVbWKvKysLL3//vuWwqpdu3YaPny4/Pz8HJLcHz3//PMaOnRohTGtWrVSSEiIMjMzrdqLiop09uzZcr9vV5aYmBhJ0v79+9W6dWuFhIRo69atVjEZGRmSVGG/kydPVnx8vGXbbDYrPDy8ynkAAAAAQFXZXeR9//33iouLk7e3t7p06SJJmjt3rl577TWtW7dON910k8OSvKRp06Zq2rRppXFdu3ZVVlaWtm3bps6dO0uSNmzYoJKSEkvhVhWXvlsYGhpq6fcvf/mLMjMzLY+Drl+/Xr6+vmrXrl25/Xh6esrT07PK5wUAAAAAe5kMwzDsObBnz56KjIzUokWL5OZ2sVYsKirSiBEjdPDgQW3ZssWhidrq7rvvVkZGhhYsWKDCwkINGzZM0dHRltc+HD9+XL169dLy5cvVpUsXHThwQCtXrtQ999yjxo0ba9euXRo3bpyaN2+uzZs3S7r4CoWoqCiFhYVp1qxZSk9P16BBgzRixAi99tprVc7NbDbLz89P2dnZ8vX1rZHrBwAAAHDlq4nawO7VNb///ntNnDjRUuBJFxc3mTBhgr7//nuHJFcdK1asUNu2bdWrVy/dc8896tGjhxYuXGjZX1hYqLS0NMvqmR4eHvriiy/Uu3dvtW3bVs8//7wefvhh/ec//7Ec4+rqqs8++0yurq7q2rWrnnjiCQ0ePFjTp0+v9esDAAAAgLLY/bimr6+vjhw5orZt21q1Hz16VI0aNap2YtUVGBhY4cvaW7ZsqcsnMcPDwy0zdhVp0aKF1q5d65AcAQAAAMDR7J7J69+/v4YPH67Vq1fr6NGjOnr0qFatWqURI0ZowIABjswRAAAAAFBFds/kzZ49WyaTSYMHD1ZRUZEkyd3dXaNHj670NQcAAAAAgJph98Irl+Tl5enAgQOSpNatW+vs2bOaPn261fffYI2FVwAAAABINVMbVLvI+6OdO3fqpptuUnFxsSO7dSoUeQAAAACkK2x1TQAAAADAlYciDwAAAACcCEUeAAAAADgRm1fXfOihhyrcn5WVZW8uAAAAAIBqsrnI8/Pzq3T/4MGD7U4IAAAAAGA/m4u8JUuW1EQeAAAAAAAH4Dt5AAAAAOBEKPIAAAAAwIlQ5AEAAACAE6HIAwAAAAAnQpEHAAAAAE6EIg8AAAAAnAhFHgAAAAA4EYo8AAAAAHAiFHkAAAAA4EQo8gAAAADAiVDkAQAAAIATocgDAAAAACdCkQcAAAAAToQiDwAAAACcCEUeAAAAADgRijwAAAAAcCIUeQAAAADgRCjyAAAAAMCJUOQBAAAAgBOhyAMAAAAAJ0KRBwAAAABOhCIPAAAAAJwIRR4AAAAAOBGKPAAAAABwIhR5AAAAAOBEnLbIO3v2rAYOHChfX1/5+/tr+PDhysnJKTf+8OHDMplMZX4+/PBDS1xZ+1etWlUblwQAAAAAlXKr6wRqysCBA3Xy5EmtX79ehYWFGjZsmEaNGqWVK1eWGR8eHq6TJ09atS1cuFBvvvmm7r77bqv2JUuWqE+fPpZtf39/h+cPAAAAAPZwyiJv3759SkxM1Hfffafo6GhJ0rvvvqt77rlHs2fPVlhYWKljXF1dFRISYtW2Zs0aPfroo2rYsKFVu7+/f6lYAAAAALgSOOXjmsnJyfL397cUeJIUGxsrFxcXpaSkVKmPbdu2KTU1VcOHDy+17+mnn1aTJk3UpUsXLV68WIZhOCx3AAAAAKgOp5zJS09PV1BQkFWbm5ubAgMDlZ6eXqU+3n//fV1//fXq1q2bVfv06dN15513ysfHR+vWrdOf//xn5eTk6Nlnny23r/z8fOXn51u2zWazDVcDAAAAAFVXr2byJk2aVO7iKJc+P/74Y7XPc/78ea1cubLMWbwpU6aoe/fuuvHGGzVx4kRNmDBBb775ZoX9zZw5U35+fpZPeHh4tXMEAAAAgLLUq5m8559/XkOHDq0wplWrVgoJCVFmZqZVe1FRkc6ePVul79J99NFHysvL0+DBgyuNjYmJ0YwZM5Sfny9PT88yYyZPnqz4+HjLttlsptADAAAAUCPqVZHXtGlTNW3atNK4rl27KisrS9u2bVPnzp0lSRs2bFBJSYliYmIqPf7999/XAw88UKVzpaamKiAgoNwCT5I8PT0r3A8AAAAAjlKviryquv7669WnTx+NHDlSCxYsUGFhocaMGaPHHnvMsrLm8ePH1atXLy1fvlxdunSxHLt//35t2bJFa9euLdXvf/7zH2VkZOiWW26Rl5eX1q9fr9dee03jx4+vtWsDAAAAgIo4ZZEnSStWrNCYMWPUq1cvubi46OGHH9a8efMs+wsLC5WWlqa8vDyr4xYvXqzmzZurd+/epfp0d3fX/PnzNW7cOBmGocjISM2ZM0cjR46s8esBAAAAgKowGaz/X+vMZrP8/PyUnZ0tX1/fuk4HAAAAQB2pidqgXq2uCQAAAACoGEUeAAAAADgRijwAAAAAcCIUeQAAAADgRCjyAAAAAMCJUOQBAAAAgBOhyAMAAAAAJ0KRBwAAAABOhCIPAAAAAJwIRR4AAAAAOBGKPAAAAABwIhR5AAAAAOBEKPIAAAAAwIlQ5AEAAACAE6HIAwAAAAAnQpEHAAAAAE6EIg8AAAAAnAhFHgAAAAA4EYo8AAAAAHAiFHkAAAAA4EQo8gAAAADAiVDkAQAAAIATocgDAAAAACdCkQcAAAAAToQiDwAAAACcCEUeAAAAADgRijwAAAAAcCIUeQAAAADgRCjyAAAAAMCJUOQBAAAAgBOhyAMAAAAAJ0KRBwAAAABOhCIPAAAAAJwIRR4AAAAAOBGKPAAAAABwIk5b5P3lL39Rt27d5OPjI39//yodYxiGEhISFBoaKm9vb8XGxurnn3+2ijl79qwGDhwoX19f+fv7a/jw4crJyamBKwAAAAAA2zltkVdQUKA//elPGj16dJWPmTVrlubNm6cFCxYoJSVFDRo0UFxcnC5cuGCJGThwoPbu3av169frs88+05YtWzRq1KiauAQAAAAAsJnJMAyjrpOoSUuXLtXYsWOVlZVVYZxhGAoLC9Pzzz+v8ePHS5Kys7MVHByspUuX6rHHHtO+ffvUrl07fffdd4qOjpYkJSYm6p577tGxY8cUFhZWpZzMZrP8/PyUnZ0tX1/fal0fAAAAgPqrJmoDp53Js9WhQ4eUnp6u2NhYS5ufn59iYmKUnJwsSUpOTpa/v7+lwJOk2NhYubi4KCUlpdZzBgAAAIA/cqvrBK4U6enpkqTg4GCr9uDgYMu+9PR0BQUFWe13c3NTYGCgJaYs+fn5ys/Pt2xnZ2dLuli1AwAAALh6XaoJHPmAZb0q8iZNmqQ33nijwph9+/apbdu2tZRR1cycOVPTpk0r1R4eHl4H2QAAAAC40pw5c0Z+fn4O6ateFXnPP/+8hg4dWmFMq1at7Oo7JCREkpSRkaHQ0FBLe0ZGhqKioiwxmZmZVscVFRXp7NmzluPLMnnyZMXHx1u2s7Ky1KJFCx05csRhv5C4+K8g4eHhOnr0KN91dCDGtWYwrjWDca05jG3NYFxrBuNaMxjXmpGdna1rrrlGgYGBDuuzXhV5TZs2VdOmTWuk74iICIWEhCgpKclS1JnNZqWkpFhW6OzatauysrK0bds2de7cWZK0YcMGlZSUKCYmpty+PT095enpWardz8+P3yA1wNfXl3GtAYxrzWBcawbjWnMY25rBuNYMxrVmMK41w8XFcculOO3CK0eOHFFqaqqOHDmi4uJipaamKjU11eqddm3bttWaNWskSSaTSWPHjtWrr76qTz/9VLt379bgwYMVFhamfv36SZKuv/569enTRyNHjtTWrVv19ddfa8yYMXrssceqvLImAAAAANSkejWTZ4uEhAQtW7bMsn3jjTdKkjZu3Kjbb79dkpSWlmZZBEWSJkyYoNzcXI0aNUpZWVnq0aOHEhMT5eXlZYlZsWKFxowZo169esnFxUUPP/yw5s2bVzsXBQAAAACVcNoib+nSpVq6dGmFMX9cwcZkMmn69OmaPn16uccEBgZq5cqV1crN09NTU6dOLfMRTtiPca0ZjGvNYFxrBuNacxjbmsG41gzGtWYwrjWjJsbV6V+GDgAAAABXE6f9Th4AAAAAXI0o8gAAAADAiVDkAQAAAIATocirIfPnz1fLli3l5eWlmJgYbd26tdzYRYsWqWfPngoICFBAQIBiY2MrjL+a2TKul1u1apVMJpPldRiwZuu4ZmVl6emnn1ZoaKg8PT113XXXae3atbWUbf1h67i+/fbbatOmjby9vRUeHq5x48bpwoULtZRt/bBlyxbdf//9CgsLk8lk0ieffFLpMZs2bdJNN90kT09PRUZGVroo19XI1nH9+OOPddddd6lp06by9fVV165d9b///a92kq1H7Pn/9ZKvv/5abm5ulnf34nf2jGt+fr5eeukltWjRQp6enmrZsqUWL15c88nWI/aM64oVK9SpUyf5+PgoNDRUTz75pM6cOVPzydYjM2fO1M0336xGjRopKChI/fr1U1paWqXHffjhh2rbtq28vLzUoUMHm/+eRZFXA1avXq34+HhNnTpV27dvV6dOnRQXF6fMzMwy4zdt2qQBAwZo48aNSk5OVnh4uHr37q3jx4/XcuZXNlvH9ZLDhw9r/Pjx6tmzZy1lWr/YOq4FBQW66667dPjwYX300UdKS0vTokWL1KxZs1rO/Mpm67iuXLlSkyZN0tSpU7Vv3z69//77Wr16tV588cVazvzKlpubq06dOmn+/PlVij906JDuvfde3XHHHUpNTdXYsWM1YsQICpI/sHVct2zZorvuuktr167Vtm3bdMcdd+j+++/Xjh07ajjT+sXWcb0kKytLgwcPVq9evWoos/rNnnF99NFHlZSUpPfff19paWn64IMP1KZNmxrMsv6xdVy//vprDR48WMOHD9fevXv14YcfauvWrRo5cmQNZ1q/bN68WU8//bS+/fZbrV+/XoWFherdu7dyc3PLPeabb77RgAEDNHz4cO3YsUP9+vVTv379tGfPnqqf2IDDdenSxXj66act28XFxUZYWJgxc+bMKh1fVFRkNGrUyFi2bFlNpVgv2TOuRUVFRrdu3Yz33nvPGDJkiNG3b99ayLR+sXVc//73vxutWrUyCgoKaivFesnWcX366aeNO++806otPj7e6N69e43mWZ9JMtasWVNhzIQJE4wbbrjBqq1///5GXFxcDWZWv1VlXMvSrl07Y9q0aY5PyEnYMq79+/c3Xn75ZWPq1KlGp06dajSv+q4q4/rf//7X8PPzM86cOVM7STmBqozrm2++abRq1cqqbd68eUazZs1qMLP6LzMz05BkbN68udyYRx991Lj33nut2mJiYoz/7//7/6p8HmbyHKygoEDbtm1TbGyspc3FxUWxsbFKTk6uUh95eXkqLCxUYGBgTaVZ79g7rtOnT1dQUJCGDx9eG2nWO/aM66effqquXbvq6aefVnBwsNq3b6/XXntNxcXFtZX2Fc+ece3WrZu2bdtmeaTz4MGDWrt2re65555aydlZJScnW/06SFJcXFyV78eompKSEp07d44/txxgyZIlOnjwoKZOnVrXqTiNTz/9VNHR0Zo1a5aaNWum6667TuPHj9f58+frOrV6rWvXrjp69KjWrl0rwzCUkZGhjz76iD+3KpGdnS1JFd4vHfFnl9O+DL2unD59WsXFxQoODrZqDw4O1o8//lilPiZOnKiwsLBSv7hXM3vG9auvvtL777+v1NTUWsiwfrJnXA8ePKgNGzZo4MCBWrt2rfbv368///nPKiws5C8lv7FnXB9//HGdPn1aPXr0kGEYKioq0lNPPcXjmtWUnp5e5q+D2WzW+fPn5e3tXUeZOZfZs2crJydHjz76aF2nUq/9/PPPmjRpkr788ku5ufFXNEc5ePCgvvrqK3l5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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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6TTijn1Ed1MxmOC+sG10vHYsPZqFujqeiIiIiIjUQCp5LpCTncmOT6fT7vB7JJoKwQR73ZtR2HMS91x6HSaz2dURRURERESkhlLJu4jyi0v56KdtDFk1gERywQQHzTFkdX+Yjn1vVrkTEREREZFKU8m7CIqKrby/7ij/XrGfU/lW6nu0p6NHChnxE+jU/1Zi3dxcHVFERERERGoJlbwqVFxUwOYvX6XRrrm8V/w4p4wIGtfzwe3Sl2jYuQWN3TX8IiIiIiLiXGoZVaDEWkzS/96g0bbXSeAkAPf5LMO46nmGdG6Ih5velikiIiIiIlVDJc+JbKWlbPp6DpFbXqGbkQpAOiEcbD2GgQPH4unl4+KEIiIiIiJS26nkOYHdbvDN1uM0/WowXe3JAJwikL3NR9Nx8AQSfPxcnFBEREREROoKlbxKMOx2vt+ZxstL97I7NZdxbu1p4HGMXU1uJ27IRLr7Bbo6ooiIiIiI1DEqeQ4w7Ha2rliIz+p/8kHhdey2x+Hv5Y53j3G4JbxAYmCIqyOKiIiIiEgdpZJXAYbdzrafvsTjx+nEle4C4D6Pr+nQ4zru7N2EQB8PFycUEREREZG6TiWvAnbPvIoE85lyV2hY2BJ5Ay2ve5KE+g1cnExEREREROQMlbwKaF2yE6vFg6SwQTQdMpnukY1dHUlERERERKQclbwK2BD8d9oMe46E6GaujiIiIiIiInJOKnkVED9mDgEBAa6OISIiIiIicl5mVwcQERERERER51HJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVqZMl7/fXXiYmJwcvLi4SEBNatW/en63/yySe0atUKLy8v2rdvz6JFiy5SUhERERERkYurxpW8BQsWMGHCBKZMmcKmTZuIi4ujf//+pKenn3P9n3/+mWHDhnHHHXeQlJTEoEGDGDRoENu3b7/IyUVERERERKqeyTAMw9UhKiIhIYGuXbvy2muvAWC324mOjmbs2LFMmjTprPWHDh1Kfn4+X3/9ddmy7t2707FjR2bPnn1Bx8zJySEwMJDs7GwCAgKccyIiIiIiIlLnVUXXqFFX8qxWKxs3bqRv375ly8xmM3379mXNmjXn3GbNmjXl1gfo37//edcXERERERGpydxdHaAiMjIysNlshIeHl1seHh7O7t27z7lNamrqOddPTU0973GKi4spLi4u+zw7Oxs407JFRERERESc5beO4cw3WNaoknexTJ8+nalTp561PDo62gVpRERERESktjt16hSBgYFO2VeNKnmhoaG4ubmRlpZWbnlaWhoRERHn3CYiIqJC6wM89thjTJgwoezzrKwsGjduTEpKitMGXv5fTk4O0dHRHDlyRPc8VgGNb9XTGFctjW/V0xhXLY1v1dL4Vj2NcdXKzs6mUaNGhISEOG2fNarkWSwWunTpwrJlyxg0aBBwZuKVZcuWcf/9959zm8TERJYtW8YDDzxQtmzJkiUkJiae9zienp54enqetTwwMFD/sKtQQECAxrcKaXyrnsa4aml8q57GuGppfKuWxrfqaYyrltnsvOlSalTJA5gwYQKjRo0iPj6ebt26MWvWLPLz87ntttsAGDlyJFFRUUyfPh2A8ePHc+mll/LSSy9x9dVX8/HHH7NhwwbmzJnjytMQERERERGpEjWu5A0dOpSTJ08yefJkUlNT6dixI4sXLy6bXCUlJaVcC+7RowcffvghTz75JI8//jjNmzfniy++oF27dq46BRERERERkSpT40oewP3333/et2euWLHirGU33HADN9xwg8PH8/T0ZMqUKed8C6dUnsa3aml8q57GuGppfKuexrhqaXyrlsa36mmMq1ZVjG+Nexi6iIiIiIiInF+Nehi6iIiIiIiI/DmVPBERERERkVpEJU9ERERERKQWUcn71euvv05MTAxeXl4kJCSwbt268647d+5cevfuTXBwMMHB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I+P76quvGm3atDG8vb2NyMhI45ZbbjGOHj168cPXAOcaW6Dcz61z/a723//+12jRooVhsViMtm3bGt98802Fjmv69eAiIiIiIiJSC9T5e/JERERERERqE5U8ERERERGRWkQlT0REREREpBZRyRMREREREalFVPJERERERERqEZU8ERERERGRWkQlT0REREREpBZRyRMREREREalFVPJERERERERqEZU8ERERERGRWkQlT0REpA657LLLeOCBBxze3jAM7rrrLkJCQjCZTGzevNmhff7VNhe6z4kTJzJo0KAKHVtEpLZzd3UAERFxPpPJ9KevT5kyhaeffvrihBGXueyyy+jYsSOzZs0qW/bZZ5/h4eHh8D4XL17M22+/zYoVK2jSpAmhoaGV3mdlbN68mR49erjk2CIi1ZVKnohILXTixImy/1+wYAGTJ08mOTm5bJmfn99Z21itViwWy0XJ52w1OfvFFhISUqnt9+/fT2RkZLliVdl9VsaWLVu45557XHZ8EZHqSG/XFBGphSIiIso+AgMDMZlM5Zb5+flx2WWXcf/99/PAAw8QGhpK//79gTNXanr16kVQUBD16tXjmmuuYf/+/WX7vuyyyxg3bhyPPPIIISEhREREnHVVcOHChbRv3x5vb2/q1atH3759yc/PZ86cOTRo0AC73V5u/YEDB3L77bcDYLfbmT59OrGxsXh7exMXF8fChQvLrX++7Oc77oXu948uu+wyxo4dywMPPEBwcDDh4eHMnTuX/Px8brvtNvz9/WnWrBnffvtt2TZ/NX4Aubm53HLLLfj6+hIZGcnLL7981tsT/2qc/+p8br31Vn788UdeeeUVTCYTJpOJQ4cOnXUcu93OjBkzaNasGZ6enjRq1Ih//OMf5xyPW2+9lbFjx5KSkoLJZCImJqYs6x/3WZGxzs/PZ+TIkfj5+REZGclLL730J1+V/3f06FEyMjIAuPLKK/Hx8aFly5asXbv2grYXEamtVPJEROqwd955B4vFwurVq5k9ezZw5hfuCRMmsGHDBpYtW4bZbGbw4MHlitk777yDr68va9euZcaMGTzzzDMsWbIEOHMVcdiwYdx+++3s2rWLFStWMGTIEAzD4IYbbuDUqVMsX768bF+ZmZksXryYW265BYDp06fz7rvvMnv2bHbs2MGDDz7I8OHD+fHHH/80+58dtyL7PdcY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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(9, 4.5))\n", - "plt.plot(transverse_magnetic_field_space, mag_z_exact, label=\"Exact\")\n", - "plt.plot(transverse_magnetic_field_space, mag_z_dmrg, label=\"DMRG\", linestyle=\"dashed\")\n", - "plt.xlabel(\"Transverse magnetic field $h$\")\n", - "plt.ylabel(\"Longitudinal magnetisation $m_z$\", rotation=90, labelpad=10)\n", - "plt.xlim((0.2, 2))\n", - "plt.ylim((-1, 1))\n", - "plt.legend(fontsize=10)\n", - "plt.tight_layout()\n", - "plt.show()\n", - "\n", - "plt.figure(figsize=(9, 4.5))\n", - "plt.plot(transverse_magnetic_field_space, mag_x_exact, label=\"Exact\")\n", - "plt.plot(transverse_magnetic_field_space, mag_x_dmrg, label=\"DMRG\", linestyle=\"dashed\")\n", - "plt.xlabel(\"Transverse magnetic field $h$\")\n", - "plt.ylabel(\"Transverse magnetisation $m_x$\", rotation=90, labelpad=10)\n", - "plt.xlim((0.2, 2))\n", - "plt.ylim((0, 1))\n", - "plt.legend(fontsize=10)\n", - "plt.tight_layout()\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.9.12 ('base')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.2" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "beb51d2e4f595594d882127529c1bc4b1aa1e76d8ded79011fd6bf52b7a41e64" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/docs/examples/ising/ising.py b/docs/examples/ising/ising.py deleted file mode 100644 index 0bc9baec..00000000 --- a/docs/examples/ising/ising.py +++ /dev/null @@ -1,246 +0,0 @@ -""" -This module contains classes and functions we use to simulate the 1D Ising module. -""" - -from typing import Union, List -import numpy as np -from scipy.sparse import csr_matrix, eye, kron - -from mdopt.mps.explicit import ExplicitMPS -from mdopt.mps.canonical import CanonicalMPS - - -class IsingExact: - """ - Class for exact representation of a transverse field Ising model in 1D. - """ - - def __init__(self, num_sites: int = 2, h_magnetic: np.float32 = 0) -> None: - """ - Initialises an instance to exactly simulate the Ising model in 1D. - - Parameters - ---------- - num_sites : int - The number of spins in the chain. - h_magnetic : np.float32 - Value of the transverse magnetic field scaled by the ZZ-interaction. - """ - self.num_sites = num_sites - self.h_magnetic = h_magnetic - self.identity = np.identity(2) - self.pauli_x = np.array([[0.0, 1.0], [1.0, 0.0]]) - self.pauli_z = np.array([[1.0, 0.0], [0.0, -1.0]]) - self.two_qubit_hamiltonian = -kron( - self.pauli_z, self.pauli_z - ) - self.h_magnetic * ( - kron(self.pauli_x, self.identity) + kron(self.identity, self.pauli_x) - ) - if num_sites < 2: - raise ValueError(f"Number of sites should be >=2, given {num_sites}") - - def hamiltonian_sparse(self) -> csr_matrix: - """ - Returns a sparse representation of the Hamiltonian. - """ - if self.num_sites == 2: - return self.two_qubit_hamiltonian - ising_recursive = IsingExact(self.num_sites - 1, self.h_magnetic) - return csr_matrix( - kron(ising_recursive.hamiltonian_sparse(), self.identity) - - kron(eye(2 ** (self.num_sites - 2)), kron(self.pauli_z, self.pauli_z)) - - self.h_magnetic * kron(eye(2 ** (self.num_sites - 1)), self.pauli_x) - ) - - def hamiltonian_dense(self) -> np.ndarray: - """ - Returns a dense representation of the Hamiltonian. - Warning: memory-intensive! Do not use for ``num_sites`` > 20. - """ - - return self.hamiltonian_sparse().todense() - - def energy(self, state: np.ndarray) -> np.float32: - """ - Computes the energy corresponding to a quantum state ``state``. - """ - return np.conjugate(state.T) @ self.hamiltonian_sparse @ state - - def z_magnetisation(self, i: int, state: np.ndarray) -> np.float32: - """ - Computes the z-magnetisation value - corresponding to a quantum state ``state`` - at site ``i``. - """ - if i == 0: - return ( - np.conjugate(state.T) - @ kron(self.pauli_z, eye(2 ** (self.num_sites - 1))).toarray() - @ state - ) - if i == self.num_sites - 1: - return ( - np.conjugate(state.T) - @ kron(eye(2 ** (self.num_sites - 1)), self.pauli_z).toarray() - @ state - ) - return ( - np.conjugate(state.T) - @ kron( - kron(eye(2**i), self.pauli_z), eye(2 ** (self.num_sites - i - 1)) - ).toarray() - @ state - ) - - def x_magnetisation(self, i: int, state: np.ndarray) -> np.float32: - """ - Computes the x-magnetisation value - corresponding to a quantum state ``state`` - at site ``i``. - """ - if i == 0: - return ( - np.conjugate(state.T) - @ kron(self.pauli_x, eye(2 ** (self.num_sites - 1))).toarray() - @ state - ) - if i == self.num_sites - 1: - return ( - np.conjugate(state.T) - @ kron(eye(2 ** (self.num_sites - 1)), self.pauli_x).toarray() - @ state - ) - return ( - np.conjugate(state.T) - @ kron( - kron(eye(2**i), self.pauli_x), eye(2 ** (self.num_sites - i - 1)) - ).toarray() - @ state - ) - - def average_chain_z_magnetisation(self, state: np.ndarray) -> np.float32: - """ - Computes the average z-magnetisation - corresponding to a quantum state ``state`` - of the whole chain. - """ - return ( - sum([self.z_magnetisation(i, state) for i in range(self.num_sites)]) - / self.num_sites - ) - - def average_chain_x_magnetisation(self, state: np.ndarray) -> np.float32: - """ - Computes the average x-magnetisation - corresponding to a quantum state ``state`` - of the whole chain. - """ - return ( - sum([self.x_magnetisation(i, state) for i in range(self.num_sites)]) - / self.num_sites - ) - - -class IsingMPO: - """ - Class for a Matrix Product Operator (MPO) representation of - a transverse field Ising model in 1D and computing relevant physical observables. - """ - - def __init__( - self, num_sites: int = int(2), h_magnetic: np.float32 = np.float32(0) - ) -> None: - """ - Initialises an instance to simulate the Ising model in 1D using MPS. - - Parameters - ---------- - num_sites : int - Number of spins in the chain. - h_magnetic : np.float32 - Value of the transverse magnetic field scaled by the ZZ-interaction. - """ - self.num_sites = num_sites - self.h_magnetic = h_magnetic - self.identity = np.identity(2) - self.pauli_x = np.array([[0.0, 1.0], [1.0, 0.0]]) - self.pauli_z = np.array([[1.0, 0.0], [0.0, -1.0]]) - if num_sites < 2: - raise ValueError(f"Number of sites should be >=2, given {num_sites}") - - def hamiltonian_mpo(self) -> List[np.ndarray]: - """Returns a Matrix Product Operator representation of the Hamiltonian. - - Follows the convention of indices from ``mdopt.mps.explicit.py``: - each tensor in the MPO list has legs ``(vL, vR, pU, pD)``, - where ``v`` stands for "virtual", p -- for "physical", - and ``L, R, U, D`` stand for "left", "right", "up", "down". - For explanation of what ``v_right`` and ``v_left`` are, - see https://arxiv.org/abs/1603.03039 page 22. - """ - v_left = np.array([0.0, 0.0, 1.0]) - v_right = np.array([1.0, 0.0, 0.0]) - - mpo_bulk = np.zeros((3, 3, 2, 2)) - mpo_bulk[0, 0] = self.identity - mpo_bulk[1, 0] = self.pauli_z - mpo_bulk[2, 0] = -self.h_magnetic * self.pauli_x - mpo_bulk[2, 1] = -1.0 * self.pauli_z - mpo_bulk[2, 2] = self.identity - - mpo_left = np.tensordot(v_left, mpo_bulk, [0, 0]).reshape((1, 3, 2, 2)) - mpo_right = np.tensordot(mpo_bulk, v_right, [1, 0]).reshape((3, 1, 2, 2)) - - mpo_list = [] - mpo_list.append(mpo_left) - for _ in range(self.num_sites - 2): - mpo_list.append(mpo_bulk) - mpo_list.append(mpo_right) - - return mpo_list - - def z_magnetisation( - self, i: int, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: - """ - Computes the z-magnetisation value - corresponding to a quantum state - in the form of an MPS at site ``i``. - """ - return mps.one_site_expectation_value(i, self.pauli_z) - - def x_magnetisation( - self, i: int, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: - """ - Computes the x-magnetisation value - corresponding to a quantum state - in the form of an MPS at site ``i``. - """ - return mps.one_site_expectation_value(i, self.pauli_x) - - def average_chain_z_magnetisation( - self, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: - """ - Computes the average z-magnetisation - corresponding to a quantum state - in the form of an MPS at site ``i``. - """ - return ( - sum([self.z_magnetisation(i, mps) for i in range(self.num_sites)]) - / self.num_sites - ) - - def average_chain_x_magnetisation( - self, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: - """ - Computes the average x-magnetisation - corresponding to a quantum state - in the form of an MPS at site ``i``. - """ - return ( - sum([self.x_magnetisation(i, mps) for i in range(self.num_sites)]) - / self.num_sites - ) diff --git a/docs/examples/ising/ising_parallel.py b/docs/examples/ising/ising_parallel.py deleted file mode 100644 index 85fa993a..00000000 --- a/docs/examples/ising/ising_parallel.py +++ /dev/null @@ -1,106 +0,0 @@ -""" -Here we parallelise our ground-state example. Co-authored by Moïse Russeau. -""" - -from multiprocessing import cpu_count, Pool -import matplotlib.pyplot as plt -import numpy as np -from threadpoolctl import threadpool_limits -from scipy.sparse.linalg import eigsh - -from ising import IsingExact, IsingMPO -from mdopt.mps.utils import create_simple_product_state -from mdopt.optimiser.dmrg import DMRG as dmrg_optimiser - -NUM_SITES = 15 - - -def exact_simulation(magnetic_field: np.float32 = 0): - """ - Exact simulation function. - """ - - exact = IsingExact(num_sites=NUM_SITES, h_magnetic=magnetic_field) - ham_sp = exact.hamiltonian_sparse() - ground_state_ex = eigsh(ham_sp, k=2, tol=1e-9)[1][:, 0] - return ( - exact.average_chain_x_magnetisation(ground_state_ex), - exact.average_chain_z_magnetisation(ground_state_ex), - ) - - -def dmrg_simulation(magnetic_field: np.float32 = 0): - """ - DMRG simulation function. - """ - - mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=magnetic_field) - hamiltonian_mpo = mpo.hamiltonian_mpo() - start_mps = create_simple_product_state(num_sites=NUM_SITES, which="+") - dmrg_container = dmrg_optimiser( - start_mps, - hamiltonian_mpo, - chi_max=128, - cut=1e-9, - mode="SA", - silent=False, - copy=True, - ) - dmrg_container.run(10) - dmrg_final_mps = dmrg_container.mps - return ( - mpo.average_chain_x_magnetisation(dmrg_final_mps), - mpo.average_chain_z_magnetisation(dmrg_final_mps), - ) - - -if __name__ == "__main__": - NUM_SITES = 15 - - transverse_magnetic_field_space = np.linspace(0.01, 2.0, 20) - - with threadpool_limits(limits=cpu_count(), user_api="blas"): - with Pool() as pool: - print("DMRGs running:") - print("") - mag_dmrg = pool.map( - func=dmrg_simulation, iterable=transverse_magnetic_field_space - ) - print("") - print("Eigensolvers running.") - print("") - mag_exact = pool.map( - func=exact_simulation, iterable=transverse_magnetic_field_space - ) - mag_x_exact = [x[0] for x in mag_exact] - mag_z_exact = [z[1] for z in mag_exact] - mag_x_dmrg = [x[0] for x in mag_dmrg] - mag_z_dmrg = [z[1] for z in mag_dmrg] - pool.close() - pool.join() - - plt.figure(figsize=(9, 4.5)) - plt.plot(transverse_magnetic_field_space, mag_z_exact, label="Exact") - plt.plot( - transverse_magnetic_field_space, mag_z_dmrg, label="DMRG", linestyle="dashed" - ) - plt.xlabel("Transverse magnetic field $h$") - plt.ylabel("Longitudinal magnetisation $m_z$", rotation=90, labelpad=10) - plt.xlim((0.2, 2)) - plt.ylim((-1, 1)) - plt.legend(fontsize=10) - plt.tight_layout() - plt.show() - - plt.figure(figsize=(9, 4.5)) - plt.plot(transverse_magnetic_field_space, mag_x_exact, label="Exact") - plt.plot( - transverse_magnetic_field_space, mag_x_dmrg, label="DMRG", linestyle="dashed" - ) - plt.xlabel("Transverse magnetic field $h$") - plt.ylabel("Transverse magnetisation $m_x$", rotation=90, labelpad=10) - plt.xlim((0.2, 2)) - plt.ylim((0, 1)) - plt.legend(fontsize=10) - plt.tight_layout() - plt.show() diff --git a/docs/mdopt.rst b/docs/mdopt.rst deleted file mode 100644 index bcffddc9..00000000 --- a/docs/mdopt.rst +++ /dev/null @@ -1,10 +0,0 @@ -modules ------------ - -.. toctree:: - :maxdepth: 4 - - mps - contractor - utils - optimiser diff --git a/docs/optimiser.rst b/docs/optimiser.rst deleted file mode 100644 index 4fc7e925..00000000 --- a/docs/optimiser.rst +++ /dev/null @@ -1,20 +0,0 @@ -Optimiser module -================= - - -The DMRG submodule --------------------------- - -.. automodule:: mdopt.optimiser.dmrg - :members: - :undoc-members: - :show-inheritance: - - -The Dephasing DMRG submodule --------------------------- - -.. automodule:: mdopt.optimiser.dephasing_dmrg - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/README.rst b/docs/source/README.rst new file mode 100644 index 00000000..9c6c0971 --- /dev/null +++ b/docs/source/README.rst @@ -0,0 +1,54 @@ +|codecov| |tests| |Documentation Status| |pre-commit.ci status| |lint| +|mypy| |Unitary Fund| |MIT license| + +mdopt +===== + +mdopt is a python package built on top of numpy for discrete +optimisation in the tensor-network (specifically, MPS-MPO) language. The +code is hosted on github, so please feel free to submit issues and pull +requests. + +Installation +------------ + +Use the package manager `pip `__ to +install mdopt. + +.. code:: bash + + pip install mdopt + +Usage +----- + +For usage, see the examples folder. + +Cite +---- + +:: + + @software{mdopt2022, + author = {Aleksandr Berezutskii}, + title = {mdopt: Discrete optimization in the tensor-network (specifically, MPS-MPO) language.}, + url = {https://github.com/quicophy/mdopt}, + year = {2022}, + } + +.. |codecov| image:: https://codecov.io/gh/quicophy/mdopt/branch/main/graph/badge.svg?token=4G7VWYX0S2 + :target: https://codecov.io/gh/quicophy/mdopt +.. |tests| image:: https://github.com/quicophy/mdopt/actions/workflows/tests.yml/badge.svg?branch=main + :target: https://github.com/quicophy/mdopt/actions/workflows/tests.yml +.. |Documentation Status| image:: https://readthedocs.org/projects/mdopt/badge/?version=latest + :target: https://mdopt.readthedocs.io/en/latest/?badge=latest +.. |pre-commit.ci status| image:: https://results.pre-commit.ci/badge/github/quicophy/mdopt/main.svg + :target: https://results.pre-commit.ci/latest/github/quicophy/mdopt/main +.. |lint| image:: https://github.com/quicophy/mdopt/actions/workflows/lint.yml/badge.svg + :target: https://github.com/quicophy/mdopt/actions/workflows/lint.yml +.. |mypy| image:: https://github.com/quicophy/mdopt/actions/workflows/mypy.yml/badge.svg?branch=main + :target: https://github.com/quicophy/mdopt/actions/workflows/mypy.yml +.. |Unitary Fund| image:: https://img.shields.io/badge/Supported%20By-Unitary%20Fund-brightgreen.svg?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACgAAAASCAYAAAApH5ymAAAAt0lEQVRIic2WUQ6AIAiGsXmC7n9Gr1Dzwcb%2BUAjN8b%2B0BNwXApbKRRcF1nGmN5y0Jon7WWO%2B6pgJLhtynzUHKTMNrNo4ZPPldikW10f7qYBEMoTmJ73z2NFHcJkAvbLUpVYmvwIigKeRsjdQEtagZ2%2F0DzsHG2h9iICrRwh2qObbGPIfMDPCMjHNQawpbc71bBZhsrpNYs3qqCFmO%2FgBjHTEqKm7eIdMg9p7PCvma%2Fz%2FwQAMfRHRDTlhQGoOLve1AAAAAElFTkSuQmCC + :target: http://unitary.fund +.. |MIT license| image:: https://img.shields.io/badge/License-MIT-blue.svg + :target: https://lbesson.mit-license.org/ diff --git a/docs/_static/_sphinx_javascript_frameworks_compat.js b/docs/source/_static/_sphinx_javascript_frameworks_compat.js similarity index 100% rename from docs/_static/_sphinx_javascript_frameworks_compat.js rename to docs/source/_static/_sphinx_javascript_frameworks_compat.js diff --git a/docs/_static/basic.css b/docs/source/_static/basic.css similarity index 100% rename from docs/_static/basic.css rename to docs/source/_static/basic.css diff --git a/docs/_static/css/badge_only.css b/docs/source/_static/css/badge_only.css similarity index 100% rename from docs/_static/css/badge_only.css rename to docs/source/_static/css/badge_only.css diff --git a/docs/_static/css/fonts/Roboto-Slab-Bold.woff b/docs/source/_static/css/fonts/Roboto-Slab-Bold.woff similarity index 100% rename from docs/_static/css/fonts/Roboto-Slab-Bold.woff rename to docs/source/_static/css/fonts/Roboto-Slab-Bold.woff diff --git a/docs/_static/css/fonts/Roboto-Slab-Bold.woff2 b/docs/source/_static/css/fonts/Roboto-Slab-Bold.woff2 similarity index 100% rename from docs/_static/css/fonts/Roboto-Slab-Bold.woff2 rename to docs/source/_static/css/fonts/Roboto-Slab-Bold.woff2 diff --git a/docs/_static/css/fonts/Roboto-Slab-Regular.woff b/docs/source/_static/css/fonts/Roboto-Slab-Regular.woff similarity index 100% rename from docs/_static/css/fonts/Roboto-Slab-Regular.woff rename to docs/source/_static/css/fonts/Roboto-Slab-Regular.woff diff --git a/docs/_static/css/fonts/Roboto-Slab-Regular.woff2 b/docs/source/_static/css/fonts/Roboto-Slab-Regular.woff2 similarity index 100% rename from docs/_static/css/fonts/Roboto-Slab-Regular.woff2 rename to docs/source/_static/css/fonts/Roboto-Slab-Regular.woff2 diff --git a/docs/_static/css/fonts/fontawesome-webfont.eot b/docs/source/_static/css/fonts/fontawesome-webfont.eot similarity index 100% rename from docs/_static/css/fonts/fontawesome-webfont.eot rename to docs/source/_static/css/fonts/fontawesome-webfont.eot diff --git a/docs/_static/css/fonts/fontawesome-webfont.svg b/docs/source/_static/css/fonts/fontawesome-webfont.svg similarity index 100% rename from docs/_static/css/fonts/fontawesome-webfont.svg rename to docs/source/_static/css/fonts/fontawesome-webfont.svg diff --git a/docs/_static/css/fonts/fontawesome-webfont.ttf b/docs/source/_static/css/fonts/fontawesome-webfont.ttf similarity index 100% rename from docs/_static/css/fonts/fontawesome-webfont.ttf rename to docs/source/_static/css/fonts/fontawesome-webfont.ttf diff --git a/docs/_static/css/fonts/fontawesome-webfont.woff b/docs/source/_static/css/fonts/fontawesome-webfont.woff similarity index 100% rename from docs/_static/css/fonts/fontawesome-webfont.woff rename to docs/source/_static/css/fonts/fontawesome-webfont.woff diff --git a/docs/_static/css/fonts/fontawesome-webfont.woff2 b/docs/source/_static/css/fonts/fontawesome-webfont.woff2 similarity index 100% rename from docs/_static/css/fonts/fontawesome-webfont.woff2 rename to docs/source/_static/css/fonts/fontawesome-webfont.woff2 diff --git a/docs/_static/css/fonts/lato-bold-italic.woff b/docs/source/_static/css/fonts/lato-bold-italic.woff similarity index 100% rename from docs/_static/css/fonts/lato-bold-italic.woff rename to docs/source/_static/css/fonts/lato-bold-italic.woff diff --git a/docs/_static/css/fonts/lato-bold-italic.woff2 b/docs/source/_static/css/fonts/lato-bold-italic.woff2 similarity index 100% rename from docs/_static/css/fonts/lato-bold-italic.woff2 rename to docs/source/_static/css/fonts/lato-bold-italic.woff2 diff --git a/docs/_static/css/fonts/lato-bold.woff b/docs/source/_static/css/fonts/lato-bold.woff similarity index 100% rename from docs/_static/css/fonts/lato-bold.woff rename to docs/source/_static/css/fonts/lato-bold.woff diff --git a/docs/_static/css/fonts/lato-bold.woff2 b/docs/source/_static/css/fonts/lato-bold.woff2 similarity index 100% rename from docs/_static/css/fonts/lato-bold.woff2 rename to docs/source/_static/css/fonts/lato-bold.woff2 diff --git a/docs/_static/css/fonts/lato-normal-italic.woff b/docs/source/_static/css/fonts/lato-normal-italic.woff similarity index 100% rename from docs/_static/css/fonts/lato-normal-italic.woff rename to docs/source/_static/css/fonts/lato-normal-italic.woff diff --git a/docs/_static/css/fonts/lato-normal-italic.woff2 b/docs/source/_static/css/fonts/lato-normal-italic.woff2 similarity index 100% rename from docs/_static/css/fonts/lato-normal-italic.woff2 rename to docs/source/_static/css/fonts/lato-normal-italic.woff2 diff --git a/docs/_static/css/fonts/lato-normal.woff b/docs/source/_static/css/fonts/lato-normal.woff similarity index 100% rename from docs/_static/css/fonts/lato-normal.woff rename to docs/source/_static/css/fonts/lato-normal.woff diff --git a/docs/_static/css/fonts/lato-normal.woff2 b/docs/source/_static/css/fonts/lato-normal.woff2 similarity index 100% rename from docs/_static/css/fonts/lato-normal.woff2 rename to docs/source/_static/css/fonts/lato-normal.woff2 diff --git a/docs/_static/css/theme.css b/docs/source/_static/css/theme.css similarity index 100% rename from docs/_static/css/theme.css rename to docs/source/_static/css/theme.css diff --git a/docs/_static/doctools.js b/docs/source/_static/doctools.js similarity index 100% rename from docs/_static/doctools.js rename to docs/source/_static/doctools.js diff --git a/docs/_static/documentation_options.js b/docs/source/_static/documentation_options.js similarity index 100% rename from docs/_static/documentation_options.js rename to docs/source/_static/documentation_options.js diff --git a/docs/_static/file.png b/docs/source/_static/file.png similarity index 100% rename from docs/_static/file.png rename to docs/source/_static/file.png diff --git a/docs/_static/jquery-3.6.0.js b/docs/source/_static/jquery-3.6.0.js similarity index 100% rename from docs/_static/jquery-3.6.0.js rename to docs/source/_static/jquery-3.6.0.js diff --git a/docs/_static/jquery.js b/docs/source/_static/jquery.js similarity index 100% rename from docs/_static/jquery.js rename to docs/source/_static/jquery.js diff --git a/docs/_static/js/badge_only.js b/docs/source/_static/js/badge_only.js similarity index 100% rename from docs/_static/js/badge_only.js rename to docs/source/_static/js/badge_only.js diff --git a/docs/_static/js/html5shiv-printshiv.min.js b/docs/source/_static/js/html5shiv-printshiv.min.js similarity index 100% rename from docs/_static/js/html5shiv-printshiv.min.js rename to docs/source/_static/js/html5shiv-printshiv.min.js diff --git a/docs/_static/js/html5shiv.min.js b/docs/source/_static/js/html5shiv.min.js similarity index 100% rename from docs/_static/js/html5shiv.min.js rename to docs/source/_static/js/html5shiv.min.js diff --git a/docs/_static/js/theme.js b/docs/source/_static/js/theme.js similarity index 100% rename from docs/_static/js/theme.js rename to docs/source/_static/js/theme.js diff --git a/docs/_static/language_data.js b/docs/source/_static/language_data.js similarity index 100% rename from docs/_static/language_data.js rename to docs/source/_static/language_data.js diff --git a/docs/_static/minus.png b/docs/source/_static/minus.png similarity index 100% rename from docs/_static/minus.png rename to docs/source/_static/minus.png diff --git a/docs/_static/plus.png b/docs/source/_static/plus.png similarity index 100% rename from docs/_static/plus.png rename to docs/source/_static/plus.png diff --git a/docs/_static/pygments.css b/docs/source/_static/pygments.css similarity index 100% rename from docs/_static/pygments.css rename to docs/source/_static/pygments.css diff --git a/docs/_static/searchtools.js b/docs/source/_static/searchtools.js similarity index 100% rename from docs/_static/searchtools.js rename to docs/source/_static/searchtools.js diff --git a/docs/_static/underscore-1.13.1.js b/docs/source/_static/underscore-1.13.1.js similarity index 100% rename from docs/_static/underscore-1.13.1.js rename to docs/source/_static/underscore-1.13.1.js diff --git a/docs/_static/underscore.js b/docs/source/_static/underscore.js similarity index 100% rename from docs/_static/underscore.js rename to docs/source/_static/underscore.js diff --git a/docs/source/classical_ldpc.ipynb b/docs/source/classical_ldpc.ipynb new file mode 100644 index 00000000..0e41e2b8 --- /dev/null +++ b/docs/source/classical_ldpc.ipynb @@ -0,0 +1,814 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decoding a classical LDPC code" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this experiment, we decode a classical linear error correcting code -- Low Density Parity Check (LDPC) code.\n", + "First, we build a Matrix Product State containing the superposition of all codewords of a code instance.\n", + "Then, we demostrate simple decoding of a classical LDPC code using Dephasing DMRG --\n", + "our own built-in DMRG-like optimisation algorithm to solve the main component problem --\n", + "the problem of finding a computational basis state cotributing the most to a given state." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from tqdm import tqdm\n", + "import qecstruct as qec\n", + "import matplotlib.pyplot as plt\n", + "from mdopt.optimiser.utils import (\n", + " ConstraintString,\n", + " IDENTITY,\n", + " SWAP,\n", + " XOR_BULK,\n", + " XOR_LEFT,\n", + " XOR_RIGHT,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " linear_code_constraint_sites,\n", + " linear_code_prepare_message,\n", + " linear_code_codewords,\n", + " linear_code_checks,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " apply_bitflip_bias,\n", + " apply_constraints,\n", + " decode_linear,\n", + ")\n", + "from mdopt.mps.utils import (\n", + " create_simple_product_state,\n", + " create_custom_product_state,\n", + ")\n", + "from mdopt.utils.utils import mpo_to_matrix" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first fix a random seed." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "SEED = 123" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we're going to define the parameters of a classical LDPC code. Since our first experiment will be getting out all of the codewords, we start with a small code so that we can do a dense-form simulation to check against the MPS-MPO evolution simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "NUM_BITS, NUM_CHECKS = 12, 9\n", + "CHECK_DEGREE, BIT_DEGREE = 4, 3\n", + "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", + " raise ValueError(\"The Tanner graph of the code must be bipartite.\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us construct the code object from ``qecstruct`` and prepare the initial MPS state as well as its dense-form vis-à-vis." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "example_code = qec.random_regular_code(\n", + " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", + ")\n", + "\n", + "state = create_simple_product_state(NUM_BITS, which=\"+\")\n", + "state_dense = state.dense(flatten=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, we translate the error correcting code to the MPS-MPO language. This means we get the sites where the parity checks will be applied. We will construct MPOs using this data. These lists mention not only the sites where we will apply the XOR constraints but also other tensors, such as SWAPs (a.k.a. tensors' legs' crossings) as well as the boundary XOR constraints. In what follows we define the list of these auxiliary tensors and the corresponding sites where they should reside." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[0], [6, 10], [1, 2, 3, 4, 5, 7, 8, 9], [11]],\n", + " [[2], [4, 8], [3, 5, 6, 7, 9], [10]],\n", + " [[1], [6, 9], [2, 3, 4, 5, 7, 8], [10]],\n", + " [[0], [4, 7], [1, 2, 3, 5, 6], [8]],\n", + " [[2], [4, 6], [3, 5], [7]],\n", + " [[3], [5, 7], [4, 6], [8]],\n", + " [[0], [2, 3], [1, 4, 5, 6, 7, 8], [9]],\n", + " [[1], [5, 9], [2, 3, 4, 6, 7, 8, 10], [11]],\n", + " [[1], [3, 5], [2, 4, 6, 7, 8, 9, 10], [11]]]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "code_constraint_sites = linear_code_constraint_sites(example_code)\n", + "tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "code_constraint_sites" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, we are ready to check the codewords! We will do this by explicitly constructing the MPS containing equal superposition of all codewords, densifying it and finally checking all the non-zero elements. This MPS will be prepared by applying constraint MPOs to a all-plus state while renormalising it after each contraction so that the norm isn't being lost. We start with the MPS-MPO contraction:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 9/9 [00:00<00:00, 173.58it/s]\n" + ] + } + ], + "source": [ + "state = apply_constraints(\n", + " state,\n", + " code_constraint_sites,\n", + " tensors,\n", + " renormalise=True,\n", + " result_to_explicit=True,\n", + " silent=False,\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and continue by the dense-form simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 9/9 [00:01<00:00, 5.94it/s]\n" + ] + } + ], + "source": [ + "# Preparing the codeword superposition state in the dense form.\n", + "for j in tqdm(range(NUM_CHECKS)):\n", + "\n", + " # Preparing the MPO.\n", + " constraint_string = ConstraintString(tensors, code_constraint_sites[j])\n", + " constraint_mpo = constraint_string.mpo()\n", + "\n", + " # Finding the starting site of the MPS to build a correct dense-form operator.\n", + " START_SITE = min(constraint_string.flat())\n", + "\n", + " # Preparing the dense-form operator.\n", + " identities_l = [IDENTITY for _ in range(START_SITE)]\n", + " identities_r = [\n", + " IDENTITY for _ in range(NUM_BITS - len(constraint_mpo) - START_SITE)\n", + " ]\n", + " full_mpo = identities_l + constraint_mpo + identities_r\n", + " mpo_dense = mpo_to_matrix(full_mpo, interlace=False, group=True)\n", + "\n", + " # Doing the contraction in dense form.\n", + " state_dense = mpo_dense @ state_dense" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to check that the two objects represent the same thing." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Codewords from the generator matrix:\n", + "[ 0 58 407 429 3666 3688 4037 4095]\n", + "Codewords from the dense-form simulation:\n", + "[ 0 58 407 429 3666 3688 4037 4095]\n", + "Codewords from the MPS-form simulation:\n", + "[ 0 58 407 429 3666 3688 4037 4095]\n", + "\n", + "All lists of codewords match: True\n" + ] + } + ], + "source": [ + "# Tolerance under which we round tensor elements to zero.\n", + "TOL = 1e-12\n", + "mps_dense = state.dense(flatten=True)\n", + "mps_dense[np.abs(mps_dense) < TOL] = 0\n", + "\n", + "# Retreiving codewords.\n", + "cwords = linear_code_codewords(example_code)\n", + "cwords_to_compare_mps = np.flatnonzero(mps_dense)\n", + "cwords_to_compare_dense = np.flatnonzero(state_dense)\n", + "\n", + "print()\n", + "print(\"Codewords from the generator matrix:\")\n", + "print(cwords)\n", + "print(\"Codewords from the dense-form simulation:\")\n", + "print(cwords_to_compare_mps)\n", + "print(\"Codewords from the MPS-form simulation:\")\n", + "print(cwords_to_compare_dense)\n", + "print(\"\")\n", + "print(\n", + " \"All lists of codewords match:\",\n", + " np.logical_and(\n", + " np.array_equal(cwords, cwords_to_compare_mps),\n", + " np.array_equal(cwords_to_compare_mps, cwords_to_compare_dense),\n", + " ),\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have checked that we are able to prepare the codeword state, let's try and do the decoding. The setup is as follows: we receive a message (which might contain errors) and need to find what was the initial message. In order to do this, we first apply a bitflip bias to our MPS, which biases the state towards the received message by redistributing the amplitudes according to the Hamming distance from the message. Then, we apply the parity checks and solve the main component problem. Let's see how this works in practice. Note, that the final overlap quantity received from the algorithm can be either $0$ or $1$ (the anticipated outcome) because in the end we need a basis product state." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Retreiving a perturbed codeword:\n", + "\n", + "The initial codeword is 00001011111000010001\n", + "The perturbed codeword is 00000011111010000100\n", + "\n", + "Applying constraints:\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 15/15 [00:17<00:00, 1.14s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Decoding:\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1/1 [00:00<00:00, 7.00it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The overlap of the density MPO main component and the initial codeword state: 1.0\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print(\"\")\n", + "print(\"Retreiving a perturbed codeword:\")\n", + "print(\"\")\n", + "\n", + "# Defining the parameters of a classical LDPC code.\n", + "NUM_BITS, NUM_CHECKS = 20, 15\n", + "CHECK_DEGREE, BIT_DEGREE = 4, 3\n", + "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", + " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", + "\n", + "# Defining the bias channel parameter and the error probability.\n", + "PROB_ERROR = 0.15\n", + "PROB_BIAS = PROB_ERROR\n", + "\n", + "# Maximum bond dimension and spectra cut for contractor/DMRG.\n", + "CHI_MAX_CONTRACTOR = 1e4\n", + "CHI_MAX_DMRG = 1e4\n", + "CUT = 1e-12\n", + "# Number of DMRG sweeps.\n", + "NUM_DMRG_RUNS = 1\n", + "\n", + "# Constructing the code as a qecstruct object.\n", + "example_code = qec.random_regular_code(\n", + " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", + ")\n", + "\n", + "# Getting the sites where each string of constraints should be applied.\n", + "code_constraint_sites = linear_code_constraint_sites(example_code)\n", + "\n", + "# Building an initial and a perturbed codeword.\n", + "INITIAL_CODEWORD, PERTURBED_CODEWORD = linear_code_prepare_message(\n", + " example_code, PROB_ERROR, error_model=qec.BinarySymmetricChannel, seed=SEED\n", + ")\n", + "print(\"The initial codeword is\", INITIAL_CODEWORD)\n", + "print(\"The perturbed codeword is\", PERTURBED_CODEWORD)\n", + "print(\"\")\n", + "\n", + "# Building the corresponding matrix product states.\n", + "initial_codeword_state = create_custom_product_state(\n", + " INITIAL_CODEWORD, form=\"Right-canonical\"\n", + ")\n", + "perturbed_codeword_state = create_custom_product_state(\n", + " PERTURBED_CODEWORD, form=\"Right-canonical\"\n", + ")\n", + "\n", + "# Applying the bitflip bias to the perturbed codeword state.\n", + "perturbed_codeword_state = apply_bitflip_bias(\n", + " mps=perturbed_codeword_state,\n", + " sites_to_bias=\"All\",\n", + " prob_bias_list=PROB_BIAS,\n", + " renormalise=True,\n", + ")\n", + "\n", + "print(\"Applying constraints:\")\n", + "print(\"\")\n", + "# Applying the parity constraints defined by the code.\n", + "perturbed_codeword_state = apply_constraints(\n", + " perturbed_codeword_state,\n", + " code_constraint_sites,\n", + " tensors,\n", + " chi_max=CHI_MAX_CONTRACTOR,\n", + " renormalise=True,\n", + " result_to_explicit=False,\n", + " strategy=\"Naive\",\n", + " silent=False,\n", + ")\n", + "\n", + "print(\"\")\n", + "print(\"Decoding:\")\n", + "print(\"\")\n", + "# Decoding the perturbed codeword.\n", + "dmrg_container, success = decode_linear(\n", + " message=perturbed_codeword_state,\n", + " codeword=initial_codeword_state,\n", + " code=example_code,\n", + " num_runs=NUM_DMRG_RUNS,\n", + " chi_max_dmrg=CHI_MAX_DMRG,\n", + " cut=CUT,\n", + " silent=False,\n", + ")\n", + "print(\"\")\n", + "print(\n", + " \"The overlap of the density MPO main component and the initial codeword state: \",\n", + " success,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now take a look at how the bond dimensions and entropies behave throughout the decoding process while applying the parity checks." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 100/100 [00:40<00:00, 2.47it/s]\n" + ] + } + ], + "source": [ + "NUM_BITS = 16\n", + "CHI_MAX_CONTRACTOR = 1e4\n", + "CHI_MAX_DMRG = CHI_MAX_CONTRACTOR\n", + "PROB_ERROR = 0.15\n", + "PROB_BIAS = PROB_ERROR\n", + "CUT = 0\n", + "NUM_DMRG_RUNS = 1\n", + "NUM_EXPERIMENTS = 100\n", + "\n", + "SEED = 123\n", + "seed_seq = np.random.SeedSequence(SEED)\n", + "\n", + "CHECK_DEGREE, BIT_DEGREE = 4, 3\n", + "NUM_CHECKS = int(BIT_DEGREE * NUM_BITS / CHECK_DEGREE)\n", + "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", + " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", + "\n", + "entropies = np.zeros((NUM_EXPERIMENTS, NUM_CHECKS, NUM_BITS - 1))\n", + "bond_dimensions = np.zeros((NUM_EXPERIMENTS, NUM_CHECKS, NUM_BITS - 1))\n", + "\n", + "for l in tqdm(range(NUM_EXPERIMENTS)):\n", + " new_seed = seed_seq.spawn(1)[0]\n", + " rng = np.random.default_rng(new_seed)\n", + " random_integer = rng.integers(1, 10**8 + 1)\n", + " SEED = random_integer\n", + "\n", + "\n", + " code = qec.random_regular_code(\n", + " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", + " )\n", + " code_constraint_sites = linear_code_constraint_sites(code)\n", + "\n", + "\n", + " INITIAL_CODEWORD, PERTURBED_CODEWORD = linear_code_prepare_message(\n", + " code, PROB_ERROR, error_model=qec.BinarySymmetricChannel, seed=SEED\n", + " )\n", + " tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "\n", + "\n", + " initial_codeword_state = create_custom_product_state(\n", + " INITIAL_CODEWORD, form=\"Right-canonical\"\n", + " )\n", + " perturbed_codeword_state = create_custom_product_state(\n", + " PERTURBED_CODEWORD, form=\"Right-canonical\"\n", + " )\n", + "\n", + "\n", + " perturbed_codeword_state = apply_bitflip_bias(\n", + " mps=perturbed_codeword_state,\n", + " sites_to_bias=\"All\",\n", + " prob_bias_list=PROB_BIAS,\n", + " renormalise=True,\n", + " )\n", + " perturbed_codeword_state, entrs, bons = apply_constraints(\n", + " perturbed_codeword_state,\n", + " code_constraint_sites,\n", + " tensors,\n", + " chi_max=CHI_MAX_CONTRACTOR,\n", + " renormalise=True,\n", + " result_to_explicit=False,\n", + " strategy=\"Naive\",\n", + " silent=True,\n", + " return_entropies_and_bond_dims=True\n", + " )\n", + "\n", + "\n", + " entropies[l] = np.array(entrs)\n", + " bond_dimensions[l] = np.array(bons)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# Here we average over all the experiments.\n", + "\n", + "entropies = np.mean(entropies, axis=0)\n", + "bond_dimensions = np.mean(bond_dimensions, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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jh075Ha79dlnn8ntdqt9+/Y+72n9+vU+7ykyMvKk9wAAtZGRkaEFCxZo6dKl+vLLL3XXXXepvLxcI0eOlCSNGDHCp0t+3LhxWrNmjZ5++ml99dVXmjJlirZs2aL09HSn3gJd6gCqFx0drcsvv1yXX365Jk2apNtuu01ZWVm65ZZbanR+WVmZJGnBggVKSUnx+Vl4ePgpz23QwHcpEpfLJY+n6gkdJybfGD8bV3ns2LFfbcflcp2y3ZooKytTeHi4tm7detJ7aNy4sff/x8TE+CStAFBbw4YN0/79+zV58mQVFhaqe/fuWrNmjXdiUH5+vs+kxIsvvljLli3TI488ooceekjt2rXTqlWr1LlzZ6feAgkngJrr1KmTd5LQL50Ys+l2u737EhISlJSUpF27dmn48OGWxXHWWWdJqlqWqUePHpJk6XJMn3zyic/rjz/+WO3atVN4eLh69Oght9ut4uJiXXrppZZdEwBOJT09vdoK5c8nLZ5w/fXX6/rrr7c5qpoj4QRwkh9++EHXX3+9Ro0apa5du6pJkybasmWLZsyYoWuuucb0nPj4eMXExGjNmjU6++yzFR0drbi4OE2dOlVjx45VXFycrrzySlVUVGjLli366aeflJGRUav4YmJidNFFF2n69Olq27atiouL9cgjj5zOW/aRn5+vjIwM3XHHHdq2bZuee+45Pf3005Kk9u3ba/jw4RoxYoSefvpp9ejRQ/v371dOTo66du2qQYMGWRYHANQXJJwATtK4cWOlpKToL3/5i7755hsdO3ZMycnJGj16tB566CHTcyIiIvTss8/q0Ucf1eTJk3XppZcqNzdXt912mxo2bKinnnpKDzzwgBo1aqQuXbpo/PjxpxXjokWLdOutt6pnz576zW9+oxkzZuiKK644rTZPGDFihI4cOaLevXsrPDxc48aN0+233+79+eLFi/X444/rvvvu0969e9W8eXNddNFFuuqqqyy5PgDUNzzaEgAAALZiljoAAABsRcIJAAAAW5FwAgAAwFYknAAAALAVCScAAABsRcIJAAAAW5FwAgAAwFYknAAAALAVCScAAABsRcIJAAAAW5FwAgAAwFb/P34aeCfcAA1xAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 6))\n", + "plt.imshow(\n", + " entropies, cmap=\"viridis\"\n", + ")\n", + "plt.colorbar(label=\"Entropy\")\n", + "plt.xlabel(\"Site number\")\n", + "plt.ylabel(\"Time ←\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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BQAAQLW2b9+urVu3auPGjerQoYPCwnyHyrz66qs1jkkBCgAAYIZL8JKkpk2b6u6777Y0JgUoAAAAqrVq1SrLY1KAAgAAmGAhel/Hjx/XoUOHJEnXXHONLr/8cr9jMQkJAAAA1SorK9MDDzyghIQE3Xzzzbr55puVmJio0aNH69SpU37FpAAFAAAwYwRoq2UyMjKUm5urv//97youLlZxcbFee+015ebmatKkSX7F5BI8AAAAqvW3v/1Nf/3rX9WnTx/vvjvuuEORkZEaPny4li1bVuOYFKAAAABmmAUvSTp16pTi4uLO2R8bG8sleAAAACuxEH2VXr16acaMGSovL/fu+/777zVz5kz16tXLr5h0QAEAAFCtZ555Rv3791fLli3VpUsXSdKBAwcUERGhzZs3+xWTDigAAICZIJuENG/ePLlcLk2YMMG7r7y8XOnp6WrRooWaNGmioUOHqrCw0P83MdGxY0cdOXJE2dnZ6tq1q7p27ap58+bpyJEj6tChg18x6YACAAAEuT179ujPf/6zOnfu7LN/4sSJ+sc//qG//OUviomJ0dixYzVkyBC9++67lr5/o0aNNGbMGMvi0QEFAAAwEyQd0JMnT2rkyJFauXKlmjVr5t1fUlKi5557Tk899ZRuueUWXX/99Vq1apXee+897dy507/PbOKbb77x/jk/P1/Tp0/X5MmT9c477/gdkwIUAADAZqWlpT5bRUVFtcemp6dr4MCBSk1N9dmfl5enyspKn/3t2rVTq1attGPHjkvO8YMPPlDr1q0VGxurdu3aaf/+/erRo4eefvpprVixQrfccos2bNjgV2wKUAAAABOBnAWflJSkmJgY75adnW2aw8svv6x9+/aZPl9QUKCGDRuqadOmPvvj4uJUUFBwyZ9/ypQp6tSpk9555x316dNHgwYN0sCBA1VSUqJvv/1WDz30kObNm+dXbMaAAgAA2Cw/P1/R0dHex+Hh4abHPProo9qyZYsiIiLsTE9S1bjTt99+W507d1aXLl20YsUKPfLIIwoJqepfjhs3TjfccINfsemAAgAAmAngGNDo6GifzawAzcvLU1FRka677jo1aNBADRo0UG5urhYtWqQGDRooLi5Op0+fVnFxsc/rCgsLFR8ff8kf/8SJE944TZo0UePGjX3GoDZr1kzfffedX7HpgAIAAJgIxMLxNYnXr18/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qeHDh8swDC1btszpdGyVl5enZ555Rvv27ZPL5XI6Hf8YAViInpGPkrgEX63LLrtMoaGhKiws9NlfWFio+Ph4h7JyztixY/XGG29o69atatmypdPp2C4vL09FRUW67rrr1KBBAzVo0EC5ublatGiRGjRoILfb7XSKtkhISNC1117rs699+/Y6duyYQxk5Z/LkyZo2bZpGjBihTp066Ve/+pUmTpyo7Oxsp1NzzNnvRr43q5wtPj///HNt2bKl3nU///Wvf6moqEitWrXyfm9+/vnnmjRpklq3bu10enAYBWg1GjZsqOuvv145OTnefR6PRzk5OerVq5eDmdnLMAyNHTtW69ev19tvv63k5GSnU3JEv3799MEHH2j//v3erXv37ho5cqT279+v0NBQp1O0Re/evc9Zhuvw4cO64oorHMrIOadOnVJIiO9XaGhoqDz1eHxXcnKy4uPjfb43S0tLtWvXrnr1vSn9v+LzyJEjeuutt9SiRQunU7Ldr371K/373//2+d5MTEzU5MmTtXnzZqfTuyiGxxOQDVyCP6+MjAylpaWpe/fu6tmzpxYuXKiysjKNGjXK6dRsk56errVr1+q1115TVFSUdxxXTEyMIiMjHc7OPlFRUeeMe23cuLFatGhRr8bDTpw4UTfeeKPmzp2r4cOHa/fu3VqxYoVWrFjhdGq2u/POOzVnzhy1atVKHTp00Pvvv6+nnnpKDzzwgNOpBdTJkyf1ySefeB8fPXpU+/fvV/PmzdWqVStNmDBBs2fPVps2bZScnKysrCwlJiaed4Z4bXS+85CQkKBf/OIX2rdvn9544w253W7vd2fz5s3VsKG1s6qddKHfhx8X3mFhYYqPj9c111xjd6oIMizDdAFLlizRH/7wBxUUFKhr165atGiRUlJSnE7LNtWN21m1apXuv/9+e5MJMn369Kl3yzBJ0htvvKHMzEwdOXJEycnJysjI0JgxY5xOy3bfffedsrKytH79ehUVFSkxMVH33nuvpk+fXqcKjB/btm2b+vbte87+tLQ0rV69WoZhaMaMGVqxYoWKi4t100036U9/+pPatm3rQLaBc77z8Pvf/77aq0Vbt25Vnz59ApydfS70+/BjrVu3rlXLMN0SeU9AlmF6+/t19X4ZJgpQAACAH/AWoOHDA1OAVrxS7wtQxoACAADAVowBBQAAMGMYkiyeNMSFZ0l0QAEAAGAzOqAAAAAmDI8hw2Vtx5KpN1XogAIAAMBWdEABAADMGB5ZPwaUheglOqAAAACwGQUoAL+5XC5t2LDB6TQs1adPn6BfJBuAPQyPEZANFKAAqnH8+HE9/PDDatWqlcLDwxUfH6/+/fvr3Xff9R7z1VdfacCAAZKk//3f/5XL5dL+/fsdyhgAUFswBhSAqaFDh+r06dNas2aNrrzyShUWFionJ0fffPON95j4+HgHM6w93G63XC6XQkL4Pz9Qm5wxKiwfs3lGlZbGq7UMAPiRb7/91pBkbNu27bzHSTLWr1/v/fMPt5/97Gfe41auXGm0a9fOCA8PN6655hpj6dKl5437s5/9zBg3bpwxefJko1mzZkZcXJwxY8YM7/NHjx41JBnvv//+OTlv3brVMAzD2Lp1qyHJ2LRpk9G1a1cjIiLC6Nu3r1FYWGj885//NNq1a2dERUUZ9957r1FWVubz3unp6UZ6eroRHR1ttGjRwnj88ccNj8fjPaa8vNyYNGmSkZiYaDRq1Mjo2bOn930NwzBWrVplxMTEGK+99prRvn17IzQ01Dh69Oh5PzOA4PH9998b8fHx53yvWbXFx8cb33//vdMf01F0QAGco0mTJmrSpIk2bNigG264QeHh4Rd8ze7du9WzZ0+99dZb6tChgxo2rLp/8osvvqjp06dryZIl6tatm95//32NGTNGjRs3VlpaWrXx1qxZo4yMDO3atUs7duzQ/fffr969e+vWW2+t0Wf5/e9/ryVLlqhRo0YaPny4hg8frvDwcK1du1YnT57U3XffrcWLF2vq1Kk+7z169Gjt3r1be/fu1YMPPqhWrVppzJgxkqSxY8fqww8/1Msvv6zExEStX79et99+uz744AO1adNGknTq1CnNnz9fzz77rFq0aKHY2Nga5Q3AORERETp69KhOnz4dkPgNGzZUREREQGLXGk5XwACC01//+lejWbNmRkREhHHjjTcamZmZxoEDB3yO0Q86oGZdScMwjKuuuspYu3atz74nnnjC6NWrV7Xv/bOf/cy46aabfPb16NHDmDp1arXvVV0H9K233vIek52dbUgyPv30U+++hx56yOjfv7/Pe7dv396n4zl16lSjffv2hmEYxueff26EhoYaX3zxhU9+/fr1MzIzMw3DqOqASjL2799f7WcEgPqMAUkATA0dOlRffvmlXn/9dd1+++3atm2brrvuOq1evfqiY5SVlenTTz/V6NGjvV3VJk2aaPbs2fr000/P+9rOnTv7PE5ISFBRUVGNP8cP48TFxalRo0a68sorffb9OO4NN9wgl8vlfdyrVy8dOXJEbrdbH3zwgdxut9q2bevzmXJzc30+U8OGDc/5DACAKlyCB1CtiIgI3Xrrrbr11luVlZWlX//615oxY4buv//+i3r9yZMnJUkrV65USkqKz3OhoaHnfW1YWJjPY5fLJY+najLA2ck8xg9uaVdZaT6w/4dxXC7XeeNejJMnTyo0NFR5eXnnfIYmTZp4/xwZGelTxAIA/h8KUAAX7dprr6123c+zYz7dbrd3X1xcnBITE/XZZ59p5MiRluVx+eWXS6paBqpbt26SZOnyT7t27fJ5vHPnTrVp00ahoaHq1q2b3G63ioqK9NOf/tSy9wSA+oQCFMA5vvnmGw0bNkwPPPCAOnfurKioKO3du1cLFizQXXfdZfqa2NhYRUZGatOmTWrZsqUiIiIUExOjmTNnavz48YqJidHtt9+uiooK7d27V99++60yMjL8yi8yMlI33HCD5s2bp+TkZBUVFenxxx+/lI/s49ixY8rIyNBDDz2kffv2afHixXryySclSW3bttXIkSN133336cknn1S3bt10/Phx5eTkqHPnzho4cKBleQBAXUUBCuAcTZo0UUpKip5++ml9+umnqqysVFJSksaMGaPf/va3pq9p0KCBFi1apFmzZmn69On66U9/qm3btunXv/61GjVqpD/84Q+aPHmyGjdurE6dOl3y3Yaef/55jR49Wtdff72uueYaLViwQLfddtslxTzrvvvu0/fff6+ePXsqNDRUjz76qB588EHv86tWrdLs2bM1adIkffHFF7rssst0ww03aNCgQZa8PwDUdS7jh4OoAAAAgABjFjwAAABsRQEKAAAAW1GAAgAAwFYUoAAAALAVBSgAAABsRQEKAAAAW1GAAgAAwFYUoAAAALAVBSgAAABsRQEKAAAAW1GAAgAAwFYUoAAAALDV/w/TDPZOckXEWAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 6))\n", + "plt.imshow(bond_dimensions, cmap=\"viridis\")\n", + "plt.colorbar(label=\"Bond dimension\")\n", + "plt.ylabel(\"Time ←\")\n", + "plt.xlabel(\"Site number\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Nice, we do see how entanglement grows during the evolution and declines towards the end!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now try to take a look at how the truncation affects the threshold for this family of codes. By definition, the threshold is the crossover error probability at which the code transitions from being unable to correct errors to being able to correct errors reliably. What we expect to see is how the logical error rate vs physical error rate curve will move up with more truncation." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 5/5 [02:05<00:00, 25.14s/it]\n", + "100%|██████████| 5/5 [00:39<00:00, 7.96s/it]\n", + "100%|██████████| 5/5 [00:16<00:00, 3.34s/it]\n", + "100%|██████████| 5/5 [00:07<00:00, 1.54s/it]\n" + ] + } + ], + "source": [ + "NUM_EXPERIMENTS = 10\n", + "CUT = 1e-12\n", + "NUM_DMRG_RUNS = 1\n", + "CHI_MAX_DMRG = 1e4\n", + "\n", + "SEED = 123\n", + "seed_seq = np.random.SeedSequence(SEED)\n", + "\n", + "system_sizes = [24]\n", + "max_bond_dims = [128, 64, 32, 16]\n", + "error_rates = np.linspace(0.1, 0.3, 5)\n", + "failures_statistics = {}\n", + "\n", + "for NUM_BITS in system_sizes:\n", + " for CHI_MAX_CONTRACTOR in max_bond_dims:\n", + " for PROB_ERROR in tqdm(error_rates):\n", + "\n", + " failures = []\n", + "\n", + " for l in range(NUM_EXPERIMENTS):\n", + " new_seed = seed_seq.spawn(1)[0]\n", + " rng = np.random.default_rng(new_seed)\n", + " random_integer = rng.integers(1, 10**8 + 1)\n", + " SEED = random_integer\n", + "\n", + " CHECK_DEGREE, BIT_DEGREE = 4, 3\n", + " NUM_CHECKS = int(BIT_DEGREE * NUM_BITS / CHECK_DEGREE)\n", + " if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", + " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", + " PROB_BIAS = PROB_ERROR\n", + " CHI_MAX_DMRG = CHI_MAX_CONTRACTOR\n", + "\n", + " code = qec.random_regular_code(\n", + " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qec.Rng(SEED)\n", + " )\n", + " code_constraint_sites = linear_code_constraint_sites(code)\n", + "\n", + " INITIAL_CODEWORD, PERTURBED_CODEWORD = linear_code_prepare_message(\n", + " code, PROB_ERROR, error_model=qec.BinarySymmetricChannel, seed=SEED\n", + " )\n", + " tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "\n", + " initial_codeword_state = create_custom_product_state(\n", + " INITIAL_CODEWORD, form=\"Right-canonical\"\n", + " )\n", + " perturbed_codeword_state = create_custom_product_state(\n", + " PERTURBED_CODEWORD, form=\"Right-canonical\"\n", + " )\n", + "\n", + " perturbed_codeword_state = apply_bitflip_bias(\n", + " mps=perturbed_codeword_state,\n", + " sites_to_bias=\"All\",\n", + " prob_bias_list=PROB_BIAS,\n", + " renormalise=True,\n", + " )\n", + "\n", + " perturbed_codeword_state = apply_constraints(\n", + " perturbed_codeword_state,\n", + " code_constraint_sites,\n", + " tensors,\n", + " chi_max=CHI_MAX_CONTRACTOR,\n", + " renormalise=True,\n", + " result_to_explicit=False,\n", + " strategy=\"Naive\",\n", + " silent=True,\n", + " )\n", + "\n", + " dmrg_container, success = decode_linear(\n", + " message=perturbed_codeword_state,\n", + " codeword=initial_codeword_state,\n", + " code=code,\n", + " num_runs=NUM_DMRG_RUNS,\n", + " chi_max_dmrg=CHI_MAX_DMRG,\n", + " cut=CUT,\n", + " silent=True,\n", + " )\n", + " failures.append(1-success)\n", + "\n", + " failures_statistics[NUM_BITS, CHI_MAX_CONTRACTOR, PROB_ERROR] = failures" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "failure_rates = {}\n", + "error_bars = {}\n", + "\n", + "for system_size in system_sizes:\n", + " for chi_max in max_bond_dims:\n", + " for error_rate in error_rates:\n", + " failure_rates[system_size, chi_max, error_rate] = np.mean(\n", + " failures_statistics[system_size, chi_max, error_rate]\n", + " )\n", + " error_bars[system_size, chi_max, error_rate] = (\n", + " np.std(failures_statistics[system_size, chi_max, error_rate])\n", + " * 1.96\n", + " / 100\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 6))\n", + "for system_size in system_sizes:\n", + " for chi_max in max_bond_dims:\n", + " plt.errorbar(\n", + " error_rates,\n", + " [\n", + " failure_rates[system_size, chi_max, error_rate]\n", + " for error_rate in error_rates\n", + " ],\n", + " yerr=[\n", + " error_bars[system_size, chi_max, error_rate]\n", + " for error_rate in error_rates\n", + " ],\n", + " fmt=\"o--\",\n", + " label=f\"System size: {system_size}, max bond dim: {chi_max}\",\n", + " )\n", + "plt.legend()\n", + "plt.xlabel(\"Error rate\")\n", + "plt.ylabel(\"Failure rate\")\n", + "plt.grid()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.9", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "cd00668ec6929851fcf19d7aebdf8f5927f35d0f54b527f252ebcdaf64fd8c43" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/conf.py b/docs/source/conf.py similarity index 92% rename from docs/conf.py rename to docs/source/conf.py index 75c044f8..c47f7066 100644 --- a/docs/conf.py +++ b/docs/source/conf.py @@ -12,6 +12,7 @@ # import os import sys +import datetime import sphinx_rtd_theme from sphinx.ext.autodoc import ClassDocumenter, _ @@ -21,11 +22,11 @@ # -- Project information ----------------------------------------------------- project = "mdopt" -copyright = "2023, Aleksandr Berezutskii" +copyright = str(datetime.date.today().year) + ", Aleksandr Berezutskii" author = "Aleksandr Berezutskii" # The full version, including alpha/beta/rc tags -release = "0.3.0" +release = "0.5.0" # -- General configuration --------------------------------------------------- @@ -40,8 +41,12 @@ "myst_parser", "sphinx_rtd_theme", "nbsphinx", + "IPython.sphinxext.ipython_console_highlighting", ] +# Do not execute notebooks during build time +nbsphinx_execute = "never" + # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/docs/source/csp_codes.ipynb b/docs/source/csp_codes.ipynb new file mode 100644 index 00000000..53bdd2b7 --- /dev/null +++ b/docs/source/csp_codes.ipynb @@ -0,0 +1,217 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decoding CSP quantum error correcting codes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import numpy as np\n", + "from tqdm import tqdm\n", + "import qecstruct as qec\n", + "import matplotlib.pyplot as plt\n", + "from mdopt.optimiser.utils import (\n", + " ConstraintString,\n", + " IDENTITY,\n", + " SWAP,\n", + " XOR_BULK,\n", + " XOR_LEFT,\n", + " XOR_RIGHT,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " linear_code_constraint_sites,\n", + " linear_code_prepare_message,\n", + " linear_code_codewords,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " apply_bitflip_bias,\n", + " apply_constraints,\n", + " decode_linear,\n", + ")\n", + "from mdopt.mps.utils import (\n", + " create_simple_product_state,\n", + " create_custom_product_state,\n", + ")\n", + "from mdopt.utils.utils import mpo_to_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "f = open(\"data-csp-codes/batch_1/codes/qubits_30/code_0.json\")\n", + "data = json.load(f)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x_stabs': [[1, 3, 5, 8, 10, 13, 14, 16, 27],\n", + " [4, 8, 11, 12, 13, 14, 15, 18, 19, 21, 22, 24],\n", + " [2, 3, 5, 8, 10, 15, 16, 17, 26, 29],\n", + " [9, 11, 24, 25, 26, 27],\n", + " [13, 16, 17, 18, 20, 22],\n", + " [4, 5, 12, 20, 23, 28],\n", + " [0, 5, 6, 8, 11, 17, 20, 21],\n", + " [0, 1, 2, 6, 7, 9, 10, 11, 13, 14, 19, 24, 25],\n", + " [6, 12, 14, 18, 19, 23],\n", + " [2, 3, 4, 9, 16, 25, 28, 29],\n", + " [6, 7, 9, 10, 12, 15, 28, 29],\n", + " [1, 2, 6, 12, 13, 14, 16, 21, 22, 23, 27],\n", + " [0, 2, 5, 7, 11, 26, 29]],\n", + " 'z_stabs': [[3, 5, 6, 8, 10, 11, 23, 25],\n", + " [0, 6, 7, 9, 18, 22, 26, 29],\n", + " [0, 2, 4, 10, 12, 14, 21],\n", + " [4, 6, 10, 12, 13, 17, 19, 23, 28],\n", + " [1, 9, 10, 11, 12, 13, 15, 16, 21, 23, 24, 26],\n", + " [1, 5, 10, 16, 20, 29],\n", + " [3, 6, 8, 12, 14, 19, 20, 21, 22, 25, 27],\n", + " [0, 7, 9, 11, 15, 29],\n", + " [1, 2, 3, 8, 21, 26, 27],\n", + " [0, 1, 3, 5, 6, 14, 18, 20, 23, 28],\n", + " [0, 2, 9, 10, 12, 13, 15, 17, 23, 24],\n", + " [0, 8, 18, 19, 22, 26, 27],\n", + " [2, 4, 7, 8, 16, 17, 28],\n", + " [2, 5, 13, 20, 24, 25]],\n", + " 'num_qubits': 30}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 3, 5, 8, 10, 13, 14, 16, 27],\n", + " [4, 8, 11, 12, 13, 14, 15, 18, 19, 21, 22, 24],\n", + " [2, 3, 5, 8, 10, 15, 16, 17, 26, 29],\n", + " [9, 11, 24, 25, 26, 27],\n", + " [13, 16, 17, 18, 20, 22],\n", + " [4, 5, 12, 20, 23, 28],\n", + " [0, 5, 6, 8, 11, 17, 20, 21],\n", + " [0, 1, 2, 6, 7, 9, 10, 11, 13, 14, 19, 24, 25],\n", + " [6, 12, 14, 18, 19, 23],\n", + " [2, 3, 4, 9, 16, 25, 28, 29],\n", + " [6, 7, 9, 10, 12, 15, 28, 29],\n", + " [1, 2, 6, 12, 13, 14, 16, 21, 22, 23, 27],\n", + " [0, 2, 5, 7, 11, 26, 29]]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data[\"x_stabs\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "NUM_BITS = 60" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "state = create_simple_product_state(NUM_BITS, which=\"+\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 3, 5, 8, 10, 13, 14, 16, 27],\n", + " [4, 8, 11, 12, 13, 14, 15, 18, 19, 21, 22, 24],\n", + " [2, 3, 5, 8, 10, 15, 16, 17, 26, 29],\n", + " [9, 11, 24, 25, 26, 27],\n", + " [13, 16, 17, 18, 20, 22],\n", + " [4, 5, 12, 20, 23, 28],\n", + " [0, 5, 6, 8, 11, 17, 20, 21],\n", + " [0, 1, 2, 6, 7, 9, 10, 11, 13, 14, 19, 24, 25],\n", + " [6, 12, 14, 18, 19, 23],\n", + " [2, 3, 4, 9, 16, 25, 28, 29],\n", + " [6, 7, 9, 10, 12, 15, 28, 29],\n", + " [1, 2, 6, 12, 13, 14, 16, 21, 22, 23, 27],\n", + " [0, 2, 5, 7, 11, 26, 29]]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "code_constraint_sites = data[\"x_stabs\"]\n", + "tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "code_constraint_sites" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.11", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/examples.rst b/docs/source/examples.rst new file mode 100644 index 00000000..d4482f35 --- /dev/null +++ b/docs/source/examples.rst @@ -0,0 +1,15 @@ +Examples +======== + +.. toctree:: + :maxdepth: 2 + :caption: Notebook Examples: + + classical_ldpc.ipynb + csp_codes.ipynb + ground_state.ipynb + hypergraph_product.ipynb + main_component.ipynb + mps-rand-circ.ipynb + shor.ipynb + toric.ipynb diff --git a/docs/source/ground_state.ipynb b/docs/source/ground_state.ipynb new file mode 100644 index 00000000..c5a71142 --- /dev/null +++ b/docs/source/ground_state.ipynb @@ -0,0 +1,282 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Ground state search for a 1D quantum Ising model" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this experiment we will use our DMRG optimiser to find the ground state\n", + "of an open-bounded transverse field Ising chain. The Hamiltonian reads:\n", + "$$\n", + "H = - \\sum_{i=1}^{N-1} Z_i Z_{i+1} - h * \\sum_{i=1}^{N} X_i.\n", + "$$\n", + "Here, the magnetic field is in the units of the nearest-neighbour ZZ-interaction.\n", + "We find the ground state of this Hamiltonian and compute some observables." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from opt_einsum import contract\n", + "from tqdm import tqdm\n", + "from scipy.sparse.linalg import eigsh\n", + "\n", + "from ising import IsingExact, IsingMPO\n", + "from mdopt.mps.utils import create_simple_product_state\n", + "from mdopt.optimiser.dmrg import DMRG as dmrg" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first check we build the right MPO. We do this by virtue of constructing a 3-site MPO and then changing it into the Hamiltonian." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checking the exact and the MPO Hamiltonians being the same: True\n" + ] + } + ], + "source": [ + "NUM_SITES = 3\n", + "H_MAGNETIC = 1.0\n", + "ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", + "ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", + "ham_mpo = ising_mpo.hamiltonian_mpo()\n", + "m = contract(\n", + " \"zabc, adef, dygh -> begcfh\",\n", + " ham_mpo[0],\n", + " ham_mpo[1],\n", + " ham_mpo[2],\n", + " optimize=[(0, 1), (0, 1)],\n", + ").reshape((8, 8))\n", + "\n", + "print(\n", + " \"Checking the exact and the MPO Hamiltonians being the same:\",\n", + " (ising_exact.hamiltonian_dense() == m).all(),\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, we solve the model by both exact diagonalisation and DMRG. Afterwards, we need to check that the ground states are the same up to a phase." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DMRG running:\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 10/10 [00:21<00:00, 2.11s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Eigensolver running.\n", + "The ground states are the same: True\n" + ] + } + ], + "source": [ + "NUM_SITES = 10\n", + "H_MAGNETIC = 1.0\n", + "NUM_DMRG_RUNS = 10\n", + "CHI_MAX = 128\n", + "CUT = 1e-12\n", + "MODE = \"SA\"\n", + "TOL = 1e-7\n", + "ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", + "ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=H_MAGNETIC)\n", + "ham_mpo = ising_mpo.hamiltonian_mpo()\n", + "ham_sparse = ising_exact.hamiltonian_sparse()\n", + "\n", + "mps_start = create_simple_product_state(NUM_SITES, which=\"+\")\n", + "\n", + "print(\"DMRG running:\")\n", + "print(\"\")\n", + "engine = dmrg(mps_start, ham_mpo, chi_max=CHI_MAX, cut=CUT, mode=MODE)\n", + "engine.run(NUM_DMRG_RUNS)\n", + "print(\"\")\n", + "ground_state_mps = engine.mps\n", + "print(\"Eigensolver running.\")\n", + "ground_state_exact = eigsh(ham_sparse, k=2, tol=TOL)[1][:, 0]\n", + "print(\n", + " \"The ground states are the same:\",\n", + " np.isclose(abs(ground_state_mps.dense()), abs(ground_state_exact)).all(),\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we would like to compare the magnetisation plots from exact diagonalisation and DMRG. The plots should coincide exactly." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 20/20 [07:11<00:00, 21.58s/it]\n" + ] + } + ], + "source": [ + "transverse_magnetic_field_space = np.linspace(0.2, 2.0, 20)\n", + "mag_z_exact = []\n", + "mag_x_exact = []\n", + "mag_z_dmrg = []\n", + "mag_x_dmrg = []\n", + "for magnetic_field in tqdm(transverse_magnetic_field_space):\n", + " ising_exact = IsingExact(num_sites=NUM_SITES, h_magnetic=magnetic_field)\n", + " ising_mpo = IsingMPO(num_sites=NUM_SITES, h_magnetic=magnetic_field)\n", + " ham_mpo = ising_mpo.hamiltonian_mpo()\n", + " ham_sparse = ising_exact.hamiltonian_sparse()\n", + " mps_start = create_simple_product_state(num_sites=NUM_SITES, which=\"+\")\n", + " engine = dmrg(mps_start, ham_mpo, chi_max=CHI_MAX, cut=CUT, mode=MODE, silent=True)\n", + " engine.run(NUM_DMRG_RUNS)\n", + " ground_state_mps = engine.mps\n", + " ground_state_exact = eigsh(ham_sparse, k=2, tol=TOL)[1][:, 0]\n", + "\n", + " mag_z_exact.append(ising_exact.average_chain_z_magnetisation(ground_state_exact))\n", + " mag_x_exact.append(ising_exact.average_chain_x_magnetisation(ground_state_exact))\n", + "\n", + " mag_z_dmrg.append(ising_mpo.average_chain_z_magnetisation(ground_state_mps))\n", + " mag_x_dmrg.append(ising_mpo.average_chain_x_magnetisation(ground_state_mps))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can take a look at the plots!" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(5, 4))\n", + "plt.plot(transverse_magnetic_field_space, mag_z_exact, label=\"Exact\", linewidth=3)\n", + "plt.plot(transverse_magnetic_field_space, mag_z_dmrg, label=\"DMRG\", linestyle=\"dashed\", linewidth=3)\n", + "plt.xlabel(\"Transverse magnetic field $h$\")\n", + "plt.ylabel(\"Longitudinal magnetisation $m_z$\", rotation=90, labelpad=10)\n", + "plt.xlim((0.2, 2))\n", + "plt.ylim((-1, 1))\n", + "plt.legend(fontsize=10)\n", + "plt.grid(True)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "plt.figure(figsize=(5, 4))\n", + "plt.plot(transverse_magnetic_field_space, mag_x_exact, label=\"Exact\", linewidth=3)\n", + "plt.plot(transverse_magnetic_field_space, mag_x_dmrg, label=\"DMRG\", linestyle=\"dashed\", linewidth=3)\n", + "plt.xlabel(\"Transverse magnetic field $h$\")\n", + "plt.ylabel(\"Transverse magnetisation $m_x$\", rotation=90, labelpad=10)\n", + "plt.xlim((0.2, 2))\n", + "plt.ylim((0, 1))\n", + "plt.legend(fontsize=10)\n", + "plt.grid(True)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.12 ('base')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "beb51d2e4f595594d882127529c1bc4b1aa1e76d8ded79011fd6bf52b7a41e64" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/hypergraph_product.ipynb b/docs/source/hypergraph_product.ipynb new file mode 100644 index 00000000..6026d81b --- /dev/null +++ b/docs/source/hypergraph_product.ipynb @@ -0,0 +1,236 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decoding Hypergraph Product Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import qecstruct as qc\n", + "\n", + "from mdopt.optimiser.dephasing_dmrg import DephasingDMRG\n", + "from mdopt.mps.utils import (\n", + " create_custom_product_state,\n", + " create_simple_product_state,\n", + " inner_product,\n", + " marginalise,\n", + ")\n", + "from mdopt.optimiser.utils import (\n", + " XOR_BULK,\n", + " XOR_LEFT,\n", + " XOR_RIGHT,\n", + " COPY_LEFT,\n", + " SWAP,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " css_code_constraint_sites,\n", + " css_code_logicals_sites,\n", + " apply_bitflip_bias,\n", + " apply_constraints,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "SEED = 123\n", + "NUM_BITS, NUM_CHECKS = 10, 6\n", + "CHECK_DEGREE, BIT_DEGREE = 5, 3\n", + "if NUM_BITS / NUM_CHECKS != CHECK_DEGREE / BIT_DEGREE:\n", + " raise ValueError(\"The Tanner graph of the code must be bipartite.\")\n", + "code = qc.random_regular_code(\n", + " NUM_BITS, NUM_CHECKS, BIT_DEGREE, CHECK_DEGREE, qc.Rng(SEED)\n", + ")\n", + "hgpc = qc.hypergraph_product(code, code)\n", + "num_sites = 2 * hgpc.length() + hgpc.num_x_logicals() + hgpc.num_z_logicals()\n", + "num_logicals = hgpc.num_x_logicals() + hgpc.num_z_logicals()\n", + "error = \"0\" * num_sites\n", + "string_state = \"+\" * num_logicals + error\n", + "error_mps = create_custom_product_state(string=string_state, form=\"Right-canonical\")\n", + "constraints_tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "logicals_tensors = [COPY_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "chi_max = 64" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "constraints_sites = css_code_constraint_sites(hgpc)\n", + "logicals_sites = css_code_logicals_sites(hgpc)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "renormalise = True\n", + "result_to_explicit = False\n", + "sites_to_bias = list(range(num_logicals, num_sites))\n", + "error_mps = apply_bitflip_bias(\n", + " mps=error_mps,\n", + " sites_to_bias=sites_to_bias,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 60/60 [00:43<00:00, 1.36it/s]\n", + "100%|██████████| 60/60 [01:13<00:00, 1.22s/it]\n", + "100%|██████████| 2/2 [00:01<00:00, 1.73it/s]\n" + ] + } + ], + "source": [ + "error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[0],\n", + " constraints_tensors,\n", + " chi_max=chi_max,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")\n", + "error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[1],\n", + " constraints_tensors,\n", + " chi_max=chi_max,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")\n", + "error_mps = apply_constraints(\n", + " error_mps,\n", + " logicals_sites,\n", + " logicals_tensors,\n", + " chi_max=chi_max,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "sites_to_marginalise = list(range(num_logicals, len(error)))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "logicals = marginalise(mps=error_mps, sites_to_marginalise=sites_to_marginalise)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "num_dmrg_sites = len(logicals)\n", + "mps_dmrg_start = create_simple_product_state(num_dmrg_sites, which=\"+\")\n", + "mps_dmrg_target = create_simple_product_state(num_dmrg_sites, which=\"0\")\n", + "engine = DephasingDMRG(\n", + " mps=mps_dmrg_start,\n", + " mps_target=mps_dmrg_target,\n", + " chi_max=chi_max,\n", + " mode=\"LA\",\n", + " silent=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1/1 [00:00<00:00, 2.48it/s]\n" + ] + } + ], + "source": [ + "engine.run(num_iter=1)\n", + "mps_dmrg_final = engine.mps" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.0\n" + ] + } + ], + "source": [ + "overlap = abs(inner_product(mps_dmrg_final, mps_dmrg_target))\n", + "print(overlap)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.11", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/index.rst b/docs/source/index.rst similarity index 93% rename from docs/index.rst rename to docs/source/index.rst index e40b8b02..20a0d264 100644 --- a/docs/index.rst +++ b/docs/source/index.rst @@ -15,4 +15,4 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` -* :ref:`search` +* :ref:`search` \ No newline at end of file diff --git a/docs/examples/main_component/main_component.ipynb b/docs/source/main_component.ipynb similarity index 85% rename from docs/examples/main_component/main_component.ipynb rename to docs/source/main_component.ipynb index c6703514..37001a41 100644 --- a/docs/examples/main_component/main_component.ipynb +++ b/docs/source/main_component.ipynb @@ -1,15 +1,22 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The main component problem" + ] + }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "In this example we will solve the Main Component Problem (MCP). This is a subroutine of our decoding algorithm but is interesting on its own. The problem reads as follows:\n", + "In this example we demonstrate solving the Main Component Problem (MCP). This is a subroutine of our decoding algorithm but is quite interesting on its own. The problem reads as follows:\n", "$$\n", "\\underset{\\phi_i \\in \\mathbb{C}^2}{\\arg \\max }\\left[\\otimes_i\\left\\langle\\phi_i\\right|\\right] \\rho\\left[\\otimes_i\\left|\\phi_i\\right\\rangle\\right],\n", "$$\n", - "which basically means finding a basis state which contributes most to a given pure state." + "which essentially means finding a basis state which contributes most to a given pure state." ] }, { @@ -57,7 +64,7 @@ "metadata": {}, "outputs": [], "source": [ - "num_sites = 9\n", + "num_sites = 10\n", "psi = create_state_vector(num_sites)" ] }, @@ -85,7 +92,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we create an exact MPS version of the state and its Matrix Product Density Operator." + "Now, we create an exact Matrix Product State (MPS) version of the state and its Matrix Product Density Operator (MPDO)." ] }, { @@ -94,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "mps = mps_from_dense(psi, form=\"Right-canonical\")\n", + "mps = mps_from_dense(psi)\n", "mpdo = mps.density_mpo()" ] }, @@ -115,7 +122,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 512/512 [00:00<00:00, 6802.72it/s]\n" + "100%|██████████| 1024/1024 [00:00<00:00, 5645.63it/s]\n" ] } ], @@ -147,16 +154,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:00<00:00, 3.26it/s]\n" + "100%|██████████| 1/1 [00:00<00:00, 1.13it/s]\n" ] } ], "source": [ "mps_start = create_simple_product_state(num_sites, which=\"+\")\n", - "engine = dmrg(\n", - " mps_start, mpdo, chi_max=1e4, cut=1e-12, mode=\"LA\", copy=True, silent=False\n", - ")\n", - "engine.run(num_iter=1)\n", + "engine = dmrg(mps_start, mpdo, mode=\"LA\")\n", + "engine.run()\n", "max_excited_mps_from_dmrg = engine.mps\n", "\n", "overlaps_dmrg = []\n", @@ -191,7 +196,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 10/10 [00:00<00:00, 44.25it/s]\n" + "100%|██████████| 1/1 [00:00<00:00, 16.07it/s]\n" ] } ], @@ -200,13 +205,9 @@ "dephasing_engine = deph_dmrg(\n", " mps_start,\n", " mps,\n", - " chi_max=1e4,\n", - " cut=1e-12,\n", " mode=\"LA\",\n", - " copy=True,\n", - " silent=False,\n", ")\n", - "dephasing_engine.run(num_iter=10)\n", + "dephasing_engine.run()\n", "main_component_mps = dephasing_engine.mps\n", "\n", "overlaps_dephased = []\n", @@ -263,13 +264,6 @@ " main_component_exact == main_component_dephased,\n", ")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -288,7 +282,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.10.13" }, "orig_nbformat": 4, "vscode": { diff --git a/docs/source/mdopt.contractor.rst b/docs/source/mdopt.contractor.rst new file mode 100644 index 00000000..f8c2ad08 --- /dev/null +++ b/docs/source/mdopt.contractor.rst @@ -0,0 +1,21 @@ +mdopt.contractor package +======================== + +Submodules +---------- + +mdopt.contractor.contractor module +---------------------------------- + +.. automodule:: mdopt.contractor.contractor + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: mdopt.contractor + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/mps.rst b/docs/source/mdopt.mps.rst similarity index 53% rename from docs/mps.rst rename to docs/source/mdopt.mps.rst index 0c58417e..0b102950 100644 --- a/docs/mps.rst +++ b/docs/source/mdopt.mps.rst @@ -1,8 +1,10 @@ -MPS module +mdopt.mps package ================= +Submodules +---------- -The Canonical MPS submodule +mdopt.mps.canonical module -------------------------- .. automodule:: mdopt.mps.canonical @@ -10,18 +12,26 @@ The Canonical MPS submodule :undoc-members: :show-inheritance: -The Explicit MPS submodule --------------------------- +mdopt.mps.explicit module +------------------------- .. automodule:: mdopt.mps.explicit :members: :undoc-members: :show-inheritance: -The Utils submodule --------------------------- +mdopt.mps.utils module +---------------------- .. automodule:: mdopt.mps.utils :members: :undoc-members: :show-inheritance: + +Module contents +--------------- + +.. automodule:: mdopt.mps + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/mdopt.optimiser.rst b/docs/source/mdopt.optimiser.rst new file mode 100644 index 00000000..87fbc5d2 --- /dev/null +++ b/docs/source/mdopt.optimiser.rst @@ -0,0 +1,37 @@ +mdopt.optimiser package +======================= + +Submodules +---------- + +mdopt.optimiser.dephasing\_dmrg module +-------------------------------------- + +.. automodule:: mdopt.optimiser.dephasing_dmrg + :members: + :undoc-members: + :show-inheritance: + +mdopt.optimiser.dmrg module +--------------------------- + +.. automodule:: mdopt.optimiser.dmrg + :members: + :undoc-members: + :show-inheritance: + +mdopt.optimiser.utils module +---------------------------- + +.. automodule:: mdopt.optimiser.utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: mdopt.optimiser + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/mdopt.rst b/docs/source/mdopt.rst new file mode 100644 index 00000000..a8f07792 --- /dev/null +++ b/docs/source/mdopt.rst @@ -0,0 +1,21 @@ +mdopt package +============= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + mdopt.contractor + mdopt.mps + mdopt.optimiser + mdopt.utils + +Module contents +--------------- + +.. automodule:: mdopt + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/mdopt.utils.rst b/docs/source/mdopt.utils.rst new file mode 100644 index 00000000..3355138b --- /dev/null +++ b/docs/source/mdopt.utils.rst @@ -0,0 +1,21 @@ +mdopt.utils package +=================== + +Submodules +---------- + +mdopt.utils.utils module +------------------------ + +.. automodule:: mdopt.utils.utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: mdopt.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/modules.rst b/docs/source/modules.rst similarity index 100% rename from docs/modules.rst rename to docs/source/modules.rst diff --git a/docs/source/mps-rand-circ.ipynb b/docs/source/mps-rand-circ.ipynb new file mode 100644 index 00000000..b4de0d9e --- /dev/null +++ b/docs/source/mps-rand-circ.ipynb @@ -0,0 +1,324 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Random circuit simulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this notebook, we demonstrate simulation of random checkerboard quantum circuits of variying depths. The aim is to track how fidelity decays for a fixed maximum MPS bond dimension." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from tqdm import tqdm\n", + "from scipy.stats import unitary_group\n", + "import matplotlib.pyplot as plt\n", + "from mdopt.utils.utils import create_random_mpo, svd\n", + "from mdopt.mps.utils import create_simple_product_state\n", + "from mdopt.contractor.contractor import mps_mpo_contract" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def create_mpo(gate: np.ndarray) -> list:\n", + " \"\"\"\n", + " Creates a two-site MPO from a two-qubit gate by virtue of QR decomposition.\n", + " \"\"\"\n", + " q, r = np.linalg.qr(gate)\n", + " q_shape = q.shape\n", + " r_shape = r.shape\n", + " q = q.reshape((1, q_shape[1], PHYS_DIM, PHYS_DIM))\n", + " r = r.reshape((r_shape[0], 1, PHYS_DIM, PHYS_DIM))\n", + " return [q, r]\n", + "\n", + "\n", + "def create_mpo_from_layer(layer):\n", + " \"\"\"\n", + " Creates an MPO from a layer of two-site MPOs.\n", + " \"\"\"\n", + " mpo = []\n", + " for _, gate in enumerate(layer):\n", + " mpo += create_mpo(gate)\n", + " return mpo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PHYS_DIM = 2\n", + "\n", + "circ_depths = [4, 6, 8, 10, 12, 14, 16, 18, 20]\n", + "bond_dims = [8, 10, 12, 14, 16, 18, 20, 22, 24]\n", + "num_qubits = [10]\n", + "\n", + "tails = {}\n", + "for NUM_QUBITS in num_qubits:\n", + " for BOND_DIM in bond_dims:\n", + " for NUM_LAYERS_CIRC in tqdm(circ_depths):\n", + "\n", + " state = create_simple_product_state(\n", + " num_sites=NUM_QUBITS,\n", + " phys_dim=PHYS_DIM,\n", + " which=\"0\",\n", + " form=\"Right-canonical\",\n", + " )\n", + " state.tolerance = np.inf\n", + "\n", + " tails_iter = []\n", + "\n", + " for k in range(NUM_LAYERS_CIRC):\n", + " layer = unitary_group.rvs(\n", + " PHYS_DIM**2, size=NUM_QUBITS // PHYS_DIM - k % 2\n", + " )\n", + " mpo = create_mpo_from_layer(layer)\n", + " state = mps_mpo_contract(\n", + " mps=state,\n", + " mpo=mpo,\n", + " start_site=k % 2,\n", + " renormalise=True,\n", + " chi_max=1e4,\n", + " cut=0,\n", + " inplace=False,\n", + " result_to_explicit=True,\n", + " )\n", + "\n", + " sing_vals = state.singular_values[NUM_QUBITS // 2]\n", + "\n", + " if len(sing_vals) > BOND_DIM:\n", + " tails_iter.append(1 - np.sum(np.square(sing_vals[2:])))\n", + "\n", + " tails[\n", + " \"numqubits\"\n", + " + str(NUM_QUBITS)\n", + " + \"_bonddim\"\n", + " + str(BOND_DIM)\n", + " + \"_circlayers\"\n", + " + str(NUM_LAYERS_CIRC)\n", + " ] = tails_iter" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fidelities_total = {}\n", + "for chi in bond_dims:\n", + " fidelities_total[chi] = [\n", + " np.prod(\n", + " tails[\n", + " \"numqubits\"\n", + " + str(NUM_QUBITS)\n", + " + \"_bonddim\"\n", + " + str(chi)\n", + " + \"_circlayers\"\n", + " + str(depth)\n", + " ]\n", + " )\n", + " for depth in circ_depths\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "greens = plt.get_cmap(\"Greens\")\n", + "plt.figure(figsize=(4, 3))\n", + "for qubits in num_qubits:\n", + " for chi in bond_dims:\n", + " try:\n", + " plt.plot(\n", + " circ_depths,\n", + " fidelities_total[chi],\n", + " \"-o\",\n", + " label=\"$\\chi=$\" + str(chi),\n", + " color=greens(chi / max(bond_dims)),\n", + " linewidth=0.8,\n", + " zorder=chi,\n", + " )\n", + " except:\n", + " KeyError\n", + "plt.xticks(np.arange(4, 22, 2), fontsize=8)\n", + "plt.yticks(fontsize=8)\n", + "plt.legend(prop={\"size\": 8})\n", + "plt.ylabel(\"Fidelity\", fontdict={\"size\": 8})\n", + "plt.xlabel(\"Number of circuit layers\", fontdict={\"size\": 8})\n", + "#plt.title(str(qubits) + \" qubits\", fontsize=9)\n", + "plt.yscale(\"log\")\n", + "# plt.savefig('mps_'+str(num_qubits)+'.pdf', dpi=600, bbox_inches='tight')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PHYS_DIM = 2\n", + "\n", + "circ_depths = [4, 6, 8, 10, 12, 14, 16, 18, 20]\n", + "bond_dims = [8, 10, 12, 14, 16, 18, 20, 22, 24]\n", + "num_qubits = [30]\n", + "\n", + "tails = {}\n", + "for NUM_QUBITS in num_qubits:\n", + " for BOND_DIM in bond_dims:\n", + " for NUM_LAYERS_CIRC in tqdm(circ_depths):\n", + "\n", + " state = create_simple_product_state(\n", + " num_sites=NUM_QUBITS,\n", + " phys_dim=PHYS_DIM,\n", + " which=\"0\",\n", + " form=\"Right-canonical\",\n", + " )\n", + " state.tolerance = np.inf\n", + "\n", + " tails_iter = []\n", + "\n", + " for k in range(NUM_LAYERS_CIRC):\n", + " layer = unitary_group.rvs(\n", + " PHYS_DIM**2, size=NUM_QUBITS // PHYS_DIM - k % 2\n", + " )\n", + " mpo = create_mpo_from_layer(layer)\n", + " state = mps_mpo_contract(\n", + " mps=state,\n", + " mpo=mpo,\n", + " start_site=k % 2,\n", + " renormalise=False,\n", + " chi_max=1e4,\n", + " cut=1e-12,\n", + " inplace=False,\n", + " result_to_explicit=False,\n", + " )\n", + "\n", + " state, errors = state.compress(\n", + " chi_max=BOND_DIM,\n", + " cut=1e-12,\n", + " renormalise=False,\n", + " strategy=\"svd\",\n", + " return_truncation_errors=True,\n", + " )\n", + "\n", + " fidels = [1-error for error in errors]\n", + " tails_iter.append(fidels)\n", + "\n", + " tails[\n", + " \"numqubits\"\n", + " + str(NUM_QUBITS)\n", + " + \"_bonddim\"\n", + " + str(BOND_DIM)\n", + " + \"_circlayers\"\n", + " + str(NUM_LAYERS_CIRC)\n", + " ] = tails_iter" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fidelities_total = {}\n", + "for chi in bond_dims:\n", + " fidelities_total[chi] = [\n", + " np.prod(\n", + " tails[\n", + " \"numqubits\"\n", + " + str(NUM_QUBITS)\n", + " + \"_bonddim\"\n", + " + str(chi)\n", + " + \"_circlayers\"\n", + " + str(depth)\n", + " ]\n", + " )\n", + " for depth in circ_depths\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "greens = plt.get_cmap(\"Greens\")\n", + "plt.figure(figsize=(4, 3))\n", + "for qubits in num_qubits:\n", + " for chi in bond_dims:\n", + " try:\n", + " plt.plot(\n", + " circ_depths,\n", + " fidelities_total[chi],\n", + " \"-o\",\n", + " label=\"$\\chi=$\" + str(chi),\n", + " color=greens(chi / max(bond_dims)),\n", + " linewidth=0.8,\n", + " zorder=chi,\n", + " )\n", + " except:\n", + " KeyError\n", + "plt.xticks(np.arange(4, 22, 2), fontsize=8)\n", + "plt.yticks(fontsize=8)\n", + "plt.legend(prop={\"size\": 8})\n", + "plt.ylabel(\"Fidelity\", fontdict={\"size\": 8})\n", + "plt.xlabel(\"Number of circuit layers\", fontdict={\"size\": 8})\n", + "#plt.title(str(qubits) + \" qubits\", fontsize=9)\n", + "plt.yscale(\"log\")\n", + "# plt.savefig('mera_'+str(num_qubits)+'.pdf', dpi=600, bbox_inches='tight')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.11", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/requirements.txt b/docs/source/requirements.txt similarity index 93% rename from docs/requirements.txt rename to docs/source/requirements.txt index 27521681..cec4b9e2 100644 --- a/docs/requirements.txt +++ b/docs/source/requirements.txt @@ -4,4 +4,5 @@ sphinxcontrib-napoleon==0.7 myst-parser==0.18.1 ipykernel nbsphinx +ipython mdopt diff --git a/docs/source/shor-decoder.png b/docs/source/shor-decoder.png new file mode 100644 index 00000000..afa00b64 Binary files /dev/null and b/docs/source/shor-decoder.png differ diff --git a/docs/source/shor.ipynb b/docs/source/shor.ipynb new file mode 100644 index 00000000..7bdce982 --- /dev/null +++ b/docs/source/shor.ipynb @@ -0,0 +1,741 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decoding Shor's code" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this experiment, we decode Shor's nine-qubit quantum error correcting code which protects a single qubit from all types of errors. Here, we demonstrate error-based correction, which means that the decoder takes a Pauli error as input and outputs the most likely logical operator. After one run of the algorithm we will end up with a probability distribution over I, X, Z, Y Pauli operators which are to be applied to the logical qubit encoded." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import qecstruct as qc\n", + "import qecsim.paulitools as pt\n", + "import matplotlib.pyplot as plt\n", + "from tqdm import tqdm\n", + "\n", + "from mdopt.mps.utils import marginalise, create_custom_product_state\n", + "from mdopt.contractor.contractor import mps_mpo_contract\n", + "from mdopt.optimiser.utils import (\n", + " SWAP,\n", + " COPY_LEFT,\n", + " XOR_BULK,\n", + " XOR_LEFT,\n", + " XOR_RIGHT,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " css_code_checks,\n", + " css_code_logicals,\n", + " css_code_logicals_sites,\n", + " css_code_constraint_sites,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " apply_constraints,\n", + " apply_bitflip_bias,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " pauli_to_mps,\n", + " decode_shor,\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first import the code from `qecstruct` and take a look at it." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "X stabilizers:\n", + "[0, 1, 2, 3, 4, 5]\n", + "[3, 4, 5, 6, 7, 8]\n", + "Z stabilizers:\n", + "[0, 1]\n", + "[1, 2]\n", + "[3, 4]\n", + "[4, 5]\n", + "[6, 7]\n", + "[7, 8]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "code = qc.shor_code()\n", + "code" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This quantum error correcting code is defined on $9$ physical qubits and has $2$ logical operators because it encodes $1$ logical qubit. This means we will need $9*2 + 2 = 20$ sites in our MPS." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "num_logicals = code.num_x_logicals() + code.num_z_logicals()\n", + "num_sites = 2 * len(code) + num_logicals\n", + "\n", + "assert num_sites == 20\n", + "assert num_logicals == 2" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us define the initial state. First of all we will check that no error implies no correction. This means starting from the all-zeros state followed by decoding will return all-zeros state for the logical operators (the final logical operator will thus be identity operator). Thus, we start from the all-zero state for the error and the $|+\\rangle$ state for the logicals." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "error_state = \"0\" * (num_sites - num_logicals)\n", + "logicals_state = \"+\" * num_logicals\n", + "state_string = logicals_state + error_state\n", + "error_mps = create_custom_product_state(string=state_string)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, we get the sites where the checks will be applied. We will need to construct MPOs using this data." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X checks:\n", + "[2, 4, 6, 8, 10, 12]\n", + "[8, 10, 12, 14, 16, 18]\n", + "Z checks:\n", + "[3, 5]\n", + "[5, 7]\n", + "[9, 11]\n", + "[11, 13]\n", + "[15, 17]\n", + "[17, 19]\n" + ] + } + ], + "source": [ + "checks_x, checks_z = css_code_checks(code)\n", + "print(\"X checks:\")\n", + "for check in checks_x:\n", + " print(check)\n", + "print(\"Z checks:\")\n", + "for check in checks_z:\n", + " print(check)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These lists mention only the sites where we will apply the XOR constraints. However, the MPOs will also consist of other tensors, such as SWAPs (tensors' legs crossings) and boundary XOR constraints. In what follows we define the list of these auxiliary tensors and the corresponding sites where they reside." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "constraints_tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "logicals_tensors = [COPY_LEFT, XOR_BULK, SWAP, XOR_RIGHT]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Full X-check lists of sites:\n", + "[[2], [4, 6, 8, 10], [3, 5, 7, 9, 11], [12]]\n", + "[[8], [10, 12, 14, 16], [9, 11, 13, 15, 17], [18]]\n", + "Full Z-check lists of sites:\n", + "[[3], [], [4], [5]]\n", + "[[5], [], [6], [7]]\n", + "[[9], [], [10], [11]]\n", + "[[11], [], [12], [13]]\n", + "[[15], [], [16], [17]]\n", + "[[17], [], [18], [19]]\n" + ] + } + ], + "source": [ + "constraints_sites = css_code_constraint_sites(code)\n", + "print(\"Full X-check lists of sites:\")\n", + "for string in constraints_sites[0]:\n", + " print(string)\n", + "print(\"Full Z-check lists of sites:\")\n", + "for string in constraints_sites[1]:\n", + " print(string)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now take a look at the logical operators." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2]\n", + "\n", + "[0, 3, 6]\n", + "\n" + ] + } + ], + "source": [ + "print(code.x_logicals_binary())\n", + "print(code.z_logicals_binary())" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to again translate it to our MPO language by changing the indices since we add the logical-operator sites to the beginning of the MPS." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6]\n", + "[3, 9, 15]\n" + ] + } + ], + "source": [ + "print(css_code_logicals(code)[0])\n", + "print(css_code_logicals(code)[1])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now goes the same operation of adding sites where auxiliary tensors should be placed." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0], [2, 4], [1, 3, 5], [6]]\n", + "[[1], [3, 9], [2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14], [15]]\n" + ] + } + ], + "source": [ + "logicals_sites = css_code_logicals_sites(code)\n", + "print(css_code_logicals_sites(code)[0])\n", + "print(css_code_logicals_sites(code)[1])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now the fun part, MPS-MPO contraction. But first, we apply the bias channel to our error state. This is done to bias our output towards the received input. This is done by distributing the amplitude around the initial basis product state to other basis product states in the descending order by Hamming distance." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, the tensor network we are going to build is going to look as follows:\n", + "\"Tensor-network" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "renormalise = True\n", + "result_to_explicit = False\n", + "sites_to_bias = list(range(num_logicals, num_sites))\n", + "error_mps = apply_bitflip_bias(\n", + " mps=error_mps,\n", + " sites_to_bias=sites_to_bias,\n", + " renormalise=renormalise,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 2/2 [00:00<00:00, 515.33it/s]\n", + "100%|██████████| 6/6 [00:00<00:00, 1387.62it/s]\n", + "100%|██████████| 2/2 [00:00<00:00, 403.47it/s]\n" + ] + } + ], + "source": [ + "error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[0],\n", + " constraints_tensors,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")\n", + "error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[1],\n", + " constraints_tensors,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")\n", + "error_mps = apply_constraints(\n", + " error_mps,\n", + " logicals_sites,\n", + " logicals_tensors,\n", + " renormalise=renormalise,\n", + " result_to_explicit=result_to_explicit,\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we marginalise over the message bits to get the probability distribution over the four possibilities of a logical operator: $I$, $X$, $Z$, $Y$." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.61225663 0.06778069 0.28807136 0.03189132]\n" + ] + } + ], + "source": [ + "sites_to_marginalise = list(range(num_logicals, len(error_state) + num_logicals))\n", + "logical = marginalise(mps=error_mps, sites_to_marginalise=sites_to_marginalise).dense(\n", + " flatten=True, renormalise=True, norm=1\n", + ")\n", + "print(logical)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which indeed tells us that most likely we do not need to apply any operator!" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now put all of this into a function. We'll need this to run the decoder over a bunch of single- and multiqubit errors." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now generate all possible one-, two- and three-qubit errors using `qecsim`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "one_qubit_paulis = pt.ipauli(n_qubits=len(code), min_weight=1, max_weight=1)\n", + "two_qubit_paulis = pt.ipauli(n_qubits=len(code), min_weight=2, max_weight=2)\n", + "three_qubit_paulis = pt.ipauli(n_qubits=len(code), min_weight=3, max_weight=3)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 27/27 [00:00<00:00, 49.52it/s]\n" + ] + } + ], + "source": [ + "one_qubit_errors = [pauli_to_mps(pauli) for pauli in one_qubit_paulis]\n", + "one_qubit_outputs = [\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(one_qubit_errors)\n", + "]\n", + "one_qubit_corrections = [output[0] for output in one_qubit_outputs]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 324/324 [00:06<00:00, 50.83it/s]\n" + ] + } + ], + "source": [ + "two_qubit_errors = [pauli_to_mps(pauli) for pauli in two_qubit_paulis]\n", + "two_qubit_outputs = [\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(two_qubit_errors)\n", + "]\n", + "two_qubit_corrections = [output[0] for output in two_qubit_outputs]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 2268/2268 [00:44<00:00, 51.11it/s]\n" + ] + } + ], + "source": [ + "three_qubit_errors = [pauli_to_mps(pauli) for pauli in three_qubit_paulis]\n", + "three_qubit_outputs = [\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(three_qubit_errors)\n", + "]\n", + "three_qubit_corrections = [output[0] for output in three_qubit_outputs]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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PqrVamzYsCGeeOKJeO6552LBggXjzl933XXxoQ99KHbt2lU7dujQoXj55ZdjyZIl57xmoVCItra2cRsAMHXV9cxHT09P7NixI5588slobW2tPcdRLBZj1qxZUSwW484774ze3t5ob2+Ptra2uOeee2LJkiW+6QIARESd8bF169aIiFi2bNm449u2bYv169dHRMRPfvKTmDZtWqxduzYqlUqsXLkyfvaznzVkWACg+dUVH9Vq9T3XzJw5M7Zs2RJbtmw576EAgKnL73YBAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFLVHR979uyJW2+9Nbq7u6OlpSV27tw57vz69eujpaVl3LZq1apGzQsANLm642N0dDQWLVoUW7Zsecc1q1atildffbW2/frXv76gIQGAqWN6vS9YvXp1rF69+l3XFAqF6OrqOu+hAICpa0Ke+di9e3d0dHTEJz7xibj77rvjxIkT77i2UqlEuVwetwEAU1fD42PVqlXx2GOPxa5du+LHP/5xDA4OxurVq+PNN9885/r+/v4oFou1rVQqNXokAOAiUvfHLu/ltttuq/33Zz7zmbj22mvj6quvjt27d8fNN9981vq+vr7o7e2t7ZfLZQECAFPYhH/V9qqrroq5c+fG4cOHz3m+UChEW1vbuA0AmLomPD5eeeWVOHHiRMybN2+ibwUANIG6P3Y5ffr0uHcxjh49GgcOHIj29vZob2+PTZs2xdq1a6OrqyuOHDkS9913X3z0ox+NlStXNnRwAKA51R0fL7zwQtx00021/bee11i3bl1s3bo1Dh48GL/85S/j5MmT0d3dHStWrIgf/OAHUSgUGjc1ANC06o6PZcuWRbVafcfzf/zjHy9oIABgavO7XQCAVOIDAEglPgCAVOIDAEglPgCA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(one_qubit_corrections)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAcIklEQVR4nO3df4zU9Z348dcAt6P0dpcuCrubroBe/XEnUNRzj57ngXCFxdAzcr1TMQctB7aHNGXTqNuzKuaS3VbPkvY4uUtUrimUXhOLPUy4CBZo44qK2XA2HhECimEXWwk7ssSVH/P94+J8bwpo1844710ej+ST7Hw+n/nMaxrGffYzn9nJ5PP5fAAAJGRYpQcAAPhNAgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkjKj0AB/FqVOn4uDBg1FdXR2ZTKbS4wAAv4V8Ph/vvPNONDY2xrBhH3yOZFAGysGDB6OpqanSYwAAH8GBAwfiU5/61AfuMygDpbq6OiL+9wnW1NRUeBoA4LeRy+Wiqamp8Hv8gwzKQHn/bZ2amhqBAgCDzG9zeYaLZAGA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5Iyo9QIrG3/N0pUcYsP0dN1Z6BAAoGWdQAIDkCBQAIDkCBQBIjkABAJIjUACA5Aw4ULZv3x5z586NxsbGyGQysWHDhqLtmUzmjMtDDz1U2Gf8+PGnbe/o6PidnwwAMDQMOFD6+vpi8uTJsWrVqjNu7+7uLloef/zxyGQyMW/evKL9HnzwwaL9li1b9tGeAQAw5Az476C0tLRES0vLWbfX19cX3X7qqadi+vTpcfHFFxetr66uPm1fAICIMl+DcujQoXj66adj0aJFp23r6OiI0aNHx5QpU+Khhx6KEydOnPU4/f39kcvlihYAYOgq61+S/fd///eorq6Om2++uWj9V7/61bjqqquirq4unnvuuWhra4vu7u545JFHznic9vb2WLFiRTlHBQASUtZAefzxx2P+/Plx3nnnFa1vbW0t/Dxp0qSoqqqKO+64I9rb2yObzZ52nLa2tqL75HK5aGpqKt/gAEBFlS1Qfv7zn8fu3bvjRz/60Yfu29zcHCdOnIj9+/fHZZdddtr2bDZ7xnABAIamsl2D8thjj8XVV18dkydP/tB9u7q6YtiwYTFmzJhyjQMADCIDPoNy9OjR2LNnT+H2vn37oqurK+rq6uKiiy6KiP99C+bHP/5x/NM//dNp9+/s7IwdO3bE9OnTo7q6Ojo7O2P58uVx++23xyc/+cnf4akAAEPFgAPlpZdeiunTpxduv39tyIIFC2LNmjUREbF+/frI5/Nx6623nnb/bDYb69evjwceeCD6+/tjwoQJsXz58qJrTACAc1smn8/nKz3EQOVyuaitrY3e3t6oqakp+fHH3/N0yY9Zbvs7bqz0CADwgQby+9t38QAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBhwo27dvj7lz50ZjY2NkMpnYsGFD0faFCxdGJpMpWmbPnl20z+HDh2P+/PlRU1MTo0aNikWLFsXRo0d/pycCAAwdAw6Uvr6+mDx5cqxateqs+8yePTu6u7sLyw9/+MOi7fPnz49f/vKX8cwzz8TGjRtj+/btsWTJkoFPDwAMSSMGeoeWlpZoaWn5wH2y2WzU19efcdurr74amzZtihdffDGuueaaiIj43ve+F3PmzImHH344GhsbBzoSADDElOUalK1bt8aYMWPisssui6985Svx9ttvF7Z1dnbGqFGjCnESETFz5swYNmxY7Nix44zH6+/vj1wuV7QAAENXyQNl9uzZ8f3vfz+2bNkS3/rWt2Lbtm3R0tISJ0+ejIiInp6eGDNmTNF9RowYEXV1ddHT03PGY7a3t0dtbW1haWpqKvXYAEBCBvwWz4e55ZZbCj9PnDgxJk2aFJdcckls3bo1ZsyY8ZGO2dbWFq2trYXbuVxOpADAEFb2jxlffPHFccEFF8SePXsiIqK+vj7eeuuton1OnDgRhw8fPut1K9lsNmpqaooWAGDoKnugvPnmm/H2229HQ0NDRERMnTo1jhw5Ejt37izs8+yzz8apU6eiubm53OMAAIPAgN/iOXr0aOFsSETEvn37oqurK+rq6qKuri5WrFgR8+bNi/r6+ti7d2/cdddd8Qd/8Acxa9asiIi44oorYvbs2bF48eJYvXp1HD9+PO6888645ZZbfIIHAIiIj3AG5aWXXoopU6bElClTIiKitbU1pkyZEvfdd18MHz48du3aFZ///Ofj0ksvjUWLFsXVV18dP//5zyObzRaOsXbt2rj88stjxowZMWfOnLjuuuvi3/7t30r3rACAQW3AZ1CmTZsW+Xz+rNv/67/+60OPUVdXF+vWrRvoQwMA5wjfxQMAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJGXCgbN++PebOnRuNjY2RyWRiw4YNhW3Hjx+Pu+++OyZOnBif+MQnorGxMf72b/82Dh48WHSM8ePHRyaTKVo6Ojp+5ycDAAwNAw6Uvr6+mDx5cqxateq0bceOHYuXX345vvnNb8bLL78cTz75ZOzevTs+//nPn7bvgw8+GN3d3YVl2bJlH+0ZAABDzoiB3qGlpSVaWlrOuK22tjaeeeaZonX//M//HNdee2288cYbcdFFFxXWV1dXR319/UAfHgA4B5T9GpTe3t7IZDIxatSoovUdHR0xevTomDJlSjz00ENx4sSJsx6jv78/crlc0QIADF0DPoMyEO+++27cfffdceutt0ZNTU1h/Ve/+tW46qqroq6uLp577rloa2uL7u7ueOSRR854nPb29lixYkU5RwUAElK2QDl+/Hj89V//deTz+Xj00UeLtrW2thZ+njRpUlRVVcUdd9wR7e3tkc1mTztWW1tb0X1yuVw0NTWVa3QAoMLKEijvx8nrr78ezz77bNHZkzNpbm6OEydOxP79++Oyyy47bXs2mz1juAAAQ1PJA+X9OHnttdfiZz/7WYwePfpD79PV1RXDhg2LMWPGlHocAGAQGnCgHD16NPbs2VO4vW/fvujq6oq6urpoaGiIv/qrv4qXX345Nm7cGCdPnoyenp6IiKirq4uqqqro7OyMHTt2xPTp06O6ujo6Oztj+fLlcfvtt8cnP/nJ0j0zAGDQGnCgvPTSSzF9+vTC7fevDVmwYEE88MAD8dOf/jQiIj7zmc8U3e9nP/tZTJs2LbLZbKxfvz4eeOCB6O/vjwkTJsTy5cuLrjEBAM5tAw6UadOmRT6fP+v2D9oWEXHVVVfF888/P9CHBQDOIb6LBwBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIzotIDAMBQNv6epys9wkeyv+PGij6+MygAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGfAgbJ9+/aYO3duNDY2RiaTiQ0bNhRtz+fzcd9990VDQ0Ocf/75MXPmzHjttdeK9jl8+HDMnz8/ampqYtSoUbFo0aI4evTo7/REAIChY8CB0tfXF5MnT45Vq1adcfu3v/3t+O53vxurV6+OHTt2xCc+8YmYNWtWvPvuu4V95s+fH7/85S/jmWeeiY0bN8b27dtjyZIlH/1ZAABDyoC/zbilpSVaWlrOuC2fz8fKlSvj3nvvjb/8y7+MiIjvf//7MXbs2NiwYUPccsst8eqrr8amTZvixRdfjGuuuSYiIr73ve/FnDlz4uGHH47Gxsbf4ekAAENBSa9B2bdvX/T09MTMmTML62pra6O5uTk6OzsjIqKzszNGjRpViJOIiJkzZ8awYcNix44dZzxuf39/5HK5ogUAGLpKGig9PT0RETF27Nii9WPHji1s6+npiTFjxhRtHzFiRNTV1RX2+U3t7e1RW1tbWJqamko5NgCQmEHxKZ62trbo7e0tLAcOHKj0SABAGZU0UOrr6yMi4tChQ0XrDx06VNhWX18fb731VtH2EydOxOHDhwv7/KZsNhs1NTVFCwAwdJU0UCZMmBD19fWxZcuWwrpcLhc7duyIqVOnRkTE1KlT48iRI7Fz587CPs8++2ycOnUqmpubSzkOADBIDfhTPEePHo09e/YUbu/bty+6urqirq4uLrroovja174W//iP/xif/vSnY8KECfHNb34zGhsb46abboqIiCuuuCJmz54dixcvjtWrV8fx48fjzjvvjFtuucUneACAiPgIgfLSSy/F9OnTC7dbW1sjImLBggWxZs2auOuuu6Kvry+WLFkSR44cieuuuy42bdoU5513XuE+a9eujTvvvDNmzJgRw4YNi3nz5sV3v/vdEjwdAGAoyOTz+XylhxioXC4XtbW10dvbW5brUcbf83TJj1lu+zturPQIAJzBYPydElGe3ysD+f09KD7FAwCcWwQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAckoeKOPHj49MJnPasnTp0oiImDZt2mnbvvzlL5d6DABgEBtR6gO++OKLcfLkycLtV155Jf7iL/4ivvCFLxTWLV68OB588MHC7ZEjR5Z6DABgECt5oFx44YVFtzs6OuKSSy6JP//zPy+sGzlyZNTX15f6oQGAIaKs16C899578YMf/CC+9KUvRSaTKaxfu3ZtXHDBBXHllVdGW1tbHDt2rJxjAACDTMnPoPxfGzZsiCNHjsTChQsL62677bYYN25cNDY2xq5du+Luu++O3bt3x5NPPnnW4/T390d/f3/hdi6XK+fYAECFlTVQHnvssWhpaYnGxsbCuiVLlhR+njhxYjQ0NMSMGTNi7969cckll5zxOO3t7bFixYpyjgoAJKRsb/G8/vrrsXnz5vi7v/u7D9yvubk5IiL27Nlz1n3a2tqit7e3sBw4cKCkswIAaSnbGZQnnngixowZEzfeeOMH7tfV1RUREQ0NDWfdJ5vNRjabLeV4AEDCyhIop06diieeeCIWLFgQI0b8/4fYu3dvrFu3LubMmROjR4+OXbt2xfLly+P666+PSZMmlWMUAGAQKkugbN68Od5444340pe+VLS+qqoqNm/eHCtXroy+vr5oamqKefPmxb333luOMQCAQaosgfK5z30u8vn8aeubmppi27Zt5XhIAGAI8V08AEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkJySB8oDDzwQmUymaLn88ssL2999991YunRpjB49On7/938/5s2bF4cOHSr1GADAIFaWMyh/9Ed/FN3d3YXlF7/4RWHb8uXL4z//8z/jxz/+cWzbti0OHjwYN998cznGAAAGqRFlOeiIEVFfX3/a+t7e3njsscdi3bp1ccMNN0RExBNPPBFXXHFFPP/88/Enf/In5RgHABhkynIG5bXXXovGxsa4+OKLY/78+fHGG29ERMTOnTvj+PHjMXPmzMK+l19+eVx00UXR2dlZjlEAgEGo5GdQmpubY82aNXHZZZdFd3d3rFixIv7sz/4sXnnllejp6YmqqqoYNWpU0X3Gjh0bPT09Zz1mf39/9Pf3F27ncrlSjw0AJKTkgdLS0lL4edKkSdHc3Bzjxo2L//iP/4jzzz//Ix2zvb09VqxYUaoRAYDElf1jxqNGjYpLL7009uzZE/X19fHee+/FkSNHivY5dOjQGa9ZeV9bW1v09vYWlgMHDpR5agCgksoeKEePHo29e/dGQ0NDXH311fF7v/d7sWXLlsL23bt3xxtvvBFTp0496zGy2WzU1NQULQDA0FXyt3i+/vWvx9y5c2PcuHFx8ODBuP/++2P48OFx6623Rm1tbSxatChaW1ujrq4uampqYtmyZTF16lSf4AEACkoeKG+++Wbceuut8fbbb8eFF14Y1113XTz//PNx4YUXRkTEd77znRg2bFjMmzcv+vv7Y9asWfEv//IvpR4DABjESh4o69ev/8Dt5513XqxatSpWrVpV6ocGAIYI38UDACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGdEpQcA+E3j73m60iMM2P6OGys9AgwpzqAAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQK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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(two_qubit_corrections)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(three_qubit_corrections)\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now check by hand that some of the decoder's nontrivial outputs are indeed correct. First of all, from all one-qubit errors we get an Identity operator which corresponds to the fact that Shor's code corrects all one-qubit errors. However, Shor's code can also correct some two-qubit errors." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "one_qubit_paulis = list(pt.ipauli(n_qubits=len(code), min_weight=1, max_weight=1))\n", + "two_qubit_paulis = list(pt.ipauli(n_qubits=len(code), min_weight=2, max_weight=2))\n", + "three_qubit_paulis = list(pt.ipauli(n_qubits=len(code), min_weight=3, max_weight=3))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's take a look at the first 20 errors which result in the Identity logical operator as the output." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XXIIIIIII\n", + "XZIIIIIII\n", + "XYIIIIIII\n", + "ZXIIIIIII\n", + "YXIIIIIII\n", + "XIXIIIIII\n", + "XIZIIIIII\n", + "XIYIIIIII\n", + "ZIXIIIIII\n", + "YIXIIIIII\n", + "XIIZIIIII\n", + "ZIIXIIIII\n" + ] + } + ], + "source": [ + "limit = 20\n", + "for i, correction in enumerate(two_qubit_corrections):\n", + " if correction == \"I\":\n", + " print(two_qubit_paulis[i])\n", + " if i > limit:\n", + " break" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now want to dive a bit more into what is happening inside the decoder to be able to better understand the results, even though the current setup is already sufficient for calculating thresholds. For example, the first error $(X_0 X_1)$ from the list above would trigger the first $X$ parity check in the case of measuring it. This can be seen from the actual tensor network we are building (see the image below). However, in the current setup the stabilizers are being set to $0$, which is the result of the fact that the $\\text{XOR}$ tensors we use project out the inputs of odd (i.e., equal to $1$) parity. What happens next after applying the logical-operator MPOs and marginalising basically spits out a marginal distribution over codewords corresponding to different parities of the logical operators.\n", + "\n", + "\"Tensor-network" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now take a look at the errors which result in the $X$ logical operator as the output." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ZZIIIIIII\n", + "ZYIIIIIII\n", + "YZIIIIIII\n", + "YYIIIIIII\n", + "ZIZIIIIII\n", + "ZIYIIIIII\n", + "YIZIIIIII\n", + "YIYIIIIII\n", + "IZZIIIIII\n", + "IZYIIIIII\n", + "IYZIIIIII\n", + "IYYIIIIII\n", + "IIIZZIIII\n", + "IIIZYIIII\n", + "IIIYZIIII\n", + "IIIYYIIII\n", + "IIIZIZIII\n", + "IIIZIYIII\n", + "IIIYIZIII\n", + "IIIYIYIII\n", + "IIIIZZIII\n", + "IIIIZYIII\n", + "IIIIYZIII\n", + "IIIIYYIII\n", + "IIIIIIZZI\n", + "IIIIIIZYI\n", + "IIIIIIYZI\n", + "IIIIIIYYI\n", + "IIIIIIZIZ\n", + "IIIIIIZIY\n", + "IIIIIIYIZ\n", + "IIIIIIYIY\n", + "IIIIIIIZZ\n", + "IIIIIIIZY\n", + "IIIIIIIYZ\n", + "IIIIIIIYY\n" + ] + } + ], + "source": [ + "for i, correction in enumerate(two_qubit_corrections):\n", + " if correction == \"X\":\n", + " print(two_qubit_paulis[i])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly to the previous case, the first error $(Z_0 Z_1)$ from the list above would trigger the first $Z$ parity check which in its turn would trigger the $\\text{XOR}$ tensor corresponding to the $X$ logical-operator MPO therefore the $X$ logical as the most likely output." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.11", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "64c06a7280c9749d5771a76ca6109d7df6b2615ddb3b9b0828f83fb315c7f8a2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/toric.ipynb b/docs/source/toric.ipynb new file mode 100644 index 00000000..17a48044 --- /dev/null +++ b/docs/source/toric.ipynb @@ -0,0 +1,882 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decoding the Toric code" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this experiment, we’ll use ``mdopt`` to compute the threshold of the toric code. Hereafter, we assume an independent noise model as well as perfect syndrome measurements." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from tqdm import tqdm\n", + "import qecstruct as qc\n", + "import qecsim.paulitools as pt\n", + "import matplotlib.pyplot as plt\n", + "from scipy.sparse import hstack, kron, eye, csc_matrix, block_diag\n", + "\n", + "from mdopt.mps.utils import marginalise, create_custom_product_state\n", + "from mdopt.contractor.contractor import mps_mpo_contract\n", + "from mdopt.optimiser.utils import (\n", + " SWAP,\n", + " COPY_LEFT,\n", + " XOR_BULK,\n", + " XOR_LEFT,\n", + " XOR_RIGHT,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " css_code_checks,\n", + " css_code_logicals,\n", + " css_code_logicals_sites,\n", + " css_code_constraint_sites,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " apply_constraints,\n", + " apply_bitflip_bias,\n", + ")\n", + "from examples.decoding.decoding import (\n", + " pauli_to_mps,\n", + " decode_shor,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "def repetition_code(n):\n", + " \"\"\"\n", + " Parity check matrix of a repetition code with length n.\n", + " \"\"\"\n", + " row_ind, col_ind = zip(*((i, j) for i in range(n) for j in (i, (i + 1) % n)))\n", + " data = np.ones(2 * n, dtype=np.uint8)\n", + " return csc_matrix((data, (row_ind, col_ind)))\n", + "\n", + "\n", + "def toric_code_x_checks(L):\n", + " \"\"\"\n", + " Sparse check matrix for the X stabilisers of a toric code with\n", + " lattice size L, constructed as the hypergraph product of\n", + " two repetition codes.\n", + " \"\"\"\n", + " Hr = repetition_code(L)\n", + " H = hstack(\n", + " [kron(Hr, eye(Hr.shape[1])), kron(eye(Hr.shape[0]), Hr.T)], dtype=np.uint8\n", + " )\n", + " H.data = H.data % 2\n", + " H.eliminate_zeros()\n", + " checks = csc_matrix(H).toarray()\n", + " return [list(np.nonzero(check)[0]) for check in checks]\n", + "\n", + "\n", + "def toric_code_x_logicals(L):\n", + " \"\"\"\n", + " Sparse binary matrix with each row corresponding to an X logical operator\n", + " of a toric code with lattice size L. Constructed from the\n", + " homology groups of the repetition codes using the Kunneth\n", + " theorem.\n", + " \"\"\"\n", + " H1 = csc_matrix(([1], ([0], [0])), shape=(1, L), dtype=np.uint8)\n", + " H0 = csc_matrix(np.ones((1, L), dtype=np.uint8))\n", + " x_logicals = block_diag([kron(H1, H0), kron(H0, H1)])\n", + " x_logicals.data = x_logicals.data % 2\n", + " x_logicals.eliminate_zeros()\n", + " logicals = csc_matrix(x_logicals).toarray()\n", + " return [list(np.nonzero(logical)[0]) for logical in logicals]\n", + "\n", + "\n", + "def toric_code_constraint_sites(L):\n", + "\n", + " stabilizers = toric_code_x_checks(L)\n", + " sites_x = [np.nonzero(stabilizers[i])[0] for i in range(len(stabilizers))]\n", + " sites_x = [2*site + 3 for site in sites_x]\n", + "\n", + " constraints_strings_x = []\n", + "\n", + " for sites in sites_x:\n", + " xor_left_sites_x = [sites[0]]\n", + " xor_bulk_sites_x = [sites[i] for i in range(1, len(sites) - 1)]\n", + " xor_right_sites_x = [sites[-1]]\n", + "\n", + " swap_sites_x = list(range(sites[0] + 1, sites[-1]))\n", + " for k in range(1, len(sites) - 1):\n", + " swap_sites_x.remove(sites[k])\n", + "\n", + " constraints_strings_x.append(\n", + " [xor_left_sites_x, xor_bulk_sites_x, swap_sites_x, xor_right_sites_x]\n", + " )\n", + "\n", + " return constraints_strings_x\n", + "\n", + "\n", + "def toric_code_logicals_sites(L):\n", + "\n", + " sites = toric_code_x_logicals(L)\n", + " sites_x, sites_z = np.array(sites[0]), np.array(sites[1])\n", + " sites_x = list(2*sites_x + 3)\n", + " sites_z = list(2*sites_z + 3)\n", + "\n", + " copy_site_x = [0]\n", + " copy_site_z = [1]\n", + "\n", + " xor_right_site_x = [sites_x[-1]]\n", + " xor_right_site_z = [sites_z[-1]]\n", + "\n", + " xor_bulk_sites_x = [sites_x[i] for i in range(len(sites_x) - 1)]\n", + " xor_bulk_sites_z = [sites_z[i] for i in range(len(sites_z) - 1)]\n", + "\n", + " swap_sites_x = list(range(copy_site_x[0] + 1, xor_right_site_x[0]))\n", + " swap_sites_x = [site for site in swap_sites_x if site not in xor_bulk_sites_x]\n", + " swap_sites_z = list(range(copy_site_z[0] + 1, xor_right_site_z[0]))\n", + " swap_sites_z = [site for site in swap_sites_z if site not in xor_bulk_sites_z]\n", + "\n", + " string_x = [copy_site_x, xor_bulk_sites_x, swap_sites_x, xor_right_site_x]\n", + " string_z = [copy_site_z, xor_bulk_sites_z, swap_sites_z, xor_right_site_z]\n", + "\n", + " return string_x, string_z" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[5], [7], [6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[5], [7], [6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]],\n", + " [[3], [5, 7], [4, 6, 8], [9]]]" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "toric_code_constraint_sites(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "sites = toric_code_x_logicals(L=3)\n", + "sites_x, sites_z = np.array(sites[0]), np.array(sites[1])\n", + "sites_x = list(2*sites_x + 3)\n", + "sites_z = list(2*sites_z + 3)\n", + "\n", + "copy_site_x = [0]\n", + "copy_site_z = [1]\n", + "\n", + "xor_right_site_x = [sites_x[-1]]\n", + "xor_right_site_z = [sites_z[-1]]\n", + "\n", + "xor_bulk_sites_x = [sites_x[i] for i in range(len(sites_x) - 1)]\n", + "xor_bulk_sites_z = [sites_z[i] for i in range(len(sites_z) - 1)]\n", + "\n", + "swap_sites_x = list(range(copy_site_x[0] + 1, xor_right_site_x[0]))\n", + "swap_sites_x = [site for site in swap_sites_x if site not in xor_bulk_sites_x]\n", + "swap_sites_z = list(range(copy_site_z[0] + 1, xor_right_site_z[0]))\n", + "swap_sites_z = [site for site in swap_sites_z if site not in xor_bulk_sites_z]" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[1], [2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[1], [2], [], [3]],\n", + " [[0], [1, 2], [], [3]],\n", + " [[0], [1, 2], [], [3]]]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "toric_code_constraint_sites(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[0, 1, 2], [9, 12, 15]]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "toric_code_x_logicals(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[21, 27, 33]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sites_z" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([[0], [3, 5], [1, 2, 4, 6], [7]],\n", + " [[1],\n", + " [21, 27],\n", + " [2,\n", + " 3,\n", + " 4,\n", + " 5,\n", + " 6,\n", + " 7,\n", + " 8,\n", + " 9,\n", + " 10,\n", + " 11,\n", + " 12,\n", + " 13,\n", + " 14,\n", + " 15,\n", + " 16,\n", + " 17,\n", + " 18,\n", + " 19,\n", + " 20,\n", + " 22,\n", + " 23,\n", + " 24,\n", + " 25,\n", + " 26,\n", + " 28,\n", + " 29,\n", + " 30,\n", + " 31,\n", + " 32],\n", + " [33]])" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "toric_code_logicals_sites(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "[0, 3, 6] -> [3, 9, 15]\n", + "[0, 1, 2] -> [2, 4, 6]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "code = shor_code()\n", + "log_matrix_x = code.z_logicals_binary()\n", + "array_x = np.zeros((log_matrix_x.num_rows(), log_matrix_x.num_columns()), dtype=int)\n", + "for row, cols in enumerate(log_matrix_x.rows()):\n", + " for col in cols:\n", + " array_x[row, col] = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "array_x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qecstruct import shor_code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "shor_code().x_logicals_binary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "shor_code().z_logicals_binary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "css_code_logicals(shor_code())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def css_code_logicals(code: CssCode):\n", + " \"\"\"\n", + " Returns the list of MPS sites where the logical constraints should be applied.\n", + "\n", + " Parameters\n", + " ----------\n", + " code : qec.CssCode\n", + " The CSS code object.\n", + "\n", + " Returns\n", + " -------\n", + " logicals : Tuple[List[int]]\n", + " List of logical operators, first X, then Z.\n", + " \"\"\"\n", + "\n", + " log_matrix_x = code.z_logicals_binary()\n", + " array_x = np.zeros((log_matrix_x.num_rows(), log_matrix_x.num_columns()), dtype=int)\n", + " for row, cols in enumerate(log_matrix_x.rows()):\n", + " for col in cols:\n", + " array_x[row, col] = 1\n", + "\n", + " log_matrix_z = code.x_logicals_binary()\n", + " array_z = np.zeros((log_matrix_z.num_rows(), log_matrix_z.num_columns()), dtype=int)\n", + " for row, cols in enumerate(log_matrix_z.rows()):\n", + " for col in cols:\n", + " array_z[row, col] = 1\n", + "\n", + " x_logicals = [\n", + " 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() + 1\n", + " for row in array_x\n", + " ]\n", + " x_logicals = [list(x_logical) for x_logical in x_logicals]\n", + " z_logicals = [\n", + " 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals()\n", + " for row in array_z\n", + " ]\n", + " z_logicals = [list(z_logical) for z_logical in z_logicals]\n", + "\n", + " return z_logicals[0], x_logicals[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "[0, 1, 2] -> [2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def decode_toric(\n", + " lattice_size: int,\n", + " error: str,\n", + " renormalise: bool = True,\n", + " silent: bool = False,\n", + "):\n", + " \"\"\"\n", + " This function does error-based decoding of the toric code.\n", + " It takes as input an error string and returns the most likely Pauli correction.\n", + "\n", + " Parameters\n", + " ----------\n", + " lattice_size : int\n", + " The lattice size of the toric code.\n", + " error : str\n", + " The error in a string format.\n", + " The way the decoder takes the error is as follows:\n", + " \"X_0 Z_0 X_1 Z_1 ...\"\n", + " renormalise : bool\n", + " Whether to renormalise the singular values during contraction.\n", + " silent : bool\n", + " Whether to show the progress bars or not.\n", + "\n", + " Raises\n", + " ------\n", + " ValueError\n", + " If the error string length does not correspond to the code.\n", + " \"\"\"\n", + "\n", + " num_logicals = 2\n", + " num_sites = 2 * lattice_size ** 2 + num_logicals\n", + "\n", + " if len(error) != num_sites - num_logicals:\n", + " raise ValueError(\n", + " f\"The error length is {len(error)}, expected {num_sites - num_logicals}.\"\n", + " )\n", + "\n", + " logicals_state = \"+\" * num_logicals\n", + " state_string = logicals_state + error\n", + " error_mps = create_custom_product_state(string=state_string)\n", + "\n", + " constraints_tensors = [XOR_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + " logicals_tensors = [COPY_LEFT, XOR_BULK, SWAP, XOR_RIGHT]\n", + "\n", + " constraints_sites = toric_code_constraint_sites(lattice_size)\n", + " logicals_sites = toric_code_logicals_sites(lattice_size)\n", + " sites_to_bias = list(range(num_logicals, num_sites))\n", + "\n", + " error_mps = apply_bitflip_bias(\n", + " mps=error_mps, sites_to_bias=sites_to_bias, renormalise=renormalise\n", + " )\n", + "\n", + " error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[0],\n", + " constraints_tensors,\n", + " renormalise=renormalise,\n", + " silent=silent,\n", + " )\n", + " error_mps = apply_constraints(\n", + " error_mps,\n", + " constraints_sites[1],\n", + " constraints_tensors,\n", + " renormalise=renormalise,\n", + " silent=silent,\n", + " )\n", + " error_mps = apply_constraints(\n", + " error_mps,\n", + " logicals_sites,\n", + " logicals_tensors,\n", + " renormalise=renormalise,\n", + " silent=silent,\n", + " )\n", + "\n", + " sites_to_marginalise = list(range(num_logicals, len(error) + num_logicals))\n", + " logical = marginalise(\n", + " mps=error_mps,\n", + " sites_to_marginalise=sites_to_marginalise,\n", + " ).dense(flatten=True, renormalise=True, norm=1)\n", + "\n", + " if np.argmax(logical) == 0:\n", + " return \"I\", logical\n", + " if np.argmax(logical) == 1:\n", + " return \"X\", logical\n", + " if np.argmax(logical) == 2:\n", + " return \"Z\", logical\n", + " if np.argmax(logical) == 3:\n", + " return \"Y\", logical" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "shor_code().z_logicals_binary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def css_code_logicals(code: CssCode):\n", + " \"\"\"\n", + " Returns the list of MPS sites where the logical constraints should be applied.\n", + "\n", + " Parameters\n", + " ----------\n", + " code : qec.CssCode\n", + " The CSS code object.\n", + "\n", + " Returns\n", + " -------\n", + " logicals : Tuple[List[int]]\n", + " List of logical operators, first X, then Z.\n", + " \"\"\"\n", + "\n", + " log_matrix_x = code.z_logicals_binary()\n", + " array_x = np.zeros((log_matrix_x.num_rows(), log_matrix_x.num_columns()), dtype=int)\n", + " for row, cols in enumerate(log_matrix_x.rows()):\n", + " for col in cols:\n", + " array_x[row, col] = 1\n", + "\n", + " log_matrix_z = code.x_logicals_binary()\n", + " array_z = np.zeros((log_matrix_z.num_rows(), log_matrix_z.num_columns()), dtype=int)\n", + " for row, cols in enumerate(log_matrix_z.rows()):\n", + " for col in cols:\n", + " array_z[row, col] = 1\n", + "\n", + " x_logicals = [\n", + " 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals() + 1\n", + " for row in array_x\n", + " ]\n", + " x_logicals = [list(x_logical) for x_logical in x_logicals]\n", + " z_logicals = [\n", + " 2 * np.nonzero(row)[0] + code.num_x_logicals() + code.num_z_logicals()\n", + " for row in array_z\n", + " ]\n", + " z_logicals = [list(z_logical) for z_logical in z_logicals]\n", + "\n", + " return z_logicals[0], x_logicals[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "css_code_logicals_sites(shor_code())[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stabilizers = toric_code_x_stabilisers(L=3)\n", + "logicals = toric_code_x_logicals(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stabilizers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logicals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from examples.decoding.decoding import css_code_logicals, css_code_logicals_sites, css_code_checks\n", + "from qecstruct import shor_code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "css_code_checks(shor_code())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "css_code_logicals(shor_code())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "css_code_logicals_sites(shor_code())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_x_logicals(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toric_code_logicals_sites(L=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mdopt-ZdbamFdU-py3.11", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "64c06a7280c9749d5771a76ca6109d7df6b2615ddb3b9b0828f83fb315c7f8a2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/utils.rst b/docs/utils.rst deleted file mode 100644 index d6d0f6f2..00000000 --- a/docs/utils.rst +++ /dev/null @@ -1,11 +0,0 @@ -Utils module -================= - - -The Utils submodule ------------------------- - -.. automodule:: mdopt.utils.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/examples/decoding/shor.ipynb b/examples/decoding/shor.ipynb index b0182f14..cdbf3b5e 100644 --- a/examples/decoding/shor.ipynb +++ b/examples/decoding/shor.ipynb @@ -88,7 +88,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This quantum error correcting code is defined on $9$ physical qubits and has $2$ logical operators. This means we will need $9*2 + 2 = 20$ sites in our MPS." + "This quantum error correcting code is defined on $9$ physical qubits and has $2$ logical operators because it encodes $1$ logical qubit. This means we will need $9*2 + 2 = 20$ sites in our MPS." ] }, { @@ -325,11 +325,10 @@ "result_to_explicit = False\n", "sites_to_bias = list(range(num_logicals, num_sites))\n", "error_mps = apply_bitflip_bias(\n", - " mps=error_mps,\n", - " sites_to_bias=sites_to_bias,\n", - " renormalise=renormalise,\n", - " result_to_explicit=result_to_explicit,\n", - " )" + " mps=error_mps,\n", + " sites_to_bias=sites_to_bias,\n", + " renormalise=renormalise,\n", + ")" ] }, { @@ -341,9 +340,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 2/2 [00:00<00:00, 468.72it/s]\n", - "100%|██████████| 6/6 [00:00<00:00, 1460.16it/s]\n", - "100%|██████████| 2/2 [00:00<00:00, 369.93it/s]\n" + "100%|██████████| 2/2 [00:00<00:00, 515.33it/s]\n", + "100%|██████████| 6/6 [00:00<00:00, 1387.62it/s]\n", + "100%|██████████| 2/2 [00:00<00:00, 403.47it/s]\n" ] } ], @@ -394,7 +393,9 @@ ], "source": [ "sites_to_marginalise = list(range(num_logicals, len(error_state) + num_logicals))\n", - "logical = marginalise(mps=error_mps, sites_to_marginalise=sites_to_marginalise).dense(flatten=True, renormalise=True, norm=1)\n", + "logical = marginalise(mps=error_mps, sites_to_marginalise=sites_to_marginalise).dense(\n", + " flatten=True, renormalise=True, norm=1\n", + ")\n", "print(logical)" ] }, @@ -442,17 +443,16 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 27/27 [00:00<00:00, 104.44it/s]\n" + "100%|██████████| 27/27 [00:00<00:00, 49.52it/s]\n" ] } ], "source": [ "one_qubit_errors = [pauli_to_mps(pauli) for pauli in one_qubit_paulis]\n", "one_qubit_outputs = [\n", - " decode_shor(\n", - " error, renormalise=renormalise, result_to_explicit=result_to_explicit\n", - " ) for error in tqdm(one_qubit_errors)\n", - " ]\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(one_qubit_errors)\n", + "]\n", "one_qubit_corrections = [output[0] for output in one_qubit_outputs]" ] }, @@ -465,17 +465,16 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 324/324 [00:02<00:00, 108.97it/s]\n" + "100%|██████████| 324/324 [00:06<00:00, 50.83it/s]\n" ] } ], "source": [ "two_qubit_errors = [pauli_to_mps(pauli) for pauli in two_qubit_paulis]\n", "two_qubit_outputs = [\n", - " decode_shor(\n", - " error, renormalise=renormalise, result_to_explicit=result_to_explicit\n", - " ) for error in tqdm(two_qubit_errors)\n", - " ]\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(two_qubit_errors)\n", + "]\n", "two_qubit_corrections = [output[0] for output in two_qubit_outputs]" ] }, @@ -488,17 +487,16 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 2268/2268 [00:21<00:00, 107.60it/s]\n" + "100%|██████████| 2268/2268 [00:44<00:00, 51.11it/s]\n" ] } ], "source": [ "three_qubit_errors = [pauli_to_mps(pauli) for pauli in three_qubit_paulis]\n", "three_qubit_outputs = [\n", - " decode_shor(\n", - " error, renormalise=renormalise, result_to_explicit=result_to_explicit\n", - " ) for error in tqdm(three_qubit_errors)\n", - " ]\n", + " decode_shor(error, renormalise=renormalise)\n", + " for error in tqdm(three_qubit_errors)\n", + "]\n", "three_qubit_corrections = [output[0] for output in three_qubit_outputs]" ] }, @@ -509,7 +507,7 @@ "outputs": [ { "data": { - "image/png": "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PqrVamzYsCGeeOKJeO6552LBggXjzl933XXxoQ99KHbt2lU7dujQoXj55ZdjyZIl57xmoVCItra2cRsAMHXV9cxHT09P7NixI5588slobW2tPcdRLBZj1qxZUSwW484774ze3t5ob2+Ptra2uOeee2LJkiW+6QIARESd8bF169aIiFi2bNm449u2bYv169dHRMRPfvKTmDZtWqxduzYqlUqsXLkyfvaznzVkWACg+dUVH9Vq9T3XzJw5M7Zs2RJbtmw576EAgKnL73YBAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFLVHR979uyJW2+9Nbq7u6OlpSV27tw57vz69eujpaVl3LZq1apGzQsANLm642N0dDQWLVoUW7Zsecc1q1atildffbW2/frXv76gIQGAqWN6vS9YvXp1rF69+l3XFAqF6OrqOu+hAICpa0Ke+di9e3d0dHTEJz7xibj77rvjxIkT77i2UqlEuVwetwEAU1fD42PVqlXx2GOPxa5du+LHP/5xDA4OxurVq+PNN9885/r+/v4oFou1rVQqNXokAOAiUvfHLu/ltttuq/33Zz7zmbj22mvj6quvjt27d8fNN9981vq+vr7o7e2t7ZfLZQECAFPYhH/V9qqrroq5c+fG4cOHz3m+UChEW1vbuA0AmLomPD5eeeWVOHHiRMybN2+ibwUANIG6P3Y5ffr0uHcxjh49GgcOHIj29vZob2+PTZs2xdq1a6OrqyuOHDkS9913X3z0ox+NlStXNnRwAKA51R0fL7zwQtx00021/bee11i3bl1s3bo1Dh48GL/85S/j5MmT0d3dHStWrIgf/OAHUSgUGjc1ANC06o6PZcuWRbVafcfzf/zjHy9oIABgavO7XQCAVOIDAEglPgCAVOIDAEglPgCA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", + "image/png": "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PqrVamzYsCGeeOKJeO6552LBggXjzl933XXxoQ99KHbt2lU7dujQoXj55ZdjyZIl57xmoVCItra2cRsAMHXV9cxHT09P7NixI5588slobW2tPcdRLBZj1qxZUSwW484774ze3t5ob2+Ptra2uOeee2LJkiW+6QIARESd8bF169aIiFi2bNm449u2bYv169dHRMRPfvKTmDZtWqxduzYqlUqsXLkyfvaznzVkWACg+dUVH9Vq9T3XzJw5M7Zs2RJbtmw576EAgKnL73YBAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFLVHR979uyJW2+9Nbq7u6OlpSV27tw57vz69eujpaVl3LZq1apGzQsANLm642N0dDQWLVoUW7Zsecc1q1atildffbW2/frXv76gIQGAqWN6vS9YvXp1rF69+l3XFAqF6OrqOu+hAICpa0Ke+di9e3d0dHTEJz7xibj77rvjxIkT77i2UqlEuVwetwEAU1fD42PVqlXx2GOPxa5du+LHP/5xDA4OxurVq+PNN9885/r+/v4oFou1rVQqNXokAOAiUvfHLu/ltttuq/33Zz7zmbj22mvj6quvjt27d8fNN9981vq+vr7o7e2t7ZfLZQECAFPYhH/V9qqrroq5c+fG4cOHz3m+UChEW1vbuA0AmLomPD5eeeWVOHHiRMybN2+ibwUANIG6P3Y5ffr0uHcxjh49GgcOHIj29vZob2+PTZs2xdq1a6OrqyuOHDkS9913X3z0ox+NlStXNnRwAKA51R0fL7zwQtx00021/bee11i3bl1s3bo1Dh48GL/85S/j5MmT0d3dHStWrIgf/OAHUSgUGjc1ANC06o6PZcuWRbVafcfzf/zjHy9oIABgavO7XQCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEhVd3zs2bMnbr311uju7o6WlpbYuXPnuPPVajUefPDBmDdvXsyaNSuWL18eL774YqPmBQCaXN3xMTo6GosWLYotW7ac8/zDDz8cP/3pT+PRRx+N559/Pj784Q/HypUr4/XXX7/gYQGA5je93hesXr06Vq9efc5z1Wo1Nm/eHA888EB85StfiYiIxx57LDo7O2Pnzp1x2223Xdi0AEDTa+gzH0ePHo2hoaFYvnx57VixWIzFixfH3r17z/maSqUS5XJ53AYATF0NjY+hoaGIiOjs7Bx3vLOzs3buf/X390exWKxtpVKpkSMBABeZSf+2S19fX4yMjNS2Y8eOTfZIAMAEamh8dHV1RUTE8PDwuOPDw8O1c/+rUChEW1vbuA0AmLoaGh8LFiyIrq6u2LVrV+1YuVyO559/PpYsWdLIWwEATarub7ucPn06Dh8+XNs/evRoHDhwINrb2+Pyyy+PjRs3xg9/+MP42Mc+FgsWLIjvfe970d3dHWvWrGnk3ABAk6o7Pl544YW46aabavu9vb0REbFu3brYvn173HfffTE6Ohrf+ta34uTJk3HjjTfGwMBAzJw5s3FTAwBNq6VarVYne4i3K5fLUSwWY2RkxPMfMAVdef/Tkz1C3V760S2TPQJc9Or5+T3p33YBAD5YxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkEp8AACpxAcAkKrh8fH9738/Wlpaxm3XXHNNo28DADSp6RNx0U9/+tPx7LPP/v9Npk/IbQCAJjQhVTB9+vTo6uqaiEsDAE1uQp75ePHFF6O7uzuuuuqq+OY3vxkvv/zyO66tVCpRLpfHbQDA1NXw+Fi8eHFs3749BgYGYuvWrXH06NH44he/GKdOnTrn+v7+/igWi7WtVCo1eiQA4CLSUq1WqxN5g5MnT8YVV1wRjzzySNx5551nna9UKlGpVGr75XI5SqVSjIyMRFtb20SOBkyCK+9/erJHqNtLP7plskeAi165XI5isfi+fn5P+JOgs2fPjo9//ONx+PDhc54vFApRKBQmegwA4CIx4f/Ox+nTp+PIkSMxb968ib4VANAEGh4f3/nOd2JwcDBeeuml+Mtf/hJf/epX45JLLonbb7+90bcCAJpQwz92eeWVV+L222+PEydOxGWXXRY33nhj7Nu3Ly677LJG3woAaEINj4/HH3+80ZcEAKYQv9sFAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVBMWH1u2bIkrr7wyZs6cGYsXL46//vWvE3UrAKCJTEh8/OY3v4ne3t546KGH4m9/+1ssWrQoVq5cGf/85z8n4nYAQBOZkPh45JFH4q677oo77rgjPvWpT8Wjjz4al156afziF7+YiNsBAE1keqMv+MYbb8T+/fujr6+vdmzatGmxfPny2Lt371nrK5VKVCqV2v7IyEhERJTL5UaPBlwExiqvTfYIdfP/I3hvb/09qVar77m24fHx73//O958883o7Owcd7yzszP+8Y9/nLW+v78/Nm3adNbxUqnU6NEAzktx82RPAM3j1KlTUSwW33VNw+OjXn19fdHb21vbHxsbi//85z8xZ86caGlpmcTJgEYrl8tRKpXi2LFj0dbWNtnjAA1UrVbj1KlT0d3d/Z5rGx4fc+fOjUsuuSSGh4fHHR8eHo6urq6z1hcKhSgUCuOOzZ49u9FjAReRtrY28QFT0Hu94/GWhj9wOmPGjLjuuuti165dtWNjY2Oxa9euWLJkSaNvBwA0mQn52KW3tzfWrVsXn/vc5+Lzn/98bN68OUZHR+OOO+6YiNsBAE1kQuLj61//evzrX/+KBx98MIaGhuKzn/1sDAwMnPUQKvDBUigU4qGHHjrro1bgg6Wl+n6+EwMA0CB+twsAkEp8AACpxAcAkEp8AACpxAeQav369bFmzZrJHgOYROIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEglPgCAVOIDAEjVUq1Wq5M9BADwweGdDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFKJDwAglfgAAFL9HxXGoosU7nOhAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -530,7 +528,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAcIklEQVR4nO3df4zU9Z348dcAt6P0dpcuCrubroBe/XEnUNRzj57ngXCFxdAzcr1TMQctB7aHNGXTqNuzKuaS3VbPkvY4uUtUrimUXhOLPUy4CBZo44qK2XA2HhECimEXWwk7ssSVH/P94+J8bwpo1844710ej+ST7Hw+n/nMaxrGffYzn9nJ5PP5fAAAJGRYpQcAAPhNAgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkjKj0AB/FqVOn4uDBg1FdXR2ZTKbS4wAAv4V8Ph/vvPNONDY2xrBhH3yOZFAGysGDB6OpqanSYwAAH8GBAwfiU5/61AfuMygDpbq6OiL+9wnW1NRUeBoA4LeRy+Wiqamp8Hv8gwzKQHn/bZ2amhqBAgCDzG9zeYaLZAGA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5Iyo9QIrG3/N0pUcYsP0dN1Z6BAAoGWdQAIDkCBQAIDkCBQBIjkABAJIjUACA5Aw4ULZv3x5z586NxsbGyGQysWHDhqLtmUzmjMtDDz1U2Gf8+PGnbe/o6PidnwwAMDQMOFD6+vpi8uTJsWrVqjNu7+7uLloef/zxyGQyMW/evKL9HnzwwaL9li1b9tGeAQAw5Az476C0tLRES0vLWbfX19cX3X7qqadi+vTpcfHFFxetr66uPm1fAICIMl+DcujQoXj66adj0aJFp23r6OiI0aNHx5QpU+Khhx6KEydOnPU4/f39kcvlihYAYOgq61+S/fd///eorq6Om2++uWj9V7/61bjqqquirq4unnvuuWhra4vu7u545JFHznic9vb2WLFiRTlHBQASUtZAefzxx2P+/Plx3nnnFa1vbW0t/Dxp0qSoqqqKO+64I9rb2yObzZ52nLa2tqL75HK5aGpqKt/gAEBFlS1Qfv7zn8fu3bvjRz/60Yfu29zcHCdOnIj9+/fHZZdddtr2bDZ7xnABAIamsl2D8thjj8XVV18dkydP/tB9u7q6YtiwYTFmzJhyjQMADCIDPoNy9OjR2LNnT+H2vn37oqurK+rq6uKiiy6KiP99C+bHP/5x/NM//dNp9+/s7IwdO3bE9OnTo7q6Ojo7O2P58uVx++23xyc/+cnf4akAAEPFgAPlpZdeiunTpxduv39tyIIFC2LNmjUREbF+/frI5/Nx6623nnb/bDYb69evjwceeCD6+/tjwoQJsXz58qJrTACAc1smn8/nKz3EQOVyuaitrY3e3t6oqakp+fHH3/N0yY9Zbvs7bqz0CADwgQby+9t38QAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBhwo27dvj7lz50ZjY2NkMpnYsGFD0faFCxdGJpMpWmbPnl20z+HDh2P+/PlRU1MTo0aNikWLFsXRo0d/pycCAAwdAw6Uvr6+mDx5cqxateqs+8yePTu6u7sLyw9/+MOi7fPnz49f/vKX8cwzz8TGjRtj+/btsWTJkoFPDwAMSSMGeoeWlpZoaWn5wH2y2WzU19efcdurr74amzZtihdffDGuueaaiIj43ve+F3PmzImHH344GhsbBzoSADDElOUalK1bt8aYMWPisssui6985Svx9ttvF7Z1dnbGqFGjCnESETFz5swYNmxY7Nix44zH6+/vj1wuV7QAAENXyQNl9uzZ8f3vfz+2bNkS3/rWt2Lbtm3R0tISJ0+ejIiInp6eGDNmTNF9RowYEXV1ddHT03PGY7a3t0dtbW1haWpqKvXYAEBCBvwWz4e55ZZbCj9PnDgxJk2aFJdcckls3bo1ZsyY8ZGO2dbWFq2trYXbuVxOpADAEFb2jxlffPHFccEFF8SePXsiIqK+vj7eeuuton1OnDgRhw8fPut1K9lsNmpqaooWAGDoKnugvPnmm/H2229HQ0NDRERMnTo1jhw5Ejt37izs8+yzz8apU6eiubm53OMAAIPAgN/iOXr0aOFsSETEvn37oqurK+rq6qKuri5WrFgR8+bNi/r6+ti7d2/cdddd8Qd/8Acxa9asiIi44oorYvbs2bF48eJYvXp1HD9+PO6888645ZZbfIIHAIiIj3AG5aWXXoopU6bElClTIiKitbU1pkyZEvfdd18MHz48du3aFZ///Ofj0ksvjUWLFsXVV18dP//5zyObzRaOsXbt2rj88stjxowZMWfOnLjuuuvi3/7t30r3rACAQW3AZ1CmTZsW+Xz+rNv/67/+60OPUVdXF+vWrRvoQwMA5wjfxQMAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJGXCgbN++PebOnRuNjY2RyWRiw4YNhW3Hjx+Pu+++OyZOnBif+MQnorGxMf72b/82Dh48WHSM8ePHRyaTKVo6Ojp+5ycDAAwNAw6Uvr6+mDx5cqxateq0bceOHYuXX345vvnNb8bLL78cTz75ZOzevTs+//nPn7bvgw8+GN3d3YVl2bJlH+0ZAABDzoiB3qGlpSVaWlrOuK22tjaeeeaZonX//M//HNdee2288cYbcdFFFxXWV1dXR319/UAfHgA4B5T9GpTe3t7IZDIxatSoovUdHR0xevTomDJlSjz00ENx4sSJsx6jv78/crlc0QIADF0DPoMyEO+++27cfffdceutt0ZNTU1h/Ve/+tW46qqroq6uLp577rloa2uL7u7ueOSRR854nPb29lixYkU5RwUAElK2QDl+/Hj89V//deTz+Xj00UeLtrW2thZ+njRpUlRVVcUdd9wR7e3tkc1mTztWW1tb0X1yuVw0NTWVa3QAoMLKEijvx8nrr78ezz77bNHZkzNpbm6OEydOxP79++Oyyy47bXs2mz1juAAAQ1PJA+X9OHnttdfiZz/7WYwePfpD79PV1RXDhg2LMWPGlHocAGAQGnCgHD16NPbs2VO4vW/fvujq6oq6urpoaGiIv/qrv4qXX345Nm7cGCdPnoyenp6IiKirq4uqqqro7OyMHTt2xPTp06O6ujo6Oztj+fLlcfvtt8cnP/nJ0j0zAGDQGnCgvPTSSzF9+vTC7fevDVmwYEE88MAD8dOf/jQiIj7zmc8U3e9nP/tZTJs2LbLZbKxfvz4eeOCB6O/vjwkTJsTy5cuLrjEBAM5tAw6UadOmRT6fP+v2D9oWEXHVVVfF888/P9CHBQDOIb6LBwBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIzotIDAMBQNv6epys9wkeyv+PGij6+MygAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGfAgbJ9+/aYO3duNDY2RiaTiQ0bNhRtz+fzcd9990VDQ0Ocf/75MXPmzHjttdeK9jl8+HDMnz8/ampqYtSoUbFo0aI4evTo7/REAIChY8CB0tfXF5MnT45Vq1adcfu3v/3t+O53vxurV6+OHTt2xCc+8YmYNWtWvPvuu4V95s+fH7/85S/jmWeeiY0bN8b27dtjyZIlH/1ZAABDyoC/zbilpSVaWlrOuC2fz8fKlSvj3nvvjb/8y7+MiIjvf//7MXbs2NiwYUPccsst8eqrr8amTZvixRdfjGuuuSYiIr73ve/FnDlz4uGHH47Gxsbf4ekAAENBSa9B2bdvX/T09MTMmTML62pra6O5uTk6OzsjIqKzszNGjRpViJOIiJkzZ8awYcNix44dZzxuf39/5HK5ogUAGLpKGig9PT0RETF27Nii9WPHji1s6+npiTFjxhRtHzFiRNTV1RX2+U3t7e1RW1tbWJqamko5NgCQmEHxKZ62trbo7e0tLAcOHKj0SABAGZU0UOrr6yMi4tChQ0XrDx06VNhWX18fb731VtH2EydOxOHDhwv7/KZsNhs1NTVFCwAwdJU0UCZMmBD19fWxZcuWwrpcLhc7duyIqVOnRkTE1KlT48iRI7Fz587CPs8++2ycOnUqmpubSzkOADBIDfhTPEePHo09e/YUbu/bty+6urqirq4uLrroovja174W//iP/xif/vSnY8KECfHNb34zGhsb46abboqIiCuuuCJmz54dixcvjtWrV8fx48fjzjvvjFtuucUneACAiPgIgfLSSy/F9OnTC7dbW1sjImLBggWxZs2auOuuu6Kvry+WLFkSR44cieuuuy42bdoU5513XuE+a9eujTvvvDNmzJgRw4YNi3nz5sV3v/vdEjwdAGAoyOTz+XylhxioXC4XtbW10dvbW5brUcbf83TJj1lu+zturPQIAJzBYPydElGe3ysD+f09KD7FAwCcWwQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAckoeKOPHj49MJnPasnTp0oiImDZt2mnbvvzlL5d6DABgEBtR6gO++OKLcfLkycLtV155Jf7iL/4ivvCFLxTWLV68OB588MHC7ZEjR5Z6DABgECt5oFx44YVFtzs6OuKSSy6JP//zPy+sGzlyZNTX15f6oQGAIaKs16C899578YMf/CC+9KUvRSaTKaxfu3ZtXHDBBXHllVdGW1tbHDt2rJxjAACDTMnPoPxfGzZsiCNHjsTChQsL62677bYYN25cNDY2xq5du+Luu++O3bt3x5NPPnnW4/T390d/f3/hdi6XK+fYAECFlTVQHnvssWhpaYnGxsbCuiVLlhR+njhxYjQ0NMSMGTNi7969cckll5zxOO3t7bFixYpyjgoAJKRsb/G8/vrrsXnz5vi7v/u7D9yvubk5IiL27Nlz1n3a2tqit7e3sBw4cKCkswIAaSnbGZQnnngixowZEzfeeOMH7tfV1RUREQ0NDWfdJ5vNRjabLeV4AEDCyhIop06diieeeCIWLFgQI0b8/4fYu3dvrFu3LubMmROjR4+OXbt2xfLly+P666+PSZMmlWMUAGAQKkugbN68Od5444340pe+VLS+qqoqNm/eHCtXroy+vr5oamqKefPmxb333luOMQCAQaosgfK5z30u8vn8aeubmppi27Zt5XhIAGAI8V08AEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkJySB8oDDzwQmUymaLn88ssL2999991YunRpjB49On7/938/5s2bF4cOHSr1GADAIFaWMyh/9Ed/FN3d3YXlF7/4RWHb8uXL4z//8z/jxz/+cWzbti0OHjwYN998cznGAAAGqRFlOeiIEVFfX3/a+t7e3njsscdi3bp1ccMNN0RExBNPPBFXXHFFPP/88/Enf/In5RgHABhkynIG5bXXXovGxsa4+OKLY/78+fHGG29ERMTOnTvj+PHjMXPmzMK+l19+eVx00UXR2dlZjlEAgEGo5GdQmpubY82aNXHZZZdFd3d3rFixIv7sz/4sXnnllejp6YmqqqoYNWpU0X3Gjh0bPT09Zz1mf39/9Pf3F27ncrlSjw0AJKTkgdLS0lL4edKkSdHc3Bzjxo2L//iP/4jzzz//Ix2zvb09VqxYUaoRAYDElf1jxqNGjYpLL7009uzZE/X19fHee+/FkSNHivY5dOjQGa9ZeV9bW1v09vYWlgMHDpR5agCgksoeKEePHo29e/dGQ0NDXH311fF7v/d7sWXLlsL23bt3xxtvvBFTp0496zGy2WzU1NQULQDA0FXyt3i+/vWvx9y5c2PcuHFx8ODBuP/++2P48OFx6623Rm1tbSxatChaW1ujrq4uampqYtmyZTF16lSf4AEACkoeKG+++Wbceuut8fbbb8eFF14Y1113XTz//PNx4YUXRkTEd77znRg2bFjMmzcv+vv7Y9asWfEv//IvpR4DABjESh4o69ev/8Dt5513XqxatSpWrVpV6ocGAIYI38UDACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGdEpQcA+E3j73m60iMM2P6OGys9AgwpzqAAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQK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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAcIklEQVR4nO3df4zU9Z348dcAt6P0dpcuCrubroBe/XEnUNRzj57ngXCFxdAzcr1TMQctB7aHNGXTqNuzKuaS3VbPkvY4uUtUrimUXhOLPUy4CBZo44qK2XA2HhECimEXWwk7ssSVH/P94+J8bwpo1844710ej+ST7Hw+n/nMaxrGffYzn9nJ5PP5fAAAJGRYpQcAAPhNAgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkjKj0AB/FqVOn4uDBg1FdXR2ZTKbS4wAAv4V8Ph/vvPNONDY2xrBhH3yOZFAGysGDB6OpqanSYwAAH8GBAwfiU5/61AfuMygDpbq6OiL+9wnW1NRUeBoA4LeRy+Wiqamp8Hv8gwzKQHn/bZ2amhqBAgCDzG9zeYaLZAGA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5Iyo9QIrG3/N0pUcYsP0dN1Z6BAAoGWdQAIDkCBQAIDkCBQBIjkABAJIjUACA5Aw4ULZv3x5z586NxsbGyGQysWHDhqLtmUzmjMtDDz1U2Gf8+PGnbe/o6PidnwwAMDQMOFD6+vpi8uTJsWrVqjNu7+7uLloef/zxyGQyMW/evKL9HnzwwaL9li1b9tGeAQAw5Az476C0tLRES0vLWbfX19cX3X7qqadi+vTpcfHFFxetr66uPm1fAICIMl+DcujQoXj66adj0aJFp23r6OiI0aNHx5QpU+Khhx6KEydOnPU4/f39kcvlihYAYOgq61+S/fd///eorq6Om2++uWj9V7/61bjqqquirq4unnvuuWhra4vu7u545JFHznic9vb2WLFiRTlHBQASUtZAefzxx2P+/Plx3nnnFa1vbW0t/Dxp0qSoqqqKO+64I9rb2yObzZ52nLa2tqL75HK5aGpqKt/gAEBFlS1Qfv7zn8fu3bvjRz/60Yfu29zcHCdOnIj9+/fHZZdddtr2bDZ7xnABAIamsl2D8thjj8XVV18dkydP/tB9u7q6YtiwYTFmzJhyjQMADCIDPoNy9OjR2LNnT+H2vn37oqurK+rq6uKiiy6KiP99C+bHP/5x/NM//dNp9+/s7IwdO3bE9OnTo7q6Ojo7O2P58uVx++23xyc/+cnf4akAAEPFgAPlpZdeiunTpxduv39tyIIFC2LNmjUREbF+/frI5/Nx6623nnb/bDYb69evjwceeCD6+/tjwoQJsXz58qJrTACAc1smn8/nKz3EQOVyuaitrY3e3t6oqakp+fHH3/N0yY9Zbvs7bqz0CADwgQby+9t38QAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBhwo27dvj7lz50ZjY2NkMpnYsGFD0faFCxdGJpMpWmbPnl20z+HDh2P+/PlRU1MTo0aNikWLFsXRo0d/pycCAAwdAw6Uvr6+mDx5cqxateqs+8yePTu6u7sLyw9/+MOi7fPnz49f/vKX8cwzz8TGjRtj+/btsWTJkoFPDwAMSSMGeoeWlpZoaWn5wH2y2WzU19efcdurr74amzZtihdffDGuueaaiIj43ve+F3PmzImHH344GhsbBzoSADDElOUalK1bt8aYMWPisssui6985Svx9ttvF7Z1dnbGqFGjCnESETFz5swYNmxY7Nix44zH6+/vj1wuV7QAAENXyQNl9uzZ8f3vfz+2bNkS3/rWt2Lbtm3R0tISJ0+ejIiInp6eGDNmTNF9RowYEXV1ddHT03PGY7a3t0dtbW1haWpqKvXYAEBCBvwWz4e55ZZbCj9PnDgxJk2aFJdcckls3bo1ZsyY8ZGO2dbWFq2trYXbuVxOpADAEFb2jxlffPHFccEFF8SePXsiIqK+vj7eeuuton1OnDgRhw8fPut1K9lsNmpqaooWAGDoKnugvPnmm/H2229HQ0NDRERMnTo1jhw5Ejt37izs8+yzz8apU6eiubm53OMAAIPAgN/iOXr0aOFsSETEvn37oqurK+rq6qKuri5WrFgR8+bNi/r6+ti7d2/cdddd8Qd/8Acxa9asiIi44oorYvbs2bF48eJYvXp1HD9+PO6888645ZZbfIIHAIiIj3AG5aWXXoopU6bElClTIiKitbU1pkyZEvfdd18MHz48du3aFZ///Ofj0ksvjUWLFsXVV18dP//5zyObzRaOsXbt2rj88stjxowZMWfOnLjuuuvi3/7t30r3rACAQW3AZ1CmTZsW+Xz+rNv/67/+60OPUVdXF+vWrRvoQwMA5wjfxQMAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJGXCgbN++PebOnRuNjY2RyWRiw4YNhW3Hjx+Pu+++OyZOnBif+MQnorGxMf72b/82Dh48WHSM8ePHRyaTKVo6Ojp+5ycDAAwNAw6Uvr6+mDx5cqxateq0bceOHYuXX345vvnNb8bLL78cTz75ZOzevTs+//nPn7bvgw8+GN3d3YVl2bJlH+0ZAABDzoiB3qGlpSVaWlrOuK22tjaeeeaZonX//M//HNdee2288cYbcdFFFxXWV1dXR319/UAfHgA4B5T9GpTe3t7IZDIxatSoovUdHR0xevTomDJlSjz00ENx4sSJsx6jv78/crlc0QIADF0DPoMyEO+++27cfffdceutt0ZNTU1h/Ve/+tW46qqroq6uLp577rloa2uL7u7ueOSRR854nPb29lixYkU5RwUAElK2QDl+/Hj89V//deTz+Xj00UeLtrW2thZ+njRpUlRVVcUdd9wR7e3tkc1mTztWW1tb0X1yuVw0NTWVa3QAoMLKEijvx8nrr78ezz77bNHZkzNpbm6OEydOxP79++Oyyy47bXs2mz1juAAAQ1PJA+X9OHnttdfiZz/7WYwePfpD79PV1RXDhg2LMWPGlHocAGAQGnCgHD16NPbs2VO4vW/fvujq6oq6urpoaGiIv/qrv4qXX345Nm7cGCdPnoyenp6IiKirq4uqqqro7OyMHTt2xPTp06O6ujo6Oztj+fLlcfvtt8cnP/nJ0j0zAGDQGnCgvPTSSzF9+vTC7fevDVmwYEE88MAD8dOf/jQiIj7zmc8U3e9nP/tZTJs2LbLZbKxfvz4eeOCB6O/vjwkTJsTy5cuLrjEBAM5tAw6UadOmRT6fP+v2D9oWEXHVVVfF888/P9CHBQDOIb6LBwBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIjUACA5AgUACA5AgUASI5AAQCSI1AAgOQIFAAgOQIFAEiOQAEAkiNQAIDkCBQAIDkCBQBIjkABAJIzotIDAMBQNv6epys9wkeyv+PGij6+MygAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGfAgbJ9+/aYO3duNDY2RiaTiQ0bNhRtz+fzcd9990VDQ0Ocf/75MXPmzHjttdeK9jl8+HDMnz8/ampqYtSoUbFo0aI4evTo7/REAIChY8CB0tfXF5MnT45Vq1adcfu3v/3t+O53vxurV6+OHTt2xCc+8YmYNWtWvPvuu4V95s+fH7/85S/jmWeeiY0bN8b27dtjyZIlH/1ZAABDyoC/zbilpSVaWlrOuC2fz8fKlSvj3nvvjb/8y7+MiIjvf//7MXbs2NiwYUPccsst8eqrr8amTZvixRdfjGuuuSYiIr73ve/FnDlz4uGHH47Gxsbf4ekAAENBSa9B2bdvX/T09MTMmTML62pra6O5uTk6OzsjIqKzszNGjRpViJOIiJkzZ8awYcNix44dZzxuf39/5HK5ogUAGLpKGig9PT0RETF27Nii9WPHji1s6+npiTFjxhRtHzFiRNTV1RX2+U3t7e1RW1tbWJqamko5NgCQmEHxKZ62trbo7e0tLAcOHKj0SABAGZU0UOrr6yMi4tChQ0XrDx06VNhWX18fb731VtH2EydOxOHDhwv7/KZsNhs1NTVFCwAwdJU0UCZMmBD19fWxZcuWwrpcLhc7duyIqVOnRkTE1KlT48iRI7Fz587CPs8++2ycOnUqmpubSzkOADBIDfhTPEePHo09e/YUbu/bty+6urqirq4uLrroovja174W//iP/xif/vSnY8KECfHNb34zGhsb46abboqIiCuuuCJmz54dixcvjtWrV8fx48fjzjvvjFtuucUneACAiPgIgfLSSy/F9OnTC7dbW1sjImLBggWxZs2auOuuu6Kvry+WLFkSR44cieuuuy42bdoU5513XuE+a9eujTvvvDNmzJgRw4YNi3nz5sV3v/vdEjwdAGAoyOTz+XylhxioXC4XtbW10dvbW5brUcbf83TJj1lu+zturPQIAJzBYPydElGe3ysD+f09KD7FAwCcWwQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAckoeKOPHj49MJnPasnTp0oiImDZt2mnbvvzlL5d6DABgEBtR6gO++OKLcfLkycLtV155Jf7iL/4ivvCFLxTWLV68OB588MHC7ZEjR5Z6DABgECt5oFx44YVFtzs6OuKSSy6JP//zPy+sGzlyZNTX15f6oQGAIaKs16C899578YMf/CC+9KUvRSaTKaxfu3ZtXHDBBXHllVdGW1tbHDt2rJxjAACDTMnPoPxfGzZsiCNHjsTChQsL62677bYYN25cNDY2xq5du+Luu++O3bt3x5NPPnnW4/T390d/f3/hdi6XK+fYAECFlTVQHnvssWhpaYnGxsbCuiVLlhR+njhxYjQ0NMSMGTNi7969cckll5zxOO3t7bFixYpyjgoAJKRsb/G8/vrrsXnz5vi7v/u7D9yvubk5IiL27Nlz1n3a2tqit7e3sBw4cKCkswIAaSnbGZQnnngixowZEzfeeOMH7tfV1RUREQ0NDWfdJ5vNRjabLeV4AEDCyhIop06diieeeCIWLFgQI0b8/4fYu3dvrFu3LubMmROjR4+OXbt2xfLly+P666+PSZMmlWMUAGAQKkugbN68Od5444340pe+VLS+qqoqNm/eHCtXroy+vr5oamqKefPmxb333luOMQCAQaosgfK5z30u8vn8aeubmppi27Zt5XhIAGAI8V08AEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkJySB8oDDzwQmUymaLn88ssL2999991YunRpjB49On7/938/5s2bF4cOHSr1GADAIFaWMyh/9Ed/FN3d3YXlF7/4RWHb8uXL4z//8z/jxz/+cWzbti0OHjwYN998cznGAAAGqRFlOeiIEVFfX3/a+t7e3njsscdi3bp1ccMNN0RExBNPPBFXXHFFPP/88/Enf/In5RgHABhkynIG5bXXXovGxsa4+OKLY/78+fHGG29ERMTOnTvj+PHjMXPmzMK+l19+eVx00UXR2dlZjlEAgEGo5GdQmpubY82aNXHZZZdFd3d3rFixIv7sz/4sXnnllejp6YmqqqoYNWpU0X3Gjh0bPT09Zz1mf39/9Pf3F27ncrlSjw0AJKTkgdLS0lL4edKkSdHc3Bzjxo2L//iP/4jzzz//Ix2zvb09VqxYUaoRAYDElf1jxqNGjYpLL7009uzZE/X19fHee+/FkSNHivY5dOjQGa9ZeV9bW1v09vYWlgMHDpR5agCgksoeKEePHo29e/dGQ0NDXH311fF7v/d7sWXLlsL23bt3xxtvvBFTp0496zGy2WzU1NQULQDA0FXyt3i+/vWvx9y5c2PcuHFx8ODBuP/++2P48OFx6623Rm1tbSxatChaW1ujrq4uampqYtmyZTF16lSf4AEACkoeKG+++Wbceuut8fbbb8eFF14Y1113XTz//PNx4YUXRkTEd77znRg2bFjMmzcv+vv7Y9asWfEv//IvpR4DABjESh4o69ev/8Dt5513XqxatSpWrVpV6ocGAIYI38UDACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQKAJAcgQIAJGdEpQcA+E3j73m60iMM2P6OGys9AgwpzqAAAMkRKABAcgQKAJAcgQIAJEegAADJESgAQHIECgCQHIECACRHoAAAyREoAEByBAoAkByBAgAkR6AAAMkRKABAcgQK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", "text/plain": [ "
" ] @@ -551,7 +549,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAk1ElEQVR4nO3df2zU9eHH8Vd/0CsU7mqZvaOhlM6xQRVlg1lO3b4KHRU7I6Fxw1QssxGHLRt0gnaDiqAWGwYMVqhbupZFCBuZ4qysUmqEbBwF69ywMOY2tHV41znWO8BwLe19/1j4bCegO2i9d+vzkXwS+nm/P/d5f5abPPPp57iYUCgUEgAAgEFio70AAACADyNQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABgnPtoLuBy9vb06ceKERowYoZiYmGgvBwAA/A9CoZBOnTqltLQ0xcZ+9D2SARkoJ06cUHp6erSXAQAALkN7e7tGjx79kXMGZKCMGDFC0r8v0G63R3k1AADgfxEIBJSenm79Pf5RBmSgnP+1jt1uJ1AAABhg/pfHM3hIFgAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYJyIAqWnp0fLly9XZmamhg4dqmuuuUarVq1SKBSy5oRCIZWXl2vUqFEaOnSocnJy9NZbb4W9zsmTJ1VQUCC73a7k5GQVFRXp9OnTfXNFAABgwIsoUJ5++mlt3rxZP/7xj3X06FE9/fTTqqys1MaNG605lZWV2rBhg6qrq9Xc3KykpCTl5ubq7Nmz1pyCggK1traqsbFR9fX12rdvn+bPn993VwUAAAa0mNB/3/74GF//+tfldDpVU1Nj7cvPz9fQoUP17LPPKhQKKS0tTd/73vf08MMPS5L8fr+cTqfq6uo0Z84cHT16VFlZWTp06JCmTJkiSWpoaNAdd9yhd999V2lpaR+7jkAgIIfDIb/fL7vdHuk1f6yxj77U56/Z395enRftJQAA8JEi+fs7ojsoN910k5qamvTnP/9ZkvSHP/xBv/3tbzVz5kxJ0vHjx+X1epWTk2Md43A4lJ2dLY/HI0nyeDxKTk624kSScnJyFBsbq+bm5oueNxgMKhAIhG0AAGDwio9k8qOPPqpAIKDx48crLi5OPT09evLJJ1VQUCBJ8nq9kiSn0xl2nNPptMa8Xq9SU1PDFxEfr5SUFGvOh1VUVOjxxx+PZKkAAGAAi+gOyi9/+Utt3bpV27Zt0+uvv64tW7ZozZo12rJlS3+tT5JUVlYmv99vbe3t7f16PgAAEF0R3UFZsmSJHn30Uc2ZM0eSNHHiRL3zzjuqqKhQYWGhXC6XJMnn82nUqFHWcT6fT5MmTZIkuVwudXR0hL3uuXPndPLkSev4D7PZbLLZbJEsFQAADGAR3UH54IMPFBsbfkhcXJx6e3slSZmZmXK5XGpqarLGA4GAmpub5Xa7JUlut1udnZ1qaWmx5rzyyivq7e1Vdnb2ZV8IAAAYPCK6g3LnnXfqySef1JgxY3Tttdfq97//vdauXav7779fkhQTE6NFixbpiSee0Lhx45SZmanly5crLS1Ns2bNkiRNmDBBt99+ux544AFVV1eru7tbJSUlmjNnzv/0CR4AADD4RRQoGzdu1PLly/XQQw+po6NDaWlpevDBB1VeXm7NWbp0qc6cOaP58+ers7NTt9xyixoaGpSYmGjN2bp1q0pKSjR9+nTFxsYqPz9fGzZs6LurAgAAA1pE/w6KKfh3UC7Ev4MCADBdv/07KAAAAJ8EAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxIvo2YwDAxfElo0Df4g4KAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgRBcrYsWMVExNzwVZcXCxJOnv2rIqLizVy5EgNHz5c+fn58vl8Ya/R1tamvLw8DRs2TKmpqVqyZInOnTvXd1cEAAAGvIgC5dChQ3rvvfesrbGxUZJ09913S5IWL16sF198UTt27NDevXt14sQJzZ492zq+p6dHeXl56urq0v79+7VlyxbV1dWpvLy8Dy8JAAAMdBEFytVXXy2Xy2Vt9fX1uuaaa/R///d/8vv9qqmp0dq1azVt2jRNnjxZtbW12r9/vw4cOCBJ2r17t44cOaJnn31WkyZN0syZM7Vq1SpVVVWpq6urXy4QAAAMPJf9DEpXV5eeffZZ3X///YqJiVFLS4u6u7uVk5NjzRk/frzGjBkjj8cjSfJ4PJo4caKcTqc1Jzc3V4FAQK2trZc8VzAYVCAQCNsAAMDgddmBsnPnTnV2dmrevHmSJK/Xq4SEBCUnJ4fNczqd8nq91pz/jpPz4+fHLqWiokIOh8Pa0tPTL3fZAABgALjsQKmpqdHMmTOVlpbWl+u5qLKyMvn9fmtrb2/v93MCAIDoib+cg9555x3t2bNHzz33nLXP5XKpq6tLnZ2dYXdRfD6fXC6XNefgwYNhr3X+Uz7n51yMzWaTzWa7nKUCAIAB6LLuoNTW1io1NVV5eXnWvsmTJ2vIkCFqamqy9h07dkxtbW1yu92SJLfbrcOHD6ujo8Oa09jYKLvdrqysrMu9BgAAMMhEfAelt7dXtbW1KiwsVHz8fw53OBwqKipSaWmpUlJSZLfbtXDhQrndbk2dOlWSNGPGDGVlZWnu3LmqrKyU1+vVsmXLVFxczB0SAABgiThQ9uzZo7a2Nt1///0XjK1bt06xsbHKz89XMBhUbm6uNm3aZI3HxcWpvr5eCxYskNvtVlJSkgoLC7Vy5coruwoAADCoRBwoM2bMUCgUuuhYYmKiqqqqVFVVdcnjMzIytGvXrkhPCwAAPkX4Lh4AAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcSIOlL///e+69957NXLkSA0dOlQTJ07Ua6+9Zo2HQiGVl5dr1KhRGjp0qHJycvTWW2+FvcbJkydVUFAgu92u5ORkFRUV6fTp01d+NQAAYFCIKFD+9a9/6eabb9aQIUP0m9/8RkeOHNEPf/hDXXXVVdacyspKbdiwQdXV1WpublZSUpJyc3N19uxZa05BQYFaW1vV2Nio+vp67du3T/Pnz++7qwIAAANafCSTn376aaWnp6u2ttbal5mZaf05FApp/fr1WrZsme666y5J0s9//nM5nU7t3LlTc+bM0dGjR9XQ0KBDhw5pypQpkqSNGzfqjjvu0Jo1a5SWltYX1wUAAAawiO6g/PrXv9aUKVN09913KzU1VV/84hf105/+1Bo/fvy4vF6vcnJyrH0Oh0PZ2dnyeDySJI/Ho+TkZCtOJCknJ0exsbFqbm6+0usBAACDQESB8re//U2bN2/WuHHj9PLLL2vBggX6zne+oy1btkiSvF6vJMnpdIYd53Q6rTGv16vU1NSw8fj4eKWkpFhzPiwYDCoQCIRtAABg8IroVzy9vb2aMmWKnnrqKUnSF7/4Rb355puqrq5WYWFhvyxQkioqKvT444/32+sDAACzRHQHZdSoUcrKygrbN2HCBLW1tUmSXC6XJMnn84XN8fl81pjL5VJHR0fY+Llz53Ty5ElrzoeVlZXJ7/dbW3t7eyTLBgAAA0xEgXLzzTfr2LFjYfv+/Oc/KyMjQ9K/H5h1uVxqamqyxgOBgJqbm+V2uyVJbrdbnZ2damlpsea88sor6u3tVXZ29kXPa7PZZLfbwzYAADB4RfQrnsWLF+umm27SU089pW984xs6ePCgfvKTn+gnP/mJJCkmJkaLFi3SE088oXHjxikzM1PLly9XWlqaZs2aJenfd1xuv/12PfDAA6qurlZ3d7dKSko0Z84cPsEDAAAkRRgoX/7yl/X888+rrKxMK1euVGZmptavX6+CggJrztKlS3XmzBnNnz9fnZ2duuWWW9TQ0KDExERrztatW1VSUqLp06crNjZW+fn52rBhQ99dFQAAGNBiQqFQKNqLiFQgEJDD4ZDf7++XX/eMffSlPn/N/vb26rxoLwH4VOO/G8DHi+Tvb76LBwAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABgnokBZsWKFYmJiwrbx48db42fPnlVxcbFGjhyp4cOHKz8/Xz6fL+w12tralJeXp2HDhik1NVVLlizRuXPn+uZqAADAoBAf6QHXXnut9uzZ858XiP/PSyxevFgvvfSSduzYIYfDoZKSEs2ePVu/+93vJEk9PT3Ky8uTy+XS/v379d577+m+++7TkCFD9NRTT/XB5QAAgMEg4kCJj4+Xy+W6YL/f71dNTY22bdumadOmSZJqa2s1YcIEHThwQFOnTtXu3bt15MgR7dmzR06nU5MmTdKqVav0yCOPaMWKFUpISLjyKwIAAANexM+gvPXWW0pLS9NnP/tZFRQUqK2tTZLU0tKi7u5u5eTkWHPHjx+vMWPGyOPxSJI8Ho8mTpwop9NpzcnNzVUgEFBra+slzxkMBhUIBMI2AAAweEUUKNnZ2aqrq1NDQ4M2b96s48eP6ytf+YpOnTolr9erhIQEJScnhx3jdDrl9XolSV6vNyxOzo+fH7uUiooKORwOa0tPT49k2QAAYICJ6Fc8M2fOtP58/fXXKzs7WxkZGfrlL3+poUOH9vnizisrK1Npaan1cyAQIFIAABjEruhjxsnJyfr85z+vv/zlL3K5XOrq6lJnZ2fYHJ/PZz2z4nK5LvhUz/mfL/Zcy3k2m012uz1sAwAAg9cVBcrp06f117/+VaNGjdLkyZM1ZMgQNTU1WePHjh1TW1ub3G63JMntduvw4cPq6Oiw5jQ2NsputysrK+tKlgIAAAaRiH7F8/DDD+vOO+9URkaGTpw4occee0xxcXG655575HA4VFRUpNLSUqWkpMhut2vhwoVyu92aOnWqJGnGjBnKysrS3LlzVVlZKa/Xq2XLlqm4uFg2m61fLhDoS2MffSnaS4jY26vzor0EAIhYRIHy7rvv6p577tE///lPXX311brlllt04MABXX311ZKkdevWKTY2Vvn5+QoGg8rNzdWmTZus4+Pi4lRfX68FCxbI7XYrKSlJhYWFWrlyZd9eFQAAGNAiCpTt27d/5HhiYqKqqqpUVVV1yTkZGRnatWtXJKcFAACfMnwXDwAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADDOFQXK6tWrFRMTo0WLFln7zp49q+LiYo0cOVLDhw9Xfn6+fD5f2HFtbW3Ky8vTsGHDlJqaqiVLlujcuXNXshQAADCIXHagHDp0SM8884yuv/76sP2LFy/Wiy++qB07dmjv3r06ceKEZs+ebY339PQoLy9PXV1d2r9/v7Zs2aK6ujqVl5df/lUAAIBB5bIC5fTp0yooKNBPf/pTXXXVVdZ+v9+vmpoarV27VtOmTdPkyZNVW1ur/fv368CBA5Kk3bt368iRI3r22Wc1adIkzZw5U6tWrVJVVZW6urr65qoAAMCAdlmBUlxcrLy8POXk5ITtb2lpUXd3d9j+8ePHa8yYMfJ4PJIkj8ejiRMnyul0WnNyc3MVCATU2tp60fMFg0EFAoGwDQAADF7xkR6wfft2vf766zp06NAFY16vVwkJCUpOTg7b73Q65fV6rTn/HSfnx8+PXUxFRYUef/zxSJcKAAAGqIjuoLS3t+u73/2utm7dqsTExP5a0wXKysrk9/utrb29/RM7NwAA+ORFFCgtLS3q6OjQl770JcXHxys+Pl579+7Vhg0bFB8fL6fTqa6uLnV2doYd5/P55HK5JEkul+uCT/Wc//n8nA+z2Wyy2+1hGwAAGLwiCpTp06fr8OHDeuONN6xtypQpKigosP48ZMgQNTU1WcccO3ZMbW1tcrvdkiS3263Dhw+ro6PDmtPY2Ci73a6srKw+uiwAADCQRfQMyogRI3TdddeF7UtKStLIkSOt/UVFRSotLVVKSorsdrsWLlwot9utqVOnSpJmzJihrKwszZ07V5WVlfJ6vVq2bJmKi4tls9n66LIAAMBAFvFDsh9n3bp1io2NVX5+voLBoHJzc7Vp0yZrPC4uTvX19VqwYIHcbreSkpJUWFiolStX9vVSAADAAHXFgfLqq6+G/ZyYmKiqqipVVVVd8piMjAzt2rXrSk8NAAAGKb6LBwAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABgnokDZvHmzrr/+etntdtntdrndbv3mN7+xxs+ePavi4mKNHDlSw4cPV35+vnw+X9hrtLW1KS8vT8OGDVNqaqqWLFmic+fO9c3VAACAQSGiQBk9erRWr16tlpYWvfbaa5o2bZruuusutba2SpIWL16sF198UTt27NDevXt14sQJzZ492zq+p6dHeXl56urq0v79+7VlyxbV1dWpvLy8b68KAAAMaPGRTL7zzjvDfn7yySe1efNmHThwQKNHj1ZNTY22bdumadOmSZJqa2s1YcIEHThwQFOnTtXu3bt15MgR7dmzR06nU5MmTdKqVav0yCOPaMWKFUpISOi7KwMAAAPWZT+D0tPTo+3bt+vMmTNyu91qaWlRd3e3cnJyrDnjx4/XmDFj5PF4JEkej0cTJ06U0+m05uTm5ioQCFh3YS4mGAwqEAiEbQAAYPCKOFAOHz6s4cOHy2az6dvf/raef/55ZWVlyev1KiEhQcnJyWHznU6nvF6vJMnr9YbFyfnx82OXUlFRIYfDYW3p6emRLhsAAAwgEQfKF77wBb3xxhtqbm7WggULVFhYqCNHjvTH2ixlZWXy+/3W1t7e3q/nAwAA0RXRMyiSlJCQoM997nOSpMmTJ+vQoUP60Y9+pG9+85vq6upSZ2dn2F0Un88nl8slSXK5XDp48GDY653/lM/5ORdjs9lks9kiXSoAABigrvjfQent7VUwGNTkyZM1ZMgQNTU1WWPHjh1TW1ub3G63JMntduvw4cPq6Oiw5jQ2NsputysrK+tKlwIAAAaJiO6glJWVaebMmRozZoxOnTqlbdu26dVXX9XLL78sh8OhoqIilZaWKiUlRXa7XQsXLpTb7dbUqVMlSTNmzFBWVpbmzp2ryspKeb1eLVu2TMXFxdwhAQAAlogCpaOjQ/fdd5/ee+89ORwOXX/99Xr55Zf1ta99TZK0bt06xcbGKj8/X8FgULm5udq0aZN1fFxcnOrr67VgwQK53W4lJSWpsLBQK1eu7NurAgAAA1pEgVJTU/OR44mJiaqqqlJVVdUl52RkZGjXrl2RnBYAAHzK8F08AADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADBOfLQXAADAYDb20ZeivYTL8vbqvKienzsoAADAOAQKAAAwTkSBUlFRoS9/+csaMWKEUlNTNWvWLB07dixsztmzZ1VcXKyRI0dq+PDhys/Pl8/nC5vT1tamvLw8DRs2TKmpqVqyZInOnTt35VcDAAAGhYgCZe/evSouLtaBAwfU2Nio7u5uzZgxQ2fOnLHmLF68WC+++KJ27NihvXv36sSJE5o9e7Y13tPTo7y8PHV1dWn//v3asmWL6urqVF5e3ndXBQAABrSIHpJtaGgI+7murk6pqalqaWnRV7/6Vfn9ftXU1Gjbtm2aNm2aJKm2tlYTJkzQgQMHNHXqVO3evVtHjhzRnj175HQ6NWnSJK1atUqPPPKIVqxYoYSEhL67OgAAMCBd0TMofr9fkpSSkiJJamlpUXd3t3Jycqw548eP15gxY+TxeCRJHo9HEydOlNPptObk5uYqEAiotbX1oucJBoMKBAJhGwAAGLwuO1B6e3u1aNEi3XzzzbruuuskSV6vVwkJCUpOTg6b63Q65fV6rTn/HSfnx8+PXUxFRYUcDoe1paenX+6yAQDAAHDZgVJcXKw333xT27dv78v1XFRZWZn8fr+1tbe39/s5AQBA9FzWP9RWUlKi+vp67du3T6NHj7b2u1wudXV1qbOzM+wuis/nk8vlsuYcPHgw7PXOf8rn/JwPs9lsstlsl7NUAAAwAEV0ByUUCqmkpETPP/+8XnnlFWVmZoaNT548WUOGDFFTU5O179ixY2pra5Pb7ZYkud1uHT58WB0dHdacxsZG2e12ZWVlXcm1AACAQSKiOyjFxcXatm2bXnjhBY0YMcJ6ZsThcGjo0KFyOBwqKipSaWmpUlJSZLfbtXDhQrndbk2dOlWSNGPGDGVlZWnu3LmqrKyU1+vVsmXLVFxczF0SAAAgKcJA2bx5syTp1ltvDdtfW1urefPmSZLWrVun2NhY5efnKxgMKjc3V5s2bbLmxsXFqb6+XgsWLJDb7VZSUpIKCwu1cuXKK7sSAAAwaEQUKKFQ6GPnJCYmqqqqSlVVVZeck5GRoV27dkVyagAA8CnCd/EAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjBNxoOzbt0933nmn0tLSFBMTo507d4aNh0IhlZeXa9SoURo6dKhycnL01ltvhc05efKkCgoKZLfblZycrKKiIp0+ffqKLgQAAAweEQfKmTNndMMNN6iqquqi45WVldqwYYOqq6vV3NyspKQk5ebm6uzZs9acgoICtba2qrGxUfX19dq3b5/mz59/+VcBAAAGlfhID5g5c6Zmzpx50bFQKKT169dr2bJluuuuuyRJP//5z+V0OrVz507NmTNHR48eVUNDgw4dOqQpU6ZIkjZu3Kg77rhDa9asUVpa2hVcDgAAGAz69BmU48ePy+v1Kicnx9rncDiUnZ0tj8cjSfJ4PEpOTrbiRJJycnIUGxur5ubmi75uMBhUIBAI2wAAwODVp4Hi9XolSU6nM2y/0+m0xrxer1JTU8PG4+PjlZKSYs35sIqKCjkcDmtLT0/vy2UDAADDDIhP8ZSVlcnv91tbe3t7tJcEAAD6UZ8GisvlkiT5fL6w/T6fzxpzuVzq6OgIGz937pxOnjxpzfkwm80mu90etgEAgMGrTwMlMzNTLpdLTU1N1r5AIKDm5ma53W5JktvtVmdnp1paWqw5r7zyinp7e5Wdnd2XywEAAANUxJ/iOX36tP7yl79YPx8/flxvvPGGUlJSNGbMGC1atEhPPPGExo0bp8zMTC1fvlxpaWmaNWuWJGnChAm6/fbb9cADD6i6ulrd3d0qKSnRnDlz+AQPAACQdBmB8tprr+m2226zfi4tLZUkFRYWqq6uTkuXLtWZM2c0f/58dXZ26pZbblFDQ4MSExOtY7Zu3aqSkhJNnz5dsbGxys/P14YNG/rgcgAAwGAQcaDceuutCoVClxyPiYnRypUrtXLlykvOSUlJ0bZt2yI9NQAA+JQYEJ/iAQAAny4ECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4UQ2UqqoqjR07VomJicrOztbBgwejuRwAAGCIqAXKL37xC5WWluqxxx7T66+/rhtuuEG5ubnq6OiI1pIAAIAhohYoa9eu1QMPPKBvfetbysrKUnV1tYYNG6af/exn0VoSAAAwRHw0TtrV1aWWlhaVlZVZ+2JjY5WTkyOPx3PB/GAwqGAwaP3s9/slSYFAoF/W1xv8oF9etz/11/8WCMd7A5fCewOXMhDfG1L/vD/Ov2YoFPrYuVEJlPfff189PT1yOp1h+51Op/70pz9dML+iokKPP/74BfvT09P7bY0DjWN9tFcAU/HewKXw3sBH6c/3x6lTp+RwOD5yTlQCJVJlZWUqLS21fu7t7dXJkyc1cuRIxcTE9Om5AoGA0tPT1d7eLrvd3qevjU8v3lfoD7yv0F/6670VCoV06tQppaWlfezcqATKZz7zGcXFxcnn84Xt9/l8crlcF8y32Wyy2Wxh+5KTk/tzibLb7fwfHn2O9xX6A+8r9Jf+eG993J2T86LykGxCQoImT56spqYma19vb6+amprkdrujsSQAAGCQqP2Kp7S0VIWFhZoyZYpuvPFGrV+/XmfOnNG3vvWtaC0JAAAYImqB8s1vflP/+Mc/VF5eLq/Xq0mTJqmhoeGCB2c/aTabTY899tgFv1ICrgTvK/QH3lfoLya8t2JC/8tnfQAAAD5BfBcPAAAwDoECAACMQ6AAAADjECgAAMA4BMqHzJs3T7NmzYr2MjAI9PT06KabbtLs2bPD9vv9fqWnp+sHP/hBlFaGgezVV19VTEzMJbfbbrst2kvEABQKhZSTk6Pc3NwLxjZt2qTk5GS9++67n+iaCBSgn8TFxamurk4NDQ3aunWrtX/hwoVKSUnRY489FsXVYaC66aab9N57712wPfPMM4qJidFDDz0U7SViAIqJiVFtba2am5v1zDPPWPuPHz+upUuXauPGjRo9evQnuyY+Zhxu3rx56uzs1M6dO6O9FAwSGzZs0IoVK9Ta2qqDBw/q7rvv1qFDh3TDDTdEe2kYJI4ePars7Gx95zvf0RNPPBHt5WAA27Jli0pKSvTHP/5RY8eO1fTp05WcnKznnnvuE18LgfIhBAr6WigU0rRp0xQXF6fDhw9r4cKFWrZsWbSXhUGis7NTN954o8aPH68XXnihz79AFZ8+s2bNkt/v1+zZs7Vq1Sq1trbq6quv/sTXQaB8CIGC/vCnP/1JEyZM0MSJE/X6668rPn5AfJE4DNfb26uvf/3revvtt9Xc3KwRI0ZEe0kYBDo6OnTttdfq5MmT+tWvfhW15zJ5BgX4BPzsZz/TsGHDdPz48U/8QTMMXt///vfl8Xj0wgsvECfoM6mpqXrwwQc1YcKEqH5ohEAB+tn+/fu1bt061dfX68Ybb1RRUZG4cYkrtX37dq1Zs0bbt2/XuHHjor0cDDLx8fFRv9NLoAD96IMPPtC8efO0YMEC3XbbbaqpqdHBgwdVXV0d7aVhAHvjjTdUVFSk1atXX/RjocBgQKAA/aisrEyhUEirV6+WJI0dO1Zr1qzR0qVL9fbbb0d3cRiQ3n//fc2aNUu33nqr7r33Xnm93rDtH//4R7SXCPQJntQD+snevXtVVVWlV199VcOGDbP2P/jgg3ruuedUVFSkPXv28KkLROSll17SO++8o3feeUejRo26YDwjI4P4xaDAp3gAAIBx+BUPAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOP8PVsBgm/Hso/AAAAAASUVORK5CYII=", + "image/png": "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", "text/plain": [ "
" ] @@ -619,11 +617,10 @@ "source": [ "limit = 20\n", "for i, correction in enumerate(two_qubit_corrections):\n", - " if correction==\"I\":\n", - " print(\n", - " two_qubit_paulis[i]\n", - " )\n", - " if i > limit: break" + " if correction == \"I\":\n", + " print(two_qubit_paulis[i])\n", + " if i > limit:\n", + " break" ] }, { @@ -694,10 +691,8 @@ ], "source": [ "for i, correction in enumerate(two_qubit_corrections):\n", - " if correction==\"X\":\n", - " print(\n", - " two_qubit_paulis[i]\n", - " )" + " if correction == \"X\":\n", + " print(two_qubit_paulis[i])" ] }, { @@ -725,7 +720,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.8" }, "orig_nbformat": 4, "vscode": { diff --git a/examples/ising/ground_state.ipynb b/examples/ising/ground_state.ipynb index 1ef973b5..c5a71142 100644 --- a/examples/ising/ground_state.ipynb +++ b/examples/ising/ground_state.ipynb @@ -1,5 +1,12 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Ground state search for a 1D quantum Ising model" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -97,7 +104,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 10/10 [00:23<00:00, 2.33s/it]\n" + "100%|██████████| 10/10 [00:21<00:00, 2.11s/it]\n" ] }, { @@ -156,7 +163,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 20/20 [08:05<00:00, 24.25s/it]\n" + "100%|██████████| 20/20 [07:11<00:00, 21.58s/it]\n" ] } ], @@ -199,9 +206,9 @@ "outputs": [ { "data": { - "image/png": "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Blaza3/0zTffSJLOnj2rs2fPqkGDBpZ9999/v1q0aKFFixYpLCxMJSUlat++vQoKCi7m4+1tcz5XIoo8AAAA4CpnMplsfmzySnTgwAGNGzdOixYt0urVqzVkyBB98cUXcnFx0ZkzZ5SWlqZFixapZ8+ekqSvvvrK6viOHTvqvffe09mzZ8uczfPw8FBxce1/d9FWrK4JAAAAoN7Iz89Xenq61ef06dMqLi7WE088obi4OA0bNkxLlizRrl279NZbb0mSAgIC1LhxYy1cuFD79+/Xhg0bFB8fb9X3gAEDFBISon79+unrr7/WwYMH9a9//UvJycmSpJYtW+rQoUNKTU3V6dOnlZ+fX+vXXxUUeQAAAADqjcTERIWGhlp9evToob/85S/65Zdf9I9//EOSFBoaqoULF+rll1/Wzp075eLiolWrVmnbtm1q3769xo0bpzfffNOqbw8PD61bt05BQUG655571KFDB73++utydb34WOnDDz+sPn366I477lDTpk31wQcf1Pr1V4XJMAyjrpO42pjNZvn5+Sk7O1u+vr51nQ4AAACuIhcuXNChQ4cUEREhLy+vuk7nqlDRmNdEbcBMHgAAAAA4EYo8AAAAAHAiFHkAAAAA4EQo8gAAAADAiVDkAQAAAIATocgDAAAAACdCkQcAAAAAToQiDwAAAACcCEUeAAAAADgRijwAAAAAcCIUeQAAAADqhaFDh8pkMslkMsnd3V3BwcG66667tHjxYpWUlFjiWrZsKZPJpFWrVpXq44YbbpDJZNLSpUtLxZtMJvn4+KhDhw567733Sh1rGIYWLVqkrl27ytfXVw0bNtQNN9yg5557Tvv376+Ra7YHRR4AAACAeqNPnz46efKkDh8+rP/+97+644479Nxzz+m+++5TUVGRJS48PFxLliyxOvbbb79Venq6GjRoUKrf6dOn6+TJk9qzZ4+eeOIJjRw5Uv/9738t+w3D0OOPP65nn31W99xzj9atW6cffvhB77//vry8vPTqq6/W3EXbyK2uEwAAAACAqvL09FRISIgkqVmzZrrpppt0yy23qFevXlq6dKlGjBghSRo4cKDmzp2ro0ePKjw8XJK0ePFiDRw4UMuXLy/Vb6NGjSz9Tpw4UbNmzdL69et19913S5JWr16tVatW6d///rceeOABy3HXXHONbrnlFhmGUaPXbQtm8gAA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rjWDca05jG3NYFxrBuNaMxjXmpGdna1rrrlGgYGBDuuzXhV5TZs2VdOmTWuk74iICIWEhCgpKclS1JnNZqWkpFhW6OzatauysrK0bds2de7cWZK0YcMGlZSUKCYmpty+PT095enpWardz8+P3yA1wNfXl3GtAYxrzWBcawbjWnMY25rBuNYMxrVmMK41w8XFcculOO3CK0eOHFFqaqqOHDmi4uJipaamKjU11eqddm3bttWaNWskSSaTSWPHjtWrr76qTz/9VLt379bgwYMVFhamfv36SZKuv/569enTRyNHjtTWrVv19ddfa8yYMXrssceqvLImAAAAANSkejWTZ4uEhAQtW7bMsn3jjTdKkjZu3Kjbb79dkpSWlmZZBEWSJkyYoNzcXI0aNUpZWVnq0aOHEhMT5eXlZYlZsWKFxowZo169esnFxUUPP/yw5s2bVzsXBQAAAACVcNoib+nSpVq6dGmFMX9cwcZkMmn69OmaPn16uccEBgZq5cqV1crN09NTU6dOLfMRTtiPca0ZjGvNYFxrBuNacxjbmsG41gzGtWYwrjWjJsbV6V+GDgAAAABXE6f9Th4AAAAAXI0o8gAAAADAiVDkAQAAAIATocirIfPnz1fLli3l5eWlmJgYbd26tdzYRYsWqWfPngoICFBAQIBiY2MrjL+a2TKul1u1apVMJpPldRiwZuu4ZmVl6emnn1ZoaKg8PT113XXXae3atbWUbf1h67i+/fbbatOmjby9vRUeHq5x48bpwoULtZRt/bBlyxbdf//9CgsLk8lk0ieffFLpMZs2bdJNN90kT09PRUZGVroo19XI1nH9+OOPddddd6lp06by9fVV165d9b///a92kq1H7Pn/9ZKvv/5abm5ulnf34nf2jGt+fr5eeukltWjRQp6enmrZsqUWL15c88nWI/aM64oVK9SpUyf5+PgoNDRUTz75pM6cOVPzydYjM2fO1M0336xGjRopKChI/fr1U1paWqXHffjhh2rbtq28vLzUoUMHm/+eRZFXA1avXq34+HhNnTpV27dvV6dOnRQXF6fMzMwy4zdt2qQBAwZo48aNSk5OVnh4uHr37q3jx4/XcuZXNlvH9ZLDhw9r/Pjx6tmzZy1lWr/YOq4FBQW66667dPjwYX300UdKS0vTokWL1KxZs1rO/Mpm67iuXLlSkyZN0tSpU7Vv3z69//77Wr16tV588cVazvzKlpubq06dOmn+/PlVij906JDuvfde3XHHHUpNTdXYsWM1YsQICpI/sHVct2zZorvuuktr167Vtm3bdMcdd+j+++/Xjh07ajjT+sXWcb0kKytLgwcPVq9evWoos/rNnnF99NFHlZSUpPfff19paWn64IMP1KZNmxrMsv6xdVy//vprDR48WMOHD9fevXv14YcfauvWrRo5cmQNZ1q/bN68WU8//bS+/fZbrV+/XoWFherdu7dyc3PLPeabb77RgAEDNHz4cO3YsUP9+vVTv379tGfPnqqf2IDDdenSxXj66act28XFxUZYWJgxc+bMKh1fVFRkNGrUyFi2bFlNpVgv2TOuRUVFRrdu3Yz33nvPGDJkiNG3b99ayLR+sXVc//73vxutWrUyCgoKaivFesnWcX366aeNO++806otPj7e6N69e43mWZ9JMtasWVNhzIQJE4wbbrjBqq1///5GXFxcDWZWv1VlXMvSrl07Y9q0aY5PyEnYMq79+/c3Xn75ZWPq1KlGp06dajSv+q4q4/rf//7X8PPzM86cOVM7STmBqozrm2++abRq1cqqbd68eUazZs1qMLP6LzMz05BkbN68udyYRx991Lj33nut2mJiYoz/7//7/6p8HmbyHKygoEDbtm1TbGyspc3FxUWxsbFKTk6uUh95eXkqLCxUYGBgTaVZ79g7rtOnT1dQUJCGDx9eG2nWO/aM66effqquXbvq6aefVnBwsNq3b6/XXntNxcXFtZX2Fc+ece3WrZu2bdtmeaTz4MGDWrt2re65555aydlZJScnW/06SFJcXFyV78eompKSEp07d44/txxgyZIlOnjwoKZOnVrXqTiNTz/9VNHR0Zo1a5aaNWum6667TuPHj9f58+frOrV6rWvXrjp69KjWrl0rwzCUkZGhjz76iD+3KpGdnS1JFd4vHfFnl9O+DL2unD59WsXFxQoODrZqDw4O1o8//lilPiZOnKiwsLBSv7hXM3vG9auvvtL777+v1NTUWsiwfrJnXA8ePKgNGzZo4MCBWrt2rfbv368///nPKiws5C8lv7FnXB9//HGdPn1aPXr0kGEYKioq0lNPPcXjmtWUnp5e5q+D2WzW+fPn5e3tXUeZOZfZs2crJydHjz76aF2nUq/9/PPPmjRpkr788ku5ufFXNEc5ePCgvvrqK3l5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", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, "metadata": {}, @@ -209,9 +216,9 @@ }, { "data": { - "image/png": "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6TTijn1Ed1MxmOC+sG10vHYsPZqFujqeiIiIiIjUQCp5LpCTncmOT6fT7vB7JJoKwQR73ZtR2HMS91x6HSaz2dURRURERESkhlLJu4jyi0v56KdtDFk1gERywQQHzTFkdX+Yjn1vVrkTEREREZFKU8m7CIqKrby/7ij/XrGfU/lW6nu0p6NHChnxE+jU/1Zi3dxcHVFERERERGoJlbwqVFxUwOYvX6XRrrm8V/w4p4wIGtfzwe3Sl2jYuQWN3TX8IiIiIiLiXGoZVaDEWkzS/96g0bbXSeAkAPf5LMO46nmGdG6Ih5velikiIiIiIlVDJc+JbKWlbPp6DpFbXqGbkQpAOiEcbD2GgQPH4unl4+KEIiIiIiJS26nkOYHdbvDN1uM0/WowXe3JAJwikL3NR9Nx8AQSfPxcnFBEREREROoKlbxKMOx2vt+ZxstL97I7NZdxbu1p4HGMXU1uJ27IRLr7Bbo6ooiIiIiI1DEqeQ4w7Ha2rliIz+p/8kHhdey2x+Hv5Y53j3G4JbxAYmCIqyOKiIiIiEgdpZJXAYbdzrafvsTjx+nEle4C4D6Pr+nQ4zru7N2EQB8PFycUEREREZG6TiWvAnbPvIoE85lyV2hY2BJ5Ay2ve5KE+g1cnExEREREROQMlbwKaF2yE6vFg6SwQTQdMpnukY1dHUlERERERKQclbwK2BD8d9oMe46E6GaujiIiIiIiInJOKnkVED9mDgEBAa6OISIiIiIicl5mVwcQERERERER51HJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVU8kRERERERGoRlTwREREREZFaRCVPRERERESkFlHJExERERERqUVqZMl7/fXXiYmJwcvLi4SEBNatW/en63/yySe0atUKLy8v2rdvz6JFiy5SUhERERERkYurxpW8BQsWMGHCBKZMmcKmTZuIi4ujf//+pKenn3P9n3/+mWHDhnHHHXeQlJTEoEGDGDRoENu3b7/IyUVERERERKqeyTAMw9UhKiIhIYGuXbvy2muvAWC324mOjmbs2LFMmjTprPWHDh1Kfn4+X3/9ddmy7t2707FjR2bPnn1Bx8zJySEwMJDs7GwCAgKccyIiIiIiIlLnVUXXqFFX8qxWKxs3bqRv375ly8xmM3379mXNmjXn3GbNmjXl1gfo37//edcXERERERGpydxdHaAiMjIysNlshIeHl1seHh7O7t27z7lNamrqOddPTU0973GKi4spLi4u+zw7Oxs407JFRERERESc5beO4cw3WNaoknexTJ8+nalTp561PDo62gVpRERERESktjt16hSBgYFO2VeNKnmhoaG4ubmRlpZWbnlaWhoRERHn3CYiIqJC6wM89thjTJgwoezzrKwsGjduTEpKitMGXv5fTk4O0dHRHDlyRPc8VgGNb9XTGFctjW/V0xhXLY1v1dL4Vj2NcdXKzs6mUaNGhISEOG2fNarkWSwWunTpwrJlyxg0aBBwZuKVZcuWcf/9959zm8TERJYtW8YDDzxQtmzJkiUkJiae9zienp54enqetTwwMFD/sKtQQECAxrcKaXyrnsa4aml8q57GuGppfKuWxrfqaYyrltnsvOlSalTJA5gwYQKjRo0iPj6ebt26MWvWLPLz87ntttsAGDlyJFFRUUyfPh2A8ePHc+mll/LSSy9x9dVX8/HHH7NhwwbmzJnjytMQERERERGpEjWu5A0dOpSTJ08yefJkUlNT6dixI4sXLy6bXCUlJaVcC+7RowcffvghTz75JI8//jjNmzfniy++oF27dq46BRERERERkSpT40oewP3333/et2euWLHirGU33HADN9xwg8PH8/T0ZMqUKed8C6dUnsa3aml8q57GuGppfKuexrhqaXyrlsa36mmMq1ZVjG+Nexi6iIiIiIiInF+Nehi6iIiIiIiI/DmVPBERERERkVpEJU9ERERERKQWUcn71euvv05MTAxeXl4kJCSwbt268647d+5cevfuTXBwMMHB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I+P76quvGm3atDG8vb2NyMhI45ZbbjGOHj168cPXAOcaW6Dcz61z/a723//+12jRooVhsViMtm3bGt98802Fjmv69eAiIiIiIiJSC9T5e/JERERERERqE5U8ERERERGRWkQlT0REREREpBZRyRMREREREalFVPJERERERERqEZU8ERERERGRWkQlT0REREREpBZRyRMREREREalFVPJERERERERqEZU8ERERERGRWkQlT0REpA657LLLeOCBBxze3jAM7rrrLkJCQjCZTGzevNmhff7VNhe6z4kTJzJo0KAKHVtEpLZzd3UAERFxPpPJ9KevT5kyhaeffvrihBGXueyyy+jYsSOzZs0qW/bZZ5/h4eHh8D4XL17M22+/zYoVK2jSpAmhoaGV3mdlbN68mR49erjk2CIi1ZVKnohILXTixImy/1+wYAGTJ08mOTm5bJmfn99Z21itViwWy0XJ52w1OfvFFhISUqnt9+/fT2RkZLliVdl9VsaWLVu45557XHZ8EZHqSG/XFBGphSIiIso+AgMDMZlM5Zb5+flx2WWXcf/99/PAAw8QGhpK//79gTNXanr16kVQUBD16tXjmmuuYf/+/WX7vuyyyxg3bhyPPPIIISEhREREnHVVcOHChbRv3x5vb2/q1atH3759yc/PZ86cOTRo0AC73V5u/YEDB3L77bcDYLfbmT59OrGxsXh7exMXF8fChQvLrX++7Oc77oXu948uu+wyxo4dywMPPEBwcDDh4eHMnTuX/Px8brvtNvz9/WnWrBnffvtt2TZ/NX4Aubm53HLLLfj6+hIZGcnLL7981tsT/2qc/+p8br31Vn788UdeeeUVTCYTJpOJQ4cOnXUcu93OjBkzaNasGZ6enjRq1Ih//OMf5xyPW2+9lbFjx5KSkoLJZCImJqYs6x/3WZGxzs/PZ+TIkfj5+REZGclLL730J1+V/3f06FEyMjIAuPLKK/Hx8aFly5asXbv2grYXEamtVPJEROqwd955B4vFwurVq5k9ezZw5hfuCRMmsGHDBpYtW4bZbGbw4MHlitk777yDr68va9euZcaMGTzzzDMsWbIEOHMVcdiwYdx+++3s2rWLFStWMGTIEAzD4IYbbuDUqVMsX768bF+ZmZksXryYW265BYDp06fz7rvvMnv2bHbs2MGDDz7I8OHD+fHHH/80+58dtyL7PdcY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", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, "metadata": {}, @@ -219,25 +226,27 @@ } ], "source": [ - "plt.figure(figsize=(9, 4.5))\n", - "plt.plot(transverse_magnetic_field_space, mag_z_exact, label=\"Exact\")\n", - "plt.plot(transverse_magnetic_field_space, mag_z_dmrg, label=\"DMRG\", linestyle=\"dashed\")\n", + "plt.figure(figsize=(5, 4))\n", + "plt.plot(transverse_magnetic_field_space, mag_z_exact, label=\"Exact\", linewidth=3)\n", + "plt.plot(transverse_magnetic_field_space, mag_z_dmrg, label=\"DMRG\", linestyle=\"dashed\", linewidth=3)\n", "plt.xlabel(\"Transverse magnetic field $h$\")\n", "plt.ylabel(\"Longitudinal magnetisation $m_z$\", rotation=90, labelpad=10)\n", "plt.xlim((0.2, 2))\n", "plt.ylim((-1, 1))\n", "plt.legend(fontsize=10)\n", + "plt.grid(True)\n", "plt.tight_layout()\n", "plt.show()\n", "\n", - "plt.figure(figsize=(9, 4.5))\n", - "plt.plot(transverse_magnetic_field_space, mag_x_exact, label=\"Exact\")\n", - "plt.plot(transverse_magnetic_field_space, mag_x_dmrg, label=\"DMRG\", linestyle=\"dashed\")\n", + "plt.figure(figsize=(5, 4))\n", + "plt.plot(transverse_magnetic_field_space, mag_x_exact, label=\"Exact\", linewidth=3)\n", + "plt.plot(transverse_magnetic_field_space, mag_x_dmrg, label=\"DMRG\", linestyle=\"dashed\", linewidth=3)\n", "plt.xlabel(\"Transverse magnetic field $h$\")\n", "plt.ylabel(\"Transverse magnetisation $m_x$\", rotation=90, labelpad=10)\n", "plt.xlim((0.2, 2))\n", "plt.ylim((0, 1))\n", "plt.legend(fontsize=10)\n", + "plt.grid(True)\n", "plt.tight_layout()\n", "plt.show()" ] @@ -259,7 +268,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.10.13" }, "orig_nbformat": 4, "vscode": { diff --git a/examples/ising/ising.py b/examples/ising/ising.py index 0bc9baec..7be2c95f 100644 --- a/examples/ising/ising.py +++ b/examples/ising/ising.py @@ -15,7 +15,7 @@ class IsingExact: Class for exact representation of a transverse field Ising model in 1D. """ - def __init__(self, num_sites: int = 2, h_magnetic: np.float32 = 0) -> None: + def __init__(self, num_sites: int = 2, h_magnetic: float = 0) -> None: """ Initialises an instance to exactly simulate the Ising model in 1D. @@ -23,7 +23,7 @@ def __init__(self, num_sites: int = 2, h_magnetic: np.float32 = 0) -> None: ---------- num_sites : int The number of spins in the chain. - h_magnetic : np.float32 + h_magnetic : float Value of the transverse magnetic field scaled by the ZZ-interaction. """ self.num_sites = num_sites @@ -60,13 +60,13 @@ def hamiltonian_dense(self) -> np.ndarray: return self.hamiltonian_sparse().todense() - def energy(self, state: np.ndarray) -> np.float32: + def energy(self, state: np.ndarray) -> float: """ Computes the energy corresponding to a quantum state ``state``. """ return np.conjugate(state.T) @ self.hamiltonian_sparse @ state - def z_magnetisation(self, i: int, state: np.ndarray) -> np.float32: + def z_magnetisation(self, i: int, state: np.ndarray) -> float: """ Computes the z-magnetisation value corresponding to a quantum state ``state`` @@ -92,7 +92,7 @@ def z_magnetisation(self, i: int, state: np.ndarray) -> np.float32: @ state ) - def x_magnetisation(self, i: int, state: np.ndarray) -> np.float32: + def x_magnetisation(self, i: int, state: np.ndarray) -> float: """ Computes the x-magnetisation value corresponding to a quantum state ``state`` @@ -118,7 +118,7 @@ def x_magnetisation(self, i: int, state: np.ndarray) -> np.float32: @ state ) - def average_chain_z_magnetisation(self, state: np.ndarray) -> np.float32: + def average_chain_z_magnetisation(self, state: np.ndarray) -> float: """ Computes the average z-magnetisation corresponding to a quantum state ``state`` @@ -129,7 +129,7 @@ def average_chain_z_magnetisation(self, state: np.ndarray) -> np.float32: / self.num_sites ) - def average_chain_x_magnetisation(self, state: np.ndarray) -> np.float32: + def average_chain_x_magnetisation(self, state: np.ndarray) -> float: """ Computes the average x-magnetisation corresponding to a quantum state ``state`` @@ -147,9 +147,7 @@ class IsingMPO: a transverse field Ising model in 1D and computing relevant physical observables. """ - def __init__( - self, num_sites: int = int(2), h_magnetic: np.float32 = np.float32(0) - ) -> None: + def __init__(self, num_sites: int = int(2), h_magnetic: float = float(0)) -> None: """ Initialises an instance to simulate the Ising model in 1D using MPS. @@ -157,7 +155,7 @@ def __init__( ---------- num_sites : int Number of spins in the chain. - h_magnetic : np.float32 + h_magnetic : float Value of the transverse magnetic field scaled by the ZZ-interaction. """ self.num_sites = num_sites @@ -199,9 +197,7 @@ def hamiltonian_mpo(self) -> List[np.ndarray]: return mpo_list - def z_magnetisation( - self, i: int, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: + def z_magnetisation(self, i: int, mps: Union[ExplicitMPS, CanonicalMPS]) -> float: """ Computes the z-magnetisation value corresponding to a quantum state @@ -209,9 +205,7 @@ def z_magnetisation( """ return mps.one_site_expectation_value(i, self.pauli_z) - def x_magnetisation( - self, i: int, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: + def x_magnetisation(self, i: int, mps: Union[ExplicitMPS, CanonicalMPS]) -> float: """ Computes the x-magnetisation value corresponding to a quantum state @@ -221,7 +215,7 @@ def x_magnetisation( def average_chain_z_magnetisation( self, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: + ) -> float: """ Computes the average z-magnetisation corresponding to a quantum state @@ -234,7 +228,7 @@ def average_chain_z_magnetisation( def average_chain_x_magnetisation( self, mps: Union[ExplicitMPS, CanonicalMPS] - ) -> np.float32: + ) -> float: """ Computes the average x-magnetisation corresponding to a quantum state diff --git a/examples/ising/ising_parallel.py b/examples/ising/ising_parallel.py index 85fa993a..55cf7ada 100644 --- a/examples/ising/ising_parallel.py +++ b/examples/ising/ising_parallel.py @@ -15,7 +15,7 @@ NUM_SITES = 15 -def exact_simulation(magnetic_field: np.float32 = 0): +def exact_simulation(magnetic_field: float = 0): """ Exact simulation function. """ @@ -29,7 +29,7 @@ def exact_simulation(magnetic_field: np.float32 = 0): ) -def dmrg_simulation(magnetic_field: np.float32 = 0): +def dmrg_simulation(magnetic_field: float = 0): """ DMRG simulation function. """ diff --git a/examples/main_component/main_component.ipynb b/examples/main_component/main_component.ipynb index c6703514..37001a41 100644 --- a/examples/main_component/main_component.ipynb +++ b/examples/main_component/main_component.ipynb @@ -1,15 +1,22 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The main component problem" + ] + }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "In this example we will solve the Main Component Problem (MCP). This is a subroutine of our decoding algorithm but is interesting on its own. The problem reads as follows:\n", + "In this example we demonstrate solving the Main Component Problem (MCP). This is a subroutine of our decoding algorithm but is quite interesting on its own. The problem reads as follows:\n", "$$\n", "\\underset{\\phi_i \\in \\mathbb{C}^2}{\\arg \\max }\\left[\\otimes_i\\left\\langle\\phi_i\\right|\\right] \\rho\\left[\\otimes_i\\left|\\phi_i\\right\\rangle\\right],\n", "$$\n", - "which basically means finding a basis state which contributes most to a given pure state." + "which essentially means finding a basis state which contributes most to a given pure state." ] }, { @@ -57,7 +64,7 @@ "metadata": {}, "outputs": [], "source": [ - "num_sites = 9\n", + "num_sites = 10\n", "psi = create_state_vector(num_sites)" ] }, @@ -85,7 +92,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we create an exact MPS version of the state and its Matrix Product Density Operator." + "Now, we create an exact Matrix Product State (MPS) version of the state and its Matrix Product Density Operator (MPDO)." ] }, { @@ -94,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "mps = mps_from_dense(psi, form=\"Right-canonical\")\n", + "mps = mps_from_dense(psi)\n", "mpdo = mps.density_mpo()" ] }, @@ -115,7 +122,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 512/512 [00:00<00:00, 6802.72it/s]\n" + "100%|██████████| 1024/1024 [00:00<00:00, 5645.63it/s]\n" ] } ], @@ -147,16 +154,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:00<00:00, 3.26it/s]\n" + "100%|██████████| 1/1 [00:00<00:00, 1.13it/s]\n" ] } ], "source": [ "mps_start = create_simple_product_state(num_sites, which=\"+\")\n", - "engine = dmrg(\n", - " mps_start, mpdo, chi_max=1e4, cut=1e-12, mode=\"LA\", copy=True, silent=False\n", - ")\n", - "engine.run(num_iter=1)\n", + "engine = dmrg(mps_start, mpdo, mode=\"LA\")\n", + "engine.run()\n", "max_excited_mps_from_dmrg = engine.mps\n", "\n", "overlaps_dmrg = []\n", @@ -191,7 +196,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 10/10 [00:00<00:00, 44.25it/s]\n" + "100%|██████████| 1/1 [00:00<00:00, 16.07it/s]\n" ] } ], @@ -200,13 +205,9 @@ "dephasing_engine = deph_dmrg(\n", " mps_start,\n", " mps,\n", - " chi_max=1e4,\n", - " cut=1e-12,\n", " mode=\"LA\",\n", - " copy=True,\n", - " silent=False,\n", ")\n", - "dephasing_engine.run(num_iter=10)\n", + "dephasing_engine.run()\n", "main_component_mps = dephasing_engine.mps\n", "\n", "overlaps_dephased = []\n", @@ -263,13 +264,6 @@ " main_component_exact == main_component_dephased,\n", ")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -288,7 +282,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.10.13" }, "orig_nbformat": 4, "vscode": { diff --git a/generate_docs.sh b/generate_docs.sh new file mode 100755 index 00000000..95b23711 --- /dev/null +++ b/generate_docs.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +PACKAGE_DIR="mdopt" +DOCS_DIR="docs" +SPHINX_SOURCE_DIR="docs/source" +SPHINX_BUILD_DIR="docs/build" + +# Ensure the script is executed from the project root +if [ ! -d "$PACKAGE_DIR" ] || [ ! -d "$DOCS_DIR" ]; then + echo "Error: Script must be run from the root of the project." + exit 1 +fi + +# Convert README.md to README.rst +echo "Converting README.md to README.rst..." +pandoc "./README.md" -o "$SPHINX_SOURCE_DIR/README.rst" + +# Delete existing Jupyter Notebooks in the Sphinx source directory +echo "Deleting existing Jupyter Notebooks in Sphinx source directory..." +find "$SPHINX_SOURCE_DIR" -name "*.ipynb" -exec rm {} + + +# Copy Jupyter Notebooks to the Sphinx source directory +echo "Copying Jupyter Notebooks to Sphinx source directory..." +cp -r examples/*/*.ipynb "$SPHINX_SOURCE_DIR/" + +# Path to examples.rst +EXAMPLES_RST="$SPHINX_SOURCE_DIR/examples.rst" + +# Check if examples.rst exists. If yes, delete it. +if [ -f "$EXAMPLES_RST" ]; then + echo "examples.rst already exists. Deleting and recreating..." + rm "$EXAMPLES_RST" +fi + +# Proceed to create (or recreate) examples.rst and fill it +echo "Creating examples.rst..." +echo "Examples" > "$EXAMPLES_RST" +echo "========" >> "$EXAMPLES_RST" +echo "" >> "$EXAMPLES_RST" +echo ".. toctree::" >> "$EXAMPLES_RST" +echo " :maxdepth: 2" >> "$EXAMPLES_RST" +echo " :caption: Notebook Examples:" >> "$EXAMPLES_RST" +echo "" >> "$EXAMPLES_RST" + +# Dynamically list notebooks in examples.rst +for notebook in "$SPHINX_SOURCE_DIR"/*.ipynb; do + notebook_name=$(basename "$notebook") + echo " $notebook_name" >> "$SPHINX_SOURCE_DIR/examples.rst" +done + +# Generate .rst files with sphinx-apidoc +echo "Generating .rst files with sphinx-apidoc..." +sphinx-apidoc -o "$SPHINX_SOURCE_DIR" "$PACKAGE_DIR" --force + +echo "Cleaning up previous builds..." +rm -rf "$SPHINX_BUILD_DIR" + +# Build the Sphinx documentation +echo "Building Sphinx documentation..." +sphinx-build -b html "$SPHINX_SOURCE_DIR" "$SPHINX_BUILD_DIR" + +# Alternatively, if you're using the Makefile generated by Sphinx: +# make -C "$DOCS_DIR" html + +echo "Documentation generation complete. Check the $SPHINX_BUILD_DIR directory." diff --git a/mdopt/contractor/contractor.py b/mdopt/contractor/contractor.py index 6327d1e9..29f85b11 100644 --- a/mdopt/contractor/contractor.py +++ b/mdopt/contractor/contractor.py @@ -67,7 +67,7 @@ def apply_two_site_unitary( b_2: np.ndarray, unitary: np.ndarray, chi_max: int = int(1e4), - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), ) -> Tuple[np.ndarray, np.ndarray]: """ Applies a two-site unitary operator to a right-canonical MPS as follows:: @@ -96,7 +96,7 @@ def apply_two_site_unitary( The second MPS right-isometric tensor to apply the unitary to. unitary : np.ndarray The unitary tensor we apply. - cut : np.float32 + cut : float Singular values smaller than this will be discarded. chi_max : int Maximum number of singular values to keep. @@ -152,7 +152,7 @@ def apply_two_site_unitary( chi_max=chi_max, cut=cut, renormalise=False, - return_residual_spectrum=True, + return_truncation_error=True, ) b_1_updated = contract( "ijkl, mkl -> ijm", @@ -170,7 +170,7 @@ def mps_mpo_contract( start_site: int = int(0), renormalise: bool = False, chi_max: int = int(1e4), - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), inplace: bool = False, result_to_explicit: bool = False, ) -> Union[ExplicitMPS, CanonicalMPS]: @@ -213,7 +213,7 @@ def mps_mpo_contract( involving two neigbouring MPS sites. chi_max : int Maximum bond dimension to keep. - cut : np.float32 + cut : float Cutoff for the singular values. inplace : bool Whether to modify the current MPS or create a new one. @@ -241,9 +241,7 @@ def mps_mpo_contract( mps = mps.mixed_canonical(start_site) assert isinstance(mps, CanonicalMPS) if mps.orth_centre != start_site: - mps = cast( - CanonicalMPS, mps.move_orth_centre(start_site, renormalise=renormalise) - ) + mps = cast(CanonicalMPS, mps.move_orth_centre(start_site, renormalise=False)) for i, tensor in enumerate(mpo): if len(tensor.shape) != 4: @@ -282,7 +280,7 @@ def mps_mpo_contract( chi_max=chi_max, cut=cut, renormalise=renormalise, - return_residual_spectrum=True, + return_truncation_error=True, ) orth_centre_index += 1 @@ -320,7 +318,7 @@ def mps_mpo_contract( chi_max=chi_max, cut=cut, renormalise=renormalise, - return_residual_spectrum=True, + return_truncation_error=True, ) mps.tensors[orth_centre_index + 1] = contract( "ij, jkl -> ikl", np.diag(singular_values), b_r, optimize=[(0, 1)] diff --git a/mdopt/mps/canonical.py b/mdopt/mps/canonical.py index eb227366..c7144703 100644 --- a/mdopt/mps/canonical.py +++ b/mdopt/mps/canonical.py @@ -63,7 +63,7 @@ class CanonicalMPS: Position of the orthogonality centre, does not support negative indexing. As a convention, this attribute is taken ``0`` for a right-canonical form, ``len(tensors) - 1`` for a left-canonical form, ``None`` for a product state. - tolerance : np.float32 + tolerance : float Numerical tolerance to zero out the singular values in Singular Value Decomposition. chi_max : int The maximum bond dimension to keep in Singular Value Decompositions. @@ -88,7 +88,7 @@ def __init__( self, tensors: List[np.ndarray], orth_centre: Optional[int] = None, - tolerance: np.float32 = np.float32(1e-12), + tolerance: float = float(1e-12), chi_max: int = int(1e4), ) -> None: self.tensors = tensors @@ -313,22 +313,20 @@ def density_mpo(self) -> List[np.ndarray]: return list(mpo) - def entanglement_entropy( - self, tolerance: np.float32 = np.float32(1e-12) - ) -> np.ndarray: + def entanglement_entropy(self, tolerance: float = float(1e-12)) -> np.ndarray: """ Returns the entanglement entropy for bipartitions at each of the bonds. """ return self.explicit(tolerance=tolerance).entanglement_entropy() - def check_orth_centre(self) -> Optional[int]: + def check_orth_centre(self) -> Optional[Union[int, List[int]]]: """ Checks the current position of the orthogonality centre by checking each tensor for the isometry conditions. Note, this method does not update the current instance's ``orth_centre`` attribute. """ - _, flags_left, flags_right = mdopt.mps.utils.find_orth_centre( # type: ignore + orth_centres, flags_left, flags_right = mdopt.mps.utils.find_orth_centre( # type: ignore self, return_orth_flags=True ) @@ -349,7 +347,7 @@ def check_orth_centre(self) -> Optional[int]: if all(flags_left) and all(flags_right): return 0 - return None + return orth_centres def move_orth_centre( self, @@ -390,7 +388,7 @@ def move_orth_centre( singular_values = [] if self.orth_centre is None: - self.orth_centre = self.check_orth_centre() + self.orth_centre = self.check_orth_centre() # type: ignore if self.orth_centre is None: raise ValueError("The orthogonality centre value is set to None.") @@ -409,11 +407,12 @@ def move_orth_centre( for i in range(begin, final): two_site_tensor = mps.two_site_tensor_next(i) - u_l, singular_values_bond, v_r = split_two_site_tensor( + u_l, singular_values_bond, v_r, _ = split_two_site_tensor( two_site_tensor, chi_max=self.chi_max, renormalise=renormalise, strategy="svd", + return_truncation_error=True, ) singular_values.append(singular_values_bond) mps.tensors[i] = u_l @@ -442,13 +441,17 @@ def move_orth_centre_to_border( renormalise : bool Whether to renormalise singular values during each SVD. + Notes + ----- Returns a new version of the current :class:`CanonicalMPS` instance with the orthogonality centre moved to the closest (from the current position) border. """ if self.orth_centre is None: - self.orth_centre = self.check_orth_centre() + self.orth_centre = self.check_orth_centre() # type: ignore + if self.orth_centre is None: + raise ValueError("There is no orthogonality center present.") - if self.orth_centre == 0: + elif self.orth_centre == 0: return self.copy(), "first" elif self.orth_centre == self.num_sites - 1: @@ -474,7 +477,7 @@ def move_orth_centre_to_border( return cast("CanonicalMPS", mps), "last" def explicit( - self, tolerance: np.float32 = np.float32(1e-12), renormalise: bool = True + self, tolerance: float = float(1e-12), renormalise: bool = True ) -> "mdopt.mps.explicit.ExplicitMPS": # type: ignore """ Transforms a :class:`CanonicalMPS` instance into a :class:`ExplicitMPS` instance. @@ -483,7 +486,7 @@ def explicit( Parameters ---------- - tolerance : np.float32 + tolerance : float Numerical tolerance for the singular values. renormalise : bool Whether to renormalise singular values during each SVD. @@ -528,7 +531,7 @@ def explicit( return mdopt.mps.explicit.ExplicitMPS( # type: ignore explicit_tensors, - singular_values, + singular_values, # type: ignore tolerance=tolerance, ) # type: ignore @@ -570,19 +573,27 @@ def mixed_canonical( CanonicalMPS, self.move_orth_centre(orth_centre, renormalise=renormalise) ) - def norm(self) -> np.float32: + def norm(self) -> float: """ Computes the norm of the current MPS, that is, the modulus squared of its inner product with itself. """ - return np.float32(abs(mdopt.mps.utils.inner_product(self, self)) ** 2) # type: ignore + if self.orth_centre: + norm = contract( + "ijk, ijk", + np.conjugate(self.tensors[self.orth_centre]), + self.tensors[self.orth_centre], + ) + return float(abs(norm)) + + return float(abs(mdopt.mps.utils.inner_product(self, self))) # type: ignore def one_site_expectation_value( self, site: int, operator: np.ndarray, - ) -> Union[np.float32, np.complex128]: + ) -> Union[float, np.complex128]: """ Computes an expectation value of an arbitrary one-site operator (not necessarily unitary) on the given site. @@ -630,7 +641,7 @@ def two_site_expectation_value( self, site: int, operator: np.ndarray, - ) -> Union[np.float32, np.complex128]: + ) -> Union[float, np.complex128]: """ Computes an expectation value of an arbitrary two-site operator (not necessarily unitary) on the given site and its next neighbour. @@ -685,6 +696,246 @@ def two_site_expectation_value( optimize=[(0, 1), (0, 1)], ) + def compress_bond( + self, + bond: int, + chi_max: int = int(1e4), + cut: float = float(1e-12), + renormalise: bool = False, + strategy: str = "svd", + return_truncation_error: bool = False, + ) -> Tuple["CanonicalMPS", Optional[float]]: + """ + Compresses the bond at a given site, i.e., reduces its bond dimension. + + Parameters + ---------- + bond : int + The index of the bond to compress. + chi_max : int + The maximum bond dimension to keep. + cut : float + Singular values smaller than this will be discarded. + renormalise: bool + Whether to renormalise the singular value spectrum after the cut. + strategy : str + Which strategy to use for decomposition at the bond. + Available options: ``svd``, ``qr`` and ``svd_advanced``. + return_truncation_error : bool + Whether to return the truncation error. + + Returns + ------- + compressed_mps: CanonicalMPS + The new compressed Matrix Product State. + truncation_error : Optional[float] + The truncation error. + Returned only if `return_truncation_error` is set to True. + + Raises + ------ + ValueError + If the bond index is out of range. + ValueError + If the compression strategy is not supported. + + Notes + ----- + 1) The bonds are being enumerated from the right side of the tensors. + For example, the bond ``0`` is a bond to the right of tensor ``0``. + 2) The compression scheme ``svd_advanced`` follows + the scheme outlined in Fig.2 of https://arxiv.org/abs/1708.08932. + This strategy can give speed ups for large bond dimensions + by doing two SVDs on moderate-size matrices instead of one SVD on a large matrix. + """ + + if bond not in range(self.num_bonds): + raise ValueError( + f"Bond given {bond}, with the number of bonds in the MPS {self.num_bonds}." + ) + + if strategy not in ["svd", "qr", "svd_advanced"]: + raise ValueError(f"Unsupported compression strategy: {strategy}") + + mps_compressed = self.move_orth_centre( + final_pos=bond, return_singular_values=False, renormalise=False + ) + mps_compressed = cast("CanonicalMPS", mps_compressed) + + tensor_left = mps_compressed.tensors[bond] # the orthogonality centre + tensor_right = mps_compressed.tensors[bond + 1] + + if strategy == "svd": + two_site_tensor = contract( + "ijk, klm -> ijlm", tensor_left, tensor_right, optimize=[(0, 1)] + ) + u_l, singular_values, v_r, truncation_error = split_two_site_tensor( + tensor=two_site_tensor, + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + strategy=strategy, + return_truncation_error=return_truncation_error, + ) + + mps_compressed.tensors[bond] = contract( + "ijk, kl -> ijl", u_l, np.diag(singular_values) + ) + mps_compressed.tensors[bond + 1] = v_r + + if return_truncation_error: + return mps_compressed, truncation_error + + if strategy == "qr": + two_site_tensor = contract("ijk, klm -> ijlm", tensor_left, tensor_right) + q_l, r_r, truncation_error, _ = split_two_site_tensor( + tensor=two_site_tensor, + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + strategy=strategy, + return_truncation_error=return_truncation_error, + ) + + mps_compressed.tensors[bond] = q_l + mps_compressed.tensors[bond + 1] = r_r + + if return_truncation_error: + return mps_compressed, truncation_error + + if strategy == "svd_advanced": + chi_left, phys_left, _ = tensor_left.shape + _, phys_right, chi_right = tensor_right.shape + tensor_left = tensor_left.reshape(chi_left * phys_left, -1) + tensor_right = tensor_right.reshape(-1, phys_right * chi_right) + + iso_left_0, sing_vals_left, iso_left_1, _ = svd( + mat=tensor_left, + cut=cut, + chi_max=chi_max, + renormalise=renormalise, + return_truncation_error=return_truncation_error, + ) + iso_right_0, sing_vals_right, iso_right_1, _ = svd( + mat=tensor_right, + cut=cut, + chi_max=chi_max, + renormalise=renormalise, + return_truncation_error=return_truncation_error, + ) + + two_site_tensor = contract( + "ij, jk, kl, lm -> im", + np.diag(sing_vals_left), + iso_left_1, + iso_right_0, + np.diag(sing_vals_right), + optimize=[(0, 1), (0, 1), (0, 1)], + ) + + iso_left_new, sing_vals_new, iso_right_new, truncation_error = svd( + mat=two_site_tensor, + cut=cut, + chi_max=chi_max, + renormalise=renormalise, + return_truncation_error=return_truncation_error, + ) + + tensor_left_new = contract( + "ij, jk, kl -> il", + iso_left_0, + iso_left_new, + np.sqrt(np.diag(sing_vals_new)), + optimize=[(0, 1), (0, 1)], + ) + tensor_right_new = contract( + "ij, jk, kl -> il", + np.sqrt(np.diag(sing_vals_new)), + iso_right_new, + iso_right_1, + optimize=[(0, 1), (0, 1)], + ) + + mps_compressed.tensors[bond] = tensor_left_new.reshape( + chi_left, phys_left, len(sing_vals_new) + ) + mps_compressed.tensors[bond + 1] = tensor_right_new.reshape( + len(sing_vals_new), phys_right, chi_right + ) + + if return_truncation_error: + return mps_compressed, truncation_error + + return mps_compressed, None + + def compress( + self, + chi_max: int = int(1e4), + cut: float = float(1e-12), + renormalise: bool = False, + strategy: str = "svd", + return_truncation_errors: bool = False, + ) -> Tuple["CanonicalMPS", List[Optional[float]]]: + """ + Compresses the MPS, i.e., runs the ``compress_bond`` method for each bond. + + Parameters + ---------- + chi_max : int + The maximum bond dimension to keep. + cut : float + Singular values smaller than this will be discarded. + renormalise: bool + Whether to renormalise the singular value spectrum after the cut. + strategy : str + Which strategy to use for decomposition at the bond. + Available options: ``svd``, ``qr`` and ``svd_advanced``. + return_truncation_errors : bool + Whether to return the list of truncation errors (for each bond). + + Returns + ------- + compressed_mps: CanonicalMPS + The new compressed Matrix Product State. + truncation_errors : Optional[List[float]] + The truncation errors. + Returned only if `return_truncation_errors` is set to True. + + Raises + ------ + ValueError + If the compression strategy is not supported. + """ + + if strategy not in ["svd", "qr", "svd_advanced"]: + raise ValueError(f"Unsupported compression strategy: {strategy}") + + truncation_errors = [] + mps_compressed, position = self.move_orth_centre_to_border(renormalise=False) + + if position == "last": + mps_compressed = mps_compressed.reverse() + + for bond in range(self.num_bonds): + mps_compressed, truncation_error = mps_compressed.compress_bond( + bond=bond, + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + strategy=strategy, + return_truncation_error=True, + ) + truncation_errors.append(truncation_error) + + if position == "last": + mps_compressed = mps_compressed.reverse() + truncation_errors = truncation_errors[::-1] + + if return_truncation_errors: + return mps_compressed, truncation_errors + + return mps_compressed, [None] + def marginal( self, sites_to_marginalise: List[int], canonicalise: bool = False ) -> "CanonicalMPS": # type: ignore diff --git a/mdopt/mps/explicit.py b/mdopt/mps/explicit.py index 07c98c67..3099eb28 100644 --- a/mdopt/mps/explicit.py +++ b/mdopt/mps/explicit.py @@ -14,17 +14,19 @@ where ``L`` is the length of the MPS, the corresponding singular value tensors at the boundaries would be the identities of the same dimension. -We index sites with ``i`` from ``0`` to ``L-1``, with bond ``i`` being left of site ``i``. +We index MPS tensors with ``i`` from ``0`` to ``L-1``, +while the singular values matrices are indexed from the left of each tensor, i.e., +the singular values matrux with index ``i`` is to the left of site ``i``. Essentially, it corresponds to storing each ``Γ[i]`` and ``Λ[i]`` as shown in fig.4b in reference `[1]`_. """ from functools import reduce from copy import deepcopy -from typing import Literal, Iterable, List, Union, cast +from typing import Literal, Iterable, List, Union, Optional, Tuple, cast import numpy as np from opt_einsum import contract -from scipy.special import xlogy +from scipy.special import xlogy # pylint: disable=E0611 import mdopt from mdopt.mps.canonical import CanonicalMPS @@ -43,7 +45,7 @@ class ExplicitMPS: singular_values : List[List] The singular values at each of the bonds, ``singular_values[i]`` is left of ``tensors[i]``. Each singular values list at each bond is normalised to 1. - tolerance : np.float32 + tolerance : float Absolute tolerance of the normalisation of the singular value spectrum at each bond. num_sites : int Number of sites. @@ -66,7 +68,7 @@ def __init__( self, tensors: List[np.ndarray], singular_values: List[List], - tolerance: np.float32 = np.float32(1e-12), + tolerance: float = float(1e-12), chi_max: int = int(1e4), ) -> None: self.tensors = tensors @@ -98,7 +100,7 @@ def __init__( if abs(norm - 1) > tolerance: raise ValueError( "The norm of each singular values tensor must be 1, " - f"instead the norm is {norm} at bond {i + 1}." + f"instead the norm is {norm} at bond {i}." ) @property @@ -337,17 +339,15 @@ def entanglement_entropy(self) -> np.ndarray: Returns the entanglement entropy for bipartitions at each of the bonds. """ - entropy = np.zeros(shape=(self.num_bonds,), dtype=np.float32) + entropy = np.zeros(shape=(self.num_bonds,), dtype=float) for bond in range(self.num_bonds): singular_values = self.singular_values[bond].copy() singular_values = np.array(singular_values) # type: ignore - singular_values[singular_values < self.tolerance] = 0 - singular_values2 = [ - singular_value**2 for singular_value in singular_values - ] + singular_values[singular_values < self.tolerance] = 0 # type: ignore + singular_values2 = [singular_value**2 for singular_value in singular_values] entropy[bond] = -1 * np.sum( - np.fromiter((xlogy(s, s) for s in singular_values2), dtype=np.float32) + np.fromiter((xlogy(s, s) for s in singular_values2), dtype=float) ) return entropy @@ -361,7 +361,7 @@ def right_canonical(self) -> CanonicalMPS: return CanonicalMPS( list(self.one_site_right_iso_iter()), - orth_centre=None, + orth_centre=0, tolerance=self.tolerance, chi_max=self.chi_max, ) @@ -375,7 +375,7 @@ def left_canonical(self) -> CanonicalMPS: return CanonicalMPS( list(self.one_site_left_iso_iter()), - orth_centre=None, + orth_centre=self.num_sites - 1, tolerance=self.tolerance, chi_max=self.chi_max, ) @@ -423,19 +423,19 @@ def mixed_canonical(self, orth_centre: int) -> CanonicalMPS: chi_max=self.chi_max, ) - def norm(self) -> np.float32: + def norm(self) -> float: """ Computes the norm of the current MPS, that is, the modulus squared of its inner product with itself. """ - return np.float32(abs(mdopt.mps.utils.inner_product(self, self)) ** 2) # type: ignore + return float(abs(mdopt.mps.utils.inner_product(self, self))) # type: ignore def one_site_expectation_value( self, site: int, operator: np.ndarray, - ) -> Union[np.float32, np.complex128]: + ) -> Union[float, np.complex128]: """ Computes an expectation value of an arbitrary one-site operator (not necessarily unitary) on the given site. @@ -489,7 +489,7 @@ def two_site_expectation_value( self, site: int, operator: np.ndarray, - ) -> Union[np.float32, np.complex128]: + ) -> Union[float, np.complex128]: """ Computes an expectation value of an arbitrary two-site operator (not necessarily unitary) on the given site and its next neighbour. @@ -545,6 +545,125 @@ def two_site_expectation_value( optimize=[(0, 1), (0, 1)], ) + def compress_bond( + self, + bond: int, + chi_max: int = int(1e4), + cut: float = float(1e-12), + renormalise: bool = False, + return_truncation_error: bool = False, + ) -> Tuple["ExplicitMPS", Optional[float]]: + """ + Compresses the bond at a given site, i.e., reduces its bond dimension. + The compression is performed via trimming the singular values at the bond. + + Parameters + ---------- + bond : int + The index of the bond to compress. + chi_max : int + The maximum bond dimension to keep. + cut : float + Singular values smaller than this will be discarded. + renormalise: bool + Whether to renormalise the singular value spectrum after the cut. + return_truncation_error : bool + Whether to return the truncation error. + + Returns + ------- + compressed_mps: ExplicitMPS + The new compressed Matrix Product State. + truncation_error : Optional[float] + The truncation error. + Returned only if `return_truncation_error` is True. + + Raises + ------ + ValueError + If the bond index is out of range. + + Notes + ----- + The bonds are being enumerated from the right side of the tensors. + For example, the bond ``0`` is a bond to the right of tensor ``0``. + Note, the singular value matrices obey a different numbering. + """ + + if bond not in range(self.num_bonds): + raise ValueError( + f"Bond given {bond}, with the number of bonds in the MPS {self.num_bonds}." + ) + + tensor_left = self.tensors[bond] + singular_values = self.singular_values[bond + 1] + tensor_right = self.tensors[bond + 1] + + max_num = min(chi_max, np.sum(singular_values > cut)) # type: ignore + singular_values_new = singular_values[:max_num] + residual_spectrum = singular_values[max_num:] + truncation_error = np.linalg.norm(residual_spectrum) ** 2 + + if renormalise: + singular_values_new /= np.linalg.norm(singular_values_new) # type: ignore + + self.tensors[bond] = tensor_left[..., :max_num] + self.singular_values[bond + 1] = singular_values_new + self.tensors[bond + 1] = tensor_right[:max_num, ...] + + if return_truncation_error: + return self, float(truncation_error) + + return self, None + + def compress( + self, + chi_max: int = int(1e4), + cut: float = float(1e-12), + renormalise: bool = False, + return_truncation_errors: bool = False, + ) -> Tuple["ExplicitMPS", List[Optional[float]]]: + """ + Compresses the MPS, i.e., runs the ``compress_bond`` method for each bond. + + Parameters + ---------- + chi_max : int + The maximum bond dimension to keep. + cut : float + Singular values smaller than this will be discarded. + renormalise: bool + Whether to renormalise the singular value spectrum after the cut. + return_truncation_errors : bool + Whether to return the list of truncation errors (for each bond). + + Returns + ------- + compressed_mps: CanonicalMPS + The new compressed Matrix Product State. + truncation_errors : Optional[List[float]] + The truncation errors. + Returned only if `return_truncation_errors` is set to True. + """ + + truncation_errors = [] + mps_compressed = self.copy() + + for bond in range(self.num_bonds): + mps_compressed, truncation_error = mps_compressed.compress_bond( + bond=bond, + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + return_truncation_error=True, + ) + truncation_errors.append(truncation_error) + + if return_truncation_errors: + return mps_compressed, truncation_errors + + return mps_compressed, [None] + def marginal( self, sites_to_marginalise: List[int], diff --git a/mdopt/mps/utils.py b/mdopt/mps/utils.py index 1f4687a2..a3c0cac4 100644 --- a/mdopt/mps/utils.py +++ b/mdopt/mps/utils.py @@ -132,7 +132,7 @@ def is_canonical(mps: CanonicalMPS, tolerance: float = 1e-12): ---------- mps : CanonicalMPS The MPS to check the canonical form of. - tolerance : np.float32 + tolerance : float Numerical tolerance for checking the isometry property. Returns @@ -162,8 +162,8 @@ def is_canonical(mps: CanonicalMPS, tolerance: float = 1e-12): contract("ijk, ljk -> il", tensor, np.conjugate(tensor), optimize=[(0, 1)]) ) - identity_left = np.identity(to_be_identity_left.shape[0], dtype=np.float32) - identity_right = np.identity(to_be_identity_right.shape[0], dtype=np.float32) + identity_left = np.identity(to_be_identity_left.shape[0], dtype=float) + identity_right = np.identity(to_be_identity_right.shape[0], dtype=float) flags_left.append( np.isclose( @@ -187,7 +187,7 @@ def is_canonical(mps: CanonicalMPS, tolerance: float = 1e-12): def inner_product( mps_1: Union[ExplicitMPS, CanonicalMPS], mps_2: Union[ExplicitMPS, CanonicalMPS] -) -> Union[np.float32, np.complex128]: +) -> Union[float, np.complex128]: """ Returns an inner product between 2 Matrix Product States. @@ -200,7 +200,7 @@ def inner_product( Returns ------- - product : Union[np.float32, np.complex128] + product : Union[float, np.complex128] The value of the inner product. Raises @@ -243,7 +243,7 @@ def inner_product( product = reduce(lambda a, b: np.tensordot(a, b, (-1, 0)), tensors)[0][0] if np.isclose(np.imag(product), 0): - return np.float32(np.real(product)) + return float(np.real(product)) return np.complex128(product) @@ -252,7 +252,7 @@ def mps_from_dense( state_vector: np.ndarray, phys_dim: int = int(2), chi_max: int = int(1e4), - tolerance: np.float32 = np.float32(1e-12), + tolerance: float = float(1e-12), form: str = "Explicit", orth_centre: Optional[int] = None, ) -> Union[ExplicitMPS, CanonicalMPS]: @@ -268,7 +268,7 @@ def mps_from_dense( the dimension of each physical leg of the MPS. chi_max : int Maximum number of singular values to keep. - tolerance : np.float32 + tolerance : float Absolute tolerance of the normalisation of the singular value spectrum at each bond. form : str The form of the MPS. Available options: @@ -358,6 +358,7 @@ def create_simple_product_state( which: str = "0", phys_dim: int = 2, form: str = "Explicit", + tolerance: float = float(1e-12), ) -> Union[ExplicitMPS, CanonicalMPS]: r""" Creates a simple product-state MPS. @@ -379,6 +380,11 @@ def create_simple_product_state( | ``Explicit`` : The :class:`ExplicitMPS` form (by default). | ``Right-canonical`` : The :class:`CanonicalMPS` right-canonical form. | ``Left-canonical`` : The :class:`CanonicalMPS` left-canonical form. + tolerance : float + For the Explicit form: + absolute tolerance of the normalisation of the singular value spectrum at each bond. + For the Canonical form: + numerical tolerance to zero out the singular values in Singular Value Decomposition. Returns ------- @@ -413,17 +419,24 @@ def create_simple_product_state( singular_values = [[1.0] for _ in range(num_sites + 1)] if form == "Right-canonical": - return ExplicitMPS(tensors, singular_values).right_canonical() + mps = ExplicitMPS(tensors, singular_values).right_canonical() + mps.orth_centre = None + return mps if form == "Left-canonical": - return ExplicitMPS(tensors, singular_values).left_canonical() + mps = ExplicitMPS(tensors, singular_values).left_canonical() + mps.orth_centre = None + return mps if form == "Mixed-canonical": raise ValueError("Mixed-canonical form is not defined for a product state.") - return ExplicitMPS(tensors, singular_values) + return ExplicitMPS(tensors, singular_values, tolerance=tolerance) def create_custom_product_state( - string: str, phys_dim: int = 2, form: str = "Explicit" + string: str, + phys_dim: int = 2, + form: str = "Explicit", + tolerance: float = float(1e-12), ) -> Union[ExplicitMPS, CanonicalMPS]: r""" Creates a custom product-state MPS defined by the ``string`` argument. @@ -440,6 +453,11 @@ def create_custom_product_state( | ``Explicit`` : The :class:`ExplicitMPS` form (by default). | ``Right-canonical`` : The :class:`CanonicalMPS` right-canonical form. | ``Left-canonical`` : The :class:`CanonicalMPS` left-canonical form. + tolerance : float + For the Explicit form: + absolute tolerance of the normalisation of the singular value spectrum at each bond. + For the Canonical form: + numerical tolerance to zero out the singular values in Singular Value Decomposition. Returns ------- @@ -486,20 +504,24 @@ def create_custom_product_state( singular_values = [[1.0] for _ in range(num_sites + 1)] if form == "Right-canonical": - return ExplicitMPS(tensors, singular_values).right_canonical() + mps = ExplicitMPS(tensors, singular_values).right_canonical() + mps.orth_centre = None + return mps if form == "Left-canonical": - return ExplicitMPS(tensors, singular_values).left_canonical() + mps = ExplicitMPS(tensors, singular_values).left_canonical() + mps.orth_centre = None + return mps if form == "Mixed-canonical": raise ValueError("Mixed-canonical form is not defined for a product state.") - return ExplicitMPS(tensors, singular_values) + return ExplicitMPS(tensors, singular_values, tolerance=tolerance) def marginalise( mps: Union[ExplicitMPS, CanonicalMPS], sites_to_marginalise: List[int], canonicalise: bool = False, -) -> Union[CanonicalMPS, np.float32, np.complex128]: +) -> Union[CanonicalMPS, float, np.complex128]: r""" Computes a marginal over a subset of sites of an MPS. This function was created to not act inplace. diff --git a/mdopt/optimiser/dephasing_dmrg.py b/mdopt/optimiser/dephasing_dmrg.py index 018e8d15..a1fb7b60 100644 --- a/mdopt/optimiser/dephasing_dmrg.py +++ b/mdopt/optimiser/dephasing_dmrg.py @@ -20,7 +20,6 @@ performing the kronecker product explicitly. """ - from typing import Union, cast import numpy as np import scipy.sparse @@ -194,7 +193,7 @@ class DephasingDMRG: | ``SM`` : Smallest (in magnitude) eigenvalues. | ``LA`` : Largest (algebraic) eigenvalues. | ``SA`` : Smallest (algebraic) eigenvalues. - cut : np.float32 + cut : float The lower boundary of the spectrum, i.e., all the singular values smaller than that will be discarded. silent : bool @@ -206,7 +205,7 @@ def __init__( mps: Union[ExplicitMPS, CanonicalMPS], mps_target: Union[ExplicitMPS, CanonicalMPS], chi_max: int = int(1e4), - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), mode: str = "SA", silent: bool = False, copy: bool = True, @@ -228,8 +227,8 @@ def __init__( if isinstance(self.mps, CanonicalMPS): self.mps = self.mps.right_canonical() self.mps = mps - self.left_environments = [np.zeros(shape=(1,), dtype=np.float32)] * len(mps) - self.right_environments = [np.zeros(shape=(1,), dtype=np.float32)] * len(mps) + self.left_environments = [np.zeros(shape=(1,), dtype=float)] * len(mps) + self.right_environments = [np.zeros(shape=(1,), dtype=float)] * len(mps) self.mps_target = mps_target.right_canonical() self.chi_max = chi_max self.cut = cut @@ -239,14 +238,14 @@ def __init__( start_bond_dim = self.mps_target.tensors[0].shape[0] chi = mps.tensors[0].shape[0] left_environment = np.zeros( - [chi, start_bond_dim, start_bond_dim, chi], dtype=np.float32 + [chi, start_bond_dim, start_bond_dim, chi], dtype=float ) right_environment = np.zeros( - [chi, start_bond_dim, start_bond_dim, chi], dtype=np.float32 + [chi, start_bond_dim, start_bond_dim, chi], dtype=float ) - left_environment[:, 0, 0, :] = np.eye(chi, dtype=np.float32) + left_environment[:, 0, 0, :] = np.eye(chi, dtype=float) right_environment[:, start_bond_dim - 1, start_bond_dim - 1, :] = np.eye( - chi, dtype=np.float32 + chi, dtype=float ) self.left_environments[0] = left_environment self.right_environments[-1] = right_environment @@ -305,7 +304,7 @@ def update_bond(self, i: int) -> None: chi_max=self.chi_max, cut=self.cut, renormalise=True, - return_residual_spectrum=True, + return_truncation_error=True, ) if isinstance(self.mps, CanonicalMPS): diff --git a/mdopt/optimiser/dmrg.py b/mdopt/optimiser/dmrg.py index c6368f1e..fad79805 100644 --- a/mdopt/optimiser/dmrg.py +++ b/mdopt/optimiser/dmrg.py @@ -152,7 +152,7 @@ class DMRG: and ``L``, ``R``, ``U``, ``D`` -- for "left", "right", "up", "down" accordingly. chi_max : int The highest bond dimension of an MPS allowed. - cut : np.float32 + cut : float The lower boundary of the spectrum, i.e., all the singular values smaller than that will be discarded. mode : str @@ -172,7 +172,7 @@ def __init__( mps: Union[ExplicitMPS, CanonicalMPS], mpo: List[np.ndarray], chi_max: int = int(1e4), - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), mode: str = "SA", silent: bool = False, copy: bool = True, @@ -196,8 +196,8 @@ def __init__( self.mps = mps.copy() if isinstance(self.mps, CanonicalMPS): self.mps = self.mps.right_canonical() - self.left_environments = [np.zeros(shape=(1,), dtype=np.float32)] * len(mps) - self.right_environments = [np.zeros(shape=(1,), dtype=np.float32)] * len(mps) + self.left_environments = [np.zeros(shape=(1,), dtype=float)] * len(mps) + self.right_environments = [np.zeros(shape=(1,), dtype=float)] * len(mps) self.mpo = mpo self.chi_max = chi_max self.cut = cut @@ -206,10 +206,10 @@ def __init__( start_bond_dim = self.mpo[0].shape[0] chi = mps.tensors[0].shape[0] - left_environment = np.zeros([chi, start_bond_dim, chi], dtype=np.float32) - right_environment = np.zeros([chi, start_bond_dim, chi], dtype=np.float32) - left_environment[:, 0, :] = np.eye(chi, dtype=np.float32) - right_environment[:, start_bond_dim - 1, :] = np.eye(chi, dtype=np.float32) + left_environment = np.zeros([chi, start_bond_dim, chi], dtype=float) + right_environment = np.zeros([chi, start_bond_dim, chi], dtype=float) + left_environment[:, 0, :] = np.eye(chi, dtype=float) + right_environment[:, start_bond_dim - 1, :] = np.eye(chi, dtype=float) self.left_environments[0] = left_environment self.right_environments[-1] = right_environment for i in reversed(range(1, len(mps))): @@ -267,7 +267,7 @@ def update_bond(self, i: int) -> None: chi_max=self.chi_max, cut=self.cut, renormalise=True, - return_residual_spectrum=True, + return_truncation_error=True, ) if isinstance(self.mps, CanonicalMPS): diff --git a/mdopt/optimiser/utils.py b/mdopt/optimiser/utils.py index 64b28403..71892922 100644 --- a/mdopt/optimiser/utils.py +++ b/mdopt/optimiser/utils.py @@ -76,7 +76,7 @@ class ConstraintString: def __init__(self, constraints: List[np.ndarray], sites: List[List[int]]) -> None: self.constraints = [ - np.array(constraint, dtype=np.float32) for constraint in constraints + np.array(constraint, dtype=float) for constraint in constraints ] self.sites = sites diff --git a/mdopt/utils/utils.py b/mdopt/utils/utils.py index adcabb43..59058577 100644 --- a/mdopt/utils/utils.py +++ b/mdopt/utils/utils.py @@ -9,11 +9,11 @@ def svd( mat: np.ndarray, - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), chi_max: int = int(1e4), renormalise: bool = False, - return_residual_spectrum: bool = False, -) -> Tuple[np.ndarray, list, np.ndarray, Optional[List[float]]]: + return_truncation_error: bool = False, +) -> Tuple[np.ndarray, list, np.ndarray, Optional[float]]: """ Performs Singular Value Decomposition with different features. @@ -21,15 +21,14 @@ def svd( ---------- mat : np.ndarray Matrix provided as a ``np.ndarray`` with 2 dimensions. - cut : np.float32 + cut : float Singular values smaller than this will be discarded. chi_max : int Maximum number of singular values to keep. renormalise : bool Whether to renormalise the singular value spectrum after the cut. - return_residual_spectrum : bool - Whether to return the residual spectrum, i.e., - the singular values we have thrown away. + return_truncation_error : bool + Whether to return the truncation error. Returns ------- @@ -39,8 +38,13 @@ def svd( The singular values, sorted in non-increasing order. v_r : np.ndarray Unitary matrix having right singular vectors as rows. - residual_spectrum : Optional[List[float]] - The discarded singular values. Only returned if `return_residual_spectrum` is True. + residual_spectrum : Optional[float] + The discarded singular values. Only returned if `return_truncation_error` is True. + + Raises + ------ + ValueError + If the input matrix does not have 2 dimensions. """ if len(mat.shape) != 2: @@ -63,27 +67,97 @@ def svd( ) max_num = min(chi_max, np.sum(singular_values > cut)) - ind = np.argsort(singular_values)[::-1][:max_num] - - ind_res = np.argsort(singular_values)[::-1][max_num:] - residual_spectrum = singular_values[ind_res] - - u_l, singular_values, v_r = u_l[:, ind], singular_values[ind], v_r[ind, :] + residual_spectrum = singular_values[max_num:] + truncation_error = np.linalg.norm(residual_spectrum) ** 2 + u_l, singular_values, v_r = ( + u_l[:, :max_num], + singular_values[:max_num], + v_r[:max_num, :], + ) if renormalise: singular_values /= np.linalg.norm(singular_values) - if return_residual_spectrum: + if return_truncation_error: return ( np.asarray(u_l), cast(list, singular_values), np.asarray(v_r), - residual_spectrum, + float(truncation_error), ) return np.asarray(u_l), cast(list, singular_values), np.asarray(v_r), None +def qr( + mat: np.ndarray, + cut: float = float(1e-12), + chi_max: int = int(1e4), + renormalise: bool = False, + return_truncation_error: bool = False, +) -> Tuple[np.ndarray, np.ndarray, Optional[float]]: + """ + Performs QR Decomposition with a possibility for truncation. + + Parameters + ---------- + mat : np.ndarray + Matrix provided as a ``np.ndarray`` with 2 dimensions. + cut : float + Threshold below which the diagonal values of R are discarded. + chi_max : int + Maximum number of columns/rows to keep after truncation. + renormalise : bool + Whether to renormalise the matrix after truncation. + return_truncation_error : bool + Whether to return the truncation error. + + Returns + ------- + Q : np.ndarray + The orthogonal matrix after truncation. + R : np.ndarray + The upper triangular matrix after truncation. + truncation_error : Optional[float] + The truncation error. + Returned only if `return_truncation_error` is True. + + Raises + ------ + ValueError + If the input matrix does not have 2 dimensions. + + Notes + ----- + The truncation is based on the magnitudes of the absolute values + of the diagonal elements of R. + """ + + if len(mat.shape) != 2: + raise ValueError(f"Input matrix must have 2 dimensions, got {len(mat.shape)}.") + + q_l, r_r, pivots = scipy.linalg.qr( + mat, pivoting=True, mode="economic", check_finite=False + ) + + abs_diag_r = np.absolute(np.diag(r_r)) + effective_rank = min(chi_max, int(np.sum(abs_diag_r > cut))) + truncation_indices = list(range(len(abs_diag_r)))[:effective_rank] + + permutation_matrix = np.eye(mat.shape[1])[:, pivots] + r_r = r_r[truncation_indices, :] @ permutation_matrix.T + q_l = q_l[:, truncation_indices] + + if renormalise: + r_r /= np.linalg.norm(np.diag(r_r)) + + if return_truncation_error: + truncation_error = np.linalg.norm(mat - np.dot(q_l, r_r)) + return q_l, r_r, float(truncation_error) + + return q_l, r_r, None + + def kron_tensors( tensor_1: np.ndarray, tensor_2: np.ndarray, @@ -166,13 +240,13 @@ def kron_tensors( def split_two_site_tensor( tensor: np.ndarray, chi_max: int = int(1e4), - cut: np.float32 = np.float32(1e-12), + cut: float = float(1e-12), renormalise: bool = False, strategy: str = "svd", - return_residual_spectrum: bool = False, + return_truncation_error: bool = False, ) -> Tuple: """ - Split a two-site MPS tensor according to the following diagram + Split and truncate a two-site MPS tensor according to the following diagram (in case of the SVD strategy, similarly but without the singular vals for the others):: m n @@ -185,18 +259,17 @@ def split_two_site_tensor( tensor : np.ndarray Two-site tensor ``(i, j, k, l)``. chi_max : int - Maximum number of singular values to keep. - cut : np.float32 - Discard any singular values smaller than eps. + Maximum number of singular/diagonal values to keep. + cut : float + Discard any singular/diagonal values smaller than this. renormalise : bool - Whether to renormalise the singular value spectrum after the cut. + Whether to renormalise the singular value spectrum or the R diagonal + after the cut. strategy : str Which strategy to use for the splitting. - Available options: ``svd``, ``qr``, ``rq``. - return_residual_spectrum : bool - Whether to return the residual spectrum, i.e., - the singular values we have thrown away. - Available only for the SVD decomposition option. + Available options: ``svd`` and ``qr``. + return_truncation_error : bool + Whether to return the truncation error. Returns ------- @@ -204,16 +277,18 @@ def split_two_site_tensor( Left isometry ``(i, j, m)``. singular_values : np.ndarray List of singular values. + Only returned if the decomposition strategy is set to ``svd``. b_r : np.ndarray Right isometry ``(n, k, l)``. - residual_spectrum : Optional[List[float]] - The discarded singular values. Only returned if `return_residual_spectrum` is True - and the decomposition strategy is set to ``svd``. + truncation_error : Optional[float] + The truncation error. Raises ------ ValueError If the tensor is not four-dimensional. + ValueError + If the strategy is not one of the available ones. """ if len(tensor.shape) != 4: @@ -222,43 +297,46 @@ def split_two_site_tensor( f"while the one given has {len(tensor.shape)}." ) - if strategy not in ["svd", "qr", "rq"]: - raise ValueError("The strategy must be one of `svd`, `qr`, `rq`.") + if strategy not in ["svd", "qr"]: + raise ValueError("The strategy must be either `svd` or `qr`.") chi_v_l, phys_l, phys_r, chi_v_r = tensor.shape tensor = tensor.reshape((chi_v_l * phys_l, phys_r * chi_v_r)) if strategy == "svd": - u_l, singular_values, v_r, residual_spectrum = svd( - tensor, + u_l, singular_values, v_r, truncation_error = svd( + mat=tensor, cut=cut, chi_max=chi_max, renormalise=renormalise, - return_residual_spectrum=return_residual_spectrum, + return_truncation_error=return_truncation_error, ) chi_v_cut = len(singular_values) u_l = u_l.reshape((chi_v_l, phys_l, chi_v_cut)) v_r = v_r.reshape((chi_v_cut, phys_r, chi_v_r)) - if return_residual_spectrum: + if return_truncation_error: return ( u_l, singular_values, v_r, - residual_spectrum, + truncation_error, ) # pylint: disable=unbalanced-tuple-unpacking return u_l, singular_values, v_r if strategy == "qr": - q_l, r_r = np.linalg.qr(tensor, mode="reduced") - q_l = q_l.reshape((chi_v_l, phys_l, -1)) - r_r = r_r.reshape((-1, phys_r, chi_v_r)) - return q_l, r_r # pylint: disable=unbalanced-tuple-unpacking - - if strategy == "rq": - r_l, q_r = scipy.linalg.rq(tensor, mode="economic") - r_l = r_l.reshape((chi_v_l, phys_l, -1)) - q_r = q_r.reshape((-1, phys_r, chi_v_r)) - return r_l, q_r # pylint: disable=unbalanced-tuple-unpacking + q_l, r_r, truncation_error = qr( + mat=tensor, + cut=cut, + chi_max=chi_max, + renormalise=renormalise, + return_truncation_error=return_truncation_error, + ) + chi_v_cut = min(chi_max, q_l.shape[1]) + q_l = q_l.reshape((chi_v_l, phys_l, chi_v_cut)) + r_r = r_r.reshape((chi_v_cut, phys_r, chi_v_r)) + if return_truncation_error: + return q_l, r_r, truncation_error, None + return q_l, r_r, None, None return tuple() diff --git a/poetry.lock b/poetry.lock index 97d6bc58..b3953d7e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,66 +1,68 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "alabaster" -version = "0.7.13" -description = "A configurable sidebar-enabled Sphinx theme" +version = "0.7.16" +description = "A light, configurable Sphinx theme" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, - {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, ] [[package]] name = "anyio" -version = "3.7.0" +version = "4.3.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, - {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, ] [package.dependencies] -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (<0.22)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "appnope" -version = "0.1.3" +version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, ] [[package]] name = "argon2-cffi" -version = "21.3.0" -description = "The secure Argon2 password hashing algorithm." +version = "23.1.0" +description = "Argon2 for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, - {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, ] [package.dependencies] argon2-cffi-bindings = "*" [package.extras] -dev = ["cogapp", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "pre-commit", "pytest", "sphinx", "sphinx-notfound-page", "tomli"] -docs = ["furo", "sphinx", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] [[package]] name = "argon2-cffi-bindings" @@ -101,27 +103,32 @@ tests = ["pytest"] [[package]] name = "arrow" -version = "1.2.3" +version = "1.3.0" description = "Better dates & times for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "arrow-1.2.3-py3-none-any.whl", hash = "sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"}, - {file = "arrow-1.2.3.tar.gz", hash = "sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1"}, + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, ] [package.dependencies] python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] [[package]] name = "astroid" -version = "3.0.1" +version = "3.1.0" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.8.0" files = [ - {file = "astroid-3.0.1-py3-none-any.whl", hash = "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca"}, - {file = "astroid-3.0.1.tar.gz", hash = "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e"}, + {file = "astroid-3.1.0-py3-none-any.whl", hash = "sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819"}, + {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"}, ] [package.dependencies] @@ -129,30 +136,31 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "asttokens" -version = "2.2.1" +version = "2.4.1" description = "Annotate AST trees with source code positions" optional = false python-versions = "*" files = [ - {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, - {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] [package.dependencies] -six = "*" +six = ">=1.12.0" [package.extras] -test = ["astroid", "pytest"] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] [[package]] name = "async-lru" -version = "2.0.3" +version = "2.0.4" description = "Simple LRU cache for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "async-lru-2.0.3.tar.gz", hash = "sha256:b714c9d1415fca4e264da72a9e2abc66880ce7430e03a973341f88ea4c0d4869"}, - {file = "async_lru-2.0.3-py3-none-any.whl", hash = "sha256:00c0a8899c20b9c88663a47732689ff98189c9fa08ad9f734d7722f934d250b1"}, + {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, + {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, ] [package.dependencies] @@ -160,87 +168,87 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" 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"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[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]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "babel" -version = "2.12.1" +version = "2.14.0" description = "Internationalization utilities" 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"}, + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] -[[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" -optional = false -python-versions = "*" -files = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, -] +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "beautifulsoup4" -version = "4.12.2" +version = "4.12.3" description = "Screen-scraping library" optional = false python-versions = ">=3.6.0" files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] [package.dependencies] soupsieve = ">1.2" [package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] [[package]] name = "black" -version = "23.11.0" +version = "23.12.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"}, - {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"}, - {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"}, - {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"}, - {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"}, - {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"}, - {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"}, - {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"}, - {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"}, - {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"}, - {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"}, - {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"}, - {file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"}, - {file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"}, - {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, - {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, - {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, - {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] [package.dependencies] @@ -254,19 +262,19 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleach" -version = "6.0.0" +version = "6.1.0" description = "An easy safelist-based HTML-sanitizing tool." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, - {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, ] [package.dependencies] @@ -274,90 +282,78 @@ six = ">=1.9.0" webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.2)"] +css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] name = "cffi" -version = "1.15.1" +version = "1.16.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, ] [package.dependencies] @@ -365,97 +361,112 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -474,156 +485,143 @@ files = [ [[package]] name = "comm" -version = "0.1.3" +version = "0.2.1" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "comm-0.1.3-py3-none-any.whl", hash = "sha256:16613c6211e20223f215fc6d3b266a247b6e2641bf4e0a3ad34cb1aff2aa3f37"}, - {file = "comm-0.1.3.tar.gz", hash = "sha256:a61efa9daffcfbe66fd643ba966f846a624e4e6d6767eda9cf6e993aadaab93e"}, + {file = "comm-0.2.1-py3-none-any.whl", hash = "sha256:87928485c0dfc0e7976fd89fc1e187023cf587e7c353e4a9b417555b44adf021"}, + {file = "comm-0.2.1.tar.gz", hash = "sha256:0bc91edae1344d39d3661dcbc36937181fdaddb304790458f8b044dbc064b89a"}, ] [package.dependencies] -traitlets = ">=5.3" +traitlets = ">=4" [package.extras] -lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] test = ["pytest"] -typing = ["mypy (>=0.990)"] [[package]] name = "contourpy" -version = "1.0.7" +version = "1.2.0" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69"}, - {file = "contourpy-1.0.7-cp310-cp310-win32.whl", hash = "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3"}, - {file = "contourpy-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566"}, - {file = "contourpy-1.0.7-cp311-cp311-win32.whl", hash = "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0"}, - {file = "contourpy-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc"}, - {file = "contourpy-1.0.7-cp38-cp38-win32.whl", hash = "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66"}, - {file = "contourpy-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967"}, - {file = "contourpy-1.0.7-cp39-cp39-win32.whl", hash = "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693"}, - {file = "contourpy-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd"}, - {file = "contourpy-1.0.7.tar.gz", hash = "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e"}, -] - -[package.dependencies] -numpy = ">=1.16" - -[package.extras] -bokeh = ["bokeh", "chromedriver", "selenium"] -docs = ["furo", "sphinx-copybutton"] -mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"] -test = ["Pillow", "matplotlib", "pytest"] -test-no-images = ["pytest"] + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.3.2" +version = "7.4.3" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, - {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, - {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, - {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, - {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, - {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, - {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, - {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, - {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, - {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, - {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, - {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, - {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, - {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.dependencies] @@ -634,40 +632,48 @@ toml = ["tomli"] [[package]] name = "cycler" -version = "0.11.0" +version = "0.12.1" description = "Composable style cycles" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, - {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, ] +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + [[package]] name = "debugpy" -version = "1.6.7" +version = "1.8.1" description = "An implementation of the Debug Adapter Protocol for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"}, - {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"}, - {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"}, - {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"}, - {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"}, - {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"}, - {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"}, - {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"}, - {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"}, - {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"}, - {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"}, - {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"}, - {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"}, - {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"}, - {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"}, - {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"}, - {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"}, - {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"}, + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, ] [[package]] @@ -694,38 +700,39 @@ files = [ [[package]] name = "dill" -version = "0.3.7" +version = "0.3.8" description = "serialize all of Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, - {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "docutils" -version = "0.18.1" +version = "0.20.1" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -733,27 +740,27 @@ test = ["pytest (>=6)"] [[package]] name = "executing" -version = "1.2.0" +version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, - {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, ] [package.extras] -tests = ["asttokens", "littleutils", "pytest", "rich"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] [[package]] name = "fastjsonschema" -version = "2.17.1" +version = "2.19.1" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"}, - {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"}, + {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, + {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, ] [package.extras] @@ -761,27 +768,67 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "fonttools" -version = "4.39.4" +version = "4.49.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.39.4-py3-none-any.whl", hash = "sha256:106caf6167c4597556b31a8d9175a3fdc0356fdcd70ab19973c3b0d4c893c461"}, - {file = "fonttools-4.39.4.zip", hash = "sha256:dba8d7cdb8e2bac1b3da28c5ed5960de09e59a2fe7e63bb73f5a59e57b0430d2"}, -] - -[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)"] + {file = "fonttools-4.49.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d970ecca0aac90d399e458f0b7a8a597e08f95de021f17785fb68e2dc0b99717"}, + {file = "fonttools-4.49.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac9a745b7609f489faa65e1dc842168c18530874a5f5b742ac3dd79e26bca8bc"}, + {file = "fonttools-4.49.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ba0e00620ca28d4ca11fc700806fd69144b463aa3275e1b36e56c7c09915559"}, + {file = "fonttools-4.49.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdee3ab220283057e7840d5fb768ad4c2ebe65bdba6f75d5d7bf47f4e0ed7d29"}, + {file = "fonttools-4.49.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ce7033cb61f2bb65d8849658d3786188afd80f53dad8366a7232654804529532"}, + {file = "fonttools-4.49.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:07bc5ea02bb7bc3aa40a1eb0481ce20e8d9b9642a9536cde0218290dd6085828"}, + {file = "fonttools-4.49.0-cp310-cp310-win32.whl", hash = "sha256:86eef6aab7fd7c6c8545f3ebd00fd1d6729ca1f63b0cb4d621bccb7d1d1c852b"}, + {file = "fonttools-4.49.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fac1b7eebfce75ea663e860e7c5b4a8831b858c17acd68263bc156125201abf"}, + {file = "fonttools-4.49.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:edc0cce355984bb3c1d1e89d6a661934d39586bb32191ebff98c600f8957c63e"}, + {file = "fonttools-4.49.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:83a0d9336de2cba86d886507dd6e0153df333ac787377325a39a2797ec529814"}, + {file = "fonttools-4.49.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36c8865bdb5cfeec88f5028e7e592370a0657b676c6f1d84a2108e0564f90e22"}, + {file = "fonttools-4.49.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33037d9e56e2562c710c8954d0f20d25b8386b397250d65581e544edc9d6b942"}, + {file = "fonttools-4.49.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8fb022d799b96df3eaa27263e9eea306bd3d437cc9aa981820850281a02b6c9a"}, + {file = "fonttools-4.49.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33c584c0ef7dc54f5dd4f84082eabd8d09d1871a3d8ca2986b0c0c98165f8e86"}, + {file = "fonttools-4.49.0-cp311-cp311-win32.whl", hash = "sha256:cbe61b158deb09cffdd8540dc4a948d6e8f4d5b4f3bf5cd7db09bd6a61fee64e"}, + {file = "fonttools-4.49.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc11e5114f3f978d0cea7e9853627935b30d451742eeb4239a81a677bdee6bf6"}, + {file = "fonttools-4.49.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d647a0e697e5daa98c87993726da8281c7233d9d4ffe410812a4896c7c57c075"}, + {file = "fonttools-4.49.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f3bbe672df03563d1f3a691ae531f2e31f84061724c319652039e5a70927167e"}, + {file = "fonttools-4.49.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bebd91041dda0d511b0d303180ed36e31f4f54b106b1259b69fade68413aa7ff"}, + {file = "fonttools-4.49.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4145f91531fd43c50f9eb893faa08399816bb0b13c425667c48475c9f3a2b9b5"}, + {file = "fonttools-4.49.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ea329dafb9670ffbdf4dbc3b0e5c264104abcd8441d56de77f06967f032943cb"}, + {file = "fonttools-4.49.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c076a9e548521ecc13d944b1d261ff3d7825048c338722a4bd126d22316087b7"}, + {file = "fonttools-4.49.0-cp312-cp312-win32.whl", hash = "sha256:b607ea1e96768d13be26d2b400d10d3ebd1456343eb5eaddd2f47d1c4bd00880"}, + {file = "fonttools-4.49.0-cp312-cp312-win_amd64.whl", hash = "sha256:a974c49a981e187381b9cc2c07c6b902d0079b88ff01aed34695ec5360767034"}, + {file = "fonttools-4.49.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b85ec0bdd7bdaa5c1946398cbb541e90a6dfc51df76dfa88e0aaa41b335940cb"}, + {file = "fonttools-4.49.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:af20acbe198a8a790618ee42db192eb128afcdcc4e96d99993aca0b60d1faeb4"}, + {file = "fonttools-4.49.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d418b1fee41a1d14931f7ab4b92dc0bc323b490e41d7a333eec82c9f1780c75"}, + {file = "fonttools-4.49.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b44a52b8e6244b6548851b03b2b377a9702b88ddc21dcaf56a15a0393d425cb9"}, + {file = "fonttools-4.49.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7c7125068e04a70739dad11857a4d47626f2b0bd54de39e8622e89701836eabd"}, + {file = "fonttools-4.49.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29e89d0e1a7f18bc30f197cfadcbef5a13d99806447c7e245f5667579a808036"}, + {file = "fonttools-4.49.0-cp38-cp38-win32.whl", hash = "sha256:9d95fa0d22bf4f12d2fb7b07a46070cdfc19ef5a7b1c98bc172bfab5bf0d6844"}, + {file = "fonttools-4.49.0-cp38-cp38-win_amd64.whl", hash = "sha256:768947008b4dc552d02772e5ebd49e71430a466e2373008ce905f953afea755a"}, + {file = "fonttools-4.49.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:08877e355d3dde1c11973bb58d4acad1981e6d1140711230a4bfb40b2b937ccc"}, + {file = "fonttools-4.49.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fdb54b076f25d6b0f0298dc706acee5052de20c83530fa165b60d1f2e9cbe3cb"}, + {file = "fonttools-4.49.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0af65c720520710cc01c293f9c70bd69684365c6015cc3671db2b7d807fe51f2"}, + {file = "fonttools-4.49.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f255ce8ed7556658f6d23f6afd22a6d9bbc3edb9b96c96682124dc487e1bf42"}, + {file = "fonttools-4.49.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d00af0884c0e65f60dfaf9340e26658836b935052fdd0439952ae42e44fdd2be"}, + {file = "fonttools-4.49.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:263832fae27481d48dfafcc43174644b6706639661e242902ceb30553557e16c"}, + {file = "fonttools-4.49.0-cp39-cp39-win32.whl", hash = "sha256:0404faea044577a01bb82d47a8fa4bc7a54067fa7e324785dd65d200d6dd1133"}, + {file = "fonttools-4.49.0-cp39-cp39-win_amd64.whl", hash = "sha256:b050d362df50fc6e38ae3954d8c29bf2da52be384649ee8245fdb5186b620836"}, + {file = "fonttools-4.49.0-py3-none-any.whl", hash = "sha256:af281525e5dd7fa0b39fb1667b8d5ca0e2a9079967e14c4bfe90fd1cd13e0f18"}, + {file = "fonttools-4.49.0.tar.gz", hash = "sha256:ebf46e7f01b7af7861310417d7c49591a85d99146fc23a5ba82fdb28af156321"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] -lxml = ["lxml (>=4.0,<5)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0)"] 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)"] +unicode = ["unicodedata2 (>=15.1.0)"] woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] [[package]] @@ -796,63 +843,82 @@ files = [ ] [[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] [[package]] -name = "imagesize" -version = "1.4.1" -description = "Getting image size from png/jpeg/jpeg2000/gif file" +name = "httpcore" +version = "1.0.4" +description = "A minimal low-level HTTP client." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, - {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, + {file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"}, + {file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"}, ] +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.25.0)"] + [[package]] -name = "importlib-metadata" -version = "6.6.0" -description = "Read metadata from Python packages" +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, - {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, ] [package.dependencies] -zipp = ">=0.5" +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] [[package]] -name = "importlib-resources" -version = "5.12.0" -description = "Read resources from Python packages" +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.5" files = [ - {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, - {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +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 = "iniconfig" @@ -867,13 +933,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.26.0" +version = "6.29.3" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.26.0-py3-none-any.whl", hash = "sha256:3ba3dc97424b87b31bb46586b5167b3161b32d7820b9201a9e698c71e271602c"}, - {file = "ipykernel-6.26.0.tar.gz", hash = "sha256:553856658eb8430bbe9653ea041a41bff63e9606fc4628873fc92a6cf3abd404"}, + {file = "ipykernel-6.29.3-py3-none-any.whl", hash = "sha256:5aa086a4175b0229d4eca211e181fb473ea78ffd9869af36ba7694c947302a21"}, + {file = "ipykernel-6.29.3.tar.gz", hash = "sha256:e14c250d1f9ea3989490225cc1a542781b095a18a19447fcf2b5eaf7d0ac5bd2"}, ] [package.dependencies] @@ -887,7 +953,7 @@ matplotlib-inline = ">=0.1" nest-asyncio = "*" packaging = "*" psutil = "*" -pyzmq = ">=20" +pyzmq = ">=24" tornado = ">=6.1" traitlets = ">=5.4.0" @@ -896,75 +962,61 @@ cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] pyqt5 = ["pyqt5"] pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] [[package]] name = "ipython" -version = "8.12.2" +version = "8.22.2" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "ipython-8.12.2-py3-none-any.whl", hash = "sha256:ea8801f15dfe4ffb76dea1b09b847430ffd70d827b41735c64a0638a04103bfc"}, - {file = "ipython-8.12.2.tar.gz", hash = "sha256:c7b80eb7f5a855a88efc971fda506ff7a91c280b42cdae26643e0f601ea281ea"}, + {file = "ipython-8.22.2-py3-none-any.whl", hash = "sha256:3c86f284c8f3d8f2b6c662f885c4889a91df7cd52056fd02b7d8d6195d7f56e9"}, + {file = "ipython-8.22.2.tar.gz", hash = "sha256:2dcaad9049f9056f1fef63514f176c7d41f930daa78d05b82a176202818f2c14"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" -prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +traitlets = ">=5.13.0" [package.extras] -all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,nbconvert,nbformat,notebook,parallel,qtconsole,terminal]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] - -[[package]] -name = "ipython-genutils" -version = "0.2.0" -description = "Vestigial utilities from IPython" -optional = false -python-versions = "*" -files = [ - {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, - {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, -] +test = ["pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] [[package]] name = "ipywidgets" -version = "8.0.6" +version = "8.1.2" description = "Jupyter interactive widgets" optional = false python-versions = ">=3.7" files = [ - {file = "ipywidgets-8.0.6-py3-none-any.whl", hash = "sha256:a60bf8d2528997e05ac83fd19ea2fbe65f2e79fbe1b2b35779bdfc46c2941dcc"}, - {file = "ipywidgets-8.0.6.tar.gz", hash = "sha256:de7d779f2045d60de9f6c25f653fdae2dba57898e6a1284494b3ba20b6893bb8"}, + {file = "ipywidgets-8.1.2-py3-none-any.whl", hash = "sha256:bbe43850d79fb5e906b14801d6c01402857996864d1e5b6fa62dd2ee35559f60"}, + {file = "ipywidgets-8.1.2.tar.gz", hash = "sha256:d0b9b41e49bae926a866e613a39b0f0097745d2b9f1f3dd406641b4a57ec42c9"}, ] [package.dependencies] -ipykernel = ">=4.5.1" +comm = ">=0.1.3" ipython = ">=6.1.0" -jupyterlab-widgets = ">=3.0.7,<3.1.0" +jupyterlab-widgets = ">=3.0.10,<3.1.0" traitlets = ">=4.3.1" -widgetsnbextension = ">=4.0.7,<4.1.0" +widgetsnbextension = ">=4.0.10,<4.1.0" [package.extras] test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] @@ -985,49 +1037,46 @@ arrow = ">=0.15.0" [[package]] name = "isort" -version = "5.12.0" +version = "5.13.2" description = "A Python utility / library to sort Python imports." 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"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [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"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "jedi" -version = "0.18.2" +version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, - {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.8.3,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." 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"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] @@ -1038,13 +1087,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "json5" -version = "0.9.14" +version = "0.9.20" description = "A Python implementation of the JSON5 data format." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "json5-0.9.14-py2.py3-none-any.whl", hash = "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f"}, - {file = "json5-0.9.14.tar.gz", hash = "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02"}, + {file = "json5-0.9.20-py3-none-any.whl", hash = "sha256:f623485b37fad95783233bad9352d21526709cbd9a2ec41ddc3e950fca85b701"}, + {file = "json5-0.9.20.tar.gz", hash = "sha256:20a255981244081d5aaa4adc90d31cdbf05bed1863993cbf300b8e2cd2b6de88"}, ] [package.extras] @@ -1052,13 +1101,13 @@ dev = ["hypothesis"] [[package]] name = "jsonpointer" -version = "2.3" +version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ - {file = "jsonpointer-2.3-py2.py3-none-any.whl", hash = "sha256:51801e558539b4e9cd268638c078c6c5746c9ac96bc38152d443400e4f3793e9"}, - {file = "jsonpointer-2.3.tar.gz", hash = "sha256:97cba51526c829282218feb99dab1b1e6bdf8efd1c43dc9d57be093c0d69c99a"}, + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] @@ -1126,17 +1175,16 @@ qtconsole = "*" [[package]] name = "jupyter-client" -version = "8.2.0" +version = "8.6.0" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_client-8.2.0-py3-none-any.whl", hash = "sha256:b18219aa695d39e2ad570533e0d71fb7881d35a873051054a84ee2a17c4b7389"}, - {file = "jupyter_client-8.2.0.tar.gz", hash = "sha256:9fe233834edd0e6c0aa5f05ca2ab4bdea1842bfd2d8a932878212fc5301ddaf0"}, + {file = "jupyter_client-8.6.0-py3-none-any.whl", hash = "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99"}, + {file = "jupyter_client-8.6.0.tar.gz", hash = "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" @@ -1173,13 +1221,13 @@ test = ["flaky", "pexpect", "pytest"] [[package]] name = "jupyter-core" -version = "5.3.0" +version = "5.7.1" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.3.0-py3-none-any.whl", hash = "sha256:d4201af84559bc8c70cead287e1ab94aeef3c512848dde077b7684b54d67730d"}, - {file = "jupyter_core-5.3.0.tar.gz", hash = "sha256:6db75be0c83edbf1b7c9f91ec266a9a24ef945da630f3120e1a0046dc13713fc"}, + {file = "jupyter_core-5.7.1-py3-none-any.whl", hash = "sha256:c65c82126453a723a2804aa52409930434598fd9d35091d63dfb919d2b765bb7"}, + {file = "jupyter_core-5.7.1.tar.gz", hash = "sha256:de61a9d7fc71240f688b2fb5ab659fbb56979458dc66a71decd098e03c79e218"}, ] [package.dependencies] @@ -1188,7 +1236,7 @@ pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_ traitlets = ">=5.3" [package.extras] -docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] @@ -1218,17 +1266,16 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p [[package]] name = "jupyter-lsp" -version = "2.2.0" +version = "2.2.3" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter-lsp-2.2.0.tar.gz", hash = "sha256:8ebbcb533adb41e5d635eb8fe82956b0aafbf0fd443b6c4bfa906edeeb8635a1"}, - {file = "jupyter_lsp-2.2.0-py3-none-any.whl", hash = "sha256:9e06b8b4f7dd50300b70dd1a78c0c3b0c3d8fa68e0f2d8a5d1fbab62072aca3f"}, + {file = "jupyter-lsp-2.2.3.tar.gz", hash = "sha256:33dbcbc5df24237ff5c8b696b04ff4689fcd316cb8d4957d620fe5504d7d2c3f"}, + {file = "jupyter_lsp-2.2.3-py3-none-any.whl", hash = "sha256:57dd90d0a2e2530831793550846168c81c952b49e187aa339e455027a5f0fd2e"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jupyter-server = ">=1.1.2" [[package]] @@ -1265,17 +1312,17 @@ websocket-client = "*" [package.extras] docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "requests"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] [[package]] name = "jupyter-server-terminals" -version = "0.4.4" +version = "0.5.2" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server_terminals-0.4.4-py3-none-any.whl", hash = "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36"}, - {file = "jupyter_server_terminals-0.4.4.tar.gz", hash = "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d"}, + {file = "jupyter_server_terminals-0.5.2-py3-none-any.whl", hash = "sha256:1b80c12765da979513c42c90215481bbc39bd8ae7c0350b4f85bc3eb58d0fa80"}, + {file = "jupyter_server_terminals-0.5.2.tar.gz", hash = "sha256:396b5ccc0881e550bf0ee7012c6ef1b53edbde69e67cab1d56e89711b46052e8"}, ] [package.dependencies] @@ -1283,23 +1330,23 @@ pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} terminado = ">=0.8.3" [package.extras] -docs = ["jinja2", "jupyter-server", "mistune (<3.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] -test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] +docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] [[package]] name = "jupyterlab" -version = "4.0.3" +version = "4.1.2" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.3-py3-none-any.whl", hash = "sha256:d369944391b1d15f2d1f3cb965fb67352956279b2ae6f03ce7947a43940a8301"}, - {file = "jupyterlab-4.0.3.tar.gz", hash = "sha256:e14d1ce46a613028111d0d476a1d7d6b094003b7462bac669f5b478317abcb39"}, + {file = "jupyterlab-4.1.2-py3-none-any.whl", hash = "sha256:aa88193f03cf4d3555f6712f04d74112b5eb85edd7d222c588c7603a26d33c5b"}, + {file = "jupyterlab-4.1.2.tar.gz", hash = "sha256:5d6348b3ed4085181499f621b7dfb6eb0b1f57f3586857aadfc8e3bf4c4885f9"}, ] [package.dependencies] async-lru = ">=1.0.0" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +httpx = ">=0.25.0" ipykernel = "*" jinja2 = ">=3.0.3" jupyter-core = "*" @@ -1313,134 +1360,169 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["black[jupyter] (==23.3.0)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.0.271)"] -docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8)", "sphinx-copybutton"] -docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.2.0)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.2.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.1)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post6)", "matplotlib (==3.8.2)", "nbconvert (>=7.0.0)", "pandas (==2.2.0)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] [[package]] name = "jupyterlab-pygments" -version = "0.2.2" +version = "0.3.0" description = "Pygments theme using JupyterLab CSS variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, - {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, ] [[package]] name = "jupyterlab-server" -version = "2.23.0" +version = "2.25.3" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.23.0-py3-none-any.whl", hash = "sha256:a5ea2c839336a8ba7c38c8e7b2f24cedf919f0d439f4d2e606d9322013a95788"}, - {file = "jupyterlab_server-2.23.0.tar.gz", hash = "sha256:83c01aa4ad9451cd61b383e634d939ff713850f4640c0056b2cdb2b6211a74c7"}, + {file = "jupyterlab_server-2.25.3-py3-none-any.whl", hash = "sha256:c48862519fded9b418c71645d85a49b2f0ec50d032ba8316738e9276046088c1"}, + {file = "jupyterlab_server-2.25.3.tar.gz", hash = "sha256:846f125a8a19656611df5b03e5912c8393cea6900859baa64fa515eb64a8dc40"}, ] [package.dependencies] babel = ">=2.10" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jinja2 = ">=3.0.3" json5 = ">=0.9.0" -jsonschema = ">=4.17.3" +jsonschema = ">=4.18.0" jupyter-server = ">=1.21,<3" packaging = ">=21.3" -requests = ">=2.28" +requests = ">=2.31" [package.extras] docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] -openapi = ["openapi-core (>=0.16.1,<0.17.0)", "ruamel-yaml"] -test = ["hatch", "ipykernel", "jupyterlab-server[openapi]", "openapi-spec-validator (>=0.5.1,<0.6.0)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] +openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] [[package]] name = "jupyterlab-widgets" -version = "3.0.7" +version = "3.0.10" description = "Jupyter interactive widgets for JupyterLab" optional = false python-versions = ">=3.7" files = [ - {file = "jupyterlab_widgets-3.0.7-py3-none-any.whl", hash = "sha256:c73f8370338ec19f1bec47254752d6505b03601cbd5a67e6a0b184532f73a459"}, - {file = "jupyterlab_widgets-3.0.7.tar.gz", hash = "sha256:c3a50ed5bf528a0c7a869096503af54702f86dda1db469aee1c92dc0c01b43ca"}, + {file = "jupyterlab_widgets-3.0.10-py3-none-any.whl", hash = "sha256:dd61f3ae7a5a7f80299e14585ce6cf3d6925a96c9103c978eda293197730cb64"}, + {file = "jupyterlab_widgets-3.0.10.tar.gz", hash = "sha256:04f2ac04976727e4f9d0fa91cdc2f1ab860f965e504c29dbd6a65c882c9d04c0"}, ] [[package]] name = "kiwisolver" -version = "1.4.4" +version = "1.4.5" description = "A fast implementation of the Cassowary constraint solver" 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"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] [[package]] @@ -1469,115 +1551,114 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." 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-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, - {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"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "matplotlib" -version = "3.8.1" +version = "3.8.3" description = "Python plotting package" optional = false python-versions = ">=3.9" files = [ - {file = "matplotlib-3.8.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:e11ab864323fa73ac1b7849688d9671c47a2665242e899785b4db1a375b547e1"}, - {file = "matplotlib-3.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:43a9d40feb63c9e31a0b8b069dcbd74a912f59bdc0095d187126694cd26977e4"}, - {file = "matplotlib-3.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:608ea2951838d391e45dec2e644888db6899c752d3c29e157af9dcefb3d7d8d5"}, - {file = "matplotlib-3.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82ec95b02e894561c21e066bd0c716e4b410df141ce9441aa5af6cd937e4ade2"}, - {file = "matplotlib-3.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e3ad1759ad4a5245172c6d32b8ada603a6020d03211524c39d78d25c9a7dc0d2"}, - {file = "matplotlib-3.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:20a0fdfd3ee836179047f3782be060057b878ad37f5abe29edf006a1ff3ecd73"}, - {file = "matplotlib-3.8.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7658b7073c1d6a2922ecc0ed41602410fae88586cb8a54f7a2063d537b6beaf7"}, - {file = "matplotlib-3.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf6889643d4560fcc56f9f0941f078e4df0d72a6c3e4ca548841fc13c5642664"}, - {file = "matplotlib-3.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff842e27bc6a80de08c40e0bfdce460bd08080e8a94af131162b6a1b8948f2cc"}, - {file = "matplotlib-3.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f99d07c0e753717775be7be39ab383453b4d8b629c9fa174596b970c6555890"}, - {file = "matplotlib-3.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f34b46dbb1db1f09bfa937cd5853e5f2af232caeeff509c3ab6e43fd33780eae"}, - {file = "matplotlib-3.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1fcb49b6baf0375281979cbf26695ec10bd1cada1e311893e89533b3b70143e7"}, - {file = "matplotlib-3.8.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e17674ee127f78f26fea237e7f4d5cf910a8be82beb6260fedf358b88075b823"}, - {file = "matplotlib-3.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d921c0270647ab11c3ef283efaaa3d46fd005ba233bfb3aea75231cdf3656de8"}, - {file = "matplotlib-3.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2afe7d2f8c9e35e94fbcfcfd9b28f29cb32f0a9068cba469cf907428379c8db9"}, - {file = "matplotlib-3.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5a504ff40f81d6233603475a45497a6dca37a873393fa20ae6f7dd6596ef72b"}, - {file = "matplotlib-3.8.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cd54bbf089953140905768ed4626d7223e1ad1d7e2a138410a9c4d3b865ccd80"}, - {file = "matplotlib-3.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:27502d2452208ae784c19504644f09f83742809143bbeae147617640930aa344"}, - {file = "matplotlib-3.8.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f55fb5ff02d999a100be28bf6ffe826e1867a54c7b465409685332c9dd48ffa5"}, - {file = "matplotlib-3.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:afb72822ae410d62aa1a2920c6563cb5680de9078358f0e9474396c6c3e06be2"}, - {file = "matplotlib-3.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43cf368a4a1d8cbc426944806e5e183cead746647a64d2cdb786441546235967"}, - {file = "matplotlib-3.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c54c55457c7f5ea4dfdba0020004fc7667f5c10c8d9b8010d735345acc06c9b8"}, - {file = "matplotlib-3.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e3bb809b743653b5aab5d72ee45c8c937c28e147b0846b0826a54bece898608c"}, - {file = "matplotlib-3.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:c1b0ecaa0d1f4fe1e30f625a2347f0034a89a7d17c39efbb502e554d92ee2f61"}, - {file = "matplotlib-3.8.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ca84deaa38cb64b7dd160ca2046b45f7b5dbff2b0179642e1339fadc337446c9"}, - {file = "matplotlib-3.8.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed3b29f54f6bbf3eaca4cbd23bc260155153ace63b7f597c474fa6fc6f386530"}, - {file = "matplotlib-3.8.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d24c47a1bb47e392fbcd26fe322e4ff3431653ac1e8718e4e147d450ae97a44"}, - {file = "matplotlib-3.8.1.tar.gz", hash = "sha256:044df81c1f6f3a8e52d70c4cfcb44e77ea9632a10929932870dfaa90de94365d"}, + {file = "matplotlib-3.8.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cf60138ccc8004f117ab2a2bad513cc4d122e55864b4fe7adf4db20ca68a078f"}, + {file = "matplotlib-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f557156f7116be3340cdeef7f128fa99b0d5d287d5f41a16e169819dcf22357"}, + {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f386cf162b059809ecfac3bcc491a9ea17da69fa35c8ded8ad154cd4b933d5ec"}, + {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c5f96f57b0369c288bf6f9b5274ba45787f7e0589a34d24bdbaf6d3344632f"}, + {file = "matplotlib-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:83e0f72e2c116ca7e571c57aa29b0fe697d4c6425c4e87c6e994159e0c008635"}, + {file = "matplotlib-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:1c5c8290074ba31a41db1dc332dc2b62def469ff33766cbe325d32a3ee291aea"}, + {file = "matplotlib-3.8.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900"}, + {file = "matplotlib-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e"}, + {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7"}, + {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65"}, + {file = "matplotlib-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0"}, + {file = "matplotlib-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407"}, + {file = "matplotlib-3.8.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4"}, + {file = "matplotlib-3.8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa"}, + {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5"}, + {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1"}, + {file = "matplotlib-3.8.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7"}, + {file = "matplotlib-3.8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39"}, + {file = "matplotlib-3.8.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c4af3f7317f8a1009bbb2d0bf23dfaba859eb7dd4ccbd604eba146dccaaaf0a4"}, + {file = "matplotlib-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4c6e00a65d017d26009bac6808f637b75ceade3e1ff91a138576f6b3065eeeba"}, + {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7b49ab49a3bea17802df6872f8d44f664ba8f9be0632a60c99b20b6db2165b7"}, + {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6728dde0a3997396b053602dbd907a9bd64ec7d5cf99e728b404083698d3ca01"}, + {file = "matplotlib-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:813925d08fb86aba139f2d31864928d67511f64e5945ca909ad5bc09a96189bb"}, + {file = "matplotlib-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:cd3a0c2be76f4e7be03d34a14d49ded6acf22ef61f88da600a18a5cd8b3c5f3c"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26"}, + {file = "matplotlib-3.8.3.tar.gz", hash = "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161"}, ] [package.dependencies] contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" -importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} kiwisolver = ">=1.3.1" numpy = ">=1.21,<2" packaging = ">=20.0" @@ -1642,24 +1723,24 @@ files = [ [[package]] name = "mistune" -version = "2.0.5" -description = "A sane Markdown parser with useful plugins and renderers" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "mistune-2.0.5-py2.py3-none-any.whl", hash = "sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8"}, - {file = "mistune-2.0.5.tar.gz", hash = "sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34"}, + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] [[package]] name = "more-itertools" -version = "10.1.0" +version = "10.2.0" description = "More routines for operating on iterables, beyond itertools" optional = false python-versions = ">=3.8" files = [ - {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, - {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, + {file = "more-itertools-10.2.0.tar.gz", hash = "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1"}, + {file = "more_itertools-10.2.0-py3-none-any.whl", hash = "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684"}, ] [[package]] @@ -1681,38 +1762,38 @@ tests = ["pytest (>=4.6)"] [[package]] name = "mypy" -version = "1.7.1" +version = "1.8.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"}, - {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"}, - {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"}, - {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"}, - {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"}, - {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"}, - {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"}, - {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"}, - {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"}, - {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"}, - {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"}, - {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"}, - {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"}, - {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"}, - {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"}, - {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"}, - {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"}, - {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"}, - {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"}, - {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"}, - {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"}, - {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"}, - {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"}, - {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"}, - {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"}, - {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"}, - {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, + {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, + {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, + {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, + {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, + {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, + {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, + {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, + {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, + {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, + {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, + {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, + {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, + {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, + {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, + {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, + {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, + {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, ] [package.dependencies] @@ -1765,13 +1846,13 @@ testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4, [[package]] name = "nbclient" -version = "0.8.0" +version = "0.9.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.8.0" files = [ - {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"}, - {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"}, + {file = "nbclient-0.9.0-py3-none-any.whl", hash = "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15"}, + {file = "nbclient-0.9.0.tar.gz", hash = "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e"}, ] [package.dependencies] @@ -1787,32 +1868,31 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.4.0" -description = "Converting Jupyter Notebooks" +version = "7.16.2" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "nbconvert-7.4.0-py3-none-any.whl", hash = "sha256:af5064a9db524f9f12f4e8be7f0799524bd5b14c1adea37e34e83c95127cc818"}, - {file = "nbconvert-7.4.0.tar.gz", hash = "sha256:51b6c77b507b177b73f6729dba15676e42c4e92bcb00edc8cc982ee72e7d89d7"}, + {file = "nbconvert-7.16.2-py3-none-any.whl", hash = "sha256:0c01c23981a8de0220255706822c40b751438e32467d6a686e26be08ba784382"}, + {file = "nbconvert-7.16.2.tar.gz", hash = "sha256:8310edd41e1c43947e4ecf16614c61469ebc024898eb808cce0999860fc9fb16"}, ] [package.dependencies] beautifulsoup4 = "*" -bleach = "*" +bleach = "!=5.0.0" defusedxml = "*" -importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} jinja2 = ">=3.0" jupyter-core = ">=4.7" jupyterlab-pygments = "*" markupsafe = ">=2.0" -mistune = ">=2.0.3,<3" +mistune = ">=2.0.3,<4" nbclient = ">=0.5.0" -nbformat = ">=5.1" +nbformat = ">=5.7" packaging = "*" pandocfilters = ">=1.4.1" pygments = ">=2.4.1" tinycss2 = "*" -traitlets = ">=5.0" +traitlets = ">=5.1" [package.extras] all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] @@ -1820,18 +1900,18 @@ docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sp qtpdf = ["nbconvert[qtpng]"] qtpng = ["pyqtwebengine (>=5.15)"] serve = ["tornado (>=6.1)"] -test = ["ipykernel", "ipywidgets (>=7)", "pre-commit", "pytest", "pytest-dependency"] -webpdf = ["pyppeteer (>=1,<1.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest"] +webpdf = ["playwright"] [[package]] name = "nbformat" -version = "5.9.0" +version = "5.9.2" description = "The Jupyter Notebook format" optional = false python-versions = ">=3.8" files = [ - {file = "nbformat-5.9.0-py3-none-any.whl", hash = "sha256:8c8fa16d6d05062c26177754bfbfac22de644888e2ef69d27ad2a334cf2576e5"}, - {file = "nbformat-5.9.0.tar.gz", hash = "sha256:e98ebb6120c3efbafdee2a40af2a140cadee90bb06dd69a2a63d9551fcc7f976"}, + {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, + {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, ] [package.dependencies] @@ -1865,47 +1945,47 @@ traitlets = ">=5" [[package]] name = "nest-asyncio" -version = "1.5.6" +version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" files = [ - {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, - {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] [[package]] name = "networkx" -version = "3.1" +version = "3.2.1" description = "Python package for creating and manipulating graphs and networks" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"}, - {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"}, + {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, + {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, ] [package.extras] -default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] -developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"] -doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"] -extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] -test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] +default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "notebook" -version = "7.0.6" +version = "7.1.1" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.8" files = [ - {file = "notebook-7.0.6-py3-none-any.whl", hash = "sha256:0fe8f67102fea3744fedf652e4c15339390902ca70c5a31c4f547fa23da697cc"}, - {file = "notebook-7.0.6.tar.gz", hash = "sha256:ec6113b06529019f7f287819af06c97a2baf7a95ac21a8f6e32192898e9f9a58"}, + {file = "notebook-7.1.1-py3-none-any.whl", hash = "sha256:197d8e0595acabf4005851c8716e952a81b405f7aefb648067a761fbde267ce7"}, + {file = "notebook-7.1.1.tar.gz", hash = "sha256:818e7420fa21f402e726afb9f02df7f3c10f294c02e383ed19852866c316108b"}, ] [package.dependencies] jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.0.2,<5" +jupyterlab = ">=4.1.1,<4.2" jupyterlab-server = ">=2.22.1,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -1917,13 +1997,13 @@ test = ["importlib-resources (>=5.0)", "ipykernel", "jupyter-server[test] (>=2.4 [[package]] name = "notebook-shim" -version = "0.2.3" +version = "0.2.4" description = "A shim layer for notebook traits and config" optional = false python-versions = ">=3.7" files = [ - {file = "notebook_shim-0.2.3-py3-none-any.whl", hash = "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7"}, - {file = "notebook_shim-0.2.3.tar.gz", hash = "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9"}, + {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, + {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, ] [package.dependencies] @@ -1983,35 +2063,35 @@ tests = ["pytest", "pytest-cov", "pytest-pep8"] [[package]] name = "overrides" -version = "7.3.1" +version = "7.7.0" description = "A decorator to automatically detect mismatch when overriding a method." optional = false python-versions = ">=3.6" files = [ - {file = "overrides-7.3.1-py3-none-any.whl", hash = "sha256:6187d8710a935d09b0bcef8238301d6ee2569d2ac1ae0ec39a8c7924e27f58ca"}, - {file = "overrides-7.3.1.tar.gz", hash = "sha256:8b97c6c1e1681b78cbc9424b138d880f0803c2254c5ebaabdde57bb6c62093f2"}, + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, ] [[package]] name = "packaging" -version = "23.1" +version = "23.2" description = "Core utilities for Python packages" 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"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] name = "pandocfilters" -version = "1.5.0" +version = "1.5.1" description = "Utilities for writing pandoc filters in python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, - {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, ] [[package]] @@ -2031,131 +2111,138 @@ testing = ["docopt", "pytest (<6.0.0)"] [[package]] name = "pathspec" -version = "0.11.1" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "pexpect" -version = "4.8.0" +version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] [package.dependencies] ptyprocess = ">=0.5" -[[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -optional = false -python-versions = "*" -files = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] - [[package]] name = "pillow" -version = "10.0.1" +version = "10.2.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.8" files = [ - {file = "Pillow-10.0.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a"}, - {file = "Pillow-10.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f"}, - {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff"}, - {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf"}, - {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd"}, - {file = "Pillow-10.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0"}, - {file = "Pillow-10.0.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1"}, - {file = "Pillow-10.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205"}, - {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2"}, - {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b"}, - {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1"}, - {file = "Pillow-10.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088"}, - {file = "Pillow-10.0.1-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b"}, - {file = "Pillow-10.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a"}, - {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91"}, - {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4"}, - {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08"}, - {file = "Pillow-10.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08"}, - {file = "Pillow-10.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a"}, - {file = "Pillow-10.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d"}, - {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7"}, - {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a"}, - {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7"}, - {file = "Pillow-10.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3"}, - {file = "Pillow-10.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849"}, - {file = "Pillow-10.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f"}, - {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145"}, - {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2"}, - {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf"}, - {file = "Pillow-10.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4"}, - {file = "Pillow-10.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d"}, - {file = "Pillow-10.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d"}, - {file = "Pillow-10.0.1.tar.gz", hash = "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d"}, + {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, + {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, + {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, + {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, + {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, + {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, + {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, + {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, + {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, + {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, + {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, + {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, + {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, + {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, + {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, + {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, + {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, + {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, ] [package.extras] docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "3.5.1" +version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, - {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -2178,13 +2265,13 @@ six = ">=1.5.2" [[package]] name = "prometheus-client" -version = "0.17.0" +version = "0.20.0" description = "Python client for the Prometheus monitoring system." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.17.0-py3-none-any.whl", hash = "sha256:a77b708cf083f4d1a3fb3ce5c95b4afa32b9c521ae363354a4a910204ea095ce"}, - {file = "prometheus_client-0.17.0.tar.gz", hash = "sha256:9c3b26f1535945e85b8934fb374678d263137b78ef85f305b1156c7c881cd11b"}, + {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, + {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, ] [package.extras] @@ -2192,13 +2279,13 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.38" +version = "3.0.43" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"}, - {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"}, + {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, + {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, ] [package.dependencies] @@ -2206,25 +2293,27 @@ wcwidth = "*" [[package]] name = "psutil" -version = "5.9.5" +version = "5.9.8" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, - {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, - {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, - {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, - {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, - {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, - {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, - {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, + {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, + {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, + {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, + {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, + {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, + {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, + {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, + {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, + {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, + {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, ] [package.extras] @@ -2279,43 +2368,43 @@ files = [ [[package]] name = "pygments" -version = "2.15.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." 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"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "3.0.2" +version = "3.1.0" description = "python code static checker" optional = false python-versions = ">=3.8.0" files = [ - {file = "pylint-3.0.2-py3-none-any.whl", hash = "sha256:60ed5f3a9ff8b61839ff0348b3624ceeb9e6c2a92c514d81c9cc273da3b6bcda"}, - {file = "pylint-3.0.2.tar.gz", hash = "sha256:0d4c286ef6d2f66c8bfb527a7f8a629009e42c99707dec821a03e1b51a4c1496"}, + {file = "pylint-3.1.0-py3-none-any.whl", hash = "sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74"}, + {file = "pylint-3.1.0.tar.gz", hash = "sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23"}, ] [package.dependencies] -astroid = ">=3.0.1,<=3.1.0-dev0" +astroid = ">=3.1.0,<=3.2.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] -isort = ">=4.2.5,<6" +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] @@ -2323,49 +2412,48 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymatching" -version = "2.1.0" +version = "2.2.0" description = "A package for decoding quantum error correcting codes using minimum-weight perfect matching." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "PyMatching-2.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ab4ae5abefead03ca231e50de1408197364cd69aeca17cf3dec9a8b5a9196de9"}, - {file = "PyMatching-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:5d177de1c612e38078d6a551d6a766203341a7ca4a95587e7dc1643f61d4dff5"}, - {file = "PyMatching-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82da39eed6011b1055232cad52c6e1f5e193df802de467502b261378bc2d2104"}, - {file = "PyMatching-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3097041d1efc2934fb4c0e16edb388f8e84d7d5dd7bc21d53fd0d96ed8eb0ea"}, - {file = "PyMatching-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:5181ce33f95dc33fd64cde1fe9d626a2ecf27ef9080b8fc92803acbcb770fc0a"}, - {file = "PyMatching-2.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:ce6987ad84ef19dc4eaeb460e53f045a951e43742dac67a3cc1a5c6d50fc320c"}, - {file = "PyMatching-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:b4d5338e3328d405bf226a682d49b5aa37ef5349e10129955b68dca0b4c33ed9"}, - {file = "PyMatching-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ba82abae1234328befef97ecfc38acadcc6b23b98a0ff69639fdd970d1a4909"}, - {file = "PyMatching-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb13ece67ad2d204a095f31a030cfb4eeb02f9b35b1b15fddef13e8195ef522"}, - {file = "PyMatching-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0782f34d2ed1331e593197969956bae4273b0cb778c76707ad46e5d813755e52"}, - {file = "PyMatching-2.1.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:45e4f07a0e804dae8fee2fb16496611afded0a16aada2dfd3b4b90a33c0973ee"}, - {file = "PyMatching-2.1.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80617de9e678c3d991815535ab757d2d46f18bb9429788413a6670d9c6b462fe"}, - {file = "PyMatching-2.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7910af7cab14fe3b01ede061f058921cbe2494b66437c6aabf9f385be3e6638"}, - {file = "PyMatching-2.1.0-cp36-cp36m-win32.whl", hash = "sha256:3418d7133087191cce347dc764eff36f235f8cfaf3187e75fd58327484d42a30"}, - {file = "PyMatching-2.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:3de1bc63099ab1cd2a502e56a60c730ca0e2b52079479d770e9bacf9e0be264c"}, - {file = "PyMatching-2.1.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:91d39cea97f77ec4c8c7a0e79603c0ef5c4b6e1d8d75d1b792636f183eee3ff1"}, - {file = "PyMatching-2.1.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb793f4d560210b187dc398729ad7fbcb1d1d4d71bb443fdae01ffe6707f09ab"}, - {file = "PyMatching-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:790e58ba1fd2569ea22329da72de0386d84517a5b8af89374866a58051e1e2cb"}, - {file = "PyMatching-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:a8d17c2b53a19edbab9ba15e7bd6e56df71b3069f76d79a941b4041e386d0ddc"}, - {file = "PyMatching-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c4ee8c007e6ba4ebdec70432570075e0af1ce98f2f34948fff564893ff975dd"}, - {file = "PyMatching-2.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:d73e3a480eb6d9bdac5b11d863864cfbb136d94ae160082391042e631e19ab4d"}, - {file = "PyMatching-2.1.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b6e59711e78e282f087c6759010bb321a85f13129bec276a4444084a9ab6c742"}, - {file = "PyMatching-2.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bab8d89d4a488cb0e98dbc4405ee0d0dbba4dee523641dc6004a80443e9fa593"}, - {file = "PyMatching-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c38d84a843dc902bc50a898598e0ecfad2f9d5ece5bc007bce7efa424f97216"}, - {file = "PyMatching-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b5c6a45f3a0026960a5cc9e5b838ecb27c0b70f85109fc41d2f16368259c542"}, - {file = "PyMatching-2.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:1d85c122c70db3c0866ecc128224147e10e8a18489fa5b86a68874db96537550"}, - {file = "PyMatching-2.1.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:0a02e03418f79131727d7790cdb35e7a2724e29281831881f7a6727689419c0f"}, - {file = "PyMatching-2.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e5905b17af054c65b594e937ba80dd1889aa9f9ed0d094f4fa10047c0130e039"}, - {file = "PyMatching-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5eff8460b278fcc9fe56da9c6e2b9d2715de07ed5dcc8b39f2996de14c841e1"}, - {file = "PyMatching-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:61967336d49c621069e74673c23e8c22208543361a5ada209936e0120b9f580e"}, - {file = "PyMatching-2.1.0.tar.gz", hash = "sha256:c1fef049febc5b04b415234c64a5fee4f28a0f9c5f66d1f7f7ae81dfd79e4987"}, + {file = "PyMatching-2.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ecb65e6897ce0ce3c841771e6d4d9d22aafbc174185f2d1a6441c310d1783059"}, + {file = "PyMatching-2.2.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:2812c2602c9f1c91e73920fecbd1916b941e911538b4495265bfdc3b3e066fbe"}, + {file = "PyMatching-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f1dc0efd6cd1634f72d7ca2b260b7b287a996460075861e27af89b078eb1293"}, + {file = "PyMatching-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f11f5ea748fd69c28c93301f8aa59c6d5be6a8caec313cebc6089e29dcf5168f"}, + {file = "PyMatching-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:d08710cfc734ce8214ea242a7f1c8547105b37166ba4b61c34636bbafce967be"}, + {file = "PyMatching-2.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:353b4b0491aaf71a3ca72714bb996bdb9d8e2bf4803cf905455332f5c2d22779"}, + {file = "PyMatching-2.2.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:3136194ed00c432f4890d0e6224cd857b45013aefdecf1bad3a30a93d8da2207"}, + {file = "PyMatching-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f239f77d7c0968606b8b4d1e6ca8e86b17be59ecee236538b6e61dea0affa44d"}, + {file = "PyMatching-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5688f18d63e7981656f3c8f9ffef4ef22a74228b10e47100311a97f0184cb7"}, + {file = "PyMatching-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:ee1a5e8ed401309959baac06c784bf044cc3940b06ddfacf2a61579a8c0c70e3"}, + {file = "PyMatching-2.2.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:050b530f0854d424cb5ba4450f9c5a4283e0d9bb5ef5b849b37ac5312dcca08d"}, + {file = "PyMatching-2.2.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:2ef156437f345819c881d3aebb339c784c42f55438f07007ad24c05bb22dd61d"}, + {file = "PyMatching-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db67924b7603af9d845423b037048f982c6cc687e582239f3640a4e1b0e3caba"}, + {file = "PyMatching-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bc5b967002e941178c50cc79124688f7f4a2454d5de87678b074ed2d2cbc236"}, + {file = "PyMatching-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3fa41b776e41c2687d76c05d68dbf3b5c4cabf942b6a5051eef41d6a8590fb21"}, + {file = "PyMatching-2.2.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:a49213fcafe5ca07aaf6e05982cba612b65e0a2560c99996b8754bf8e81d5fc8"}, + {file = "PyMatching-2.2.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe02d4fd348ce7b8613cb7c995a2cc0479a7a46f233d25810d522c5cad225251"}, + {file = "PyMatching-2.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:580b9c9bb33c883b25e139bb9c2649bb1f245fe7c6b514dfb788e395c9276a0e"}, + {file = "PyMatching-2.2.0-cp37-cp37m-win32.whl", hash = "sha256:57acf834e2ba95c412060c63f70f44b0210bdd2f52395f4c9fb9b37c68d2f35c"}, + {file = "PyMatching-2.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6ab55daed4d0c35a96e5eab3162c0ffe9c5d7d13093db9d4d14bac4d6851c754"}, + {file = "PyMatching-2.2.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bf851a139a136ccbab3024bab476ecbd22ce44f4c4848f9b189ff1bf57d9adb1"}, + {file = "PyMatching-2.2.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:30b2cab3c4159d4accf87025a62e2e4bb9b45df630c8afa01f2d131734043a57"}, + {file = "PyMatching-2.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:da06e0195a918b8c304d1cbc0d37968b863d97bbd46887bfabf8c1d96d23e27f"}, + {file = "PyMatching-2.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831cf0f68b5f76cd6f1e2458f2dd5937d41b34ecc002f534eeb7e6b2db8f755"}, + {file = "PyMatching-2.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:040881cab6cac71be54851b1ef0c0ad296fb6f6a42ad02246bfdc63d50fc50a7"}, + {file = "PyMatching-2.2.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:634b2a7316e835da9def77d367cfc8dce680e44daa1643e365659e90d8f91c93"}, + {file = "PyMatching-2.2.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:749d2ddf85e18788a5b063b88340ef5674f68d3ba82180915e05c0401182d5fb"}, + {file = "PyMatching-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b99299344a62c243e1d2d9012a49976761c42dc24a9448f6972436209d6b6cd"}, + {file = "PyMatching-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72b3acd0160b49b61d5beaf184cf48edd3ee0eb16fc4fc379486f4a767cd565c"}, + {file = "PyMatching-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:5d2fe3f8a0665d40fb3e5f3115913285833434c9eb36b11740bfaede29fa7941"}, + {file = "PyMatching-2.2.0.tar.gz", hash = "sha256:d8046f5ef970c27b20d8dd55a01b89509d0eb4398abaf2ef725d77ef2b98d65a"}, ] [package.dependencies] matplotlib = "*" networkx = "*" numpy = "*" -retworkx = ">=0.11.0" scipy = "*" [package.extras] @@ -2373,13 +2461,13 @@ test = ["pytest (>=6.0)"] [[package]] name = "pyparsing" -version = "3.0.9" +version = "3.1.1" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.6.8" files = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, ] [package.extras] @@ -2387,13 +2475,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.4.3" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, - {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -2427,13 +2515,13 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" 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"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -2475,152 +2563,179 @@ files = [ [[package]] name = "pywinpty" -version = "2.0.10" +version = "2.0.13" description = "Pseudo terminal support for Windows from Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pywinpty-2.0.10-cp310-none-win_amd64.whl", hash = "sha256:4c7d06ad10f6e92bc850a467f26d98f4f30e73d2fe5926536308c6ae0566bc16"}, - {file = "pywinpty-2.0.10-cp311-none-win_amd64.whl", hash = "sha256:7ffbd66310b83e42028fc9df7746118978d94fba8c1ebf15a7c1275fdd80b28a"}, - {file = "pywinpty-2.0.10-cp37-none-win_amd64.whl", hash = "sha256:38cb924f2778b5751ef91a75febd114776b3af0ae411bc667be45dd84fc881d3"}, - {file = "pywinpty-2.0.10-cp38-none-win_amd64.whl", hash = "sha256:902d79444b29ad1833b8d5c3c9aabdfd428f4f068504430df18074007c8c0de8"}, - {file = "pywinpty-2.0.10-cp39-none-win_amd64.whl", hash = "sha256:3c46aef80dd50979aff93de199e4a00a8ee033ba7a03cadf0a91fed45f0c39d7"}, - {file = "pywinpty-2.0.10.tar.gz", hash = "sha256:cdbb5694cf8c7242c2ecfaca35c545d31fa5d5814c3d67a4e628f803f680ebea"}, + {file = "pywinpty-2.0.13-cp310-none-win_amd64.whl", hash = "sha256:697bff211fb5a6508fee2dc6ff174ce03f34a9a233df9d8b5fe9c8ce4d5eaf56"}, + {file = "pywinpty-2.0.13-cp311-none-win_amd64.whl", hash = "sha256:b96fb14698db1284db84ca38c79f15b4cfdc3172065b5137383910567591fa99"}, + {file = "pywinpty-2.0.13-cp312-none-win_amd64.whl", hash = "sha256:2fd876b82ca750bb1333236ce98488c1be96b08f4f7647cfdf4129dfad83c2d4"}, + {file = "pywinpty-2.0.13-cp38-none-win_amd64.whl", hash = "sha256:61d420c2116c0212808d31625611b51caf621fe67f8a6377e2e8b617ea1c1f7d"}, + {file = "pywinpty-2.0.13-cp39-none-win_amd64.whl", hash = "sha256:71cb613a9ee24174730ac7ae439fd179ca34ccb8c5349e8d7b72ab5dea2c6f4b"}, + {file = "pywinpty-2.0.13.tar.gz", hash = "sha256:c34e32351a3313ddd0d7da23d27f835c860d32fe4ac814d372a3ea9594f41dde"}, ] [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" 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"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] name = "pyzmq" -version = "25.1.0" +version = "25.1.2" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.6" files = [ - {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:1a6169e69034eaa06823da6a93a7739ff38716142b3596c180363dee729d713d"}, - {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:19d0383b1f18411d137d891cab567de9afa609b214de68b86e20173dc624c101"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1e931d9a92f628858a50f5bdffdfcf839aebe388b82f9d2ccd5d22a38a789dc"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d984b1b2f574bc1bb58296d3c0b64b10e95e7026f8716ed6c0b86d4679843f"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:154bddda2a351161474b36dba03bf1463377ec226a13458725183e508840df89"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cb6d161ae94fb35bb518b74bb06b7293299c15ba3bc099dccd6a5b7ae589aee3"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:90146ab578931e0e2826ee39d0c948d0ea72734378f1898939d18bc9c823fcf9"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:831ba20b660b39e39e5ac8603e8193f8fce1ee03a42c84ade89c36a251449d80"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a522510e3434e12aff80187144c6df556bb06fe6b9d01b2ecfbd2b5bfa5c60c"}, - {file = "pyzmq-25.1.0-cp310-cp310-win32.whl", hash = "sha256:be24a5867b8e3b9dd5c241de359a9a5217698ff616ac2daa47713ba2ebe30ad1"}, - {file = "pyzmq-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:5693dcc4f163481cf79e98cf2d7995c60e43809e325b77a7748d8024b1b7bcba"}, - {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:13bbe36da3f8aaf2b7ec12696253c0bf6ffe05f4507985a8844a1081db6ec22d"}, - {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:69511d604368f3dc58d4be1b0bad99b61ee92b44afe1cd9b7bd8c5e34ea8248a"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a983c8694667fd76d793ada77fd36c8317e76aa66eec75be2653cef2ea72883"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:332616f95eb400492103ab9d542b69d5f0ff628b23129a4bc0a2fd48da6e4e0b"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58416db767787aedbfd57116714aad6c9ce57215ffa1c3758a52403f7c68cff5"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cad9545f5801a125f162d09ec9b724b7ad9b6440151b89645241d0120e119dcc"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d6128d431b8dfa888bf51c22a04d48bcb3d64431caf02b3cb943269f17fd2994"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b15247c49d8cbea695b321ae5478d47cffd496a2ec5ef47131a9e79ddd7e46c"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:442d3efc77ca4d35bee3547a8e08e8d4bb88dadb54a8377014938ba98d2e074a"}, - {file = "pyzmq-25.1.0-cp311-cp311-win32.whl", hash = "sha256:65346f507a815a731092421d0d7d60ed551a80d9b75e8b684307d435a5597425"}, - {file = "pyzmq-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b45d722046fea5a5694cba5d86f21f78f0052b40a4bbbbf60128ac55bfcc7b6"}, - {file = "pyzmq-25.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f45808eda8b1d71308c5416ef3abe958f033fdbb356984fabbfc7887bed76b3f"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b697774ea8273e3c0460cf0bba16cd85ca6c46dfe8b303211816d68c492e132"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b324fa769577fc2c8f5efcd429cef5acbc17d63fe15ed16d6dcbac2c5eb00849"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:5873d6a60b778848ce23b6c0ac26c39e48969823882f607516b91fb323ce80e5"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f0d9e7ba6a815a12c8575ba7887da4b72483e4cfc57179af10c9b937f3f9308f"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:414b8beec76521358b49170db7b9967d6974bdfc3297f47f7d23edec37329b00"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:01f06f33e12497dca86353c354461f75275a5ad9eaea181ac0dc1662da8074fa"}, - {file = "pyzmq-25.1.0-cp36-cp36m-win32.whl", hash = "sha256:b5a07c4f29bf7cb0164664ef87e4aa25435dcc1f818d29842118b0ac1eb8e2b5"}, - {file = "pyzmq-25.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968b0c737797c1809ec602e082cb63e9824ff2329275336bb88bd71591e94a90"}, - {file = "pyzmq-25.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47b915ba666c51391836d7ed9a745926b22c434efa76c119f77bcffa64d2c50c"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af31493663cf76dd36b00dafbc839e83bbca8a0662931e11816d75f36155897"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5489738a692bc7ee9a0a7765979c8a572520d616d12d949eaffc6e061b82b4d1"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1fc56a0221bdf67cfa94ef2d6ce5513a3d209c3dfd21fed4d4e87eca1822e3a3"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:75217e83faea9edbc29516fc90c817bc40c6b21a5771ecb53e868e45594826b0"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3830be8826639d801de9053cf86350ed6742c4321ba4236e4b5568528d7bfed7"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3575699d7fd7c9b2108bc1c6128641a9a825a58577775ada26c02eb29e09c517"}, - {file = "pyzmq-25.1.0-cp37-cp37m-win32.whl", hash = "sha256:95bd3a998d8c68b76679f6b18f520904af5204f089beebb7b0301d97704634dd"}, - {file = "pyzmq-25.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dbc466744a2db4b7ca05589f21ae1a35066afada2f803f92369f5877c100ef62"}, - {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:3bed53f7218490c68f0e82a29c92335daa9606216e51c64f37b48eb78f1281f4"}, - {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb52e826d16c09ef87132c6e360e1879c984f19a4f62d8a935345deac43f3c12"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ddbef8b53cd16467fdbfa92a712eae46dd066aa19780681a2ce266e88fbc7165"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9301cf1d7fc1ddf668d0abbe3e227fc9ab15bc036a31c247276012abb921b5ff"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e23a8c3b6c06de40bdb9e06288180d630b562db8ac199e8cc535af81f90e64b"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4a82faae00d1eed4809c2f18b37f15ce39a10a1c58fe48b60ad02875d6e13d80"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8398a1b1951aaa330269c35335ae69744be166e67e0ebd9869bdc09426f3871"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d40682ac60b2a613d36d8d3a0cd14fbdf8e7e0618fbb40aa9fa7b796c9081584"}, - {file = "pyzmq-25.1.0-cp38-cp38-win32.whl", hash = "sha256:33d5c8391a34d56224bccf74f458d82fc6e24b3213fc68165c98b708c7a69325"}, - {file = "pyzmq-25.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c66b7ff2527e18554030319b1376d81560ca0742c6e0b17ff1ee96624a5f1afd"}, - {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:af56229ea6527a849ac9fb154a059d7e32e77a8cba27e3e62a1e38d8808cb1a5"}, - {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdca18b94c404af6ae5533cd1bc310c4931f7ac97c148bbfd2cd4bdd62b96253"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b6b42f7055bbc562f63f3df3b63e3dd1ebe9727ff0f124c3aa7bcea7b3a00f9"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c2fc7aad520a97d64ffc98190fce6b64152bde57a10c704b337082679e74f67"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86a26415a8b6af02cd8d782e3a9ae3872140a057f1cadf0133de685185c02b"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:851fb2fe14036cfc1960d806628b80276af5424db09fe5c91c726890c8e6d943"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2a21fec5c3cea45421a19ccbe6250c82f97af4175bc09de4d6dd78fb0cb4c200"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bad172aba822444b32eae54c2d5ab18cd7dee9814fd5c7ed026603b8cae2d05f"}, - {file = "pyzmq-25.1.0-cp39-cp39-win32.whl", hash = "sha256:4d67609b37204acad3d566bb7391e0ecc25ef8bae22ff72ebe2ad7ffb7847158"}, - {file = "pyzmq-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:71c7b5896e40720d30cd77a81e62b433b981005bbff0cb2f739e0f8d059b5d99"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cb27ef9d3bdc0c195b2dc54fcb8720e18b741624686a81942e14c8b67cc61a6"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c4fc2741e0513b5d5a12fe200d6785bbcc621f6f2278893a9ca7bed7f2efb7d"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc34fdd458ff77a2a00e3c86f899911f6f269d393ca5675842a6e92eea565bae"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8751f9c1442624da391bbd92bd4b072def6d7702a9390e4479f45c182392ff78"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6581e886aec3135964a302a0f5eb68f964869b9efd1dbafdebceaaf2934f8a68"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5482f08d2c3c42b920e8771ae8932fbaa0a67dff925fc476996ddd8155a170f3"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7fbcafa3ea16d1de1f213c226005fea21ee16ed56134b75b2dede5a2129e62"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adecf6d02b1beab8d7c04bc36f22bb0e4c65a35eb0b4750b91693631d4081c70"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6d39e42a0aa888122d1beb8ec0d4ddfb6c6b45aecb5ba4013c27e2f28657765"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7018289b402ebf2b2c06992813523de61d4ce17bd514c4339d8f27a6f6809492"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9e68ae9864d260b18f311b68d29134d8776d82e7f5d75ce898b40a88df9db30f"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e21cc00e4debe8f54c3ed7b9fcca540f46eee12762a9fa56feb8512fd9057161"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f666ae327a6899ff560d741681fdcdf4506f990595201ed39b44278c471ad98"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f5efcc29056dfe95e9c9db0dfbb12b62db9c4ad302f812931b6d21dd04a9119"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:48e5e59e77c1a83162ab3c163fc01cd2eebc5b34560341a67421b09be0891287"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:108c96ebbd573d929740d66e4c3d1bdf31d5cde003b8dc7811a3c8c5b0fc173b"}, - {file = "pyzmq-25.1.0.tar.gz", hash = "sha256:80c41023465d36280e801564a69cbfce8ae85ff79b080e1913f6e90481fb8957"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08"}, + {file = "pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886"}, + {file = "pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3"}, + {file = "pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097"}, + {file = "pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737"}, + {file = "pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d"}, + {file = "pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win32.whl", hash = "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68"}, + {file = "pyzmq-25.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win32.whl", hash = "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755"}, + {file = "pyzmq-25.1.2-cp38-cp38-win32.whl", hash = "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07"}, + {file = "pyzmq-25.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2"}, + {file = "pyzmq-25.1.2-cp39-cp39-win32.whl", hash = "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289"}, + {file = "pyzmq-25.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314"}, + {file = "pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226"}, ] [package.dependencies] @@ -2662,24 +2777,23 @@ files = [ [[package]] name = "qtconsole" -version = "5.4.3" +version = "5.5.1" description = "Jupyter Qt console" optional = false -python-versions = ">= 3.7" +python-versions = ">= 3.8" files = [ - {file = "qtconsole-5.4.3-py3-none-any.whl", hash = "sha256:35fd6e87b1f6d1fd41801b07e69339f8982e76afd4fa8ef35595bc6036717189"}, - {file = "qtconsole-5.4.3.tar.gz", hash = "sha256:5e4082a86a201796b2a5cfd4298352d22b158b51b57736531824715fc2a979dd"}, + {file = "qtconsole-5.5.1-py3-none-any.whl", hash = "sha256:8c75fa3e9b4ed884880ff7cea90a1b67451219279ec33deaee1d59e3df1a5d2b"}, + {file = "qtconsole-5.5.1.tar.gz", hash = "sha256:a0e806c6951db9490628e4df80caec9669b65149c7ba40f9bf033c025a5b56bc"}, ] [package.dependencies] ipykernel = ">=4.1" -ipython-genutils = "*" jupyter-client = ">=4.1" jupyter-core = "*" packaging = "*" pygments = "*" pyzmq = ">=17.1" -qtpy = ">=2.0.1" +qtpy = ">=2.4.0" traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" [package.extras] @@ -2688,13 +2802,13 @@ test = ["flaky", "pytest", "pytest-qt"] [[package]] name = "qtpy" -version = "2.3.1" +version = "2.4.1" description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." optional = false python-versions = ">=3.7" files = [ - {file = "QtPy-2.3.1-py3-none-any.whl", hash = "sha256:5193d20e0b16e4d9d3bc2c642d04d9f4e2c892590bd1b9c92bfe38a95d5a2e12"}, - {file = "QtPy-2.3.1.tar.gz", hash = "sha256:a8c74982d6d172ce124d80cafd39653df78989683f760f2281ba91a6e7b9de8b"}, + {file = "QtPy-2.4.1-py3-none-any.whl", hash = "sha256:1c1d8c4fa2c884ae742b069151b0abe15b3f70491f3972698c683b8e38de839b"}, + {file = "QtPy-2.4.1.tar.gz", hash = "sha256:a5a15ffd519550a1361bdc56ffc07fda56a6af7292f17c7b395d4083af632987"}, ] [package.dependencies] @@ -2739,25 +2853,6 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "retworkx" -version = "0.13.2" -description = "A python graph library implemented in Rust" -optional = false -python-versions = ">=3.7" -files = [ - {file = "retworkx-0.13.2-py3-none-any.whl", hash = "sha256:693336a1f1f04c5017258ddff78f018e06cfd55b8e16b1e2d8dd98fe1e752e18"}, -] - -[package.dependencies] -numpy = ">=1.16.0" -rustworkx = "0.13.2" - -[package.extras] -all = ["matplotlib (>=3.0)", "pillow (>=5.4)"] -graphviz = ["pillow (>=5.4)"] -mpl = ["matplotlib (>=3.0)"] - [[package]] name = "rfc3339-validator" version = "0.1.4" @@ -2896,117 +2991,150 @@ name = "rustworkx" version = "0.13.2" description = "A python graph library implemented in Rust" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "rustworkx-0.13.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:915aae559ac9eef1f5fc4f6b8c094d353e2b62df0cd164ac5fb44f2c5ebe19d5"}, - {file = "rustworkx-0.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51856470f221796be84497aaf933f14964395e0aff41b6d8fd342d9ac43d8f00"}, - {file = "rustworkx-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:371a3f7bdf0e35280bb7d7fc3e2a70aec6d76a564b3878563d5c0f7cf14f2cfa"}, - {file = "rustworkx-0.13.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76042e30b18735bca37f03182b3e6159977bdd568d85ef7f996e520f64f81061"}, - {file = "rustworkx-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b46cc9f89944a5d5e26d6c1602ceeff76b1f4d95790dd7ec47c9f1cc6b95f"}, - {file = "rustworkx-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3909942339d7a95a894c3255f8c74ffc7686354a1358e7984abd6059c60f36a6"}, - {file = "rustworkx-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e96b80a3821d27ce04f4429e3aa1cb29b369b8c09c517512693bacb8a36c0868"}, - {file = "rustworkx-0.13.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1ca99cd92c5e969c220a4ae8fa413c6d679e83c0dbce5f86c0fff8874fd5ed9f"}, - {file = "rustworkx-0.13.2-cp310-cp310-win32.whl", hash = "sha256:5961b11ee36fefe2909373ef4551e58588000bf2bc1c177ce190b4bf796a1a73"}, - {file = "rustworkx-0.13.2-cp310-cp310-win_amd64.whl", hash = "sha256:01b26cb2827fda7ad2de35e166fa54ad23b4136080b6cf4f897a18450f2cfb67"}, - {file = "rustworkx-0.13.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cfed0f9ee080d1b16d57ad82559bbdef3cca87b9aa3d573b7108d3ca4ad29388"}, - {file = "rustworkx-0.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4731701e661f4fb6f7e1c16441f71a071804ec6c9da7d76d742d7e9a7d19d6e4"}, - {file = "rustworkx-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c147a9efca672a4b8dd774a6f2bb78dfbce8efaea52933e3eb520d3618302832"}, - {file = "rustworkx-0.13.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbec49f04dc387a2e22b3d54a9283d4c7dbef0bd7222ee70b7d68f927da7f7fd"}, - {file = "rustworkx-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ef239663d3baf4cbdd7a8a2752f8edf544d853e89024d159bbb742efa83f26a"}, - {file = "rustworkx-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1a174674489f416d852ea42b346a59cc4c02e4bd0e11404f94c5e499de05a29"}, - {file = "rustworkx-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546d089917ad9b1ac9c95af2d6295d2b343392a651805b458958347a0e568a82"}, - {file = "rustworkx-0.13.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60933aea34c014b3dfaa6a8f5d81f6c92cf49d21cab2a3d2989590d477776997"}, - {file = "rustworkx-0.13.2-cp311-cp311-win32.whl", hash = "sha256:cd10e5654d1ce9c112f344034865a0a94b4da805764485889a723f2da2699cb7"}, - {file = "rustworkx-0.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:d5b640d5eff6574096a073d9c854d462effb30682aefeb71e5070d0ecd65c700"}, - {file = "rustworkx-0.13.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ec1260a0b81d457858a014646c1aec02d1440d62e7b8f9fb72bd819feae86865"}, - {file = "rustworkx-0.13.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:59562edf290ba2d5383ecbac047adc5ab95c9fd8f15f2c1d540562acb4aadf66"}, - {file = "rustworkx-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24a5daf8ef6d7a80c08bc1a00dea1e7b668160cf6264be1e717c1e451b486bd8"}, - {file = "rustworkx-0.13.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a658895541772e76aa895de289e3bedcf1e4676314e4f78d23520b1d5bef2146"}, - {file = "rustworkx-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2fcd805e378eec3fc9ed4338d17d2c6ee517021f9d60187dc9975d2cd761b0e"}, - {file = "rustworkx-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:542263b7eb8587e48b1f9ea010c6c9d24102b8082870b11a388dac1e74ab135a"}, - {file = "rustworkx-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bdc0745fa448d0a05d92c4c85af3a65d7264a9d2ec714f9e6645272f7e4d1cfc"}, - {file = "rustworkx-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3cfc0cecb0f400155bedcb7ba1078921f51faf14ad7231d166f2ede42fdba7b"}, - {file = "rustworkx-0.13.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbecd5ebd5679909f400e1de990d2a1fdbc2aa6a243faa23699511e4601777c5"}, - {file = "rustworkx-0.13.2-cp312-cp312-win32.whl", hash = "sha256:0fdf8733323684d4d4d3a37d05ae6f46a13483bee96ac329b841c44216328c9d"}, - {file = "rustworkx-0.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:a66a7fc98a30e7fefd225ee6eed4b8850af9baeaa7ea1df90f4091419dfa3b4b"}, - {file = "rustworkx-0.13.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:844d14a37e4ba5b56f791c2d3f23275f26649b1e11685d05cd5009b3cd4100cf"}, - {file = "rustworkx-0.13.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88b83dc818bfea1ad743f324d1edc6920ede7345943932453628771ce290d8b2"}, - {file = "rustworkx-0.13.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7207c52417b48e01e11018cb116b53873c67effd528f2696baa1b6d936c00e99"}, - {file = "rustworkx-0.13.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7014e33d25b3cd7c03004849b685fb7cf934e409c71854fe888bc71f86a26804"}, - {file = "rustworkx-0.13.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d99b6bfae1b2e59c23badaba1317a8fe527f493aa9d037a2d2910060af460852"}, - {file = "rustworkx-0.13.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38773f5421c7125339251864fdbad205d9ecaf960000f3a69157ccae0060970e"}, - {file = "rustworkx-0.13.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2a1cf52ed583225960c5f11faa88090f7e871075f29603bead69e67d4a661ad7"}, - {file = "rustworkx-0.13.2-cp37-cp37m-win32.whl", hash = "sha256:47b12d3b6aa3196f1f0747f233a8e9eece9b81a5e7eb41e1cae3960db87d18d1"}, - {file = "rustworkx-0.13.2-cp37-cp37m-win_amd64.whl", hash = "sha256:15cc9d8f684b850aba3e89f9bdbba0f0cf249a17c8eb42ef015adf6a56e29c20"}, - {file = "rustworkx-0.13.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e044469483508b53f2e246b737e49fc04f0f4ab5a6178a8eb9d423e52ebf6ead"}, - {file = "rustworkx-0.13.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6cc15ea8feed0568f7682045e7d7b18974455f910e1fc3e0b6bdcbf526bd6673"}, - {file = "rustworkx-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d82e269b5c293e301334e1e7ff10d406767bbfac70bc398496f33cfa4e80fec4"}, - {file = "rustworkx-0.13.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80e7f20cd3ecbdaa1d5ff149ce2dae0d389c9983c84dec6b95c9db669b6aedd0"}, - {file = "rustworkx-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c06b37d8b1c1d454cde38ebc5ed82eded26db865df79ba46532aef996b3f8ac"}, - {file = "rustworkx-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af329d05b4e39bf98cbfb412438dc2dc14f017a53feafec003d1fcf6470f82c8"}, - {file = "rustworkx-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f5650813ce4379c5399f1559870ba42f745d01bac05fc0c3b4805128ee03161"}, - {file = "rustworkx-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d585d9336b039b3bf5e31daa7a25d6400fe9d2025c1d1ccedcfa757132a2a15d"}, - {file = "rustworkx-0.13.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2f677a13a33a92ce185973d83be4a4621a149924800bacb37d538b617b160981"}, - {file = "rustworkx-0.13.2-cp38-cp38-win32.whl", hash = "sha256:604038ee0fe9b6f72d1c4b0529da1d15b46b757381be569f66540ab5ffb0f9c8"}, - {file = "rustworkx-0.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:24bfa0d22db1c0ec34074655f4533fb780db65d87e2189569d47608e5e80c852"}, - {file = "rustworkx-0.13.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:df27694f9822b35902a9e89458f8d37b02e452586dc30fcfeee3d95672846ac7"}, - {file = "rustworkx-0.13.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cc29b6b08d41f06aa8d011bcfc7dba17599231a1c4b172d6007a6eb5ae589124"}, - {file = "rustworkx-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:907fa93a377b18ae7360f64a20b1949e06d50faeeaaa5ff4620b697598eb1214"}, - {file = "rustworkx-0.13.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c62c99cfad1f8112297e80a9e7a23ca420b4d86a8c49f7ebdf7e1f31d43122f5"}, - {file = "rustworkx-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9553deb3a834a14192f354d2da80c2bda146523df270c7505501b1800057dc88"}, - {file = "rustworkx-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69183adf48ab25361ec2ac62b789662de49190b532a03533b2c711a4cbbd7c40"}, - {file = "rustworkx-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3db0224b41e68b1905814c4817d39a35b0d8174850a265cc3ef129439b39bc6a"}, - {file = "rustworkx-0.13.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:51fd1c1d9db2aec6f445b9f06a12e8cb579af6f208f6d8909014d00cef03b23f"}, - {file = "rustworkx-0.13.2-cp39-cp39-win32.whl", hash = "sha256:36980ad7a5e831284cc77c9f6f13631429af81010c6692c1d39519919c6901ca"}, - {file = "rustworkx-0.13.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f47df1ceda48cf1351fbeefa15fb7704c28c2f6d72c10e15f45f0eb708903bd"}, - {file = "rustworkx-0.13.2.tar.gz", hash = "sha256:0276cf0b989211859e8797b67d4c16ed6ac9eb32edb67e0a47e70d7d71e80574"}, -] - -[package.dependencies] -numpy = ">=1.16.0" - -[package.extras] -all = ["matplotlib (>=3.0)", "pillow (>=5.4)"] -graphviz = ["pillow (>=5.4)"] -mpl = ["matplotlib (>=3.0)"] + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, +] [[package]] name = "scipy" -version = "1.9.3" +version = "1.12.0" description = "Fundamental algorithms for scientific computing in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"}, - {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"}, - {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"}, - {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"}, - {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"}, - {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"}, - {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"}, -] - -[package.dependencies] -numpy = ">=1.18.5,<1.26.0" - -[package.extras] -dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"] -test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, + {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, + {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, + {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, + {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, + {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, + {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, + {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, + {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, + {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, + {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, +] + +[package.dependencies] +numpy = ">=1.22.4,<1.29.0" + +[package.extras] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "send2trash" @@ -3026,19 +3154,19 @@ win32 = ["pywin32"] [[package]] name = "setuptools" -version = "69.0.2" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, - {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "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] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -3053,13 +3181,13 @@ files = [ [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] @@ -3075,24 +3203,24 @@ files = [ [[package]] name = "soupsieve" -version = "2.4.1" +version = "2.5" description = "A modern CSS selector implementation for Beautiful Soup." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"}, - {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"}, + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, ] [[package]] name = "sphinx" -version = "7.1.2" +version = "7.2.6" description = "Python documentation generator" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, - {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, + {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, + {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, ] [package.dependencies] @@ -3101,10 +3229,9 @@ 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" +Pygments = ">=2.14" requests = ">=2.25.0" snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" @@ -3112,27 +3239,27 @@ sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" +sphinxcontrib-serializinghtml = ">=1.1.9" [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)"] +test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] [[package]] name = "sphinx-rtd-theme" -version = "1.3.0" +version = "2.0.0" description = "Read the Docs theme for Sphinx" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.6" files = [ - {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, - {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"}, + {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, + {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, ] [package.dependencies] -docutils = "<0.19" -sphinx = ">=1.6,<8" +docutils = "<0.21" +sphinx = ">=5,<8" sphinxcontrib-jquery = ">=4,<5" [package.extras] @@ -3140,47 +3267,50 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.4" +version = "1.0.8" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" 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"}, + {file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"}, + {file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +version = "1.0.6" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" 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"}, + {file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"}, + {file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.1" +version = "2.0.5" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" 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"}, + {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, + {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] [[package]] @@ -3228,43 +3358,45 @@ six = ">=1.5.2" [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +version = "1.0.7" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" 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"}, + {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, + {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] 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)." +version = "1.1.10" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" 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"}, + {file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"}, + {file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "stack-data" -version = "0.6.2" +version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" files = [ - {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, - {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, ] [package.dependencies] @@ -3277,13 +3409,13 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "terminado" -version = "0.17.1" +version = "0.18.0" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, - {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, + {file = "terminado-0.18.0-py3-none-any.whl", hash = "sha256:87b0d96642d0fe5f5abd7783857b9cab167f221a39ff98e3b9619a788a3c0f2e"}, + {file = "terminado-0.18.0.tar.gz", hash = "sha256:1ea08a89b835dd1b8c0c900d92848147cef2537243361b2e3f4dc15df9b6fded"}, ] [package.dependencies] @@ -3294,16 +3426,17 @@ tornado = ">=6.1.0" [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] [[package]] name = "threadpoolctl" -version = "3.2.0" +version = "3.3.0" description = "threadpoolctl" optional = false python-versions = ">=3.8" files = [ - {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"}, - {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"}, + {file = "threadpoolctl-3.3.0-py3-none-any.whl", hash = "sha256:6155be1f4a39f31a18ea70f94a77e0ccd57dced08122ea61109e7da89883781e"}, + {file = "threadpoolctl-3.3.0.tar.gz", hash = "sha256:5dac632b4fa2d43f42130267929af3ba01399ef4bd1882918e92dbc30365d30c"}, ] [[package]] @@ -3337,44 +3470,44 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.8" +version = "0.12.4" description = "Style preserving TOML library" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, + {file = "tomlkit-0.12.4-py3-none-any.whl", hash = "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b"}, + {file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"}, ] [[package]] name = "tornado" -version = "6.3.3" +version = "6.4" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">= 3.8" files = [ - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, - {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, - {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, - {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, ] [[package]] name = "tqdm" -version = "4.66.1" +version = "4.66.2" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, + {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"}, + {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"}, ] [package.dependencies] @@ -3388,70 +3521,81 @@ telegram = ["requests"] [[package]] name = "traitlets" -version = "5.9.0" +version = "5.14.1" description = "Traitlets Python configuration system" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"}, + {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-python-dateutil" +version = "2.8.19.20240106" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-dateutil-2.8.19.20240106.tar.gz", hash = "sha256:1f8db221c3b98e6ca02ea83a58371b22c374f42ae5bbdf186db9c9a76581459f"}, + {file = "types_python_dateutil-2.8.19.20240106-py3-none-any.whl", hash = "sha256:efbbdc54590d0f16152fa103c9879c7d4a00e82078f6e2cf01769042165acaa2"}, +] [[package]] name = "typing-extensions" -version = "4.6.3" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] name = "uri-template" -version = "1.2.0" +version = "1.3.0" description = "RFC 6570 URI Template Processor" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "uri_template-1.2.0-py3-none-any.whl", hash = "sha256:f1699c77b73b925cf4937eae31ab282a86dc885c333f2e942513f08f691fc7db"}, - {file = "uri_template-1.2.0.tar.gz", hash = "sha256:934e4d09d108b70eb8a24410af8615294d09d279ce0e7cbcdaef1bd21f932b06"}, + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, ] [package.extras] -dev = ["flake8 (<4.0.0)", "flake8-annotations", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-noqa", "flake8-requirements", "flake8-type-annotations", "flake8-use-fstring", "mypy", "pep8-naming"] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] [[package]] name = "urllib3" -version = "2.0.7" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [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"] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "wcwidth" -version = "0.2.6" +version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] [[package]] @@ -3482,47 +3626,32 @@ files = [ [[package]] name = "websocket-client" -version = "1.5.2" +version = "1.7.0" description = "WebSocket client for Python with low level API options" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "websocket-client-1.5.2.tar.gz", hash = "sha256:c7d67c13b928645f259d9b847ab5b57fd2d127213ca41ebd880de1f553b7c23b"}, - {file = "websocket_client-1.5.2-py3-none-any.whl", hash = "sha256:f8c64e28cd700e7ba1f04350d66422b6833b82a796b525a51e740b8cc8dab4b1"}, + {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, + {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, ] [package.extras] -docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] +docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] [[package]] name = "widgetsnbextension" -version = "4.0.7" +version = "4.0.10" description = "Jupyter interactive widgets for Jupyter Notebook" optional = false python-versions = ">=3.7" files = [ - {file = "widgetsnbextension-4.0.7-py3-none-any.whl", hash = "sha256:be3228a73bbab189a16be2d4a3cd89ecbd4e31948bfdc64edac17dcdee3cd99c"}, - {file = "widgetsnbextension-4.0.7.tar.gz", hash = "sha256:ea67c17a7cd4ae358f8f46c3b304c40698bc0423732e3f273321ee141232c8be"}, -] - -[[package]] -name = "zipp" -version = "3.15.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.7" -files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "widgetsnbextension-4.0.10-py3-none-any.whl", hash = "sha256:d37c3724ec32d8c48400a435ecfa7d3e259995201fbefa37163124a9fcb393cc"}, + {file = "widgetsnbextension-4.0.10.tar.gz", hash = "sha256:64196c5ff3b9a9183a8e699a4227fb0b7002f252c814098e66c4d1cd0644688f"}, ] -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - [metadata] lock-version = "2.0" -python-versions = ">=3.9,<4.0" -content-hash = "98290f5fe96a83cfac7f713d99843c0dfb48a5ed442dc9d39e46c53dd3255e9d" +python-versions = ">=3.10,<4.0" +content-hash = "d266fa1767aabc8ae065c3e8c7e9a6bc6c9963ee3c77f428b683fc3705842aed" diff --git a/pyproject.toml b/pyproject.toml index efac3d53..eee65e1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ maintainers = [ readme = "README.md" [tool.poetry.dependencies] -python = ">=3.9,<4.0" +python = ">=3.10,<4.0" scipy = "^1.9.2" opt-einsum = "^3.3.0" more-itertools = ">=8.12,<11.0" @@ -50,10 +50,12 @@ optional = true [tool.poetry.group.docs.dependencies] matplotlib = "^3.7.0" Sphinx = ">=6.2.1,<8.0.0" -sphinx-rtd-theme = "^1.2.1" +sphinx-rtd-theme = "^2.0.0" +myst-parser = "^2.0.0" sphinxcontrib-napoleon = "^0.7" -myst-parser = ">=1,<3" nbsphinx = "^0.9.2" +pygments = "^2.17.2" +ipython = "^8.22.1" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/requirements.txt b/requirements.txt index 90c89b33..0fe39d85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -click==8.1.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ - --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 -colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and platform_system == "Windows" \ +click==8.1.7 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de +colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and platform_system == "Windows" \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 contourpy==1.0.7 ; python_version >= "3.9" and python_version < "4.0" \ @@ -173,10 +173,10 @@ more-itertools==10.1.0 ; python_version >= "3.9" and python_version < "4.0" \ mpmath==1.3.0 ; python_version >= "3.9" and python_version < "4.0" \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c -networkx==3.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ - --hash=sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61 -numpy==1.23.0 ; python_version >= "3.9" and python_version < "4.0" \ +networkx==3.2.1 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6 \ + --hash=sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2 +numpy==1.23.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:092f5e6025813e64ad6d1b52b519165d08c730d099c114a9247c9bb635a2a450 \ --hash=sha256:196cd074c3f97c4121601790955f915187736f9cf458d3ee1f1b46aff2b1ade0 \ --hash=sha256:1c29b44905af288b3919803aceb6ec7fec77406d8b08aaa2e8b9e63d0fe2f160 \ @@ -199,7 +199,7 @@ numpy==1.23.0 ; python_version >= "3.9" and python_version < "4.0" \ --hash=sha256:f9c3fc2adf67762c9fe1849c859942d23f8d3e0bee7b5ed3d4a9c3eeb50a2f07 \ --hash=sha256:fc431493df245f3c627c0c05c2bd134535e7929dbe2e602b80e42bf52ff760bc \ --hash=sha256:fe8b9683eb26d2c4d5db32cd29b38fdcf8381324ab48313b5b69088e0e355379 -opt-einsum==3.3.0 ; python_version >= "3.9" and python_version < "4.0" \ +opt-einsum==3.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147 \ --hash=sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549 packaging==23.1 ; python_version >= "3.9" and python_version < "4.0" \ @@ -301,7 +301,7 @@ python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0" \ qecsim==1.0b9 ; python_version >= "3.9" and python_version < "4.0" \ --hash=sha256:71a53803ae382953a792618a212e6a4dbc0e0d60de7df039e1c32118b52e445b \ --hash=sha256:ca13b6c74cd801f2aefcc14baf1217086f5cef446402376eeb378aec6ce885da -qecstruct==0.2.9 ; python_version >= "3.9" and python_version < "4.0" \ +qecstruct==0.2.9 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:833b6fced75a03f174350f2af0e6b47fad75e9cc2e305ae4acdb4d0fac00912a \ --hash=sha256:9ea8264e163a4854961a58e20f9624359c84bcd706574879e6faadf694b1dcfc \ --hash=sha256:bc462f8e1f6ca5157be215361f04a048de3ffa8358e90499125df43f1387bd6b \ diff --git a/tests/contractor/test_contractor.py b/tests/contractor/test_contractor.py index 1bd6c77d..9f767768 100644 --- a/tests/contractor/test_contractor.py +++ b/tests/contractor/test_contractor.py @@ -181,10 +181,18 @@ def test_contractor_mps_mpo_contract(): identities_r = [identity for _ in range(num_sites - mpo_length - start_site)] full_mpo = identities_l + mpo + identities_r - mps_fin = mps_mpo_contract(mps_init, mpo, start_site, renormalise=False) - mps_fin_1 = mps_mpo_contract(mps_init, mpo, start_site, renormalise=True) + mps_fin = mps_mpo_contract( + mps=mps_init, mpo=mpo, start_site=start_site, renormalise=False + ) + mps_fin_1 = mps_mpo_contract( + mps=mps_init, mpo=mpo, start_site=start_site, renormalise=True + ) mps_fin_2 = mps_mpo_contract( - mps_init, mpo, start_site, renormalise=True, result_to_explicit=True + mps=mps_init, + mpo=mpo, + start_site=start_site, + renormalise=True, + result_to_explicit=True, ) orthogonality_centre = mps_fin_1.tensors[int(start_site + mpo_length - 1)] @@ -226,4 +234,5 @@ def test_contractor_mps_mpo_contract(): assert is_canonical(mps_fin) assert np.isclose(abs(np.linalg.norm(mps_fin.dense() - psi_fin)), 0, atol=1e-7) assert np.isclose(np.linalg.norm(orthogonality_centre), 1) + assert np.isclose(mps_fin_2.norm(), 1) assert isinstance(mps_fin_2, ExplicitMPS) diff --git a/tests/mps/test_canonical.py b/tests/mps/test_canonical.py index 2e3c3fe4..24fcc019 100644 --- a/tests/mps/test_canonical.py +++ b/tests/mps/test_canonical.py @@ -7,16 +7,16 @@ from opt_einsum import contract from mdopt.mps.utils import ( + create_simple_product_state, create_state_vector, + find_orth_centre, mps_from_dense, inner_product, is_canonical, - find_orth_centre, - create_simple_product_state, ) from mdopt.contractor.contractor import apply_one_site_operator, mps_mpo_contract from mdopt.mps.canonical import CanonicalMPS -from mdopt.utils.utils import mpo_from_matrix +from mdopt.utils.utils import mpo_from_matrix, split_two_site_tensor def test_canonical_init(): @@ -270,7 +270,7 @@ def test_canonical_entanglement_entropy(): num_sites = 4 - psi_two_body_dimer = 1 / np.sqrt(2) * np.array([0, -1, 1, 0], dtype=np.float32) + psi_two_body_dimer = 1 / np.sqrt(2) * np.array([0, -1, 1, 0], dtype=float) psi_many_body_dimer = reduce(np.kron, [psi_two_body_dimer] * num_sites) mps_dimer = mps_from_dense( @@ -319,7 +319,7 @@ def test_canonical_move_orth_centre(): assert find_orth_centre(mps_mixed_final) == [orth_centre_final] assert find_orth_centre(mps_mixed_final_renorm) == [orth_centre_final] assert find_orth_centre(mps_product) == [0] - assert mps_mixed_final_renorm.norm() == 1 + assert np.isclose(mps_mixed_final_renorm.norm() - 1, 0) def test_canonical_move_orth_centre_to_border(): @@ -351,10 +351,8 @@ def test_canonical_move_orth_centre_to_border(): assert np.isclose(tensor_1, tensor_2).all() assert position == "last" - mps, position = mps_product.move_orth_centre_to_border() - for tensor_1, tensor_2 in zip(mps.tensors, mps_product.tensors): - assert np.isclose(tensor_1, tensor_2).all() - assert position == "first" + with pytest.raises(UnboundLocalError): + mps, position = mps_product.move_orth_centre_to_border() def test_canonical_explicit(): @@ -453,7 +451,7 @@ def test_canonical_norm(): psi = create_state_vector(num_sites) mps = mps_from_dense(psi, form="Right-canonical") - assert isinstance(mps.norm(), np.float32) + assert isinstance(mps.norm(), float) assert np.isclose(mps.norm() - abs(inner_product(mps, mps)) ** 2, 0) @@ -526,6 +524,187 @@ def test_canonical_two_site_expectation_value(): assert np.isclose(abs(exp_value - exp_value_to_compare) ** 2, 0) +def test_canonical_compress_bond(): + """ + Test for the ``compress_bond`` method of the :class:`CanonicalMPS` class. + """ + + for _ in range(10): + # Testing the maximum bond dimension control + for strategy in ["svd", "qr", "svd_advanced"]: + num_sites = 10 + phys_dim = 2 + bond_to_compress = 4 + chi_max = 7 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Right-canonical" + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + chi_max=chi_max, + renormalise=False, + strategy=strategy, + return_truncation_error=True, + ) + assert mps_compressed.bond_dimensions[bond_to_compress] <= chi_max + assert truncation_error >= 0 + if strategy in ["svd", "svd_advanced"]: + assert inner_product(mps_compressed, mps_compressed) <= 1 + if strategy == "svd": + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + with pytest.raises(ValueError): + mps.compress_bond(bond=100) + with pytest.raises(ValueError): + mps.compress_bond(bond=0, strategy="strategy") + + # Testing the spectrum cut control + for strategy in ["svd", "svd_advanced"]: + num_sites = 10 + phys_dim = 2 + bond_to_compress = 4 + cut = 1e-1 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Right-canonical" + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=False, + strategy=strategy, + return_truncation_error=True, + ) + tensor_left = mps_compressed.tensors[bond_to_compress] + tensor_right = mps_compressed.tensors[bond_to_compress + 1] + two_site_tensor = contract( + "ijk, klm -> ijlm", + tensor_left, + tensor_right, + optimize=[(0, 1)], + ) + _, singular_values, _, _ = split_two_site_tensor( + tensor=two_site_tensor, return_truncation_error=True, strategy="svd" + ) + for singular_value in singular_values: + assert singular_value >= cut + assert truncation_error >= 0 + if strategy == "svd": + assert mps_compressed.norm() <= 1 + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + if strategy == "svd_advanced": + assert inner_product(mps_compressed, mps_compressed) <= 1 + assert inner_product(mps, mps_compressed) <= 1 + + # Testing the renormalisation option + for strategy in ["svd", "svd_advanced"]: + num_sites = 10 + phys_dim = 2 + bond_to_compress = 4 + cut = 1e-1 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Right-canonical" + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=True, + strategy=strategy, + return_truncation_error=True, + ) + tensor_left = mps_compressed.tensors[bond_to_compress] + tensor_right = mps_compressed.tensors[bond_to_compress + 1] + two_site_tensor = contract( + "ijk, klm -> ijlm", + tensor_left, + tensor_right, + optimize=[(0, 1)], + ) + _, singular_values, _, _ = split_two_site_tensor( + tensor=two_site_tensor, return_truncation_error=True, strategy="svd" + ) + assert np.isclose(np.linalg.norm(singular_values) - 1, 0) + for singular_value in singular_values: + assert singular_value >= cut + assert truncation_error >= 0 + if strategy == "svd": + assert np.isclose(mps_compressed.norm() - 1, 0) + if strategy == "svd_advanced": + assert np.isclose(inner_product(mps_compressed, mps_compressed) - 1, 0) + assert inner_product(mps, mps_compressed) <= 1 + + # Testing that for no cut the mps stays the same + for strategy in ["svd", "svd_advanced"]: + num_sites = 10 + phys_dim = 2 + bond_to_compress = 4 + cut = 1e-12 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Right-canonical" + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=False, + strategy=strategy, + return_truncation_error=True, + ) + tensor_left = mps_compressed.tensors[bond_to_compress] + tensor_right = mps_compressed.tensors[bond_to_compress + 1] + two_site_tensor = contract( + "ijk, klm -> ijlm", + tensor_left, + tensor_right, + optimize=[(0, 1)], + ) + _, singular_values, _, _ = split_two_site_tensor( + tensor=two_site_tensor, return_truncation_error=True, strategy="svd" + ) + for singular_value in singular_values: + assert singular_value >= cut + assert np.isclose(truncation_error, 0) + if strategy == "svd": + assert np.isclose(mps_compressed.norm() - 1, 0) + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + if strategy == "svd_advanced": + assert np.isclose(inner_product(mps_compressed, mps_compressed) - 1, 0) + assert np.isclose(inner_product(mps, mps_compressed) - 1, 0) + + +def test_canonical_compress(): + """ + Test for the ``compress`` method of the :class:`CanonicalMPS` class. + """ + + for _ in range(10): + strategy = "svd" + renormalise = False + num_sites = 10 + phys_dim = 2 + chi_max = 3 + cut = 1e-12 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Right-canonical" + ) + mps_compressed, truncation_errors = mps.compress( + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + strategy=strategy, + return_truncation_errors=True, + ) + assert inner_product(mps, mps_compressed) <= 1 + assert mps_compressed.norm() <= 1 + for bond_dim in mps_compressed.bond_dimensions: + assert bond_dim <= chi_max + for truncation_error in truncation_errors: + assert truncation_error >= 0 + assert np.isclose(mps_compressed.norm() + np.sum(truncation_errors) - 1, 0) + + def test_canonical_marginal(): """ Test for the ``marginal`` method of the :class:`CanonicalMPS` class. diff --git a/tests/mps/test_explicit.py b/tests/mps/test_explicit.py index bb626f0e..ba4d6828 100644 --- a/tests/mps/test_explicit.py +++ b/tests/mps/test_explicit.py @@ -360,9 +360,7 @@ def test_explicit_density_mpo(): density_matrix_mpo = density_matrix_mpo.transpose(correct_order) # Reshaping to the matrix form. - density_matrix_mpo = density_matrix_mpo.reshape( - (2**num_sites, 2**num_sites) - ) + density_matrix_mpo = density_matrix_mpo.reshape((2**num_sites, 2**num_sites)) # Original density matrix. density_matrix = np.tensordot(psi, np.conjugate(psi), 0) @@ -384,7 +382,7 @@ def test_explicit_entanglement_entropy(): num_sites = 4 - psi_two_body_dimer = 1 / np.sqrt(2) * np.array([0, -1, 1, 0], dtype=np.float32) + psi_two_body_dimer = 1 / np.sqrt(2) * np.array([0, -1, 1, 0], dtype=float) psi_many_body_dimer = reduce(np.kron, [psi_two_body_dimer] * num_sites) mps_dimer = mps_from_dense(psi_many_body_dimer, form="Explicit", tolerance=1e-6) @@ -425,9 +423,7 @@ def test_explicit_right_canonical(): optimize=[(0, 1)], ) - identity_right = np.identity( - to_be_identity_right.shape[0], dtype=np.float32 - ) + identity_right = np.identity(to_be_identity_right.shape[0], dtype=float) assert np.isclose(np.linalg.norm(to_be_identity_right - identity_right), 0) @@ -459,7 +455,7 @@ def test_explicit_left_canonical(): optimize=[(0, 1)], ) - identity_left = np.identity(to_be_identity_left.shape[0], dtype=np.float32) + identity_left = np.identity(to_be_identity_left.shape[0], dtype=float) assert np.isclose(np.linalg.norm(to_be_identity_left - identity_left), 0) @@ -498,7 +494,7 @@ def test_explicit_norm(): psi = create_state_vector(num_sites) mps = mps_from_dense(psi, form="Explicit") - assert isinstance(mps.norm(), np.float32) + assert isinstance(mps.norm(), float) assert np.isclose(abs(mps.norm() - abs(inner_product(mps, mps)) ** 2), 0) @@ -569,6 +565,128 @@ def test_explicit_two_site_expectation_value(): assert np.isclose(abs(exp_value - exp_value_to_compare) ** 2, 0) +def test_explicit_compress_bond(): + """ + Test for the ``compress_bond`` method of the :class:`ExplicitMPS` class. + """ + + num_sites = 10 + phys_dim = 2 + bond_to_compress = 4 + for _ in range(10): + # Testing the maximum bond dimension control + chi_max = 7 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Explicit", tolerance=np.inf + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + chi_max=chi_max, + renormalise=False, + return_truncation_error=True, + ) + assert mps_compressed.bond_dimensions[bond_to_compress] <= chi_max + assert truncation_error >= 0 + assert inner_product(mps_compressed, mps_compressed) <= 1 + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + with pytest.raises(ValueError): + mps.compress_bond(bond=100) + + # Testing the spectrum cut control + cut = 1e-1 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Explicit", tolerance=np.inf + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=False, + return_truncation_error=True, + ) + singular_values = mps.singular_values[bond_to_compress + 1] + for singular_value in singular_values: + assert singular_value >= cut + assert truncation_error >= 0 + assert mps_compressed.norm() <= 1 + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + assert inner_product(mps_compressed, mps_compressed) <= 1 + assert inner_product(mps, mps_compressed) <= 1 + + # Testing the renormalisation option + cut = 1e-1 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Explicit", tolerance=np.inf + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=True, + return_truncation_error=True, + ) + singular_values = mps.singular_values[bond_to_compress + 1] + assert np.isclose(np.linalg.norm(singular_values) - 1, 0) + for singular_value in singular_values: + assert singular_value >= cut + assert truncation_error >= 0 + assert np.isclose(mps_compressed.norm() - 1, 0) + assert np.isclose(inner_product(mps_compressed, mps_compressed) - 1, 0) + assert np.isclose(inner_product(mps, mps_compressed) - 1, 0) + + # Testing that for no cut the mps stays the same + cut = 1e-12 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Explicit", tolerance=np.inf + ) + mps_compressed, truncation_error = mps.compress_bond( + bond=bond_to_compress, + cut=cut, + renormalise=False, + return_truncation_error=True, + ) + singular_value = mps_compressed.singular_values[bond_to_compress + 1] + for singular_value in singular_values: + assert singular_value >= cut + assert np.isclose(truncation_error, 0) + assert np.isclose(mps_compressed.norm() - 1, 0) + assert np.isclose(mps_compressed.norm() + truncation_error - 1, 0) + assert np.isclose(inner_product(mps_compressed, mps_compressed) - 1, 0) + assert np.isclose(inner_product(mps, mps_compressed) - 1, 0) + + +def test_explicit_compress(): + """ + Test for the ``compress`` method of the :class:`ExplicitMPS` class. + """ + + for _ in range(10): + renormalise = False + num_sites = 10 + phys_dim = 2 + chi_max = 3 + cut = 1e-12 + psi = create_state_vector(num_sites=num_sites, phys_dim=phys_dim) + mps = mps_from_dense( + state_vector=psi, phys_dim=phys_dim, form="Explicit", tolerance=np.inf + ) + mps_compressed, truncation_errors = mps.compress( + chi_max=chi_max, + cut=cut, + renormalise=renormalise, + return_truncation_errors=True, + ) + assert inner_product(mps, mps_compressed) <= 1 + assert mps_compressed.norm() <= 1 + for bond_dim in mps_compressed.bond_dimensions: + assert bond_dim <= chi_max + for truncation_error in truncation_errors: + assert truncation_error >= 0 + assert np.sum(truncation_errors) <= mps.num_singval_mat + + def test_explicit_marginal(): """ Test for the ``marginal`` method of the :class:`ExplicitMPS` class. diff --git a/tests/mps/test_utils.py b/tests/mps/test_utils.py index 366a50ab..e0a5c981 100644 --- a/tests/mps/test_utils.py +++ b/tests/mps/test_utils.py @@ -185,6 +185,12 @@ def test_mps_utils_create_simple_product_state(): assert np.isclose(mps_4.tensors, mps_4_tensors).all() assert np.isclose(mps_5.tensors, mps_5_tensors).all() assert np.isclose(mps_6.tensors, mps_6_tensors).all() + assert mps_1.orth_centre is None + assert mps_2.orth_centre is None + assert mps_3.orth_centre is None + assert mps_4.orth_centre is None + assert mps_5.orth_centre is None + assert mps_6.orth_centre is None with pytest.raises(ValueError): create_simple_product_state(4, "0", form="Mixed-canonical") @@ -209,6 +215,8 @@ def test_mps_utils_create_custom_product_state(): assert np.isclose(mps_1.tensors, mps_tensors).all() assert np.isclose(mps_2.tensors, mps_tensors).all() + assert mps_1.orth_centre is None + assert mps_2.orth_centre is None with pytest.raises(ValueError): create_custom_product_state("0011++", form="Mixed-canonical") diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index bd052efe..0035253d 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -1,6 +1,7 @@ """Tests for the ``mdopt.utils.utils`` module.""" import pytest +import scipy import numpy as np from opt_einsum import contract @@ -11,6 +12,7 @@ mpo_to_matrix, split_two_site_tensor, svd, + qr, ) @@ -43,57 +45,206 @@ def test_utils_svd(): m = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) num_sing_values = np.random.randint(1, 10) - _, s, _, _ = svd(m, cut=1e-16, chi_max=num_sing_values, renormalise=True) - + _, s, _, _ = svd(m, chi_max=num_sing_values, renormalise=True) assert len(s) == num_sing_values + _, s, _, _ = svd(m, cut=1, renormalise=False) + for value in s: + assert np.abs(value) > 1 + + +def test_utils_qr(): + """Test for the `qr` function.""" + + for _ in range(10): + dim = np.random.randint(low=10, high=100, size=2) + mat = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) + q, r, _ = qr(mat) + mat_reconstructed = np.dot(q, r) + assert np.allclose(mat, mat_reconstructed, atol=1e-10) + + dim = np.random.randint(low=10, high=100, size=2) + mat = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) + chi_max = np.random.randint(5, 30) + q, r, _ = qr(mat, chi_max=chi_max) + assert q.shape[1] <= chi_max + assert r.shape[0] <= chi_max + + dim = np.random.randint(low=10, high=100, size=2) + mat = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) + q, r, truncation_error = qr(mat, return_truncation_error=True) + assert np.isclose(truncation_error, 0) + + dim = np.random.randint(low=10, high=100, size=2) + mat = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) + mat /= np.linalg.norm(mat) + cut = 1e-1 + q, r, _ = qr(mat, cut=cut) + _, _, pivots = scipy.linalg.qr( + mat, pivoting=True, mode="economic", check_finite=False + ) + permutation_matrix = np.eye(mat.shape[1])[:, pivots] + r = r @ permutation_matrix + for element in np.absolute(np.diag(r)): + assert element > cut + + dim = np.random.randint(low=10, high=100, size=2) + mat = np.random.uniform(size=dim) + 1j * np.random.uniform(size=dim) + q, r, _ = qr(mat, renormalise=True) + assert np.isclose(np.linalg.norm(np.diag(r)), 1, atol=1e-10) + + with pytest.raises(ValueError): + dim_invalid = np.random.randint(low=1, high=4, size=1) + mat_invalid = np.random.uniform(size=dim_invalid) + qr(mat_invalid) + def test_utils_split_two_site_tensor(): """Test for the ``split_two_site_tensor`` function.""" - for _ in range(10): + for _ in range(100): phys_dim = 2 bond_dim = np.random.randint(2, 18, size=2) tensor = np.random.uniform( size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) - u_l, singular_values, v_r, _ = split_two_site_tensor( - tensor, strategy="svd", return_residual_spectrum=True + u_l, singular_values, v_r, truncation_error = split_two_site_tensor( + tensor=tensor, + chi_max=1e4, + cut=1e-12, + strategy="svd", + renormalise=False, + return_truncation_error=True, ) - q_l, r_r, _, _ = split_two_site_tensor(tensor, strategy="qr") - r_l, q_r, _, _ = split_two_site_tensor(tensor, strategy="rq") - - should_be_t_0 = contract( + should_be_t = contract( "ijk, kl, lmn -> ijmn", u_l, np.diag(singular_values), v_r, optimize=[(0, 1), (0, 1)], ) + assert np.isclose(truncation_error, 0) + assert tensor.shape == should_be_t.shape + assert np.isclose(np.linalg.norm(tensor - should_be_t), 0) + + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + chi_max = 2 + u_l, singular_values, v_r, truncation_error = split_two_site_tensor( + tensor=tensor, + chi_max=chi_max, + cut=1e-12, + strategy="svd", + renormalise=False, + return_truncation_error=True, + ) + assert truncation_error > 0 + assert len(singular_values) == chi_max + + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + tensor /= np.linalg.norm(tensor) + cut = 0.5 + u_l, singular_values, v_r, truncation_error = split_two_site_tensor( + tensor=tensor, + chi_max=1e4, + cut=cut, + strategy="svd", + renormalise=False, + return_truncation_error=True, + ) + assert truncation_error >= 0 + for singular_value in singular_values: + assert singular_value > cut + + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + tensor /= np.linalg.norm(tensor) + cut = 0.5 + u_l, singular_values, v_r, truncation_error = split_two_site_tensor( + tensor=tensor, + chi_max=1e4, + cut=cut, + strategy="svd", + renormalise=True, + return_truncation_error=True, + ) + assert np.isclose(np.linalg.norm(singular_values), 1) + assert truncation_error >= 0 - should_be_t_1 = contract( + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + q_l, r_r, truncation_error, _ = split_two_site_tensor( + tensor=tensor, + chi_max=1e4, + cut=1e-12, + strategy="qr", + renormalise=False, + return_truncation_error=True, + ) + should_be_t = contract( "ijk, klm -> ijlm", q_l, r_r, optimize=[(0, 1)], ) + assert np.isclose(truncation_error, 0) + assert tensor.shape == should_be_t.shape + assert np.isclose(np.linalg.norm(tensor - should_be_t), 0) - should_be_t_2 = contract( + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + chi_max = 3 + q_l, r_r, truncation_error, _ = split_two_site_tensor( + tensor=tensor, + chi_max=chi_max, + cut=1e-12, + strategy="qr", + renormalise=False, + return_truncation_error=True, + ) + should_be_t = contract( "ijk, klm -> ijlm", - r_l, - q_r, + q_l, + r_r, optimize=[(0, 1)], ) + assert truncation_error > 0 + assert q_l.shape[2] == chi_max + assert r_r.shape[0] == chi_max - assert tensor.shape == should_be_t_0.shape - assert np.isclose(np.linalg.norm(tensor - should_be_t_0), 0) - - assert tensor.shape == should_be_t_1.shape - assert np.isclose(np.linalg.norm(tensor - should_be_t_1), 0) - - assert tensor.shape == should_be_t_2.shape - assert np.isclose(np.linalg.norm(tensor - should_be_t_2), 0) + bond_dim = np.random.randint(2, 18, size=2) + tensor = np.random.uniform( + size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1]) + ) + 1j * np.random.uniform(size=(bond_dim[0], phys_dim, phys_dim, bond_dim[1])) + q_l, r_r, truncation_error, _ = split_two_site_tensor( + tensor=tensor, + chi_max=1e4, + cut=1e-12, + strategy="qr", + renormalise=True, + return_truncation_error=True, + ) + should_be_t = contract( + "ijk, klm -> ijlm", + q_l, + r_r, + optimize=[(0, 1)], + ) + assert truncation_error > 0 + r_r = r_r.reshape((r_r.shape[0], r_r.shape[1] * r_r.shape[2])) + assert np.isclose(np.linalg.norm(np.diag(r_r)), 1) with pytest.raises(ValueError): tensor = np.random.uniform(