diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index 9fd00e71df..3ca9e40f37 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -2595,12 +2595,11 @@ The main calculation engine is defined in the abstract backend object :class:`qibo.backends.abstract.Backend`. This object defines the methods required by all Qibo models to perform simulation. -Qibo currently provides two different calculation backends, one based on -numpy and one based on Tensorflow. It is possible to define new backends by -inheriting :class:`qibo.backends.abstract.Backend` and implementing -its abstract methods. +Qibo supports several backends (see the :ref:`Backend drivers section `), +which can be used depending on the specific needs: +lightweight simulation, quantum machine learning, hardware execution, etc. -An additional backend is shipped as the separate library qibojit. +Among them, the default choice is a backend provided by the qibojit library. This backend is supplemented by custom operators defined under which can be used to efficiently apply gates to state vectors or density matrices. diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst index 6ea78b1836..21e25e2465 100644 --- a/doc/source/code-examples/advancedexamples.rst +++ b/doc/source/code-examples/advancedexamples.rst @@ -554,7 +554,9 @@ refer to the :ref:`Optimizers ` section of the documentation. Note that if the Stochastic Gradient Descent optimizer is used then the user has to use a backend based on tensorflow or pytorch primitives and not the default custom backend, as custom operators currently do not support automatic differentiation. -To switch the backend one can do ``qibo.set_backend("tensorflow")`` or ``qibo.set_backend("pytorch")``. +To switch the backend one can do ``qibo.set_backend(backend="qiboml", platform="tensorflow")`` +or ``qibo.set_backend(backend="qiboml", platform="pytorch")``, after ensuring the +``qiboml`` package has been installed. Check the :ref:`How to use automatic differentiation? ` section for more details. @@ -800,7 +802,7 @@ using the ``pytorch`` framework. import torch from qibo import Circuit, gates, set_backend - set_backend("pytorch") + set_backend(backend="qiboml", platform="pytorch") # Optimization parameters nepochs = 1000 @@ -1314,9 +1316,9 @@ Let's see how to use them. For starters, let's define a dummy circuit with some # visualize the circuit circuit.draw() - # q0: ─RZ─RX─RZ─RX─RZ─o────o────────M─ - # q1: ─RZ─RX─RZ─RX─RZ─X─RZ─X─o────o─M─ - # q2: ─RZ─RX─RZ─RX─RZ────────X─RZ─X─M─ + # 0: ─RZ─RX─RZ─RX─RZ─o────o────────M─ + # 1: ─RZ─RX─RZ─RX─RZ─X─RZ─X─o────o─M─ + # 2: ─RZ─RX─RZ─RX─RZ────────X─RZ─X─M─ .. testoutput:: :hide: @@ -1432,12 +1434,12 @@ number of CNOT or RX pairs (depending on the value of ``insertion_gate``) insert circuit in correspondence to the original ones. Since we decided to simulate noisy CNOTs:: Level 1 - q0: ─X─ --> q0: ─X───X──X─ - q1: ─o─ --> q1: ─o───o──o─ + 0: ─X─ --> 0: ─X───X──X─ + 1: ─o─ --> 1: ─o───o──o─ Level 2 - q0: ─X─ --> q0: ─X───X──X───X──X─ - q1: ─o─ --> q1: ─o───o──o───o──o─ + 0: ─X─ --> 0: ─X───X──X───X──X─ + 1: ─o─ --> 1: ─o───o──o───o──o─ . . @@ -1501,8 +1503,10 @@ combined with the readout mitigation: Clifford Data Regression (CDR) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For CDR instead, you don't need to define anything additional. However, keep in mind that the input -circuit is expected to be decomposed in the set of primitive gates :math:`RX(\frac{\pi}{2}), CNOT, X` and :math:`RZ(\theta)`. +For CDR instead, you don't need to define anything additional. +However, keep in mind that the input circuit is expected to be +decomposed in the set of primitive gates +:math:`RX(\frac{\pi}{2}), CNOT, X` and :math:`RZ(\theta)`. .. testcode:: @@ -1526,14 +1530,16 @@ circuit is expected to be decomposed in the set of primitive gates :math:`RX(\fr ... -Again, the mitigated expected value improves over the noisy one and is also slightly better compared to ZNE. +Again, the mitigated expected value improves over the noisy one +and is also slightly better compared to ZNE. Variable Noise CDR (vnCDR) ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Being a combination of ZNE and CDR, vnCDR requires you to define the noise levels as done in ZNE, and the same -caveat about the input circuit for CDR is valid here as well. +Being a combination of ZNE and CDR, vnCDR requires you to define +the noise levels as done in ZNE, and the same caveat about the +input circuit for CDR is valid here as well. .. testcode:: @@ -1559,8 +1565,10 @@ caveat about the input circuit for CDR is valid here as well. ... -The result is similar to the one obtained by CDR. Usually, one would expect slightly better results for vnCDR, -however, this can substantially vary depending on the circuit and the observable considered and, therefore, it is hard to tell +The result is similar to the one obtained by CDR. +Usually, one would expect slightly better results for vnCDR. +However, this can substantially vary depending on the circuit +and the observable considered and, therefore, it is hard to tell a priori. @@ -1591,8 +1599,11 @@ The use of iCS is straightforward, analogous to CDR and vnCDR. ... -Again, the mitigated expected value improves over the noisy one and is also slightly better compared to ZNE. -This was just a basic example usage of the three methods, for all the details about them you should check the API-reference page :ref:`Error Mitigation `. +Again, the mitigated expected value improves over the noisy +one and is also slightly better compared to ZNE. +This was just a basic example usage of the three methods, +for all the details about them you should check the API-reference page +:ref:`Error Mitigation `. .. _timeevol-example: @@ -2139,8 +2150,6 @@ Qibo implements a built-in transpiler with customizable options for each step. T be used at each transpiler step are reported below with a short description. The initial placement can be found with one of the following procedures: -- Trivial: logical-physical qubit mapping is an identity. -- Custom: custom logical-physical qubit mapping. - Random greedy: the best mapping is found within a set of random layouts based on a greedy policy. - Subgraph isomorphism: the initial mapping is the one that guarantees the execution of most gates at the beginning of the circuit without introducing any SWAP. @@ -2168,22 +2177,22 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile from qibo import gates from qibo.models import Circuit - from qibo.transpiler.pipeline import Passes, assert_transpiling + from qibo.transpiler.pipeline import Passes from qibo.transpiler.optimizer import Preprocessing from qibo.transpiler.router import ShortestPaths from qibo.transpiler.unroller import Unroller, NativeGates from qibo.transpiler.placer import Random + from qibo.transpiler.asserts import assert_transpiling # Define connectivity as nx.Graph def star_connectivity(): - chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(i, 2) for i in range(5) if i != 2] - chip.add_edges_from(graph_list) + chip = nx.Graph([("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")]) return chip # Define the circuit - circuit = Circuit(2) + # wire_names must match nodes in the connectivity graph. + # The index in wire_names represents the logical qubit number in the circuit. + circuit = Circuit(2, wire_names=["q0", "q1"]) circuit.add(gates.H(0)) circuit.add(gates.CZ(0, 1)) @@ -2205,13 +2214,10 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile transpiled_circ, final_layout = custom_pipeline(circuit) # Optinally call assert_transpiling to check that the final circuit can be executed on hardware - # For this test it is necessary to get the initial layout - initial_layout = custom_pipeline.get_initial_layout() assert_transpiling( original_circuit=circuit, transpiled_circuit=transpiled_circ, connectivity=star_connectivity(), - initial_layout=initial_layout, final_layout=final_layout, native_gates=NativeGates.default() ) diff --git a/doc/source/code-examples/examples.rst b/doc/source/code-examples/examples.rst index 8e3b849a38..e9d04eb7af 100644 --- a/doc/source/code-examples/examples.rst +++ b/doc/source/code-examples/examples.rst @@ -39,9 +39,9 @@ evaluation performance, e.g.: .. code-block:: python import numpy as np - # switch backend to "tensorflow" + # switch backend to "tensorflow" through the Qiboml provider import qibo - qibo.set_backend("tensorflow") + qibo.set_backend(backend="qiboml", platform="tensorflow") from qibo import Circuit, gates circuit = Circuit(2) @@ -54,7 +54,7 @@ evaluation performance, e.g.: init_state = np.ones(4) / 2.0 + i circuit(init_state) -Note that compiling is only supported when the native ``tensorflow`` backend is +Note that compiling is only supported when the ``tensorflow`` backend is used. This backend is much slower than ``qibojit`` which uses custom operators to apply gates. @@ -226,7 +226,7 @@ For applications that require the state vector to be collapsed during measuremen we refer to the :ref:`How to collapse state during measurements? ` The measured shots are obtained using pseudo-random number generators of the -underlying backend (numpy or Tensorflow). If the user has installed a custom +underlying backend. If the user has installed a custom backend (eg. qibojit) and asks for frequencies with more than 100000 shots, a custom Metropolis algorithm will be used to obtain the corresponding samples, for increase performance. The user can change the threshold for which this @@ -313,20 +313,20 @@ For example circuit.draw() # Prints ''' - q0: ─H─U1─U1─U1─U1───────────────────────────x─── - q1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─ - q2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─ - q3: ─────────o──|───────o──|────o──|──H─U1───|─x─ - q4: ────────────o──────────o───────o────o──H─x─── + 0: ─H─U1─U1─U1─U1───────────────────────────x─── + 1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─ + 2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─ + 3: ─────────o──|───────o──|────o──|──H─U1───|─x─ + 4: ────────────o──────────o───────o────o──H─x─── ''' .. testoutput:: :hide: - q0: ─H─U1─U1─U1─U1───────────────────────────x─── - q1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─ - q2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─ - q3: ─────────o──|───────o──|────o──|──H─U1───|─x─ - q4: ────────────o──────────o───────o────o──H─x─── + 0: ─H─U1─U1─U1─U1───────────────────────────x─── + 1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─ + 2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─ + 3: ─────────o──|───────o──|────o──|──H─U1───|─x─ + 4: ────────────o──────────o───────o────o──H─x─── How to visualize a circuit with style? -------------------------------------- diff --git a/doc/source/getting-started/installation.rst b/doc/source/getting-started/installation.rst index 8c356b2592..a6a9213a69 100644 --- a/doc/source/getting-started/installation.rst +++ b/doc/source/getting-started/installation.rst @@ -7,15 +7,15 @@ Operating systems support In the table below we summarize the status of *pre-compiled binaries distributed with pypi* for the packages listed above. -+------------------+------+---------+------------+ -| Operating System | qibo | qibojit | tensorflow | -+==================+======+=========+============+ -| Linux x86 | Yes | Yes | Yes | -+------------------+------+---------+------------+ -| MacOS >= 10.15 | Yes | Yes | Yes | -+------------------+------+---------+------------+ -| Windows | Yes | Yes | Yes | -+------------------+------+---------+------------+ ++------------------+------+---------+-----------+---------+ +| Operating System | qibo | qibojit |Tensorflow | Pytorch | ++==================+======+=========+===========+=========+ +| Linux x86 | Yes | Yes | Yes | Yes | ++------------------+------+---------+-----------+---------+ +| MacOS >= 10.15 | Yes | Yes | Yes | Yes | ++------------------+------+---------+-----------+---------+ +| Windows | Yes | Yes | Yes | Yes | ++------------------+------+---------+-----------+---------+ .. note:: All packages are supported for Python >= 3.9. @@ -148,35 +148,6 @@ Then proceed with the ``qibojit`` installation using ``pip`` _______________________ -.. _installing-tensorflow: - -tensorflow -^^^^^^^^^^ - -If the `TensorFlow `_ package is installed Qibo -will detect and provide to the user the possibility to use ``tensorflow`` -backend. - -This backend is used by default if ``qibojit`` is not installed, however, if -needed, in order to switch to the ``tensorflow`` backend please do: - -.. code-block:: python - - import qibo - qibo.set_backend("tensorflow") - -In order to install the package, we recommend the installation using: - -.. code-block:: bash - - pip install qibo tensorflow - -.. note:: - TensorFlow can be installed following its `documentation - `_. - -_______________________ - .. _installing-numpy: numpy @@ -197,26 +168,45 @@ please do: _______________________ -.. _installing-pytorch: +.. _installing-qml-backends: -pytorch -^^^^^^^ +Backends with automatic differentiation support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you need automatic differentiation support, for tracing gradients of your +quantum algorithm or for building some quantum machine learning routine, +the right backends for you are those provided by the `Qiboml `__ +package. -If the `PyTorch `_ package is installed Qibo -will detect and provide to the user the possibility to use ``pytorch`` -backend. +In particular, Qiboml currently support `Pytorch `_ and +`Tensorflow `_ interfaces, integrating the qibo functionalities +into these well-known machine learning frameworks. Quantum layers can be constructed +and added to your Pytorch or Tensorflow models, and trained using any supported +optimization routine. -In order to switch to the ``pytorch`` backend please do: +In order to use these quantum machine learning backends please make sure the +preferred package is installed following `Tensorflow's `_ +or `Pytorch's `_ installation instructions. + +To switch to Tensorflow or Pytorch backend please do: .. code-block:: python import qibo - qibo.set_backend("pytorch") + # in case of Tensorflow + qibo.set_backend(backend="qiboml", platform="tensorflow") + # in case of Pytorch + qibo.set_backend(backend="qiboml", platform="pytorch") -In order to install the package, we recommend the installation using: +In order to start using automatic differentiation tools with Qibo, +we recommend the installation using: .. code-block:: bash - pip install qibo torch + pip install qibo qiboml tensorflow -_______________________ +or + +.. code-block:: bash + + pip install qibo qiboml torch diff --git a/poetry.lock b/poetry.lock index 0d4b72c7b2..1ce3aa0f83 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,16 +1,5 @@ # This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. -[[package]] -name = "absl-py" -version = "2.1.0" -description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." -optional = false -python-versions = ">=3.7" -files = [ - {file = "absl-py-2.1.0.tar.gz", hash = "sha256:7820790efbb316739cde8b4e19357243fc3608a152024288513dd968d7d959ff"}, - {file = "absl_py-2.1.0-py3-none-any.whl", hash = "sha256:526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308"}, -] - [[package]] name = "alabaster" version = "0.7.16" @@ -24,13 +13,13 @@ files = [ [[package]] name = "alembic" -version = "1.13.3" +version = "1.14.0" description = "A database migration tool for SQLAlchemy." optional = false python-versions = ">=3.8" files = [ - {file = "alembic-1.13.3-py3-none-any.whl", hash = "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e"}, - {file = "alembic-1.13.3.tar.gz", hash = "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2"}, + {file = "alembic-1.14.0-py3-none-any.whl", hash = "sha256:99bd884ca390466db5e27ffccff1d179ec5c05c965cfefc0607e69f9e411cb25"}, + {file = "alembic-1.14.0.tar.gz", hash = "sha256:b00892b53b3642d0b8dbedba234dbf1924b69be83a9a769d5a624b01094e304b"}, ] [package.dependencies] @@ -117,21 +106,6 @@ six = ">=1.12.0" astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] -[[package]] -name = "astunparse" -version = "1.6.3" -description = "An AST unparser for Python" -optional = false -python-versions = "*" -files = [ - {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, - {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, -] - -[package.dependencies] -six = ">=1.6.1,<2.0" -wheel = ">=0.23.0,<1.0" - [[package]] name = "attrs" version = "21.4.0" @@ -201,21 +175,20 @@ lxml = ["lxml"] [[package]] name = "bleach" -version = "6.1.0" +version = "6.2.0" description = "An easy safelist-based HTML-sanitizing tool." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, - {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, + {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, + {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, ] [package.dependencies] -six = ">=1.9.0" webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.3)"] +css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "cachetools" @@ -614,13 +587,13 @@ files = [ [[package]] name = "colorlog" -version = "6.8.2" +version = "6.9.0" description = "Add colours to the output of Python's logging module." optional = false python-versions = ">=3.6" files = [ - {file = "colorlog-6.8.2-py3-none-any.whl", hash = "sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33"}, - {file = "colorlog-6.8.2.tar.gz", hash = "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44"}, + {file = "colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff"}, + {file = "colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2"}, ] [package.dependencies] @@ -765,73 +738,73 @@ test = ["altair", "baytune", "chocolate", "dask", "distributed", "kahypar", "mat [[package]] name = "coverage" -version = "7.6.4" +version = "7.6.7" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, - {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, - {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, - {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, - {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, - {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, - {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, - {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, - {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, - {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, - {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, - {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, - {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, - {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, - {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, - {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, + {file = "coverage-7.6.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:108bb458827765d538abcbf8288599fee07d2743357bdd9b9dad456c287e121e"}, + {file = "coverage-7.6.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c973b2fe4dc445cb865ab369df7521df9c27bf40715c837a113edaa2aa9faf45"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c6b24007c4bcd0b19fac25763a7cac5035c735ae017e9a349b927cfc88f31c1"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acbb8af78f8f91b3b51f58f288c0994ba63c646bc1a8a22ad072e4e7e0a49f1c"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad32a981bcdedb8d2ace03b05e4fd8dace8901eec64a532b00b15217d3677dd2"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:34d23e28ccb26236718a3a78ba72744212aa383141961dd6825f6595005c8b06"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e25bacb53a8c7325e34d45dddd2f2fbae0dbc230d0e2642e264a64e17322a777"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af05bbba896c4472a29408455fe31b3797b4d8648ed0a2ccac03e074a77e2314"}, + {file = "coverage-7.6.7-cp310-cp310-win32.whl", hash = "sha256:796c9b107d11d2d69e1849b2dfe41730134b526a49d3acb98ca02f4985eeff7a"}, + {file = "coverage-7.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:987a8e3da7da4eed10a20491cf790589a8e5e07656b6dc22d3814c4d88faf163"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4"}, + {file = "coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2"}, + {file = "coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb"}, + {file = "coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76"}, + {file = "coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384"}, + {file = "coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30"}, + {file = "coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3"}, + {file = "coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8"}, + {file = "coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56"}, + {file = "coverage-7.6.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37a15573f988b67f7348916077c6d8ad43adb75e478d0910957394df397d2874"}, + {file = "coverage-7.6.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6cce5c76985f81da3769c52203ee94722cd5d5889731cd70d31fee939b74bf0"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ab9763d291a17b527ac6fd11d1a9a9c358280adb320e9c2672a97af346ac2c"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cf96ceaa275f071f1bea3067f8fd43bec184a25a962c754024c973af871e1b7"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aee9cf6b0134d6f932d219ce253ef0e624f4fa588ee64830fcba193269e4daa3"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2bc3e45c16564cc72de09e37413262b9f99167803e5e48c6156bccdfb22c8327"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:623e6965dcf4e28a3debaa6fcf4b99ee06d27218f46d43befe4db1c70841551c"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850cfd2d6fc26f8346f422920ac204e1d28814e32e3a58c19c91980fa74d8289"}, + {file = "coverage-7.6.7-cp39-cp39-win32.whl", hash = "sha256:c296263093f099da4f51b3dff1eff5d4959b527d4f2f419e16508c5da9e15e8c"}, + {file = "coverage-7.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:90746521206c88bdb305a4bf3342b1b7316ab80f804d40c536fc7d329301ee13"}, + {file = "coverage-7.6.7-pp39.pp310-none-any.whl", hash = "sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671"}, + {file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"}, ] [package.dependencies] @@ -949,24 +922,24 @@ numpy = ">=1.21,<2.0" [[package]] name = "custatevec-cu11" -version = "1.6.0.post1" +version = "1.7.0" description = "cuStateVec - a component of NVIDIA cuQuantum SDK" optional = false python-versions = "*" files = [ - {file = "custatevec_cu11-1.6.0.post1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:6840bd957455d33f9df1f2e266fe33079e429b2442f5ff6ef5eae6c1b618108e"}, - {file = "custatevec_cu11-1.6.0.post1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:8d57ada4d3cc77b24b3be83b55929942186698e71edadaa952448c1b0af43539"}, + {file = "custatevec_cu11-1.7.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dabdd80bab8e19413904c8377268dcfbc0468b3a8438a04cca422502c70b34d0"}, + {file = "custatevec_cu11-1.7.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:11b3a2a79de52afaab1acc970e3d810d219e90170405aaded78ac6dcfa1bb389"}, ] [[package]] name = "custatevec-cu12" -version = "1.6.0.post1" +version = "1.7.0" description = "cuStateVec - a component of NVIDIA cuQuantum SDK" optional = false python-versions = "*" files = [ - {file = "custatevec_cu12-1.6.0.post1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4f38175cb6cb9dfa0008e5109e22bf92eeedd3aad843be3ce27ad41b53318f95"}, - {file = "custatevec_cu12-1.6.0.post1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0c875981de852091f5f3c040d705b284424171aa5df07f843728ff2fae450016"}, + {file = "custatevec_cu12-1.7.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e9c5d810285ddcdf97c980725580a0f549fccec4475a76d28779c112c79c2aa"}, + {file = "custatevec_cu12-1.7.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:df81b4eeeadc841b4c3ac4816e6b9e3dde6b288f13a2c0005fecbd0501f9ea6d"}, ] [[package]] @@ -995,31 +968,31 @@ files = [ [[package]] name = "cutensornet-cu11" -version = "2.5.0" +version = "2.6.0" description = "cuTensorNet - a component of NVIDIA cuQuantum SDK" optional = false python-versions = "*" files = [ - {file = "cutensornet_cu11-2.5.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:144f0f804a06e86efba15900fc79c234a5de09466c2245be82a795cc945c41e2"}, - {file = "cutensornet_cu11-2.5.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:be33d47531a965233c73b9ad0cbec5ce399271372d62d77393e167cb9da2894d"}, + {file = "cutensornet_cu11-2.6.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:ded8b2b3124fd2acd6ce9c13060b0ea17692bcbca727314b2930c6ab341035ef"}, + {file = "cutensornet_cu11-2.6.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f7be9781de96cd897b59ac81cfb5c407a79a9781d236a25358656e24c9e81b71"}, ] [package.dependencies] -cutensor-cu11 = ">=2.0.1,<3" +cutensor-cu11 = ">=2.0.2,<3" [[package]] name = "cutensornet-cu12" -version = "2.5.0" +version = "2.6.0" description = "cuTensorNet - a component of NVIDIA cuQuantum SDK" optional = false python-versions = "*" files = [ - {file = "cutensornet_cu12-2.5.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:3d0c55b39b5fb0696c7b219f35a8af91c14fc557f836153d2801c4e31bb3fe70"}, - {file = "cutensornet_cu12-2.5.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c2937ff3e2fd2fd984e5bb0a098919981c145ce59ada18857e9f7f4923a3e6c8"}, + {file = "cutensornet_cu12-2.6.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:39b6f50b8bd47e5a4fcb745472c1005fc9d3889b907c92a91ea76e30a91e11cd"}, + {file = "cutensornet_cu12-2.6.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:64b582679c4e16faecd9143103272376e847e4b7ff02c97cde72f39ea6243f5e"}, ] [package.dependencies] -cutensor-cu12 = ">=2.0.1,<3" +cutensor-cu12 = ">=2.0.2,<3" [[package]] name = "cycler" @@ -1139,37 +1112,37 @@ cython = ["cython"] [[package]] name = "debugpy" -version = "1.8.7" +version = "1.8.8" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.7-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:95fe04a573b8b22896c404365e03f4eda0ce0ba135b7667a1e57bd079793b96b"}, - {file = "debugpy-1.8.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:628a11f4b295ffb4141d8242a9bb52b77ad4a63a2ad19217a93be0f77f2c28c9"}, - {file = "debugpy-1.8.7-cp310-cp310-win32.whl", hash = "sha256:85ce9c1d0eebf622f86cc68618ad64bf66c4fc3197d88f74bb695a416837dd55"}, - {file = "debugpy-1.8.7-cp310-cp310-win_amd64.whl", hash = "sha256:29e1571c276d643757ea126d014abda081eb5ea4c851628b33de0c2b6245b037"}, - {file = "debugpy-1.8.7-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:caf528ff9e7308b74a1749c183d6808ffbedbb9fb6af78b033c28974d9b8831f"}, - {file = "debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0"}, - {file = "debugpy-1.8.7-cp311-cp311-win32.whl", hash = "sha256:171899588bcd412151e593bd40d9907133a7622cd6ecdbdb75f89d1551df13c2"}, - {file = "debugpy-1.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211"}, - {file = "debugpy-1.8.7-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:4d27d842311353ede0ad572600c62e4bcd74f458ee01ab0dd3a1a4457e7e3706"}, - {file = "debugpy-1.8.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c1fd62ae0356e194f3e7b7a92acd931f71fe81c4b3be2c17a7b8a4b546ec2"}, - {file = "debugpy-1.8.7-cp312-cp312-win32.whl", hash = "sha256:2f729228430ef191c1e4df72a75ac94e9bf77413ce5f3f900018712c9da0aaca"}, - {file = "debugpy-1.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:45c30aaefb3e1975e8a0258f5bbd26cd40cde9bfe71e9e5a7ac82e79bad64e39"}, - {file = "debugpy-1.8.7-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:d050a1ec7e925f514f0f6594a1e522580317da31fbda1af71d1530d6ea1f2b40"}, - {file = "debugpy-1.8.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f4349a28e3228a42958f8ddaa6333d6f8282d5edaea456070e48609c5983b7"}, - {file = "debugpy-1.8.7-cp313-cp313-win32.whl", hash = "sha256:11ad72eb9ddb436afb8337891a986302e14944f0f755fd94e90d0d71e9100bba"}, - {file = "debugpy-1.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:2efb84d6789352d7950b03d7f866e6d180284bc02c7e12cb37b489b7083d81aa"}, - {file = "debugpy-1.8.7-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:4b908291a1d051ef3331484de8e959ef3e66f12b5e610c203b5b75d2725613a7"}, - {file = "debugpy-1.8.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da8df5b89a41f1fd31503b179d0a84a5fdb752dddd5b5388dbd1ae23cda31ce9"}, - {file = "debugpy-1.8.7-cp38-cp38-win32.whl", hash = "sha256:b12515e04720e9e5c2216cc7086d0edadf25d7ab7e3564ec8b4521cf111b4f8c"}, - {file = "debugpy-1.8.7-cp38-cp38-win_amd64.whl", hash = "sha256:93176e7672551cb5281577cdb62c63aadc87ec036f0c6a486f0ded337c504596"}, - {file = "debugpy-1.8.7-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:90d93e4f2db442f8222dec5ec55ccfc8005821028982f1968ebf551d32b28907"}, - {file = "debugpy-1.8.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6db2a370e2700557a976eaadb16243ec9c91bd46f1b3bb15376d7aaa7632c81"}, - {file = "debugpy-1.8.7-cp39-cp39-win32.whl", hash = "sha256:a6cf2510740e0c0b4a40330640e4b454f928c7b99b0c9dbf48b11efba08a8cda"}, - {file = "debugpy-1.8.7-cp39-cp39-win_amd64.whl", hash = "sha256:6a9d9d6d31846d8e34f52987ee0f1a904c7baa4912bf4843ab39dadf9b8f3e0d"}, - {file = "debugpy-1.8.7-py2.py3-none-any.whl", hash = "sha256:57b00de1c8d2c84a61b90880f7e5b6deaf4c312ecbde3a0e8912f2a56c4ac9ae"}, - {file = "debugpy-1.8.7.zip", hash = "sha256:18b8f731ed3e2e1df8e9cdaa23fb1fc9c24e570cd0081625308ec51c82efe42e"}, + {file = "debugpy-1.8.8-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:e59b1607c51b71545cb3496876544f7186a7a27c00b436a62f285603cc68d1c6"}, + {file = "debugpy-1.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6531d952b565b7cb2fbd1ef5df3d333cf160b44f37547a4e7cf73666aca5d8d"}, + {file = "debugpy-1.8.8-cp310-cp310-win32.whl", hash = "sha256:b01f4a5e5c5fb1d34f4ccba99a20ed01eabc45a4684f4948b5db17a319dfb23f"}, + {file = "debugpy-1.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:535f4fb1c024ddca5913bb0eb17880c8f24ba28aa2c225059db145ee557035e9"}, + {file = "debugpy-1.8.8-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:c399023146e40ae373753a58d1be0a98bf6397fadc737b97ad612886b53df318"}, + {file = "debugpy-1.8.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09cc7b162586ea2171eea055985da2702b0723f6f907a423c9b2da5996ad67ba"}, + {file = "debugpy-1.8.8-cp311-cp311-win32.whl", hash = "sha256:eea8821d998ebeb02f0625dd0d76839ddde8cbf8152ebbe289dd7acf2cdc6b98"}, + {file = "debugpy-1.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:d4483836da2a533f4b1454dffc9f668096ac0433de855f0c22cdce8c9f7e10c4"}, + {file = "debugpy-1.8.8-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:0cc94186340be87b9ac5a707184ec8f36547fb66636d1029ff4f1cc020e53996"}, + {file = "debugpy-1.8.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64674e95916e53c2e9540a056e5f489e0ad4872645399d778f7c598eacb7b7f9"}, + {file = "debugpy-1.8.8-cp312-cp312-win32.whl", hash = "sha256:5c6e885dbf12015aed73770f29dec7023cb310d0dc2ba8bfbeb5c8e43f80edc9"}, + {file = "debugpy-1.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:19ffbd84e757a6ca0113574d1bf5a2298b3947320a3e9d7d8dc3377f02d9f864"}, + {file = "debugpy-1.8.8-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:705cd123a773d184860ed8dae99becd879dfec361098edbefb5fc0d3683eb804"}, + {file = "debugpy-1.8.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890fd16803f50aa9cb1a9b9b25b5ec321656dd6b78157c74283de241993d086f"}, + {file = "debugpy-1.8.8-cp313-cp313-win32.whl", hash = "sha256:90244598214bbe704aa47556ec591d2f9869ff9e042e301a2859c57106649add"}, + {file = "debugpy-1.8.8-cp313-cp313-win_amd64.whl", hash = "sha256:4b93e4832fd4a759a0c465c967214ed0c8a6e8914bced63a28ddb0dd8c5f078b"}, + {file = "debugpy-1.8.8-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:143ef07940aeb8e7316de48f5ed9447644da5203726fca378f3a6952a50a9eae"}, + {file = "debugpy-1.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f95651bdcbfd3b27a408869a53fbefcc2bcae13b694daee5f1365b1b83a00113"}, + {file = "debugpy-1.8.8-cp38-cp38-win32.whl", hash = "sha256:26b461123a030e82602a750fb24d7801776aa81cd78404e54ab60e8b5fecdad5"}, + {file = "debugpy-1.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3cbf1833e644a3100eadb6120f25be8a532035e8245584c4f7532937edc652a"}, + {file = "debugpy-1.8.8-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:53709d4ec586b525724819dc6af1a7703502f7e06f34ded7157f7b1f963bb854"}, + {file = "debugpy-1.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a9c013077a3a0000e83d97cf9cc9328d2b0bbb31f56b0e99ea3662d29d7a6a2"}, + {file = "debugpy-1.8.8-cp39-cp39-win32.whl", hash = "sha256:ffe94dd5e9a6739a75f0b85316dc185560db3e97afa6b215628d1b6a17561cb2"}, + {file = "debugpy-1.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5c0e5a38c7f9b481bf31277d2f74d2109292179081f11108e668195ef926c0f9"}, + {file = "debugpy-1.8.8-py2.py3-none-any.whl", hash = "sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f"}, + {file = "debugpy-1.8.8.zip", hash = "sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091"}, ] [[package]] @@ -1196,20 +1169,20 @@ files = [ [[package]] name = "deprecated" -version = "1.2.14" +version = "1.2.15" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, ] [package.dependencies] wrapt = ">=1.10,<2" [package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] [[package]] name = "dill" @@ -1408,72 +1381,63 @@ docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2. testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] -[[package]] -name = "flatbuffers" -version = "24.3.25" -description = "The FlatBuffers serialization format for Python" -optional = false -python-versions = "*" -files = [ - {file = "flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812"}, - {file = "flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4"}, -] - [[package]] name = "fonttools" -version = "4.54.1" +version = "4.55.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.54.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2"}, - {file = "fonttools-4.54.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882"}, - {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10"}, - {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e"}, - {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e"}, - {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44"}, - {file = "fonttools-4.54.1-cp310-cp310-win32.whl", hash = "sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02"}, - {file = "fonttools-4.54.1-cp310-cp310-win_amd64.whl", hash = "sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d"}, - {file = "fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20"}, - {file = "fonttools-4.54.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2"}, - {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7"}, - {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07"}, - {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8"}, - {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a"}, - {file = "fonttools-4.54.1-cp311-cp311-win32.whl", hash = "sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc"}, - {file = "fonttools-4.54.1-cp311-cp311-win_amd64.whl", hash = "sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6"}, - {file = "fonttools-4.54.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d"}, - {file = "fonttools-4.54.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08"}, - {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263"}, - {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab"}, - {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d"}, - {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714"}, - {file = "fonttools-4.54.1-cp312-cp312-win32.whl", hash = "sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac"}, - {file = "fonttools-4.54.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e"}, - {file = "fonttools-4.54.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff"}, - {file = "fonttools-4.54.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb"}, - {file = "fonttools-4.54.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a"}, - {file = "fonttools-4.54.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c"}, - {file = "fonttools-4.54.1-cp313-cp313-win32.whl", hash = "sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58"}, - {file = "fonttools-4.54.1-cp313-cp313-win_amd64.whl", hash = "sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d"}, - {file = "fonttools-4.54.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b"}, - {file = "fonttools-4.54.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c"}, - {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556"}, - {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b"}, - {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1"}, - {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386"}, - {file = "fonttools-4.54.1-cp38-cp38-win32.whl", hash = "sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664"}, - {file = "fonttools-4.54.1-cp38-cp38-win_amd64.whl", hash = "sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab"}, - {file = "fonttools-4.54.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13"}, - {file = "fonttools-4.54.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac"}, - {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986"}, - {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55"}, - {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9"}, - {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33"}, - {file = "fonttools-4.54.1-cp39-cp39-win32.whl", hash = "sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a"}, - {file = "fonttools-4.54.1-cp39-cp39-win_amd64.whl", hash = "sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7"}, - {file = "fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd"}, - {file = "fonttools-4.54.1.tar.gz", hash = "sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285"}, + {file = "fonttools-4.55.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:51c029d4c0608a21a3d3d169dfc3fb776fde38f00b35ca11fdab63ba10a16f61"}, + {file = "fonttools-4.55.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bca35b4e411362feab28e576ea10f11268b1aeed883b9f22ed05675b1e06ac69"}, + {file = "fonttools-4.55.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ce4ba6981e10f7e0ccff6348e9775ce25ffadbee70c9fd1a3737e3e9f5fa74f"}, + {file = "fonttools-4.55.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31d00f9852a6051dac23294a4cf2df80ced85d1d173a61ba90a3d8f5abc63c60"}, + {file = "fonttools-4.55.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e198e494ca6e11f254bac37a680473a311a88cd40e58f9cc4dc4911dfb686ec6"}, + {file = "fonttools-4.55.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7208856f61770895e79732e1dcbe49d77bd5783adf73ae35f87fcc267df9db81"}, + {file = "fonttools-4.55.0-cp310-cp310-win32.whl", hash = "sha256:e7e6a352ff9e46e8ef8a3b1fe2c4478f8a553e1b5a479f2e899f9dc5f2055880"}, + {file = "fonttools-4.55.0-cp310-cp310-win_amd64.whl", hash = "sha256:636caaeefe586d7c84b5ee0734c1a5ab2dae619dc21c5cf336f304ddb8f6001b"}, + {file = "fonttools-4.55.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fa34aa175c91477485c44ddfbb51827d470011e558dfd5c7309eb31bef19ec51"}, + {file = "fonttools-4.55.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:37dbb3fdc2ef7302d3199fb12468481cbebaee849e4b04bc55b77c24e3c49189"}, + {file = "fonttools-4.55.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5263d8e7ef3c0ae87fbce7f3ec2f546dc898d44a337e95695af2cd5ea21a967"}, + {file = "fonttools-4.55.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f307f6b5bf9e86891213b293e538d292cd1677e06d9faaa4bf9c086ad5f132f6"}, + {file = "fonttools-4.55.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f0a4b52238e7b54f998d6a56b46a2c56b59c74d4f8a6747fb9d4042190f37cd3"}, + {file = "fonttools-4.55.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3e569711464f777a5d4ef522e781dc33f8095ab5efd7548958b36079a9f2f88c"}, + {file = "fonttools-4.55.0-cp311-cp311-win32.whl", hash = "sha256:2b3ab90ec0f7b76c983950ac601b58949f47aca14c3f21eed858b38d7ec42b05"}, + {file = "fonttools-4.55.0-cp311-cp311-win_amd64.whl", hash = "sha256:aa046f6a63bb2ad521004b2769095d4c9480c02c1efa7d7796b37826508980b6"}, + {file = "fonttools-4.55.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:838d2d8870f84fc785528a692e724f2379d5abd3fc9dad4d32f91cf99b41e4a7"}, + {file = "fonttools-4.55.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f46b863d74bab7bb0d395f3b68d3f52a03444964e67ce5c43ce43a75efce9246"}, + {file = "fonttools-4.55.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33b52a9cfe4e658e21b1f669f7309b4067910321757fec53802ca8f6eae96a5a"}, + {file = "fonttools-4.55.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:732a9a63d6ea4a81b1b25a1f2e5e143761b40c2e1b79bb2b68e4893f45139a40"}, + {file = "fonttools-4.55.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7dd91ac3fcb4c491bb4763b820bcab6c41c784111c24172616f02f4bc227c17d"}, + {file = "fonttools-4.55.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1f0e115281a32ff532118aa851ef497a1b7cda617f4621c1cdf81ace3e36fb0c"}, + {file = "fonttools-4.55.0-cp312-cp312-win32.whl", hash = "sha256:6c99b5205844f48a05cb58d4a8110a44d3038c67ed1d79eb733c4953c628b0f6"}, + {file = "fonttools-4.55.0-cp312-cp312-win_amd64.whl", hash = "sha256:f8c8c76037d05652510ae45be1cd8fb5dd2fd9afec92a25374ac82255993d57c"}, + {file = "fonttools-4.55.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8118dc571921dc9e4b288d9cb423ceaf886d195a2e5329cc427df82bba872cd9"}, + {file = "fonttools-4.55.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01124f2ca6c29fad4132d930da69158d3f49b2350e4a779e1efbe0e82bd63f6c"}, + {file = "fonttools-4.55.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ffd58d2691f11f7c8438796e9f21c374828805d33e83ff4b76e4635633674c"}, + {file = "fonttools-4.55.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5435e5f1eb893c35c2bc2b9cd3c9596b0fcb0a59e7a14121562986dd4c47b8dd"}, + {file = "fonttools-4.55.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d12081729280c39d001edd0f4f06d696014c26e6e9a0a55488fabc37c28945e4"}, + {file = "fonttools-4.55.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7ad1f1b98ab6cb927ab924a38a8649f1ffd7525c75fe5b594f5dab17af70e18"}, + {file = "fonttools-4.55.0-cp313-cp313-win32.whl", hash = "sha256:abe62987c37630dca69a104266277216de1023cf570c1643bb3a19a9509e7a1b"}, + {file = "fonttools-4.55.0-cp313-cp313-win_amd64.whl", hash = "sha256:2863555ba90b573e4201feaf87a7e71ca3b97c05aa4d63548a4b69ea16c9e998"}, + {file = "fonttools-4.55.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:00f7cf55ad58a57ba421b6a40945b85ac7cc73094fb4949c41171d3619a3a47e"}, + {file = "fonttools-4.55.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f27526042efd6f67bfb0cc2f1610fa20364396f8b1fc5edb9f45bb815fb090b2"}, + {file = "fonttools-4.55.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e67974326af6a8879dc2a4ec63ab2910a1c1a9680ccd63e4a690950fceddbe"}, + {file = "fonttools-4.55.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61dc0a13451143c5e987dec5254d9d428f3c2789a549a7cf4f815b63b310c1cc"}, + {file = "fonttools-4.55.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b2e526b325a903868c62155a6a7e24df53f6ce4c5c3160214d8fe1be2c41b478"}, + {file = "fonttools-4.55.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b7ef9068a1297714e6fefe5932c33b058aa1d45a2b8be32a4c6dee602ae22b5c"}, + {file = "fonttools-4.55.0-cp38-cp38-win32.whl", hash = "sha256:55718e8071be35dff098976bc249fc243b58efa263768c611be17fe55975d40a"}, + {file = "fonttools-4.55.0-cp38-cp38-win_amd64.whl", hash = "sha256:553bd4f8cc327f310c20158e345e8174c8eed49937fb047a8bda51daf2c353c8"}, + {file = "fonttools-4.55.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f901cef813f7c318b77d1c5c14cf7403bae5cb977cede023e22ba4316f0a8f6"}, + {file = "fonttools-4.55.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c9679fc0dd7e8a5351d321d8d29a498255e69387590a86b596a45659a39eb0d"}, + {file = "fonttools-4.55.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd2820a8b632f3307ebb0bf57948511c2208e34a4939cf978333bc0a3f11f838"}, + {file = "fonttools-4.55.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23bbbb49bec613a32ed1b43df0f2b172313cee690c2509f1af8fdedcf0a17438"}, + {file = "fonttools-4.55.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a656652e1f5d55b9728937a7e7d509b73d23109cddd4e89ee4f49bde03b736c6"}, + {file = "fonttools-4.55.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f50a1f455902208486fbca47ce33054208a4e437b38da49d6721ce2fef732fcf"}, + {file = "fonttools-4.55.0-cp39-cp39-win32.whl", hash = "sha256:161d1ac54c73d82a3cded44202d0218ab007fde8cf194a23d3dd83f7177a2f03"}, + {file = "fonttools-4.55.0-cp39-cp39-win_amd64.whl", hash = "sha256:ca7fd6987c68414fece41c96836e945e1f320cda56fc96ffdc16e54a44ec57a2"}, + {file = "fonttools-4.55.0-py3-none-any.whl", hash = "sha256:12db5888cd4dd3fcc9f0ee60c6edd3c7e1fd44b7dd0f31381ea03df68f8a153f"}, + {file = "fonttools-4.55.0.tar.gz", hash = "sha256:7636acc6ab733572d5e7eec922b254ead611f1cdad17be3f0be7418e8bfaca71"}, ] [package.extras] @@ -1546,26 +1510,15 @@ pygments = ">=2.7" sphinx = ">=5.0,<7.0" sphinx-basic-ng = "*" -[[package]] -name = "gast" -version = "0.6.0" -description = "Python AST that abstracts the underlying Python version" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "gast-0.6.0-py3-none-any.whl", hash = "sha256:52b182313f7330389f72b069ba00f174cfe2a06411099547288839c6cbafbd54"}, - {file = "gast-0.6.0.tar.gz", hash = "sha256:88fc5300d32c7ac6ca7b515310862f71e6fdf2c029bbec7c66c0f5dd47b6b1fb"}, -] - [[package]] name = "google-api-core" -version = "2.21.0" +version = "2.23.0" description = "Google API client core library" optional = false python-versions = ">=3.7" files = [ - {file = "google_api_core-2.21.0-py3-none-any.whl", hash = "sha256:6869eacb2a37720380ba5898312af79a4d30b8bca1548fb4093e0697dc4bdf5d"}, - {file = "google_api_core-2.21.0.tar.gz", hash = "sha256:4a152fd11a9f774ea606388d423b68aa7e6d6a0ffe4c8266f74979613ec09f81"}, + {file = "google_api_core-2.23.0-py3-none-any.whl", hash = "sha256:c20100d4c4c41070cf365f1d8ddf5365915291b5eb11b83829fbd1c999b5122f"}, + {file = "google_api_core-2.23.0.tar.gz", hash = "sha256:2ceb087315e6af43f256704b871d99326b1f12a9d6ce99beaedec99ba26a0ace"}, ] [package.dependencies] @@ -1591,13 +1544,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.35.0" +version = "2.36.0" description = "Google Authentication Library" optional = false python-versions = ">=3.7" files = [ - {file = "google_auth-2.35.0-py2.py3-none-any.whl", hash = "sha256:25df55f327ef021de8be50bad0dfd4a916ad0de96da86cd05661c9297723ad3f"}, - {file = "google_auth-2.35.0.tar.gz", hash = "sha256:f4c64ed4e01e8e8b646ef34c018f8bf3338df0c8e37d8b3bba40e7f574a3278a"}, + {file = "google_auth-2.36.0-py2.py3-none-any.whl", hash = "sha256:51a15d47028b66fd36e5c64a82d2d57480075bccc7da37cde257fc94177a61fb"}, + {file = "google_auth-2.36.0.tar.gz", hash = "sha256:545e9618f2df0bcbb7dcbc45a546485b1212624716975a1ea5ae8149ce769ab1"}, ] [package.dependencies] @@ -1612,30 +1565,15 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] -[[package]] -name = "google-pasta" -version = "0.2.0" -description = "pasta is an AST-based Python refactoring library" -optional = false -python-versions = "*" -files = [ - {file = "google-pasta-0.2.0.tar.gz", hash = "sha256:c9f2c8dfc8f96d0d5808299920721be30c9eec37f2389f28904f454565c8a16e"}, - {file = "google_pasta-0.2.0-py2-none-any.whl", hash = "sha256:4612951da876b1a10fe3960d7226f0c7682cf901e16ac06e473b267a5afa8954"}, - {file = "google_pasta-0.2.0-py3-none-any.whl", hash = "sha256:b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed"}, -] - -[package.dependencies] -six = "*" - [[package]] name = "googleapis-common-protos" -version = "1.65.0" +version = "1.66.0" description = "Common protobufs used in Google APIs" optional = false python-versions = ">=3.7" files = [ - {file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"}, - {file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"}, + {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, + {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, ] [package.dependencies] @@ -1732,85 +1670,85 @@ test = ["objgraph", "psutil"] [[package]] name = "grpcio" -version = "1.67.0" +version = "1.68.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.67.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:bd79929b3bb96b54df1296cd3bf4d2b770bd1df6c2bdf549b49bab286b925cdc"}, - {file = "grpcio-1.67.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:16724ffc956ea42967f5758c2f043faef43cb7e48a51948ab593570570d1e68b"}, - {file = "grpcio-1.67.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:2b7183c80b602b0ad816315d66f2fb7887614ead950416d60913a9a71c12560d"}, - {file = "grpcio-1.67.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:efe32b45dd6d118f5ea2e5deaed417d8a14976325c93812dd831908522b402c9"}, - {file = "grpcio-1.67.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe89295219b9c9e47780a0f1c75ca44211e706d1c598242249fe717af3385ec8"}, - {file = "grpcio-1.67.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa8d025fae1595a207b4e47c2e087cb88d47008494db258ac561c00877d4c8f8"}, - {file = "grpcio-1.67.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f95e15db43e75a534420e04822df91f645664bf4ad21dfaad7d51773c80e6bb4"}, - {file = "grpcio-1.67.0-cp310-cp310-win32.whl", hash = "sha256:a6b9a5c18863fd4b6624a42e2712103fb0f57799a3b29651c0e5b8119a519d65"}, - {file = "grpcio-1.67.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6eb68493a05d38b426604e1dc93bfc0137c4157f7ab4fac5771fd9a104bbaa6"}, - {file = "grpcio-1.67.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:e91d154689639932305b6ea6f45c6e46bb51ecc8ea77c10ef25aa77f75443ad4"}, - {file = "grpcio-1.67.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cb204a742997277da678611a809a8409657b1398aaeebf73b3d9563b7d154c13"}, - {file = "grpcio-1.67.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:ae6de510f670137e755eb2a74b04d1041e7210af2444103c8c95f193340d17ee"}, - {file = "grpcio-1.67.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74b900566bdf68241118f2918d312d3bf554b2ce0b12b90178091ea7d0a17b3d"}, - {file = "grpcio-1.67.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4e95e43447a02aa603abcc6b5e727d093d161a869c83b073f50b9390ecf0fa8"}, - {file = "grpcio-1.67.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0bb94e66cd8f0baf29bd3184b6aa09aeb1a660f9ec3d85da615c5003154bc2bf"}, - {file = "grpcio-1.67.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:82e5bd4b67b17c8c597273663794a6a46a45e44165b960517fe6d8a2f7f16d23"}, - {file = "grpcio-1.67.0-cp311-cp311-win32.whl", hash = "sha256:7fc1d2b9fd549264ae585026b266ac2db53735510a207381be509c315b4af4e8"}, - {file = "grpcio-1.67.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac11ecb34a86b831239cc38245403a8de25037b448464f95c3315819e7519772"}, - {file = "grpcio-1.67.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:227316b5631260e0bef8a3ce04fa7db4cc81756fea1258b007950b6efc90c05d"}, - {file = "grpcio-1.67.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d90cfdafcf4b45a7a076e3e2a58e7bc3d59c698c4f6470b0bb13a4d869cf2273"}, - {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:77196216d5dd6f99af1c51e235af2dd339159f657280e65ce7e12c1a8feffd1d"}, - {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15c05a26a0f7047f720da41dc49406b395c1470eef44ff7e2c506a47ac2c0591"}, - {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3840994689cc8cbb73d60485c594424ad8adb56c71a30d8948d6453083624b52"}, - {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5a1e03c3102b6451028d5dc9f8591131d6ab3c8a0e023d94c28cb930ed4b5f81"}, - {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:682968427a63d898759474e3b3178d42546e878fdce034fd7474ef75143b64e3"}, - {file = "grpcio-1.67.0-cp312-cp312-win32.whl", hash = "sha256:d01793653248f49cf47e5695e0a79805b1d9d4eacef85b310118ba1dfcd1b955"}, - {file = "grpcio-1.67.0-cp312-cp312-win_amd64.whl", hash = "sha256:985b2686f786f3e20326c4367eebdaed3e7aa65848260ff0c6644f817042cb15"}, - {file = "grpcio-1.67.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:8c9a35b8bc50db35ab8e3e02a4f2a35cfba46c8705c3911c34ce343bd777813a"}, - {file = "grpcio-1.67.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:42199e704095b62688998c2d84c89e59a26a7d5d32eed86d43dc90e7a3bd04aa"}, - {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c4c425f440fb81f8d0237c07b9322fc0fb6ee2b29fbef5f62a322ff8fcce240d"}, - {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:323741b6699cd2b04a71cb38f502db98f90532e8a40cb675393d248126a268af"}, - {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:662c8e105c5e5cee0317d500eb186ed7a93229586e431c1bf0c9236c2407352c"}, - {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f6bd2ab135c64a4d1e9e44679a616c9bc944547357c830fafea5c3caa3de5153"}, - {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2f55c1e0e2ae9bdd23b3c63459ee4c06d223b68aeb1961d83c48fb63dc29bc03"}, - {file = "grpcio-1.67.0-cp313-cp313-win32.whl", hash = "sha256:fd6bc27861e460fe28e94226e3673d46e294ca4673d46b224428d197c5935e69"}, - {file = "grpcio-1.67.0-cp313-cp313-win_amd64.whl", hash = "sha256:cf51d28063338608cd8d3cd64677e922134837902b70ce00dad7f116e3998210"}, - {file = "grpcio-1.67.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:7f200aca719c1c5dc72ab68be3479b9dafccdf03df530d137632c534bb6f1ee3"}, - {file = "grpcio-1.67.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0892dd200ece4822d72dd0952f7112c542a487fc48fe77568deaaa399c1e717d"}, - {file = "grpcio-1.67.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:f4d613fbf868b2e2444f490d18af472ccb47660ea3df52f068c9c8801e1f3e85"}, - {file = "grpcio-1.67.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c69bf11894cad9da00047f46584d5758d6ebc9b5950c0dc96fec7e0bce5cde9"}, - {file = "grpcio-1.67.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9bca3ca0c5e74dea44bf57d27e15a3a3996ce7e5780d61b7c72386356d231db"}, - {file = "grpcio-1.67.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:014dfc020e28a0d9be7e93a91f85ff9f4a87158b7df9952fe23cc42d29d31e1e"}, - {file = "grpcio-1.67.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d4ea4509d42c6797539e9ec7496c15473177ce9abc89bc5c71e7abe50fc25737"}, - {file = "grpcio-1.67.0-cp38-cp38-win32.whl", hash = "sha256:9d75641a2fca9ae1ae86454fd25d4c298ea8cc195dbc962852234d54a07060ad"}, - {file = "grpcio-1.67.0-cp38-cp38-win_amd64.whl", hash = "sha256:cff8e54d6a463883cda2fab94d2062aad2f5edd7f06ae3ed030f2a74756db365"}, - {file = "grpcio-1.67.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:62492bd534979e6d7127b8a6b29093161a742dee3875873e01964049d5250a74"}, - {file = "grpcio-1.67.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eef1dce9d1a46119fd09f9a992cf6ab9d9178b696382439446ca5f399d7b96fe"}, - {file = "grpcio-1.67.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:f623c57a5321461c84498a99dddf9d13dac0e40ee056d884d6ec4ebcab647a78"}, - {file = "grpcio-1.67.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54d16383044e681f8beb50f905249e4e7261dd169d4aaf6e52eab67b01cbbbe2"}, - {file = "grpcio-1.67.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2a44e572fb762c668e4812156b81835f7aba8a721b027e2d4bb29fb50ff4d33"}, - {file = "grpcio-1.67.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:391df8b0faac84d42f5b8dfc65f5152c48ed914e13c522fd05f2aca211f8bfad"}, - {file = "grpcio-1.67.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfd9306511fdfc623a1ba1dc3bc07fbd24e6cfbe3c28b4d1e05177baa2f99617"}, - {file = "grpcio-1.67.0-cp39-cp39-win32.whl", hash = "sha256:30d47dbacfd20cbd0c8be9bfa52fdb833b395d4ec32fe5cff7220afc05d08571"}, - {file = "grpcio-1.67.0-cp39-cp39-win_amd64.whl", hash = "sha256:f55f077685f61f0fbd06ea355142b71e47e4a26d2d678b3ba27248abfe67163a"}, - {file = "grpcio-1.67.0.tar.gz", hash = "sha256:e090b2553e0da1c875449c8e75073dd4415dd71c9bde6a406240fdf4c0ee467c"}, + {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"}, + {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"}, + {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash = "sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"}, + {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash = "sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"}, + {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"}, + {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"}, + {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash = "sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"}, + {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"}, + {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"}, + {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"}, + {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash = "sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"}, + {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"}, + {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"}, + {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"}, + {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"}, + {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"}, + {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"}, + {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"}, + {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash = "sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"}, + {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash = "sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"}, + {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"}, + {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"}, + {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash = "sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"}, + {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash = "sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"}, + {file = "grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.67.0)"] +protobuf = ["grpcio-tools (>=1.68.0)"] [[package]] name = "grpcio-status" -version = "1.67.0" +version = "1.68.0" description = "Status proto mapping for gRPC" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio_status-1.67.0-py3-none-any.whl", hash = "sha256:0e79e2e01ba41a6ca6ed9d7a825323c511fe1653a646f8014c7e3c8132527acc"}, - {file = "grpcio_status-1.67.0.tar.gz", hash = "sha256:c3e5a86fa007e9e263cd5f988a8a907484da4caab582874ea2a4a6092734046b"}, + {file = "grpcio_status-1.68.0-py3-none-any.whl", hash = "sha256:0a71b15d989f02df803b4ba85c5bf1f43aeaa58ac021e5f9974b8cadc41f784d"}, + {file = "grpcio_status-1.68.0.tar.gz", hash = "sha256:8369823de22ab6a2cddb3804669c149ae7a71819e127c2dca7c2322028d52bea"}, ] [package.dependencies] googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.67.0" +grpcio = ">=1.68.0" protobuf = ">=5.26.1,<6.0dev" [[package]] @@ -1824,44 +1762,6 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] -[[package]] -name = "h5py" -version = "3.12.1" -description = "Read and write HDF5 files from Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "h5py-3.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f0f1a382cbf494679c07b4371f90c70391dedb027d517ac94fa2c05299dacda"}, - {file = "h5py-3.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cb65f619dfbdd15e662423e8d257780f9a66677eae5b4b3fc9dca70b5fd2d2a3"}, - {file = "h5py-3.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b15d8dbd912c97541312c0e07438864d27dbca857c5ad634de68110c6beb1c2"}, - {file = "h5py-3.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59685fe40d8c1fbbee088c88cd4da415a2f8bee5c270337dc5a1c4aa634e3307"}, - {file = "h5py-3.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:577d618d6b6dea3da07d13cc903ef9634cde5596b13e832476dd861aaf651f3e"}, - {file = "h5py-3.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ccd9006d92232727d23f784795191bfd02294a4f2ba68708825cb1da39511a93"}, - {file = "h5py-3.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad8a76557880aed5234cfe7279805f4ab5ce16b17954606cca90d578d3e713ef"}, - {file = "h5py-3.12.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1473348139b885393125126258ae2d70753ef7e9cec8e7848434f385ae72069e"}, - {file = "h5py-3.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:018a4597f35092ae3fb28ee851fdc756d2b88c96336b8480e124ce1ac6fb9166"}, - {file = "h5py-3.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:3fdf95092d60e8130ba6ae0ef7a9bd4ade8edbe3569c13ebbaf39baefffc5ba4"}, - {file = "h5py-3.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06a903a4e4e9e3ebbc8b548959c3c2552ca2d70dac14fcfa650d9261c66939ed"}, - {file = "h5py-3.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7b3b8f3b48717e46c6a790e3128d39c61ab595ae0a7237f06dfad6a3b51d5351"}, - {file = "h5py-3.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:050a4f2c9126054515169c49cb900949814987f0c7ae74c341b0c9f9b5056834"}, - {file = "h5py-3.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c4b41d1019322a5afc5082864dfd6359f8935ecd37c11ac0029be78c5d112c9"}, - {file = "h5py-3.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4d51919110a030913201422fb07987db4338eba5ec8c5a15d6fab8e03d443fc"}, - {file = "h5py-3.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:513171e90ed92236fc2ca363ce7a2fc6f2827375efcbb0cc7fbdd7fe11fecafc"}, - {file = "h5py-3.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:59400f88343b79655a242068a9c900001a34b63e3afb040bd7cdf717e440f653"}, - {file = "h5py-3.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e465aee0ec353949f0f46bf6c6f9790a2006af896cee7c178a8c3e5090aa32"}, - {file = "h5py-3.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba51c0c5e029bb5420a343586ff79d56e7455d496d18a30309616fdbeed1068f"}, - {file = "h5py-3.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:52ab036c6c97055b85b2a242cb540ff9590bacfda0c03dd0cf0661b311f522f8"}, - {file = "h5py-3.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2b8dd64f127d8b324f5d2cd1c0fd6f68af69084e9e47d27efeb9e28e685af3e"}, - {file = "h5py-3.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4532c7e97fbef3d029735db8b6f5bf01222d9ece41e309b20d63cfaae2fb5c4d"}, - {file = "h5py-3.12.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdf6d7936fa824acfa27305fe2d9f39968e539d831c5bae0e0d83ed521ad1ac"}, - {file = "h5py-3.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84342bffd1f82d4f036433e7039e241a243531a1d3acd7341b35ae58cdab05bf"}, - {file = "h5py-3.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:62be1fc0ef195891949b2c627ec06bc8e837ff62d5b911b6e42e38e0f20a897d"}, - {file = "h5py-3.12.1.tar.gz", hash = "sha256:326d70b53d31baa61f00b8aa5f95c2fcb9621a3ee8365d770c551a13dbbcbfdf"}, -] - -[package.dependencies] -numpy = ">=1.19.3" - [[package]] name = "httpcore" version = "0.16.3" @@ -2191,22 +2091,22 @@ scipy = [ [[package]] name = "jedi" -version = "0.19.1" +version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, - {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, + {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, + {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, ] [package.dependencies] -parso = ">=0.8.3,<0.9.0" +parso = ">=0.8.4,<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 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] [[package]] name = "jinja2" @@ -2320,27 +2220,6 @@ files = [ {file = "jupyterlab_widgets-3.0.13.tar.gz", hash = "sha256:a2966d385328c1942b683a8cd96b89b8dd82c8b8f81dda902bb2bc06d46f5bed"}, ] -[[package]] -name = "keras" -version = "3.6.0" -description = "Multi-backend Keras." -optional = false -python-versions = ">=3.9" -files = [ - {file = "keras-3.6.0-py3-none-any.whl", hash = "sha256:49585e4577f6e86bd890d96dfbcb1890f5bab5967ef831c07fd63f9d86e4bfe9"}, - {file = "keras-3.6.0.tar.gz", hash = "sha256:405727525a3522ed8f9ec0b46e0667e4c65fcf714a067322c16a00d902ded41d"}, -] - -[package.dependencies] -absl-py = "*" -h5py = "*" -ml-dtypes = "*" -namex = "*" -numpy = "*" -optree = "*" -packaging = "*" -rich = "*" - [[package]] name = "kiwisolver" version = "1.4.7" @@ -2490,52 +2369,34 @@ files = [ {file = "latexcodec-3.0.0.tar.gz", hash = "sha256:917dc5fe242762cc19d963e6548b42d63a118028cdd3361d62397e3b638b6bc5"}, ] -[[package]] -name = "libclang" -version = "18.1.1" -description = "Clang Python Bindings, mirrored from the official LLVM repo: https://github.com/llvm/llvm-project/tree/main/clang/bindings/python, to make the installation process easier." -optional = false -python-versions = "*" -files = [ - {file = "libclang-18.1.1-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:6f14c3f194704e5d09769108f03185fce7acaf1d1ae4bbb2f30a72c2400cb7c5"}, - {file = "libclang-18.1.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:83ce5045d101b669ac38e6da8e58765f12da2d3aafb3b9b98d88b286a60964d8"}, - {file = "libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl", hash = "sha256:c533091d8a3bbf7460a00cb6c1a71da93bffe148f172c7d03b1c31fbf8aa2a0b"}, - {file = "libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:54dda940a4a0491a9d1532bf071ea3ef26e6dbaf03b5000ed94dd7174e8f9592"}, - {file = "libclang-18.1.1-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:cf4a99b05376513717ab5d82a0db832c56ccea4fd61a69dbb7bccf2dfb207dbe"}, - {file = "libclang-18.1.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:69f8eb8f65c279e765ffd28aaa7e9e364c776c17618af8bff22a8df58677ff4f"}, - {file = "libclang-18.1.1-py2.py3-none-win_amd64.whl", hash = "sha256:4dd2d3b82fab35e2bf9ca717d7b63ac990a3519c7e312f19fa8e86dcc712f7fb"}, - {file = "libclang-18.1.1-py2.py3-none-win_arm64.whl", hash = "sha256:3f0e1f49f04d3cd198985fea0511576b0aee16f9ff0e0f0cad7f9c57ec3c20e8"}, - {file = "libclang-18.1.1.tar.gz", hash = "sha256:a1214966d08d73d971287fc3ead8dfaf82eb07fb197680d8b3859dbbbbf78250"}, -] - [[package]] name = "llvmlite" -version = "0.42.0" +version = "0.43.0" description = "lightweight wrapper around basic LLVM functionality" optional = false python-versions = ">=3.9" files = [ - {file = "llvmlite-0.42.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3366938e1bf63d26c34fbfb4c8e8d2ded57d11e0567d5bb243d89aab1eb56098"}, - {file = "llvmlite-0.42.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c35da49666a21185d21b551fc3caf46a935d54d66969d32d72af109b5e7d2b6f"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70f44ccc3c6220bd23e0ba698a63ec2a7d3205da0d848804807f37fc243e3f77"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f8d8717a9073b9e0246998de89929071d15b47f254c10eef2310b9aac033d"}, - {file = "llvmlite-0.42.0-cp310-cp310-win_amd64.whl", hash = "sha256:8d90edf400b4ceb3a0e776b6c6e4656d05c7187c439587e06f86afceb66d2be5"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb3975787f13eb97629052edb5017f6c170eebc1c14a0433e8089e5db43bcce6"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9"}, - {file = "llvmlite-0.42.0-cp311-cp311-win_amd64.whl", hash = "sha256:7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:08fa9ab02b0d0179c688a4216b8939138266519aaa0aa94f1195a8542faedb56"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b2fce7d355068494d1e42202c7aff25d50c462584233013eb4470c33b995e3ee"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebe66a86dc44634b59a3bc860c7b20d26d9aaffcd30364ebe8ba79161a9121f4"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d47494552559e00d81bfb836cf1c4d5a5062e54102cc5767d5aa1e77ccd2505c"}, - {file = "llvmlite-0.42.0-cp312-cp312-win_amd64.whl", hash = "sha256:05cb7e9b6ce69165ce4d1b994fbdedca0c62492e537b0cc86141b6e2c78d5888"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdd3888544538a94d7ec99e7c62a0cdd8833609c85f0c23fcb6c5c591aec60ad"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0936c2067a67fb8816c908d5457d63eba3e2b17e515c5fe00e5ee2bace06040"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a78ab89f1924fc11482209f6799a7a3fc74ddc80425a7a3e0e8174af0e9e2301"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7599b65c7af7abbc978dbf345712c60fd596aa5670496561cc10e8a71cebfb2"}, - {file = "llvmlite-0.42.0-cp39-cp39-win_amd64.whl", hash = "sha256:43d65cc4e206c2e902c1004dd5418417c4efa6c1d04df05c6c5675a27e8ca90e"}, - {file = "llvmlite-0.42.0.tar.gz", hash = "sha256:f92b09243c0cc3f457da8b983f67bd8e1295d0f5b3746c7a1861d7a99403854a"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a289af9a1687c6cf463478f0fa8e8aa3b6fb813317b0d70bf1ed0759eab6f761"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d4fd101f571a31acb1559ae1af30f30b1dc4b3186669f92ad780e17c81e91bc"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d434ec7e2ce3cc8f452d1cd9a28591745de022f931d67be688a737320dfcead"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6912a87782acdff6eb8bf01675ed01d60ca1f2551f8176a300a886f09e836a6a"}, + {file = "llvmlite-0.43.0-cp310-cp310-win_amd64.whl", hash = "sha256:14f0e4bf2fd2d9a75a3534111e8ebeb08eda2f33e9bdd6dfa13282afacdde0ed"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749"}, + {file = "llvmlite-0.43.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f99b600aa7f65235a5a05d0b9a9f31150c390f31261f2a0ba678e26823ec38f7"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:35d80d61d0cda2d767f72de99450766250560399edc309da16937b93d3b676e7"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eccce86bba940bae0d8d48ed925f21dbb813519169246e2ab292b5092aba121f"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df6509e1507ca0760787a199d19439cc887bfd82226f5af746d6977bd9f66844"}, + {file = "llvmlite-0.43.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a2872ee80dcf6b5dbdc838763d26554c2a18aa833d31a2635bff16aafefb9c9"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cd2a7376f7b3367019b664c21f0c61766219faa3b03731113ead75107f3b66c"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18e9953c748b105668487b7c81a3e97b046d8abf95c4ddc0cd3c94f4e4651ae8"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74937acd22dc11b33946b67dca7680e6d103d6e90eeaaaf932603bec6fe7b03a"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9efc739cc6ed760f795806f67889923f7274276f0eb45092a1473e40d9b867"}, + {file = "llvmlite-0.43.0-cp39-cp39-win_amd64.whl", hash = "sha256:47e147cdda9037f94b399bf03bfd8a6b6b1f2f90be94a454e3386f006455a9b4"}, + {file = "llvmlite-0.43.0.tar.gz", hash = "sha256:ae2b5b5c3ef67354824fb75517c8db5fbe93bc02cd9671f3c62271626bc041d5"}, ] [[package]] @@ -2575,30 +2436,6 @@ importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - [[package]] name = "markupsafe" version = "3.0.2" @@ -2758,17 +2595,6 @@ files = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - [[package]] name = "mistune" version = "3.0.2" @@ -2800,34 +2626,38 @@ tbb = "==2021.*" [[package]] name = "ml-dtypes" -version = "0.4.1" +version = "0.5.0" description = "" optional = false python-versions = ">=3.9" files = [ - {file = "ml_dtypes-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1fe8b5b5e70cd67211db94b05cfd58dace592f24489b038dc6f9fe347d2e07d5"}, - {file = "ml_dtypes-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c09a6d11d8475c2a9fd2bc0695628aec105f97cab3b3a3fb7c9660348ff7d24"}, - {file = "ml_dtypes-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5e8f75fa371020dd30f9196e7d73babae2abd51cf59bdd56cb4f8de7e13354"}, - {file = "ml_dtypes-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:15fdd922fea57e493844e5abb930b9c0bd0af217d9edd3724479fc3d7ce70e3f"}, - {file = "ml_dtypes-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2d55b588116a7085d6e074cf0cdb1d6fa3875c059dddc4d2c94a4cc81c23e975"}, - {file = "ml_dtypes-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e138a9b7a48079c900ea969341a5754019a1ad17ae27ee330f7ebf43f23877f9"}, - {file = "ml_dtypes-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74c6cfb5cf78535b103fde9ea3ded8e9f16f75bc07789054edc7776abfb3d752"}, - {file = "ml_dtypes-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:274cc7193dd73b35fb26bef6c5d40ae3eb258359ee71cd82f6e96a8c948bdaa6"}, - {file = "ml_dtypes-0.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:827d3ca2097085cf0355f8fdf092b888890bb1b1455f52801a2d7756f056f54b"}, - {file = "ml_dtypes-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772426b08a6172a891274d581ce58ea2789cc8abc1c002a27223f314aaf894e7"}, - {file = "ml_dtypes-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:126e7d679b8676d1a958f2651949fbfa182832c3cd08020d8facd94e4114f3e9"}, - {file = "ml_dtypes-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:df0fb650d5c582a9e72bb5bd96cfebb2cdb889d89daff621c8fbc60295eba66c"}, - {file = "ml_dtypes-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e35e486e97aee577d0890bc3bd9e9f9eece50c08c163304008587ec8cfe7575b"}, - {file = "ml_dtypes-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:560be16dc1e3bdf7c087eb727e2cf9c0e6a3d87e9f415079d2491cc419b3ebf5"}, - {file = "ml_dtypes-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad0b757d445a20df39035c4cdeed457ec8b60d236020d2560dbc25887533cf50"}, - {file = "ml_dtypes-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:ef0d7e3fece227b49b544fa69e50e607ac20948f0043e9f76b44f35f229ea450"}, - {file = "ml_dtypes-0.4.1.tar.gz", hash = "sha256:fad5f2de464fd09127e49b7fd1252b9006fb43d2edc1ff112d390c324af5ca7a"}, + {file = "ml_dtypes-0.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c32138975797e681eb175996d64356bcfa124bdbb6a70460b9768c2b35a6fa4"}, + {file = "ml_dtypes-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab046f2ff789b1f11b2491909682c5d089934835f9a760fafc180e47dcb676b8"}, + {file = "ml_dtypes-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7a9152f5876fef565516aa5dd1dccd6fc298a5891b2467973905103eb5c7856"}, + {file = "ml_dtypes-0.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:968fede07d1f9b926a63df97d25ac656cac1a57ebd33701734eaf704bc55d8d8"}, + {file = "ml_dtypes-0.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60275f2b51b56834e840c4809fca840565f9bf8e9a73f6d8c94f5b5935701215"}, + {file = "ml_dtypes-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76942f6aeb5c40766d5ea62386daa4148e6a54322aaf5b53eae9e7553240222f"}, + {file = "ml_dtypes-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e7534392682c3098bc7341648c650864207169c654aed83143d7a19c67ae06f"}, + {file = "ml_dtypes-0.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:dc74fd9995513d33eac63d64e436240f5494ec74d522a9f0920194942fc3d2d7"}, + {file = "ml_dtypes-0.5.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d4b1a70a3e5219790d6b55b9507606fc4e02911d1497d16c18dd721eb7efe7d0"}, + {file = "ml_dtypes-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a988bac6572630e1e9c2edd9b1277b4eefd1c86209e52b0d061b775ac33902ff"}, + {file = "ml_dtypes-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a38df8df61194aeaae1ab7579075779b4ad32cd1cffd012c28be227fa7f2a70a"}, + {file = "ml_dtypes-0.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:afa08343069874a30812871d639f9c02b4158ace065601406a493a8511180c02"}, + {file = "ml_dtypes-0.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d3b3db9990c3840986a0e70524e122cfa32b91139c3653df76121ba7776e015f"}, + {file = "ml_dtypes-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e04fde367b2fe901b1d47234426fe8819909bd1dd862a5adb630f27789c20599"}, + {file = "ml_dtypes-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54415257f00eb44fbcc807454efac3356f75644f1cbfc2d4e5522a72ae1dacab"}, + {file = "ml_dtypes-0.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:cb5cc7b25acabd384f75bbd78892d0c724943f3e2e1986254665a1aa10982e07"}, + {file = "ml_dtypes-0.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f2b59233a0dbb6a560b3137ed6125433289ccba2f8d9c3695a52423a369ed15"}, + {file = "ml_dtypes-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:099e09edd54e676903b4538f3815b5ab96f5b119690514602d96bfdb67172cbe"}, + {file = "ml_dtypes-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a03fc861b86cc586728e3d093ba37f0cc05e65330c3ebd7688e7bae8290f8859"}, + {file = "ml_dtypes-0.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:7ee9c320bb0f9ffdf9f6fa6a696ef2e005d1f66438d6f1c1457338e00a02e8cf"}, + {file = "ml_dtypes-0.5.0.tar.gz", hash = "sha256:3e7d3a380fe73a63c884f06136f8baa7a5249cc8e9fdec677997dd78549f8128"}, ] [package.dependencies] numpy = [ {version = ">=1.21.2", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, - {version = ">1.20", markers = "python_version < \"3.10\""}, + {version = ">=1.21", markers = "python_version < \"3.10\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.3", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] @@ -2925,17 +2755,6 @@ files = [ {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, ] -[[package]] -name = "namex" -version = "0.0.8" -description = "A simple utility to separate the implementation of your Python package and its public API surface." -optional = false -python-versions = "*" -files = [ - {file = "namex-0.0.8-py3-none-any.whl", hash = "sha256:7ddb6c2bb0e753a311b7590f84f6da659dd0c05e65cb89d519d54c0a250c0487"}, - {file = "namex-0.0.8.tar.gz", hash = "sha256:32a50f6c565c0bb10aa76298c959507abdc0e850efe085dc38f3440fcb3aa90b"}, -] - [[package]] name = "nbclient" version = "0.10.0" @@ -3067,37 +2886,37 @@ test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "numba" -version = "0.59.1" +version = "0.60.0" description = "compiling Python code using LLVM" optional = false python-versions = ">=3.9" files = [ - {file = "numba-0.59.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:97385a7f12212c4f4bc28f648720a92514bee79d7063e40ef66c2d30600fd18e"}, - {file = "numba-0.59.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b77aecf52040de2a1eb1d7e314497b9e56fba17466c80b457b971a25bb1576d"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3476a4f641bfd58f35ead42f4dcaf5f132569c4647c6f1360ccf18ee4cda3990"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:525ef3f820931bdae95ee5379c670d5c97289c6520726bc6937a4a7d4230ba24"}, - {file = "numba-0.59.1-cp310-cp310-win_amd64.whl", hash = "sha256:990e395e44d192a12105eca3083b61307db7da10e093972ca285c85bef0963d6"}, - {file = "numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051"}, - {file = "numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2801003caa263d1e8497fb84829a7ecfb61738a95f62bc05693fcf1733e978e4"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389"}, - {file = "numba-0.59.1-cp311-cp311-win_amd64.whl", hash = "sha256:0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450"}, - {file = "numba-0.59.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1cce206a3b92836cdf26ef39d3a3242fec25e07f020cc4feec4c4a865e340569"}, - {file = "numba-0.59.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c8b4477763cb1fbd86a3be7050500229417bf60867c93e131fd2626edb02238"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d80bce4ef7e65bf895c29e3889ca75a29ee01da80266a01d34815918e365835"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7ad1d217773e89a9845886401eaaab0a156a90aa2f179fdc125261fd1105096"}, - {file = "numba-0.59.1-cp312-cp312-win_amd64.whl", hash = "sha256:5bf68f4d69dd3a9f26a9b23548fa23e3bcb9042e2935257b471d2a8d3c424b7f"}, - {file = "numba-0.59.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4e0318ae729de6e5dbe64c75ead1a95eb01fabfe0e2ebed81ebf0344d32db0ae"}, - {file = "numba-0.59.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0f68589740a8c38bb7dc1b938b55d1145244c8353078eea23895d4f82c8b9ec1"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:649913a3758891c77c32e2d2a3bcbedf4a69f5fea276d11f9119677c45a422e8"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9712808e4545270291d76b9a264839ac878c5eb7d8b6e02c970dc0ac29bc8187"}, - {file = "numba-0.59.1-cp39-cp39-win_amd64.whl", hash = "sha256:8d51ccd7008a83105ad6a0082b6a2b70f1142dc7cfd76deb8c5a862367eb8c86"}, - {file = "numba-0.59.1.tar.gz", hash = "sha256:76f69132b96028d2774ed20415e8c528a34e3299a40581bae178f0994a2f370b"}, + {file = "numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d761de835cd38fb400d2c26bb103a2726f548dc30368853121d66201672e651"}, + {file = "numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:159e618ef213fba758837f9837fb402bbe65326e60ba0633dbe6c7f274d42c1b"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1527dc578b95c7c4ff248792ec33d097ba6bef9eda466c948b68dfc995c25781"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe0b28abb8d70f8160798f4de9d486143200f34458d34c4a214114e445d7124e"}, + {file = "numba-0.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:19407ced081d7e2e4b8d8c36aa57b7452e0283871c296e12d798852bc7d7f198"}, + {file = "numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8"}, + {file = "numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8"}, + {file = "numba-0.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2"}, + {file = "numba-0.60.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7da4098db31182fc5ffe4bc42c6f24cd7d1cb8a14b59fd755bfee32e34b8404"}, + {file = "numba-0.60.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38d6ea4c1f56417076ecf8fc327c831ae793282e0ff51080c5094cb726507b1c"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:62908d29fb6a3229c242e981ca27e32a6e606cc253fc9e8faeb0e48760de241e"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ebaa91538e996f708f1ab30ef4d3ddc344b64b5227b67a57aa74f401bb68b9d"}, + {file = "numba-0.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:f75262e8fe7fa96db1dca93d53a194a38c46da28b112b8a4aca168f0df860347"}, + {file = "numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:01ef4cd7d83abe087d644eaa3d95831b777aa21d441a23703d649e06b8e06b74"}, + {file = "numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:819a3dfd4630d95fd574036f99e47212a1af41cbcb019bf8afac63ff56834449"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b983bd6ad82fe868493012487f34eae8bf7dd94654951404114f23c3466d34b"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c151748cd269ddeab66334bd754817ffc0cabd9433acb0f551697e5151917d25"}, + {file = "numba-0.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:3031547a015710140e8c87226b4cfe927cac199835e5bf7d4fe5cb64e814e3ab"}, + {file = "numba-0.60.0.tar.gz", hash = "sha256:5df6158e5584eece5fc83294b949fd30b9f1125df7708862205217e068aabf16"}, ] [package.dependencies] -llvmlite = "==0.42.*" -numpy = ">=1.22,<1.27" +llvmlite = "==0.43.*" +numpy = ">=1.22,<2.1" [[package]] name = "numpy" @@ -3318,124 +3137,15 @@ files = [ {file = "opt_einsum-3.4.0.tar.gz", hash = "sha256:96ca72f1b886d148241348783498194c577fa30a8faac108586b14f1ba4473ac"}, ] -[[package]] -name = "optree" -version = "0.13.0" -description = "Optimized PyTree Utilities." -optional = false -python-versions = ">=3.7" -files = [ - {file = "optree-0.13.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7b8fe0442ac5e50b5e6bceb37dcc2cd4908e7716b869cbe6b8901cc0b489884f"}, - {file = "optree-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a1aab34de5ac7673fbfb94266bf10482be51985c7f899c3e767ce19d13ce3b4"}, - {file = "optree-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2c79961d5afeb20557c30a0ae899d14ff58cdf1c0e2c8aa3d6807600d00f619"}, - {file = "optree-0.13.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb55eb77541cf280a009829280d5844936dc8a2e4a3eb069c010a1f547dbfe97"}, - {file = "optree-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44449e3bc5e7530b50c9a1f5bcf2971ffe317e34edd74d8c9778c5d32078114d"}, - {file = "optree-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b4195a6ba2052c70bac6d73f19aa69644424c5a30fa09f7319cc1b59e15acb6"}, - {file = "optree-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7fecc701ece0500fe38fc671b5704d904e2dca9a9284b35263b0bd7e5c62527"}, - {file = "optree-0.13.0-cp310-cp310-win32.whl", hash = "sha256:46a9e66217fdf421e25c133089c94f8f99bc38a2b5a4a2c0c1e0c1b02b01dda4"}, - {file = "optree-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:ef68fdcb3b1743a46210f3c888cd15668a07422aa10b4d4130ba512aac595bf7"}, - {file = "optree-0.13.0-cp310-cp310-win_arm64.whl", hash = "sha256:d12a5665169abceb878d50b55571d6a7690bf97aaaf9a7f5438b10e474fde3f2"}, - {file = "optree-0.13.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:92d1c34b6022bedee4b3899f3a9a1105777da11a9abf1a51f4d84bed8f037fa1"}, - {file = "optree-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d05c320af21efbc132fe887640f7a2dbb36cfb38af6d4e62396fe104b78f7b72"}, - {file = "optree-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a53ae0a0eb128a69a74db4165e7e5f24d54e2711678622198f7073dcb991962f"}, - {file = "optree-0.13.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89f08fc3724b2fe7a081b69dfd3ad6625960443e1f61a984cae7c627776f12f4"}, - {file = "optree-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f22f4e46d85f24b5bc49e68043dd754b258b880ac64d72f4f4b9ac1b11f0fb2f"}, - {file = "optree-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbc884f3eab894126398c120b7f92a72a5b9f92db6d8c27d39087da871c642cd"}, - {file = "optree-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c58b94669c9072d645e02c0c65c7455f8f136ef8f7b56a5d9123847421f95b"}, - {file = "optree-0.13.0-cp311-cp311-win32.whl", hash = "sha256:54be625517ef3cf52905da7fee63795b2f154dbdb02b37e8cfd63e7fb2f266ea"}, - {file = "optree-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:e3d100890a643e12f39de4226ab4f9d0a22842b4f34ae2964d0149419e4d7aff"}, - {file = "optree-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:cb8d9a2cebc5fadde98773bb27809a72ff01d11f1037cb58f8e71e740586223e"}, - {file = "optree-0.13.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:abeb8acc83d168063b70168ccf8dfd55f5a7ce50f9af2ca025c41285781ecdd4"}, - {file = "optree-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4771266f05e99e94312add38d45bf97a4d98449aeab100f5c658c521152eb5e5"}, - {file = "optree-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc95c1d0c7acd534184bf3ba243a454e0942e4a7c8b9edd32d939fc15e33d753"}, - {file = "optree-0.13.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e48491e042f956d4232ebc138e07074100878c0080e3ba10af4c2db1ba4df9f"}, - {file = "optree-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e001d9c902e98912503eca66c93d4b4b22f5071e4ab777f4db9e140f35288f4"}, - {file = "optree-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87870346278f46a8c22866ff48716590be35b4aea16e1373e695fb6442c28c41"}, - {file = "optree-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7797c54a35e9d89b4664ec7d542745b87b5ffa9c1201c1062fdcd488eb583390"}, - {file = "optree-0.13.0-cp312-cp312-win32.whl", hash = "sha256:fc90a5373c92f4a9babb4c40fe148516f52160c0ba803bc9b2f936367f2f7437"}, - {file = "optree-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:1bc65743e8edb29e902cab894d1c4665a8fd6f8d10f75db68a2cef6c7246fa5c"}, - {file = "optree-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:de2729e1e4ae47a07ac3c70ff977ed1ebe19e7b44d5089075c94f7a9a2dc6f4f"}, - {file = "optree-0.13.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dda6efabd0621f53eb46a3789ec89c6fd2c90dfb57aebfce3fcda6eab9ed6a7e"}, - {file = "optree-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5de8da9bbdd08b6200244ee818cd15d1da0f2b06ac926dba0e686260bac7fd40"}, - {file = "optree-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca1e4854134023ba687a7abf45ed3355f773ca7198b6895d88a89030446a9f2e"}, - {file = "optree-0.13.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1ac5343e921ce21f8f10f91158ad6404a1488c1cc22ddfa6b34cfb9d997cebd"}, - {file = "optree-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e282212ddf3aafb10ca6ca223772e06ea3c31687c9cae192467b8e0a7dafbfc"}, - {file = "optree-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24fcd4cb659bcd9b675bc3401950de891b32a047c4787857fb870cd515fcc315"}, - {file = "optree-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d735a7d2d2e2eb9a88d932d35b335c10fae9038034f381b6d437dafed46497e"}, - {file = "optree-0.13.0-cp313-cp313-win32.whl", hash = "sha256:ef01e79224f0ee6cf2ca642884f0bc04e446227b96dc576c312717eb33552d57"}, - {file = "optree-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:d3f61fb669b36c1a714346b18c9c488ad33a58049b7b229785c241de18c005d7"}, - {file = "optree-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:695b3f1aab50519230e3d8d86abaedaadf91af105b569cce3b8ebe0dc612b312"}, - {file = "optree-0.13.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1318434b0740a2325c197e191e6dd53d9df0a8ac0338c67d58b476aad9d07829"}, - {file = "optree-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d58c6e8d4c4fa4e0c31bc4b876960ccba94eb5fcfb045f2b064ce55707034be9"}, - {file = "optree-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6a290ba771cc9004f9fc194d23ab11ee4aae71550ca874c3dc985af5b5f910b"}, - {file = "optree-0.13.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c95488ecbab2916de094e68f2a2c55c9475b2e979c03d91a6cd3565f9e5ff2f9"}, - {file = "optree-0.13.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f76a65ff322b3d47af2a23f60409d6d8f184804da551c734e355834e69c0dfb"}, - {file = "optree-0.13.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58cc303f982fb0f23644b7f8e98b4f64b0d031365fcc2284da896e96493176d2"}, - {file = "optree-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6866b6e4154303dc7c48c7ca3b867a8ce31d469334b67976dfc0513455aa1ca0"}, - {file = "optree-0.13.0-cp313-cp313t-win32.whl", hash = "sha256:f5ce67f81fe3d7ca5fed8fdaf93a762a63e1d125e20e425ca7200f9e54a3e3a6"}, - {file = "optree-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0008cd39169c1fc10870528b2decfea8b79e61042c12d65a964f3b1cf41cc37d"}, - {file = "optree-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:539962675b547957c64b52b7f82178febb9c0f2d47438b810bbc23cfdcf84821"}, - {file = "optree-0.13.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b08e4873814d11aa25ef3927c848b9e5cf21215b925e83875b9fe11c7a035b0e"}, - {file = "optree-0.13.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6e236c6601480997c6e1dbbd4ab2b7ea0bc82a9a7baa1f681a1b072c9c02677"}, - {file = "optree-0.13.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:557b415b41006cca88d86ad190b795455e9334d3cf5838e63c4c668a65227ccb"}, - {file = "optree-0.13.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11b78c8a18894fe9503515d073a60ebaed366aeb3cfa65e61e7e71ae833f640b"}, - {file = "optree-0.13.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4207f6fa0bd4730f5496772c139f1444b2b69e4eeb0f454e2100b5a380648f70"}, - {file = "optree-0.13.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe9fd84b7d87f365f720699dedd254882ba7e5ef927d3ba1e13413d45963b691"}, - {file = "optree-0.13.0-cp37-cp37m-win32.whl", hash = "sha256:c0f9f250f617f114061ab718d460be6be8e0a1cbbfdbbfb5541ed1c8fefee150"}, - {file = "optree-0.13.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5cf612aefe0201a2995763cce82b9cd03cbddd2bfd6f8975f910c091dfa7bb5f"}, - {file = "optree-0.13.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:46623259b10f6e3565ea0d37e0b313feb20484bccb005459b3504e1aa706b730"}, - {file = "optree-0.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e7f9184c6040365e79a0b900507c289b6a4e06ade3c9691e501d176d5cf775cf"}, - {file = "optree-0.13.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6201c065791422a73d5aeb4916e00879de9b097cf54526f82b5b3c297126d938"}, - {file = "optree-0.13.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a423897010c6d8490097671d907da1b6ee90d3fa783aaad5e36e46e0a73bc5e"}, - {file = "optree-0.13.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1fb74282fce108e07972e88dbc23f6b7650c2d3bbddbedc2002d3e0becb1c452"}, - {file = "optree-0.13.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ecab158521225b20e44d67c8afc2d9af6760985a9f489d21bf2aa8bbe467f8"}, - {file = "optree-0.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8244d0fbfe1ef15ffb443f3d32a44aff062adbef0a7fd6db3f011999df966223"}, - {file = "optree-0.13.0-cp38-cp38-win32.whl", hash = "sha256:0a34c11d637cb01217828e28eef382c621c9ec53f981d8ccbfe56e0a11cda501"}, - {file = "optree-0.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:ebe56c17bf3754335307b17be7f554c5eae47acf738471cf38dba0ec73a42c37"}, - {file = "optree-0.13.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e9c619a49984212e5f757e10d5e5f95888b0c08d67a7f2b9f395cede30712dc2"}, - {file = "optree-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50a9e2d9ffff99d45b37289a3422ed3723a45225616f5b48cea606ff0f539c0f"}, - {file = "optree-0.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d702dbcafcd16e8925e30c0e780ab3dc81450e19008fd3e77494111fc161a2b2"}, - {file = "optree-0.13.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f44a58f87059161f300e2be66ad3878fff540d27f5dcd69b21feae65c243a02"}, - {file = "optree-0.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:954899edc024f13079932418f59bbdadabc52d9dcb49c7b559c382c7be352dfc"}, - {file = "optree-0.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c736ce6f4b8857bd171f3682ef849e3d67692c3fc4db42b99c5d2c7cc1bdf11"}, - {file = "optree-0.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7941d3bd48d860d0e17ca24827b5233ea27bb4227e822eafb3897df1f43f8342"}, - {file = "optree-0.13.0-cp39-cp39-win32.whl", hash = "sha256:9f6fc47c9b10d1a9e77163ebd6f2e251af41fab895475d2ce9643423a41899af"}, - {file = "optree-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:246020f0be50fb66791d8a25c4acb59ad0b4bbdea71c998e375eba4c58fbc3e0"}, - {file = "optree-0.13.0-cp39-cp39-win_arm64.whl", hash = "sha256:069bf166b7aa48ccf8dfe76b920d2115dd8261107c7895d02500b2ce39621b40"}, - {file = "optree-0.13.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:496170a3d093a7fb69be7ce847f5b5b3aa30a6da81457ba6b54268e6e97c6b13"}, - {file = "optree-0.13.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73543a82be71c041d5b169754089a58d02063eb72ac8688533b6fc26ab6beea8"}, - {file = "optree-0.13.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:278e2c620df99f5b1477b375b01cf9658528fa0332c0bc431d3ec65857244094"}, - {file = "optree-0.13.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b32155dce29edb6f63a99a44d6da2d8fcd1c56353cc2f4af65f793a0b2712f"}, - {file = "optree-0.13.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c98a43204841cc4698155acb523d7b21a78f8b05666704359e0fddecd5d1043d"}, - {file = "optree-0.13.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c2803d4ef257f2599cffd0e9d60cfb3d4c522abbe8f5a839bd48d8edd26dae7"}, - {file = "optree-0.13.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac3b454f98d28a89c15a1170e771c61902cbc53eed126db36138b684dba5a729"}, - {file = "optree-0.13.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b74afed3db289228e0f95a8909835365f644eb69ff31cd6c0b45608ca9e56d78"}, - {file = "optree-0.13.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc3cebfd7d0826d223662f01ed0fa25932edf3f62479be13c4d6ff0fab090c34"}, - {file = "optree-0.13.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5703637ede6fba04cbeabbb47aada7d17606c2d4df73305063f4a3c829c21fc7"}, - {file = "optree-0.13.0.tar.gz", hash = "sha256:1ea493cde8c60f7950ccbd682bd67e787bf67ed2251d6d3e9ad7471b72d37538"}, -] - -[package.dependencies] -typing-extensions = ">=4.5.0" - -[package.extras] -benchmark = ["dm-tree (>=0.1,<0.2.0a0)", "jax[cpu] (>=0.4.6,<0.5.0a0)", "pandas", "tabulate", "termcolor", "torch (>=2.0,<2.4.0a0)", "torchvision"] -docs = ["docutils", "jax[cpu]", "numpy", "sphinx", "sphinx-autoapi", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx-copybutton", "sphinx-rtd-theme", "sphinxcontrib-bibtex", "torch"] -jax = ["jax"] -lint = ["black", "cpplint", "doc8", "flake8", "flake8-bugbear", "flake8-comprehensions", "flake8-docstrings", "flake8-pyi", "flake8-simplify", "isort", "mypy", "pre-commit", "pydocstyle", "pyenchant", "pylint[spelling]", "ruff", "xdoctest"] -numpy = ["numpy"] -test = ["pytest", "pytest-cov", "pytest-xdist"] -torch = ["torch"] - [[package]] name = "optuna" -version = "4.0.0" +version = "4.1.0" description = "A hyperparameter optimization framework" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "optuna-4.0.0-py3-none-any.whl", hash = "sha256:a825c32d13f6085bcb2229b2724a5078f2e0f61a7533e800e580ce41a8c6c10d"}, - {file = "optuna-4.0.0.tar.gz", hash = "sha256:844949f09e2a7353ab414e9cfd783cf0a647a65fc32a7236212ed6a37fe08973"}, + {file = "optuna-4.1.0-py3-none-any.whl", hash = "sha256:1763856b01c9238594d9d21db92611aac9980e9a6300bd658a7c6464712c704e"}, + {file = "optuna-4.1.0.tar.gz", hash = "sha256:b364e87a2038f9946c5e2770c130597538aac528b4a82c1cab5267f337ea7679"}, ] [package.dependencies] @@ -3444,11 +3154,11 @@ colorlog = "*" numpy = "*" packaging = ">=20.0" PyYAML = "*" -sqlalchemy = ">=1.3.0" +sqlalchemy = ">=1.4.2" tqdm = "*" [package.extras] -benchmark = ["asv (>=0.5.0)", "botorch", "cma", "virtualenv"] +benchmark = ["asv (>=0.5.0)", "cma", "virtualenv"] checking = ["black", "blackdoc", "flake8", "isort", "mypy", "mypy-boto3-s3", "types-PyYAML", "types-redis", "types-setuptools", "types-tqdm", "typing-extensions (>=3.10.0.0)"] document = ["ase", "cmaes (>=0.10.0)", "fvcore", "kaleido", "lightgbm", "matplotlib (!=3.6.0)", "pandas", "pillow", "plotly (>=4.9.0)", "scikit-learn", "sphinx", "sphinx-copybutton", "sphinx-gallery", "sphinx-rtd-theme (>=1.2.0)", "torch", "torchvision"] optional = ["boto3", "cmaes (>=0.10.0)", "google-cloud-storage", "matplotlib (!=3.6.0)", "pandas", "plotly (>=4.9.0)", "redis", "scikit-learn (>=0.24.2)", "scipy", "torch"] @@ -3456,13 +3166,13 @@ test = ["coverage", "fakeredis[lua]", "kaleido", "moto", "pytest", "scipy (>=1.9 [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -3921,54 +3631,54 @@ files = [ [[package]] name = "pydantic" -version = "1.10.18" +version = "1.10.19" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e405ffcc1254d76bb0e760db101ee8916b620893e6edfbfee563b3c6f7a67c02"}, - {file = "pydantic-1.10.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e306e280ebebc65040034bff1a0a81fd86b2f4f05daac0131f29541cafd80b80"}, - {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11d9d9b87b50338b1b7de4ebf34fd29fdb0d219dc07ade29effc74d3d2609c62"}, - {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b661ce52c7b5e5f600c0c3c5839e71918346af2ef20062705ae76b5c16914cab"}, - {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c20f682defc9ef81cd7eaa485879ab29a86a0ba58acf669a78ed868e72bb89e0"}, - {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c5ae6b7c8483b1e0bf59e5f1843e4fd8fd405e11df7de217ee65b98eb5462861"}, - {file = "pydantic-1.10.18-cp310-cp310-win_amd64.whl", hash = "sha256:74fe19dda960b193b0eb82c1f4d2c8e5e26918d9cda858cbf3f41dd28549cb70"}, - {file = "pydantic-1.10.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72fa46abace0a7743cc697dbb830a41ee84c9db8456e8d77a46d79b537efd7ec"}, - {file = "pydantic-1.10.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef0fe7ad7cbdb5f372463d42e6ed4ca9c443a52ce544472d8842a0576d830da5"}, - {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00e63104346145389b8e8f500bc6a241e729feaf0559b88b8aa513dd2065481"}, - {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae6fa2008e1443c46b7b3a5eb03800121868d5ab6bc7cda20b5df3e133cde8b3"}, - {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9f463abafdc92635da4b38807f5b9972276be7c8c5121989768549fceb8d2588"}, - {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3445426da503c7e40baccefb2b2989a0c5ce6b163679dd75f55493b460f05a8f"}, - {file = "pydantic-1.10.18-cp311-cp311-win_amd64.whl", hash = "sha256:467a14ee2183bc9c902579bb2f04c3d3dac00eff52e252850509a562255b2a33"}, - {file = "pydantic-1.10.18-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:efbc8a7f9cb5fe26122acba1852d8dcd1e125e723727c59dcd244da7bdaa54f2"}, - {file = "pydantic-1.10.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24a4a159d0f7a8e26bf6463b0d3d60871d6a52eac5bb6a07a7df85c806f4c048"}, - {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b74be007703547dc52e3c37344d130a7bfacca7df112a9e5ceeb840a9ce195c7"}, - {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcb20d4cb355195c75000a49bb4a31d75e4295200df620f454bbc6bdf60ca890"}, - {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:46f379b8cb8a3585e3f61bf9ae7d606c70d133943f339d38b76e041ec234953f"}, - {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbfbca662ed3729204090c4d09ee4beeecc1a7ecba5a159a94b5a4eb24e3759a"}, - {file = "pydantic-1.10.18-cp312-cp312-win_amd64.whl", hash = "sha256:c6d0a9f9eccaf7f438671a64acf654ef0d045466e63f9f68a579e2383b63f357"}, - {file = "pydantic-1.10.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d5492dbf953d7d849751917e3b2433fb26010d977aa7a0765c37425a4026ff1"}, - {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe734914977eed33033b70bfc097e1baaffb589517863955430bf2e0846ac30f"}, - {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15fdbe568beaca9aacfccd5ceadfb5f1a235087a127e8af5e48df9d8a45ae85c"}, - {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c3e742f62198c9eb9201781fbebe64533a3bbf6a76a91b8d438d62b813079dbc"}, - {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:19a3bd00b9dafc2cd7250d94d5b578edf7a0bd7daf102617153ff9a8fa37871c"}, - {file = "pydantic-1.10.18-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce3fcf75b2bae99aa31bd4968de0474ebe8c8258a0110903478bd83dfee4e3b"}, - {file = "pydantic-1.10.18-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:335a32d72c51a313b33fa3a9b0fe283503272ef6467910338e123f90925f0f03"}, - {file = "pydantic-1.10.18-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:34a3613c7edb8c6fa578e58e9abe3c0f5e7430e0fc34a65a415a1683b9c32d9a"}, - {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9ee4e6ca1d9616797fa2e9c0bfb8815912c7d67aca96f77428e316741082a1b"}, - {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23e8ec1ce4e57b4f441fc91e3c12adba023fedd06868445a5b5f1d48f0ab3682"}, - {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:44ae8a3e35a54d2e8fa88ed65e1b08967a9ef8c320819a969bfa09ce5528fafe"}, - {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5389eb3b48a72da28c6e061a247ab224381435256eb541e175798483368fdd3"}, - {file = "pydantic-1.10.18-cp38-cp38-win_amd64.whl", hash = "sha256:069b9c9fc645474d5ea3653788b544a9e0ccd3dca3ad8c900c4c6eac844b4620"}, - {file = "pydantic-1.10.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80b982d42515632eb51f60fa1d217dfe0729f008e81a82d1544cc392e0a50ddf"}, - {file = "pydantic-1.10.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aad8771ec8dbf9139b01b56f66386537c6fe4e76c8f7a47c10261b69ad25c2c9"}, - {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941a2eb0a1509bd7f31e355912eb33b698eb0051730b2eaf9e70e2e1589cae1d"}, - {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65f7361a09b07915a98efd17fdec23103307a54db2000bb92095457ca758d485"}, - {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6951f3f47cb5ca4da536ab161ac0163cab31417d20c54c6de5ddcab8bc813c3f"}, - {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7a4c5eec138a9b52c67f664c7d51d4c7234c5ad65dd8aacd919fb47445a62c86"}, - {file = "pydantic-1.10.18-cp39-cp39-win_amd64.whl", hash = "sha256:49e26c51ca854286bffc22b69787a8d4063a62bf7d83dc21d44d2ff426108518"}, - {file = "pydantic-1.10.18-py3-none-any.whl", hash = "sha256:06a189b81ffc52746ec9c8c007f16e5167c8b0a696e1a726369327e3db7b2a82"}, - {file = "pydantic-1.10.18.tar.gz", hash = "sha256:baebdff1907d1d96a139c25136a9bb7d17e118f133a76a2ef3b845e831e3403a"}, + {file = "pydantic-1.10.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a415b9e95fa602b10808113967f72b2da8722061265d6af69268c111c254832d"}, + {file = "pydantic-1.10.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:11965f421f7eb026439d4eb7464e9182fe6d69c3d4d416e464a4485d1ba61ab6"}, + {file = "pydantic-1.10.19-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5bb81fcfc6d5bff62cd786cbd87480a11d23f16d5376ad2e057c02b3b44df96"}, + {file = "pydantic-1.10.19-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83ee8c9916689f8e6e7d90161e6663ac876be2efd32f61fdcfa3a15e87d4e413"}, + {file = "pydantic-1.10.19-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0399094464ae7f28482de22383e667625e38e1516d6b213176df1acdd0c477ea"}, + {file = "pydantic-1.10.19-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8b2cf5e26da84f2d2dee3f60a3f1782adedcee785567a19b68d0af7e1534bd1f"}, + {file = "pydantic-1.10.19-cp310-cp310-win_amd64.whl", hash = "sha256:1fc8cc264afaf47ae6a9bcbd36c018d0c6b89293835d7fb0e5e1a95898062d59"}, + {file = "pydantic-1.10.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d7a8a1dd68bac29f08f0a3147de1885f4dccec35d4ea926e6e637fac03cdb4b3"}, + {file = "pydantic-1.10.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07d00ca5ef0de65dd274005433ce2bb623730271d495a7d190a91c19c5679d34"}, + {file = "pydantic-1.10.19-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad57004e5d73aee36f1e25e4e73a4bc853b473a1c30f652dc8d86b0a987ffce3"}, + {file = "pydantic-1.10.19-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dce355fe7ae53e3090f7f5fa242423c3a7b53260747aa398b4b3aaf8b25f41c3"}, + {file = "pydantic-1.10.19-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0d32227ea9a3bf537a2273fd2fdb6d64ab4d9b83acd9e4e09310a777baaabb98"}, + {file = "pydantic-1.10.19-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e351df83d1c9cffa53d4e779009a093be70f1d5c6bb7068584086f6a19042526"}, + {file = "pydantic-1.10.19-cp311-cp311-win_amd64.whl", hash = "sha256:d8d72553d2f3f57ce547de4fa7dc8e3859927784ab2c88343f1fc1360ff17a08"}, + {file = "pydantic-1.10.19-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d5b5b7c6bafaef90cbb7dafcb225b763edd71d9e22489647ee7df49d6d341890"}, + {file = "pydantic-1.10.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:570ad0aeaf98b5e33ff41af75aba2ef6604ee25ce0431ecd734a28e74a208555"}, + {file = "pydantic-1.10.19-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0890fbd7fec9e151c7512941243d830b2d6076d5df159a2030952d480ab80a4e"}, + {file = "pydantic-1.10.19-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec5c44e6e9eac5128a9bfd21610df3b8c6b17343285cc185105686888dc81206"}, + {file = "pydantic-1.10.19-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6eb56074b11a696e0b66c7181da682e88c00e5cebe6570af8013fcae5e63e186"}, + {file = "pydantic-1.10.19-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9d7d48fbc5289efd23982a0d68e973a1f37d49064ccd36d86de4543aff21e086"}, + {file = "pydantic-1.10.19-cp312-cp312-win_amd64.whl", hash = "sha256:fd34012691fbd4e67bdf4accb1f0682342101015b78327eaae3543583fcd451e"}, + {file = "pydantic-1.10.19-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a5d5b877c7d3d9e17399571a8ab042081d22fe6904416a8b20f8af5909e6c8f"}, + {file = "pydantic-1.10.19-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c46f58ef2df958ed2ea7437a8be0897d5efe9ee480818405338c7da88186fb3"}, + {file = "pydantic-1.10.19-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d8a38a44bb6a15810084316ed69c854a7c06e0c99c5429f1d664ad52cec353c"}, + {file = "pydantic-1.10.19-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a82746c6d6e91ca17e75f7f333ed41d70fce93af520a8437821dec3ee52dfb10"}, + {file = "pydantic-1.10.19-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:566bebdbe6bc0ac593fa0f67d62febbad9f8be5433f686dc56401ba4aab034e3"}, + {file = "pydantic-1.10.19-cp37-cp37m-win_amd64.whl", hash = "sha256:22a1794e01591884741be56c6fba157c4e99dcc9244beb5a87bd4aa54b84ea8b"}, + {file = "pydantic-1.10.19-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:076c49e24b73d346c45f9282d00dbfc16eef7ae27c970583d499f11110d9e5b0"}, + {file = "pydantic-1.10.19-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5d4320510682d5a6c88766b2a286d03b87bd3562bf8d78c73d63bab04b21e7b4"}, + {file = "pydantic-1.10.19-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e66aa0fa7f8aa9d0a620361834f6eb60d01d3e9cea23ca1a92cda99e6f61dac"}, + {file = "pydantic-1.10.19-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d216f8d0484d88ab72ab45d699ac669fe031275e3fa6553e3804e69485449fa0"}, + {file = "pydantic-1.10.19-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9f28a81978e936136c44e6a70c65bde7548d87f3807260f73aeffbf76fb94c2f"}, + {file = "pydantic-1.10.19-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d3449633c207ec3d2d672eedb3edbe753e29bd4e22d2e42a37a2c1406564c20f"}, + {file = "pydantic-1.10.19-cp38-cp38-win_amd64.whl", hash = "sha256:7ea24e8614f541d69ea72759ff635df0e612b7dc9d264d43f51364df310081a3"}, + {file = "pydantic-1.10.19-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:573254d844f3e64093f72fcd922561d9c5696821ff0900a0db989d8c06ab0c25"}, + {file = "pydantic-1.10.19-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ff09600cebe957ecbb4a27496fe34c1d449e7957ed20a202d5029a71a8af2e35"}, + {file = "pydantic-1.10.19-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4739c206bfb6bb2bdc78dcd40bfcebb2361add4ceac6d170e741bb914e9eff0f"}, + {file = "pydantic-1.10.19-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bfb5b378b78229119d66ced6adac2e933c67a0aa1d0a7adffbe432f3ec14ce4"}, + {file = "pydantic-1.10.19-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f31742c95e3f9443b8c6fa07c119623e61d76603be9c0d390bcf7e888acabcb"}, + {file = "pydantic-1.10.19-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6444368b651a14c2ce2fb22145e1496f7ab23cbdb978590d47c8d34a7bc0289"}, + {file = "pydantic-1.10.19-cp39-cp39-win_amd64.whl", hash = "sha256:945407f4d08cd12485757a281fca0e5b41408606228612f421aa4ea1b63a095d"}, + {file = "pydantic-1.10.19-py3-none-any.whl", hash = "sha256:2206a1752d9fac011e95ca83926a269fb0ef5536f7e053966d058316e24d929f"}, + {file = "pydantic-1.10.19.tar.gz", hash = "sha256:fea36c2065b7a1d28c6819cc2e93387b43dd5d3cf5a1e82d8132ee23f36d1f10"}, ] [package.dependencies] @@ -3994,13 +3704,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyjwt" -version = "2.9.0" +version = "2.10.0" description = "JSON Web Token implementation in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "PyJWT-2.10.0-py3-none-any.whl", hash = "sha256:543b77207db656de204372350926bed5a86201c4cbff159f623f79c7bb487a15"}, + {file = "pyjwt-2.10.0.tar.gz", hash = "sha256:7628a7eb7938959ac1b26e819a1df0fd3259505627b575e4bad6d08f76db695c"}, ] [package.extras] @@ -4523,7 +4233,7 @@ toml = ">=0.10.2,<0.11.0" [[package]] name = "qibojit" -version = "0.1.7" +version = "0.1.8" description = "Simulation tools based on numba and cupy." optional = false python-versions = "^3.9,<3.13" @@ -4533,7 +4243,7 @@ develop = false [package.dependencies] numba = ">=0.59.0" psutil = "^5.9.5" -qibo = {git = "https://github.com/qiboteam/qibo.git"} +qibo = "^0.2.13" scipy = "^1.10.1" [package.extras] @@ -4544,7 +4254,7 @@ cuquantum = ["cuquantum-python-cu12 (>=23.10.0,<24.0.0)"] type = "git" url = "https://github.com/qiboteam/qibojit.git" reference = "HEAD" -resolved_reference = "e236bb0a47082593e55bf805372e053174f51395" +resolved_reference = "290b1776c2ba272f1c9eb59cba1d31964a239f2a" [[package]] name = "qiboml" @@ -4558,17 +4268,14 @@ develop = false [package.dependencies] jax = "^0.4.25" jaxlib = "^0.4.25" -numba = "^0.59.0" numpy = "^1.26.4" -qibo = {git = "https://github.com/qiboteam/qibo.git"} -tensorflow = {version = "^2.16.1", markers = "sys_platform == \"linux\" or sys_platform == \"darwin\""} -torch = "^2.2.0" +qibo = {git = "https://github.com/qiboteam/qibo"} [package.source] type = "git" url = "https://github.com/qiboteam/qiboml.git" reference = "HEAD" -resolved_reference = "d1df69bb493522c634a49c364421bc4c821d827f" +resolved_reference = "3e52004c497ca738730e21aa5a2ca8c2f6044398" [[package]] name = "qibotn" @@ -4590,17 +4297,17 @@ cuda = ["cupy-cuda11x (>=11.6.0,<12.0.0)", "cuquantum-python-cu11 (>=23.3.0,<24. type = "git" url = "https://github.com/qiboteam/qibotn.git" reference = "HEAD" -resolved_reference = "1eb3817bf4f8770bc6622d3070fea2eca85e6b24" +resolved_reference = "4f547726b616f73d074abf77811644cf2cb54383" [[package]] name = "quimb" -version = "1.8.4" +version = "1.9.0" description = "Quantum information and many-body library." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "quimb-1.8.4-py3-none-any.whl", hash = "sha256:357c42c5c1a696ba8234e1d7e1361aabc182ac76ff046a85fabb37f63d989d2d"}, - {file = "quimb-1.8.4.tar.gz", hash = "sha256:51b7b6f09a451f44468d7b41ac990635b2e718b437aee8db992f892c3e5d30b5"}, + {file = "quimb-1.9.0-py3-none-any.whl", hash = "sha256:edb2f621948410e8ba6fa30b023888a4b6fe46682ebf0cdb7acafe2d87b964d9"}, + {file = "quimb-1.9.0.tar.gz", hash = "sha256:f5a769e0403094f4fbccd9833648e48e7fac209a43b329b0586e7c4332a1b963"}, ] [package.dependencies] @@ -4740,25 +4447,6 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} [package.extras] idna2008 = ["idna"] -[[package]] -name = "rich" -version = "13.9.3" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "rich-13.9.3-py3-none-any.whl", hash = "sha256:9836f5096eb2172c9e77df411c1b009bace4193d6a481d534fea75ebba758283"}, - {file = "rich-13.9.3.tar.gz", hash = "sha256:bc1e01b899537598cf02579d2b9f4a415104d3fc439313a7a2c165d76557a08e"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - [[package]] name = "rpcq" version = "3.11.0" @@ -4960,26 +4648,6 @@ dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] -[[package]] -name = "setuptools" -version = "75.2.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, - {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] - [[package]] name = "six" version = "1.16.0" @@ -5447,138 +5115,6 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] -[[package]] -name = "tensorboard" -version = "2.18.0" -description = "TensorBoard lets you watch Tensors Flow" -optional = false -python-versions = ">=3.9" -files = [ - {file = "tensorboard-2.18.0-py3-none-any.whl", hash = "sha256:107ca4821745f73e2aefa02c50ff70a9b694f39f790b11e6f682f7d326745eab"}, -] - -[package.dependencies] -absl-py = ">=0.4" -grpcio = ">=1.48.2" -markdown = ">=2.6.8" -numpy = ">=1.12.0" -packaging = "*" -protobuf = ">=3.19.6,<4.24.0 || >4.24.0" -setuptools = ">=41.0.0" -six = ">1.9" -tensorboard-data-server = ">=0.7.0,<0.8.0" -werkzeug = ">=1.0.1" - -[[package]] -name = "tensorboard-data-server" -version = "0.7.2" -description = "Fast data loading for TensorBoard" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb"}, - {file = "tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60"}, - {file = "tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530"}, -] - -[[package]] -name = "tensorflow" -version = "2.18.0" -description = "TensorFlow is an open source machine learning framework for everyone." -optional = false -python-versions = ">=3.9" -files = [ - {file = "tensorflow-2.18.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:8da90a9388a1f6dd00d626590d2b5810faffbb3e7367f9783d80efff882340ee"}, - {file = "tensorflow-2.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:589342fb9bdcab2e9af0f946da4ca97757677e297d934fcdc087e87db99d6353"}, - {file = "tensorflow-2.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb77fae50d699442726d1b23c7512c97cd688cc7d857b028683d4535bbf3709"}, - {file = "tensorflow-2.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:46f5a8b4e6273f488dc069fc3ac2211b23acd3d0437d919349c787fa341baa8a"}, - {file = "tensorflow-2.18.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:453cb60638a02fd26316fb36c8cbcf1569d33671f17c658ca0cf2b4626f851e7"}, - {file = "tensorflow-2.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85f1e7369af6d329b117b52e86093cd1e0458dd5404bf5b665853f873dd00b48"}, - {file = "tensorflow-2.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b8dd70fa3600bfce66ab529eebb804e1f9d7c863d2f71bc8fe9fc7a1ec3976"}, - {file = "tensorflow-2.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e8b0f499ef0b7652480a58e358a73844932047f21c42c56f7f3bdcaf0803edc"}, - {file = "tensorflow-2.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ec4133a215c59314e929e7cbe914579d3afbc7874d9fa924873ee633fe4f71d0"}, - {file = "tensorflow-2.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4822904b3559d8a9c25f0fe5fef191cfc1352ceca42ca64f2a7bc7ae0ff4a1f5"}, - {file = "tensorflow-2.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfdd65ea7e064064283dd78d529dd621257ee617218f63681935fd15817c6286"}, - {file = "tensorflow-2.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:a701c2d3dca5f2efcab315b2c217f140ebd3da80410744e87d77016b3aaf53cb"}, - {file = "tensorflow-2.18.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:336cace378c129c20fee6292f6a541165073d153a9a4c9cf4f14478a81895776"}, - {file = "tensorflow-2.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfd32134de8f95515b2d0ced89cdae15484b787d3a21893e9291def06c10c4e"}, - {file = "tensorflow-2.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada1f7290c75b34748ee7378c1b77927e4044c94b8dc72dc75e7667c4fdaeb94"}, - {file = "tensorflow-2.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:f8c946df1cb384504578fac1c199a95322373b8e04abd88aa8ae01301df469ea"}, -] - -[package.dependencies] -absl-py = ">=1.0.0" -astunparse = ">=1.6.0" -flatbuffers = ">=24.3.25" -gast = ">=0.2.1,<0.5.0 || >0.5.0,<0.5.1 || >0.5.1,<0.5.2 || >0.5.2" -google-pasta = ">=0.1.1" -grpcio = ">=1.24.3,<2.0" -h5py = ">=3.11.0" -keras = ">=3.5.0" -libclang = ">=13.0.0" -ml-dtypes = ">=0.4.0,<0.5.0" -numpy = ">=1.26.0,<2.1.0" -opt-einsum = ">=2.3.2" -packaging = "*" -protobuf = ">=3.20.3,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" -requests = ">=2.21.0,<3" -setuptools = "*" -six = ">=1.12.0" -tensorboard = ">=2.18,<2.19" -tensorflow-io-gcs-filesystem = {version = ">=0.23.1", markers = "python_version < \"3.12\""} -termcolor = ">=1.1.0" -typing-extensions = ">=3.6.6" -wrapt = ">=1.11.0" - -[package.extras] -and-cuda = ["nvidia-cublas-cu12 (==12.5.3.2)", "nvidia-cuda-cupti-cu12 (==12.5.82)", "nvidia-cuda-nvcc-cu12 (==12.5.82)", "nvidia-cuda-nvrtc-cu12 (==12.5.82)", "nvidia-cuda-runtime-cu12 (==12.5.82)", "nvidia-cudnn-cu12 (==9.3.0.75)", "nvidia-cufft-cu12 (==11.2.3.61)", "nvidia-curand-cu12 (==10.3.6.82)", "nvidia-cusolver-cu12 (==11.6.3.83)", "nvidia-cusparse-cu12 (==12.5.1.3)", "nvidia-nccl-cu12 (==2.21.5)", "nvidia-nvjitlink-cu12 (==12.5.82)"] - -[[package]] -name = "tensorflow-io-gcs-filesystem" -version = "0.37.1" -description = "TensorFlow IO" -optional = false -python-versions = "<3.13,>=3.7" -files = [ - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:249c12b830165841411ba71e08215d0e94277a49c551e6dd5d72aab54fe5491b"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:257aab23470a0796978efc9c2bcf8b0bc80f22e6298612a4c0a50d3f4e88060c"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8febbfcc67c61e542a5ac1a98c7c20a91a5e1afc2e14b1ef0cb7c28bc3b6aa70"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9679b36e3a80921876f31685ab6f7270f3411a4cc51bc2847e80d0e4b5291e27"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:32c50ab4e29a23c1f91cd0f9ab8c381a0ab10f45ef5c5252e94965916041737c"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b02f9c5f94fd62773954a04f69b68c4d576d076fd0db4ca25d5479f0fbfcdbad"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e1f2796b57e799a8ca1b75bf47c2aaa437c968408cc1a402a9862929e104cda"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee7c8ee5fe2fd8cb6392669ef16e71841133041fee8a330eff519ad9b36e4556"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:ffebb6666a7bfc28005f4fbbb111a455b5e7d6cd3b12752b7050863ecb27d5cc"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fe8dcc6d222258a080ac3dfcaaaa347325ce36a7a046277f6b3e19abc1efb3c5"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fbb33f1745f218464a59cecd9a18e32ca927b0f4d77abd8f8671b645cc1a182f"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:286389a203a5aee1a4fa2e53718c661091aa5fea797ff4fa6715ab8436b02e6c"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ee5da49019670ed364f3e5fb86b46420841a6c3cb52a300553c63841671b3e6d"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8943036bbf84e7a2be3705cb56f9c9df7c48c9e614bb941f0936c58e3ca89d6f"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:426de1173cb81fbd62becec2012fc00322a295326d90eb6c737fab636f182aed"}, - {file = "tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df00891669390078a003cedbdd3b8e645c718b111917535fa1d7725e95cdb95"}, -] - -[package.extras] -tensorflow = ["tensorflow (>=2.16.0,<2.17.0)"] -tensorflow-aarch64 = ["tensorflow-aarch64 (>=2.16.0,<2.17.0)"] -tensorflow-cpu = ["tensorflow-cpu (>=2.16.0,<2.17.0)"] -tensorflow-gpu = ["tensorflow-gpu (>=2.16.0,<2.17.0)"] -tensorflow-rocm = ["tensorflow-rocm (>=2.16.0,<2.17.0)"] - -[[package]] -name = "termcolor" -version = "2.5.0" -description = "ANSI color formatting for output in terminal" -optional = false -python-versions = ">=3.9" -files = [ - {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, - {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - [[package]] name = "threadpoolctl" version = "3.5.0" @@ -5621,13 +5157,13 @@ files = [ [[package]] name = "tomli" -version = "2.0.2" +version = "2.1.0" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, - {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, + {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"}, + {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"}, ] [[package]] @@ -5728,13 +5264,13 @@ files = [ [[package]] name = "tqdm" -version = "4.66.6" +version = "4.67.0" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.6-py3-none-any.whl", hash = "sha256:223e8b5359c2efc4b30555531f09e9f2f3589bcd7fdd389271191031b49b7a63"}, - {file = "tqdm-4.66.6.tar.gz", hash = "sha256:4bdd694238bef1485ce839d67967ab50af8f9272aab687c0d7702a01da0be090"}, + {file = "tqdm-4.67.0-py3-none-any.whl", hash = "sha256:0cd8af9d56911acab92182e88d763100d4788bdf421d251616040cc4d44863be"}, + {file = "tqdm-4.67.0.tar.gz", hash = "sha256:fe5a6f95e6fe0b9755e9469b77b9c3cf850048224ecaa8293d7d2d31f97d869a"}, ] [package.dependencies] @@ -5742,6 +5278,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +discord = ["requests"] notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] @@ -5786,13 +5323,13 @@ tutorials = ["matplotlib", "pandas", "tabulate", "torch"] [[package]] name = "types-deprecated" -version = "1.2.9.20240311" +version = "1.2.15.20241117" description = "Typing stubs for Deprecated" optional = false python-versions = ">=3.8" files = [ - {file = "types-Deprecated-1.2.9.20240311.tar.gz", hash = "sha256:0680e89989a8142707de8103f15d182445a533c1047fd9b7e8c5459101e9b90a"}, - {file = "types_Deprecated-1.2.9.20240311-py3-none-any.whl", hash = "sha256:d7793aaf32ff8f7e49a8ac781de4872248e0694c4b75a7a8a186c51167463f9d"}, + {file = "types-Deprecated-1.2.15.20241117.tar.gz", hash = "sha256:924002c8b7fddec51ba4949788a702411a2e3636cd9b2a33abd8ee119701d77e"}, + {file = "types_Deprecated-1.2.15.20241117-py3-none-any.whl", hash = "sha256:a0cc5e39f769fc54089fd8e005416b55d74aa03f6964d2ed1a0b0b2e28751884"}, ] [[package]] @@ -5878,37 +5415,6 @@ files = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] -[[package]] -name = "werkzeug" -version = "3.0.6" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "werkzeug-3.0.6-py3-none-any.whl", hash = "sha256:1bc0c2310d2fbb07b1dd1105eba2f7af72f322e1e455f2f93c993bee8c8a5f17"}, - {file = "werkzeug-3.0.6.tar.gz", hash = "sha256:a8dd59d4de28ca70471a34cba79bed5f7ef2e036a76b3ab0835474246eb41f8d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog (>=2.3)"] - -[[package]] -name = "wheel" -version = "0.44.0" -description = "A built-package format for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"}, - {file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"}, -] - -[package.extras] -test = ["pytest (>=6.0.0)", "setuptools (>=65)"] - [[package]] name = "widgetsnbextension" version = "4.0.13" @@ -6018,13 +5524,13 @@ files = [ [[package]] name = "zipp" -version = "3.20.2" +version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] [package.extras] diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py index 34c5197c0d..4cd1ab9803 100644 --- a/src/qibo/backends/__init__.py +++ b/src/qibo/backends/__init__.py @@ -8,10 +8,9 @@ from qibo.backends.clifford import CliffordBackend from qibo.backends.npmatrices import NumpyMatrices from qibo.backends.numpy import NumpyBackend -from qibo.backends.pytorch import PyTorchBackend from qibo.config import log, raise_error -QIBO_NATIVE_BACKENDS = ("numpy", "pytorch", "qulacs") +QIBO_NATIVE_BACKENDS = ("numpy", "qulacs") class MissingBackend(ValueError): @@ -40,9 +39,6 @@ def load(backend: str, **kwargs) -> Backend: + f"The native qibo backends are {QIBO_NATIVE_BACKENDS + ('clifford',)}", ) - if backend == "pytorch": - return PyTorchBackend() - if backend == "clifford": engine = kwargs.pop("platform", None) kwargs["engine"] = engine @@ -80,7 +76,7 @@ class _Global: {"backend": "qibojit", "platform": "numba"}, {"backend": "numpy"}, {"backend": "qiboml", "platform": "tensorflow"}, - {"backend": "pytorch"}, + {"backend": "qiboml", "platform": "pytorch"}, ] @classmethod @@ -136,7 +132,6 @@ def set_transpiler(cls, transpiler): def _default_transpiler(cls): from qibo.transpiler.optimizer import Preprocessing from qibo.transpiler.pipeline import Passes - from qibo.transpiler.placer import Trivial from qibo.transpiler.router import Sabre from qibo.transpiler.unroller import NativeGates, Unroller @@ -148,21 +143,12 @@ def _default_transpiler(cls): and natives is not None and connectivity_edges is not None ): - # only for q{i} naming - node_mapping = {q: i for i, q in enumerate(qubits)} - edges = [ - (node_mapping[e[0]], node_mapping[e[1]]) for e in connectivity_edges - ] - connectivity = nx.Graph() - connectivity.add_nodes_from(list(node_mapping.values())) - connectivity.add_edges_from(edges) - + connectivity = nx.Graph(connectivity_edges) return Passes( connectivity=connectivity, passes=[ - Preprocessing(connectivity), - Trivial(connectivity), - Sabre(connectivity), + Preprocessing(), + Sabre(), Unroller(NativeGates[natives]), ], ) diff --git a/src/qibo/backends/pytorch.py b/src/qibo/backends/pytorch.py deleted file mode 100644 index 48404248d2..0000000000 --- a/src/qibo/backends/pytorch.py +++ /dev/null @@ -1,281 +0,0 @@ -"""PyTorch backend.""" - -from typing import Union - -import numpy as np - -from qibo import __version__ -from qibo.backends.npmatrices import NumpyMatrices -from qibo.backends.numpy import NumpyBackend - - -class TorchMatrices(NumpyMatrices): - """Matrix representation of every gate as a torch Tensor. - - Args: - dtype (torch.dtype): Data type of the matrices. - """ - - def __init__(self, dtype): - import torch # pylint: disable=import-outside-toplevel # type: ignore - - super().__init__(dtype) - self.np = torch - self.dtype = dtype - - def _cast(self, x, dtype): - flattened = [item for sublist in x for item in sublist] - tensor_list = [self.np.as_tensor(i, dtype=dtype) for i in flattened] - return self.np.stack(tensor_list).reshape(len(x), len(x)) - - def Unitary(self, u): - return self._cast(u, dtype=self.dtype) - - -class PyTorchBackend(NumpyBackend): - def __init__(self): - super().__init__() - import torch # pylint: disable=import-outside-toplevel # type: ignore - - self.np = torch - - self.name = "pytorch" - self.versions = { - "qibo": __version__, - "numpy": np.__version__, - "torch": self.np.__version__, - } - - # Default data type used for the gate matrices is complex128 - self.dtype = self._torch_dtype(self.dtype) - # Default data type used for the real gate parameters is float64 - self.parameter_dtype = self._torch_dtype("float64") - self.matrices = TorchMatrices(self.dtype) - self.device = self.np.device("cuda:0" if torch.cuda.is_available() else "cpu") - self.nthreads = 0 - self.tensor_types = (self.np.Tensor, np.ndarray) - - # These functions in Torch works in a different way than numpy or have different names - self.np.transpose = self.np.permute - self.np.copy = self.np.clone - self.np.power = self.np.pow - self.np.expand_dims = self.np.unsqueeze - self.np.mod = self.np.remainder - self.np.right_shift = self.np.bitwise_right_shift - self.np.sign = self.np.sgn - self.np.flatnonzero = lambda x: self.np.nonzero(x).flatten() - - def _torch_dtype(self, dtype): - if dtype == "float": - dtype += "32" - return getattr(self.np, dtype) - - def set_device(self, device): # pragma: no cover - self.device = device - - def cast( - self, - x, - dtype=None, - copy: bool = False, - ): - """Casts input as a Torch tensor of the specified dtype. - - This method supports casting of single tensors or lists of tensors - as for the :class:`qibo.backends.PyTorchBackend`. - - Args: - x (Union[torch.Tensor, list[torch.Tensor], np.ndarray, list[np.ndarray], int, float, complex]): - Input to be casted. - dtype (Union[str, torch.dtype, np.dtype, type]): Target data type. - If ``None``, the default dtype of the backend is used. - Defaults to ``None``. - copy (bool, optional): If ``True``, the input tensor is copied before casting. - Defaults to ``False``. - """ - - if dtype is None: - dtype = self.dtype - elif isinstance(dtype, type): - dtype = self._torch_dtype(dtype.__name__) - elif not isinstance(dtype, self.np.dtype): - dtype = self._torch_dtype(str(dtype)) - - if isinstance(x, self.np.Tensor): - x = x.to(dtype) - elif ( - isinstance(x, list) - and len(x) > 0 - and all(isinstance(row, self.np.Tensor) for row in x) - ): - x = self.np.stack(x) - else: - x = self.np.tensor(x, dtype=dtype) - - if copy: - return x.clone() - return x - - def matrix_parametrized(self, gate): - """Convert a parametrized gate to its matrix representation in the computational basis.""" - name = gate.__class__.__name__ - _matrix = getattr(self.matrices, name) - if name == "GeneralizedRBS": - for parameter in ["theta", "phi"]: - if not isinstance(gate.init_kwargs[parameter], self.np.Tensor): - gate.init_kwargs[parameter] = self._cast_parameter( - gate.init_kwargs[parameter], trainable=gate.trainable - ) - - _matrix = _matrix( - qubits_in=gate.init_args[0], - qubits_out=gate.init_args[1], - theta=gate.init_kwargs["theta"], - phi=gate.init_kwargs["phi"], - ) - return _matrix - else: - new_parameters = [] - for parameter in gate.parameters: - if not isinstance(parameter, self.np.Tensor): - parameter = self._cast_parameter( - parameter, trainable=gate.trainable - ) - elif parameter.requires_grad: - gate.trainable = True - new_parameters.append(parameter) - gate.parameters = tuple(new_parameters) - _matrix = _matrix(*gate.parameters) - return _matrix - - def _cast_parameter(self, x, trainable): - """Cast a gate parameter to a torch tensor. - - Args: - x (Union[int, float, complex]): Parameter to be casted. - trainable (bool): If ``True``, the tensor requires gradient. - """ - if isinstance(x, int) and trainable: - return self.np.tensor(x, dtype=self.parameter_dtype, requires_grad=True) - if isinstance(x, float): - return self.np.tensor( - x, dtype=self.parameter_dtype, requires_grad=trainable - ) - return self.np.tensor(x, dtype=self.dtype, requires_grad=trainable) - - def is_sparse(self, x): - if isinstance(x, self.np.Tensor): - return x.is_sparse - - return super().is_sparse(x) - - def to_numpy(self, x): - if isinstance(x, list): - return np.asarray([self.to_numpy(i) for i in x]) - - if isinstance(x, self.np.Tensor): - return x.numpy(force=True) - - return x - - def _order_probabilities(self, probs, qubits, nqubits): - """Arrange probabilities according to the given ``qubits`` ordering.""" - if probs.dim() == 0: # pragma: no cover - return probs - unmeasured, reduced = [], {} - for i in range(nqubits): - if i in qubits: - reduced[i] = i - len(unmeasured) - else: - unmeasured.append(i) - return self.np.transpose(probs, [reduced.get(i) for i in qubits]) - - def calculate_probabilities(self, state, qubits, nqubits): - rtype = self.np.real(state).dtype - unmeasured_qubits = tuple(i for i in range(nqubits) if i not in qubits) - state = self.np.reshape(self.np.abs(state) ** 2, nqubits * (2,)) - if len(unmeasured_qubits) == 0: - probs = self.cast(state, dtype=rtype) - else: - probs = self.np.sum(self.cast(state, dtype=rtype), axis=unmeasured_qubits) - return self._order_probabilities(probs, qubits, nqubits).ravel() - - def set_seed(self, seed): - self.np.manual_seed(seed) - np.random.seed(seed) - - def sample_shots(self, probabilities, nshots): - return self.np.multinomial( - self.cast(probabilities, dtype="float"), nshots, replacement=True - ) - - def calculate_eigenvalues(self, matrix, k: int = 6, hermitian: bool = True): - if hermitian: - return self.np.linalg.eigvalsh(matrix) # pylint: disable=not-callable - return self.np.linalg.eigvals(matrix) # pylint: disable=not-callable - - def calculate_eigenvectors(self, matrix, k: int = 6, hermitian: int = True): - if hermitian: - return self.np.linalg.eigh(matrix) # pylint: disable=not-callable - return self.np.linalg.eig(matrix) # pylint: disable=not-callable - - def calculate_matrix_exp(self, a, matrix, eigenvectors=None, eigenvalues=None): - if eigenvectors is None or self.is_sparse(matrix): - return self.np.linalg.matrix_exp( # pylint: disable=not-callable - -1j * a * matrix - ) - expd = self.np.diag(self.np.exp(-1j * a * eigenvalues)) - ud = self.np.conj(eigenvectors).T - return self.np.matmul(eigenvectors, self.np.matmul(expd, ud)) - - def calculate_matrix_power( - self, - matrix, - power: Union[float, int], - precision_singularity: float = 1e-14, - ): - copied = self.cast(matrix, copy=True) - copied = self.to_numpy(copied) if power >= 0.0 else copied.detach() - copied = super().calculate_matrix_power(copied, power, precision_singularity) - return self.cast(copied, dtype=copied.dtype) - - def calculate_jacobian_matrix( - self, circuit, parameters=None, initial_state=None, return_complex: bool = True - ): - copied = circuit.copy(deep=True) - - def func(parameters): - """torch requires object(s) to be wrapped in a function.""" - copied.set_parameters(parameters) - state = self.execute_circuit(copied, initial_state=initial_state).state() - if return_complex: - return self.np.real(state), self.np.imag(state) - return self.np.real(state) - - return self.np.autograd.functional.jacobian(func, parameters) - - def _test_regressions(self, name): - if name == "test_measurementresult_apply_bitflips": - return [ - [0, 0, 0, 0, 2, 3, 0, 0, 0, 0], - [0, 0, 0, 0, 2, 3, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], - [0, 0, 0, 0, 2, 0, 0, 0, 0, 0], - ] - - if name == "test_probabilistic_measurement": - if self.device == "cuda": # pragma: no cover - return {0: 273, 1: 233, 2: 242, 3: 252} - return {1: 270, 2: 248, 3: 244, 0: 238} - - if name == "test_unbalanced_probabilistic_measurement": - if self.device == "cuda": # pragma: no cover - return {0: 196, 1: 153, 2: 156, 3: 495} - return {3: 492, 2: 176, 0: 168, 1: 164} - - if name == "test_post_measurement_bitflips_on_circuit": - return [ - {5: 30}, - {5: 17, 4: 5, 7: 4, 1: 2, 6: 2}, - {4: 9, 2: 5, 5: 5, 3: 4, 6: 4, 0: 1, 1: 1, 7: 1}, - ] diff --git a/src/qibo/gates/abstract.py b/src/qibo/gates/abstract.py index 7b24407048..2128f9dc16 100644 --- a/src/qibo/gates/abstract.py +++ b/src/qibo/gates/abstract.py @@ -273,10 +273,10 @@ def on_qubits(self, qubit_map) -> "Gate": circuit.draw() .. testoutput:: - q0: ───X───── - q1: ───|─o─X─ - q2: ─o─|─|─o─ - q3: ─X─o─X─── + 0: ───X───── + 1: ───|─o─X─ + 2: ─o─|─|─o─ + 3: ─X─o─X─── """ if self.is_controlled_by: targets = (qubit_map.get(q) for q in self.target_qubits) diff --git a/src/qibo/gates/measurements.py b/src/qibo/gates/measurements.py index 0e2ccec754..b9c075ce9e 100644 --- a/src/qibo/gates/measurements.py +++ b/src/qibo/gates/measurements.py @@ -252,9 +252,9 @@ def on_qubits(self, qubit_map) -> "Gate": circuit.draw() .. testoutput:: - q0: ─M─ - q1: ─|─ - q2: ─M─ + 0: ─M─ + 1: ─|─ + 2: ─M─ """ qubits = (qubit_map.get(q) for q in self.qubits) diff --git a/src/qibo/hamiltonians/hamiltonians.py b/src/qibo/hamiltonians/hamiltonians.py index 3209b56722..57dd02e42a 100644 --- a/src/qibo/hamiltonians/hamiltonians.py +++ b/src/qibo/hamiltonians/hamiltonians.py @@ -7,7 +7,6 @@ import numpy as np import sympy -from qibo.backends import PyTorchBackend, _check_backend from qibo.config import EINSUM_CHARS, log, raise_error from qibo.hamiltonians.abstract import AbstractHamiltonian from qibo.symbols import Z @@ -266,7 +265,7 @@ def __mul__(self, o): if self.backend.real(o) >= 0: # TODO: check for side effects K.qnp r._eigenvalues = o * self._eigenvalues elif not self.backend.is_sparse(self.matrix): - axis = (0,) if isinstance(self.backend, PyTorchBackend) else 0 + axis = (0,) if (self.backend.platform == "pytorch") else 0 r._eigenvalues = o * self.backend.flip(self._eigenvalues, axis) if self._eigenvectors is not None: if self.backend.real(o) > 0: # TODO: see above diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py index 4e65259719..31f8570d88 100644 --- a/src/qibo/models/circuit.py +++ b/src/qibo/models/circuit.py @@ -119,8 +119,23 @@ class Circuit: This circuit is symbolic and cannot perform calculations. A specific backend has to be used for performing calculations. + Circuits can be created with a specific number of qubits and wire names. + Example: + .. testcode:: + from qibo import Circuit + c = Circuit(5) # Default wire names are [0, 1, 2, 3, 4] + c = Circuit(["A", "B", "C", "D", "E"]) + c = Circuit(5, wire_names=["A", "B", "C", "D", "E"]) + c = Circuit(wire_names=["A", "B", "C", "D", "E"]) + Args: - nqubits (int): Total number of qubits in the circuit. + nqubits (int | list, optional): Number of qubits in the circuit or a list of wire names. + wire_names (list, optional): List of wire names. + - Either ``nqubits`` or ``wire_names`` must be provided. + - If only ``nqubits`` is provided, wire names will default to [``0``, ``1``, ..., ``nqubits - 1``]. + - If only ``wire_names`` is provided, ``nqubits`` will be set to the length of ``wire_names``. + - ``nqubits`` and ``wire_names`` must be consistent with each other. + init_kwargs (dict): a dictionary with the following keys - *nqubits* @@ -141,11 +156,6 @@ class Circuit: Defaults to ``False``. accelerators (dict, optional): Dictionary that maps device names to the number of times each device will be used. Defaults to ``None``. - wire_names (list or dict, optional): Names for qubit wires. - If ``None``, defaults to (``q0``, ``q1``... ``qn``). - If ``list`` is passed, length of ``list`` must match ``nqubits``. - If ``dict`` is passed, the keys should match the default pattern. - Defaults to ``None``. ndevices (int): Total number of devices. Defaults to ``None``. nglobal (int): Base two logarithm of the number of devices. Defaults to ``None``. nlocal (int): Total number of available qubits in each device. Defaults to ``None``. @@ -155,29 +165,20 @@ class Circuit: def __init__( self, - nqubits: int, + nqubits: Optional[Union[int, list]] = None, accelerators=None, density_matrix: bool = False, - wire_names: Optional[Union[list, dict]] = None, + wire_names: Optional[list] = None, ): - if not isinstance(nqubits, int): - raise_error( - TypeError, - f"Number of qubits must be an integer but is {nqubits}.", - ) - if nqubits < 1: - raise_error( - ValueError, - f"Number of qubits must be positive but is {nqubits}.", - ) + nqubits, wire_names = _resolve_qubits(nqubits, wire_names) self.nqubits = nqubits - self.wire_names = wire_names self.init_kwargs = { "nqubits": nqubits, "accelerators": accelerators, "density_matrix": density_matrix, "wire_names": wire_names, } + self.wire_names = wire_names self.queue = _Queue(nqubits) # Keep track of parametrized gates for the ``set_parameters`` method self.parametrized_gates = _ParametrizedGates() @@ -282,49 +283,29 @@ def __add__(self, circuit): @property def wire_names(self): + if self._wire_names is None: + return list(range(self.nqubits)) return self._wire_names @wire_names.setter - def wire_names(self, wire_names: Union[list, dict]): - if not isinstance(wire_names, (list, dict, type(None))): + def wire_names(self, wire_names: Optional[list]): + if not isinstance(wire_names, (list, type(None))): raise_error( TypeError, - f"``wire_names`` must be type ``list`` or ``dict``, but is {type(wire_names)}.", + f"``wire_names`` must be type ``list``, but is {type(wire_names)}.", ) - if isinstance(wire_names, list): + if wire_names is not None: if len(wire_names) != self.nqubits: raise_error( ValueError, "Number of wire names must be equal to the number of qubits, " f"but is {len(wire_names)}.", ) - - if any([not isinstance(name, str) for name in wire_names]): - raise_error(ValueError, "all wire names must be type ``str``.") - - self._wire_names = wire_names - elif isinstance(wire_names, dict): - if len(wire_names.keys()) > self.nqubits: - raise_error( - ValueError, - "number of elements in the ``wire_names`` dictionary " - + "cannot be bigger than ``nqubits``.", - ) - - if any([not isinstance(name, str) for name in wire_names.keys()]) or any( - [not isinstance(name, str) for name in wire_names.values()] - ): - raise_error( - ValueError, - "all keys and values in the ``wire_names`` dictionary must be type ``str``.", - ) - - self._wire_names = [ - wire_names.get(f"q{i}", f"q{i}") for i in range(self.nqubits) - ] + self._wire_names = wire_names.copy() else: - self._wire_names = [f"q{i}" for i in range(self.nqubits)] + self._wire_names = None + self.init_kwargs["wire_names"] = self._wire_names @property def repeated_execution(self): @@ -407,8 +388,8 @@ def light_cone(self, *qubits): qubit_map = {q: i for i, q in enumerate(sorted(qubits))} kwargs = dict(self.init_kwargs) kwargs["nqubits"] = len(qubits) + kwargs["wire_names"] = [self.wire_names[q] for q in sorted(qubits)] circuit = self.__class__(**kwargs) - circuit.wire_names = [self.wire_names[q] for q in list(sorted(qubits))] circuit.add(gate.on_qubits(qubit_map) for gate in reversed(list_of_gates)) return circuit, qubit_map @@ -1282,6 +1263,7 @@ def diagram(self, line_wrap: int = 70, legend: bool = False) -> str: """Build the string representation of the circuit diagram.""" # build string representation of gates matrix = [[] for _ in range(self.nqubits)] + wire_names = [str(name) for name in self.wire_names] idx = [0] * self.nqubits for gate in self.queue: @@ -1303,12 +1285,12 @@ def diagram(self, line_wrap: int = 70, legend: bool = False) -> str: matrix[row][col] += "─" * (1 + maxlen - len(matrix[row][col])) # Print to terminal - max_name_len = max(len(name) for name in self.wire_names) + max_name_len = max(len(name) for name in wire_names) output = "" for q in range(self.nqubits): output += ( - self.wire_names[q] - + " " * (max_name_len - len(self.wire_names[q])) + wire_names[q] + + " " * (max_name_len - len(wire_names[q])) + ": ─" + "".join(matrix[q]) + "\n" @@ -1350,8 +1332,8 @@ def chunkstring(string, length): loutput += ["" for _ in range(self.nqubits)] suffix = " ...\n" prefix = ( - self.wire_names[row] - + " " * (max_name_len - len(self.wire_names[row])) + wire_names[row] + + " " * (max_name_len - len(wire_names[row])) + ": " ) if i == 0: @@ -1388,3 +1370,32 @@ def draw(self, line_wrap: int = 70, legend: bool = False): String containing text circuit diagram. """ sys.stdout.write(self.diagram(line_wrap, legend) + "\n") + + +def _resolve_qubits(qubits, wire_names): + """Parse the input arguments for defining a circuit. Allows the user to initialize the circuit as follows: + + Example: + .. code-block:: python + from qibo import Circuit + c = Circuit(3) + c = Circuit(3, wire_names=["q0", "q1", "q2"]) + c = Circuit(["q0", "q1", "q2"]) + c = Circuit(wire_names=["q0", "q1", "q2"]) + """ + if qubits is None and wire_names is not None: + return len(wire_names), wire_names + if qubits is not None and wire_names is None: + if isinstance(qubits, int) and qubits > 0: + return qubits, None + if isinstance(qubits, list): + return len(qubits), qubits + if qubits is not None and wire_names is not None: + if isinstance(qubits, int) and isinstance(wire_names, list): + if qubits == len(wire_names): + return qubits, wire_names + + raise_error( + ValueError, + "Invalid input arguments for defining a circuit.", + ) diff --git a/src/qibo/models/error_mitigation.py b/src/qibo/models/error_mitigation.py index 07e65dd315..4ec0982ab5 100644 --- a/src/qibo/models/error_mitigation.py +++ b/src/qibo/models/error_mitigation.py @@ -328,7 +328,7 @@ def _curve_fit( Returns: ndarray: the optimal parameters. """ - if backend.name == "pytorch": + if backend.platform == "pytorch": # pytorch has some problems with the `scipy.optim.curve_fit` function # thus we use a `torch.optim` optimizer params.requires_grad = True @@ -1172,21 +1172,11 @@ def _execute_circuit(circuit, qubit_map, noise_model=None, nshots=10000, backend qibo.states.CircuitResult: The result of the circuit execution. """ from qibo.transpiler.pipeline import Passes - from qibo.transpiler.placer import Custom if backend is None: # pragma: no cover backend = get_backend() elif backend.name == "qibolab": # pragma: no cover - qubits = backend.qubits - connectivity_edges = backend.connectivity - node_mapping = {q: i for i, q in enumerate(qubits)} - edges = [(node_mapping[e[0]], node_mapping[e[1]]) for e in connectivity_edges] - connectivity = nx.Graph(edges) - transpiler = Passes( - connectivity=connectivity, - passes=[Custom(initial_map=qubit_map, connectivity=connectivity)], - ) - circuit, _ = transpiler(circuit) + circuit.wire_names = qubit_map elif noise_model is not None: circuit = noise_model.apply(circuit) diff --git a/src/qibo/optimizers.py b/src/qibo/optimizers.py index 0914800f34..65e107e9a9 100644 --- a/src/qibo/optimizers.py +++ b/src/qibo/optimizers.py @@ -282,7 +282,7 @@ def sgd( callback=callback, ) - if backend.name == "pytorch": + if backend.platform == "pytorch": if compile: log.warning( "PyTorch does not support compilation of the optimization graph." diff --git a/src/qibo/quantum_info/basis.py b/src/qibo/quantum_info/basis.py index de1a8ecbc4..f9475f7f18 100644 --- a/src/qibo/quantum_info/basis.py +++ b/src/qibo/quantum_info/basis.py @@ -105,12 +105,15 @@ def pauli_basis( basis_full = basis_single if vectorize and sparse: - if backend.name == "pytorch": - nonzero = lambda x: backend.nonzero(x, as_tuple=True) - else: - nonzero = backend.nonzero + + # if backend.platform == "pytorch": + # nonzero = lambda x: backend.nonzero(x, as_tuple=True) + # else: + # nonzero = backend.nonzero basis = vectorization(basis_full, order=order, backend=backend) - indices = nonzero(backend.abs(basis)) # abs needed because of ``tensorflow`` + indices = backend.nonzero( + backend.abs(basis) + ) # abs needed because of ``tensorflow`` basis = basis[indices].reshape(-1, dim) indices = indices[1].reshape(-1, dim) diff --git a/src/qibo/tomography/gate_set_tomography.py b/src/qibo/tomography/gate_set_tomography.py index d3b4286f32..5a8331f527 100644 --- a/src/qibo/tomography/gate_set_tomography.py +++ b/src/qibo/tomography/gate_set_tomography.py @@ -1,14 +1,13 @@ from functools import cache from inspect import signature from itertools import product -from random import Random from typing import List, Union import numpy as np from sympy import S from qibo import Circuit, gates, symbols -from qibo.backends import _check_backend +from qibo.backends import _check_backend, get_transpiler from qibo.config import raise_error from qibo.hamiltonians import SymbolicHamiltonian from qibo.transpiler.optimizer import Preprocessing @@ -261,15 +260,7 @@ def GST( backend = _check_backend(backend) if backend.name == "qibolab" and transpiler is None: # pragma: no cover - transpiler = Passes( - connectivity=backend.platform.topology, - passes=[ - Preprocessing(backend.platform.topology), - Random(backend.platform.topology), - Sabre(backend.platform.topology), - Unroller(NativeGates.default()), - ], - ) + transpiler = get_transpiler() matrices = [] empty_matrices = [] diff --git a/src/qibo/transpiler/__init__.py b/src/qibo/transpiler/__init__.py index bfe576776c..40675f0be1 100644 --- a/src/qibo/transpiler/__init__.py +++ b/src/qibo/transpiler/__init__.py @@ -1,12 +1,10 @@ from qibo.transpiler.optimizer import Preprocessing, Rearrange from qibo.transpiler.pipeline import Passes from qibo.transpiler.placer import ( - Custom, Random, ReverseTraversal, StarConnectivityPlacer, Subgraph, - Trivial, ) from qibo.transpiler.router import Sabre, ShortestPaths, StarConnectivityRouter from qibo.transpiler.unroller import NativeGates diff --git a/src/qibo/transpiler/abstract.py b/src/qibo/transpiler/abstract.py index c838262231..11e1641759 100644 --- a/src/qibo/transpiler/abstract.py +++ b/src/qibo/transpiler/abstract.py @@ -12,14 +12,11 @@ def __init__(self, connectivity: nx.Graph, *args): """A placer implements the initial logical-physical qubit mapping""" @abstractmethod - def __call__(self, circuit: Circuit, *args) -> dict: - """Find initial qubit mapping + def __call__(self, circuit: Circuit, *args): + """Find initial qubit mapping. Mapping is saved in the circuit. Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be mapped. - - Returns: - (dict): dictionary containing the initial logical to physical qubit mapping. """ @@ -29,17 +26,14 @@ def __init__(self, connectivity: nx.Graph, *args): """A router implements the mapping of a circuit on a specific hardware.""" @abstractmethod - def __call__( - self, circuit: Circuit, initial_layout: dict, *args - ) -> Tuple[Circuit, dict]: + def __call__(self, circuit: Circuit, *args) -> Tuple[Circuit, dict]: """Match circuit to hardware connectivity. Args: - circuit (:class:`qibo.models.Circuit`): circuit to be routed. - initial_layout (dict): dictionary containing the initial logical to physical qubit mapping. + circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed. Returns: - (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and dictionary containing the final logical to physical qubit mapping. + (:class:`qibo.models.circuit.Circuit`): routed circuit. """ diff --git a/src/qibo/transpiler/asserts.py b/src/qibo/transpiler/asserts.py new file mode 100644 index 0000000000..d988ce6add --- /dev/null +++ b/src/qibo/transpiler/asserts.py @@ -0,0 +1,200 @@ +from typing import Optional + +import networkx as nx +import numpy as np + +from qibo import gates +from qibo.backends.numpy import NumpyBackend +from qibo.config import raise_error +from qibo.models.circuit import Circuit +from qibo.quantum_info.random_ensembles import random_statevector +from qibo.transpiler._exceptions import ( + ConnectivityError, + DecompositionError, + PlacementError, + TranspilerPipelineError, +) +from qibo.transpiler.optimizer import Preprocessing +from qibo.transpiler.unroller import NativeGates + + +def assert_transpiling( + original_circuit: Circuit, + transpiled_circuit: Circuit, + connectivity: nx.Graph, + final_layout: dict, + native_gates: NativeGates = NativeGates.default(), + check_circuit_equivalence=True, +): + """Check that all transpiler passes have been executed correctly. + + Args: + original_circuit (qibo.models.Circuit): circuit before transpiling. + transpiled_circuit (qibo.models.Circuit): circuit after transpiling. + connectivity (networkx.Graph): chip qubits connectivity. + final_layout (dict): final physical-logical qubit mapping. + native_gates (NativeGates): native gates supported by the hardware. + check_circuit_equivalence (Bool): use simulations to check if the transpiled circuit is the same as the original. + """ + assert_connectivity(circuit=transpiled_circuit, connectivity=connectivity) + assert_decomposition( + circuit=transpiled_circuit, + native_gates=native_gates, + ) + if original_circuit.nqubits != transpiled_circuit.nqubits: + qubit_matcher = Preprocessing(connectivity=connectivity) + original_circuit = qubit_matcher(circuit=original_circuit) + assert_placement(circuit=original_circuit, connectivity=connectivity) + assert_placement(circuit=transpiled_circuit, connectivity=connectivity) + if check_circuit_equivalence: + assert_circuit_equivalence( + original_circuit=original_circuit, + transpiled_circuit=transpiled_circuit, + final_map=final_layout, + ) + + +def assert_circuit_equivalence( + original_circuit: Circuit, + transpiled_circuit: Circuit, + final_map: dict, + test_states: Optional[list] = None, + ntests: int = 3, +): + """Checks that the transpiled circuit agrees with the original using simulation. + + Args: + original_circuit (:class:`qibo.models.circuit.Circuit`): Original circuit. + transpiled_circuit (:class:`qibo.models.circuit.Circuit`): Transpiled circuit. + final_map (dict): logical-physical qubit mapping after routing. + test_states (list, optional): states on which the test is performed. + If ``None``, ``ntests`` random states will be tested. Defauts to ``None``. + ntests (int, optional): number of random states tested. Defauts to :math:`3`. + """ + backend = NumpyBackend() + if transpiled_circuit.nqubits != original_circuit.nqubits: + raise_error( + ValueError, + "Transpiled and original circuit do not have the same number of qubits.", + ) + + if test_states is None: + test_states = [ + random_statevector(dims=2**original_circuit.nqubits, backend=backend) + for _ in range(ntests) + ] + + ordering = list(final_map.values()) + + for i, state in enumerate(test_states): + target_state = backend.execute_circuit( + original_circuit, initial_state=state + ).state() + final_state = backend.execute_circuit( + transpiled_circuit, + initial_state=state, + ).state() + final_state = _transpose_qubits(final_state, ordering) + fidelity = np.abs(np.dot(np.conj(target_state), final_state)) + try: + np.testing.assert_allclose(fidelity, 1.0) + except AssertionError: + raise_error(TranspilerPipelineError, "Circuit equivalence not satisfied.") + + +def _transpose_qubits(state: np.ndarray, qubits_ordering: np.ndarray): + """Reorders qubits of a given state vector. + + Args: + state (np.ndarray): final state of the circuit. + qubits_ordering (np.ndarray): final qubit ordering. + """ + original_shape = state.shape + state = np.reshape(state, len(qubits_ordering) * (2,)) + state = np.transpose(state, qubits_ordering) + return np.reshape(state, original_shape) + + +def assert_placement(circuit: Circuit, connectivity: nx.Graph): + """Check if the layout of the circuit is consistent with the circuit and connectivity graph. + + Args: + circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check. + connectivity (:class:`networkx.Graph`, optional): Chip connectivity. + """ + if connectivity is None: + raise_error( + ValueError, + "Connectivity graph is missing.", + ) + + if circuit.nqubits != len(circuit.wire_names) or circuit.nqubits != len( + connectivity.nodes + ): + raise_error( + PlacementError, + f"Number of qubits in the circuit ({circuit.nqubits}) " + + f"does not match the number of qubits in the layout ({len(circuit.wire_names)}) " + + f"or the connectivity graph ({len(connectivity.nodes)}).", + ) + if set(circuit.wire_names) != set(connectivity.nodes): + raise_error( + PlacementError, + "Some physical qubits in the layout may be missing or duplicated.", + ) + + +def assert_connectivity(connectivity: nx.Graph, circuit: Circuit): + """Assert if a circuit can be executed on Hardware. + + No gates acting on more than two qubits. + All two-qubit operations can be performed on hardware. + + Args: + circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check. + connectivity (:class:`networkx.Graph`): chip connectivity. + """ + layout = circuit.wire_names + for gate in circuit.queue: + if len(gate.qubits) > 2 and not isinstance(gate, gates.M): + raise_error(ConnectivityError, f"{gate.name} acts on more than two qubits.") + if len(gate.qubits) == 2: + physical_qubits = (layout[gate.qubits[0]], layout[gate.qubits[1]]) + if physical_qubits not in connectivity.edges: + raise_error( + ConnectivityError, + f"The circuit does not respect the connectivity. {gate.name} acts on {physical_qubits} but only the following qubits are directly connected: {connectivity.edges}.", + ) + + +def assert_decomposition( + circuit: Circuit, + native_gates: NativeGates, +): + """Checks if a circuit has been correctly decomposed into native gates. + + Args: + circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check. + native_gates (:class:`qibo.transpiler.unroller.NativeGates`): + native gates in the transpiled circuit. + """ + for gate in circuit.queue: + if isinstance(gate, gates.M): + continue + if len(gate.qubits) <= 2: + try: + native_type_gate = NativeGates.from_gate(gate) + if not native_type_gate & native_gates: + raise_error( + DecompositionError, + f"{gate.name} is not a native gate.", + ) + except ValueError: + raise_error( + DecompositionError, + f"{gate.name} is not a native gate.", + ) + else: + raise_error( + DecompositionError, f"{gate.name} acts on more than two qubits." + ) diff --git a/src/qibo/transpiler/optimizer.py b/src/qibo/transpiler/optimizer.py index 7008957627..741078e5e9 100644 --- a/src/qibo/transpiler/optimizer.py +++ b/src/qibo/transpiler/optimizer.py @@ -1,3 +1,5 @@ +from typing import Optional + import networkx as nx from qibo import gates @@ -13,10 +15,16 @@ class Preprocessing(Optimizer): connectivity (:class:`networkx.Graph`): hardware chip connectivity. """ - def __init__(self, connectivity: nx.Graph): + def __init__(self, connectivity: Optional[nx.Graph] = None): self.connectivity = connectivity def __call__(self, circuit: Circuit) -> Circuit: + if not all(qubit in self.connectivity.nodes for qubit in circuit.wire_names): + raise_error( + ValueError, + "The circuit qubits are not in the connectivity graph.", + ) + physical_qubits = self.connectivity.number_of_nodes() logical_qubits = circuit.nqubits if logical_qubits > physical_qubits: @@ -27,7 +35,10 @@ def __call__(self, circuit: Circuit) -> Circuit: ) if logical_qubits == physical_qubits: return circuit - new_circuit = Circuit(physical_qubits) + new_wire_names = circuit.wire_names + list( + self.connectivity.nodes - circuit.wire_names + ) + new_circuit = Circuit(nqubits=physical_qubits, wire_names=new_wire_names) for gate in circuit.queue: new_circuit.add(gate) return new_circuit @@ -48,7 +59,7 @@ def __init__(self, max_qubits: int = 1): def __call__(self, circuit: Circuit): fused_circuit = circuit.fuse(max_qubits=self.max_qubits) - new = circuit.__class__(circuit.nqubits) + new = circuit.__class__(nqubits=circuit.nqubits, wire_names=circuit.wire_names) for fgate in fused_circuit.queue: if isinstance(fgate, gates.FusedGate): new.add(gates.Unitary(fgate.matrix(), *fgate.qubits)) diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py index c033850557..c1aae06775 100644 --- a/src/qibo/transpiler/pipeline.py +++ b/src/qibo/transpiler/pipeline.py @@ -1,147 +1,22 @@ -from typing import Optional - import networkx as nx -import numpy as np -from qibo.backends import NumpyBackend from qibo.config import raise_error from qibo.models import Circuit -from qibo.quantum_info.random_ensembles import random_statevector -from qibo.transpiler._exceptions import TranspilerPipelineError -from qibo.transpiler.abstract import Optimizer, Placer, Router -from qibo.transpiler.optimizer import Preprocessing -from qibo.transpiler.placer import StarConnectivityPlacer, Trivial, assert_placement -from qibo.transpiler.router import ( +from qibo.transpiler._exceptions import ( ConnectivityError, - StarConnectivityRouter, - assert_connectivity, + PlacementError, + TranspilerPipelineError, ) -from qibo.transpiler.unroller import ( - DecompositionError, - NativeGates, - Unroller, +from qibo.transpiler.abstract import Optimizer, Placer, Router +from qibo.transpiler.asserts import ( + assert_connectivity, assert_decomposition, + assert_placement, ) +from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller -def assert_circuit_equivalence( - original_circuit: Circuit, - transpiled_circuit: Circuit, - final_map: dict, - initial_map: Optional[dict] = None, - test_states: Optional[list] = None, - ntests: int = 3, -): - """Checks that the transpiled circuit agrees with the original using simulation. - - Args: - original_circuit (:class:`qibo.models.circuit.Circuit`): Original circuit. - transpiled_circuit (:class:`qibo.models.circuit.Circuit`): Transpiled circuit. - final_map (dict): logical-physical qubit mapping after routing. - initial_map (dict, optional): logical_physical qubit mapping before routing. - If ``None``, trivial initial map is used. Defauts to ``None``. - test_states (list, optional): states on which the test is performed. - If ``None``, ``ntests`` random states will be tested. Defauts to ``None``. - ntests (int, optional): number of random states tested. Defauts to :math:`3`. - """ - backend = NumpyBackend() - ordering = np.argsort(np.array(list(final_map.values()))) - if transpiled_circuit.nqubits != original_circuit.nqubits: - raise_error( - ValueError, - "Transpiled and original circuit do not have the same number of qubits.", - ) - - if test_states is None: - test_states = [ - random_statevector(dims=2**original_circuit.nqubits, backend=backend) - for _ in range(ntests) - ] - if initial_map is not None: - reordered_test_states = [] - initial_map = np.array(list(initial_map.values())) - reordered_test_states = [ - _transpose_qubits(initial_state, initial_map) - for initial_state in test_states - ] - else: - reordered_test_states = test_states - - for i in range(len(test_states)): - target_state = backend.execute_circuit( - original_circuit, initial_state=test_states[i] - ).state() - final_state = backend.execute_circuit( - transpiled_circuit, initial_state=reordered_test_states[i] - ).state() - final_state = _transpose_qubits(final_state, ordering) - fidelity = np.abs(np.dot(np.conj(target_state), final_state)) - try: - np.testing.assert_allclose(fidelity, 1.0) - except AssertionError: - raise_error(TranspilerPipelineError, "Circuit equivalence not satisfied.") - - -def _transpose_qubits(state: np.ndarray, qubits_ordering: np.ndarray): - """Reorders qubits of a given state vector. - - Args: - state (np.ndarray): final state of the circuit. - qubits_ordering (np.ndarray): final qubit ordering. - """ - original_shape = state.shape - state = np.reshape(state, len(qubits_ordering) * (2,)) - state = np.transpose(state, qubits_ordering) - return np.reshape(state, original_shape) - - -def assert_transpiling( - original_circuit: Circuit, - transpiled_circuit: Circuit, - connectivity: nx.Graph, - initial_layout: dict, - final_layout: dict, - native_gates: NativeGates = NativeGates.default(), - check_circuit_equivalence=True, -): - """Check that all transpiler passes have been executed correctly. - - Args: - original_circuit (:class:`qibo.models.Circuit`): circuit before transpiling. - transpiled_circuit (:class:`qibo.models.Circuit`): circuit after transpiling. - connectivity (:class:`networkx.Graph`): chip qubits connectivity. - initial_layout (dict): initial physical-logical qubit mapping. - final_layout (dict): final physical-logical qubit mapping. - native_gates (:class:`qibo.transpiler.unroller.NativeGates`): native gates - supported by the hardware. Defaults to - :meth:`qibo.transpiler.unroller.NativeGates.default`. - check_circuit_equivalence (bool, optional): use simulations to check if the - transpiled circuit is the same as the original. Defaults to ``True``. - """ - assert_connectivity(circuit=transpiled_circuit, connectivity=connectivity) - assert_decomposition( - circuit=transpiled_circuit, - native_gates=native_gates, - ) - if original_circuit.nqubits != transpiled_circuit.nqubits: - qubit_matcher = Preprocessing(connectivity=connectivity) - original_circuit = qubit_matcher(circuit=original_circuit) - assert_placement( - circuit=original_circuit, layout=initial_layout, connectivity=connectivity - ) - assert_placement( - circuit=transpiled_circuit, layout=final_layout, connectivity=connectivity - ) - if check_circuit_equivalence: - assert_circuit_equivalence( - original_circuit=original_circuit, - transpiled_circuit=transpiled_circuit, - initial_map=initial_layout, - final_map=final_layout, - ) - - -def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list): +def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list[str]): """Restrict the connectivity to selected qubits. Args: @@ -177,14 +52,10 @@ class Passes: If ``None``, default transpiler will be used. Defaults to ``None``. connectivity (:class:`networkx.Graph`, optional): physical qubits connectivity. - If ``None``, :class:`` is used. - Defaults to ``None``. native_gates (:class:`qibo.transpiler.unroller.NativeGates`, optional): native gates. Defaults to :math:`qibo.transpiler.unroller.NativeGates.default`. on_qubits (list, optional): list of physical qubits to be used. If "None" all qubits are used. Defaults to ``None``. - int_qubit_name (bool, optional): if `True` the `final_layout` keys are - cast to integers. """ def __init__( @@ -193,68 +64,30 @@ def __init__( connectivity: nx.Graph = None, native_gates: NativeGates = NativeGates.default(), on_qubits: list = None, - int_qubit_names: bool = False, ): if on_qubits is not None: connectivity = restrict_connectivity_qubits(connectivity, on_qubits) self.connectivity = connectivity self.native_gates = native_gates - self.passes = self.default() if passes is None else passes - self.initial_layout = None - self.int_qubit_names = int_qubit_names - - def default(self): - """Return the default transpiler pipeline for the required hardware connectivity.""" - if not isinstance(self.connectivity, nx.Graph): - raise_error( - TranspilerPipelineError, - "Define the hardware chip connectivity to use default transpiler", - ) - default_passes = [] - # preprocessing - default_passes.append(Preprocessing(connectivity=self.connectivity)) - # default placer pass - default_passes.append(StarConnectivityPlacer()) - # default router pass - default_passes.append(StarConnectivityRouter()) - # default unroller pass - default_passes.append(Unroller(native_gates=self.native_gates)) - - return default_passes + self.passes = [] if passes is None else passes def __call__(self, circuit): """ This function returns the compiled circuits and the dictionary mapping - physical (keys) to logical (values) qubit. If `int_qubit_name` is `True` - each key `i` correspond to the `i-th` qubit in the graph. + physical (keys) to logical (values) qubit. """ - final_layout = self.initial_layout = None + + final_layout = None for transpiler_pass in self.passes: if isinstance(transpiler_pass, Optimizer): transpiler_pass.connectivity = self.connectivity circuit = transpiler_pass(circuit) elif isinstance(transpiler_pass, Placer): transpiler_pass.connectivity = self.connectivity - if self.initial_layout is None: - self.initial_layout = transpiler_pass(circuit) - final_layout = ( - self.initial_layout - ) # This way the final layout will be the same as the initial layout if no router is used - else: - raise_error( - TranspilerPipelineError, - "You are defining more than one placer pass.", - ) + final_layout = transpiler_pass(circuit) elif isinstance(transpiler_pass, Router): transpiler_pass.connectivity = self.connectivity - if self.initial_layout is not None: - circuit, final_layout = transpiler_pass( - circuit, self.initial_layout - ) - else: - raise_error( - TranspilerPipelineError, "Use a placement pass before routing." - ) + circuit, final_layout = transpiler_pass(circuit) elif isinstance(transpiler_pass, Unroller): circuit = transpiler_pass(circuit) else: @@ -262,8 +95,6 @@ def __call__(self, circuit): TranspilerPipelineError, f"Unrecognised transpiler pass: {transpiler_pass}", ) - if self.int_qubit_names and final_layout is not None: - final_layout = {int(key[1:]): value for key, value in final_layout.items()} return circuit, final_layout def is_satisfied(self, circuit: Circuit): @@ -276,14 +107,9 @@ def is_satisfied(self, circuit: Circuit): (bool): satisfiability condition. """ try: + assert_placement(circuit=circuit, connectivity=self.connectivity) assert_connectivity(circuit=circuit, connectivity=self.connectivity) assert_decomposition(circuit=circuit, native_gates=self.native_gates) return True - except ConnectivityError: + except (ConnectivityError, DecompositionError, PlacementError, ValueError): return False - except DecompositionError: - return False - - def get_initial_layout(self): - """Return initial qubit layout""" - return self.initial_layout diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py index 7944ea81f2..48e2cbd8ec 100644 --- a/src/qibo/transpiler/placer.py +++ b/src/qibo/transpiler/placer.py @@ -1,71 +1,17 @@ -from typing import Optional, Union +from typing import Optional import networkx as nx from qibo import gates from qibo.backends import _check_backend_and_local_state -from qibo.config import log, raise_error +from qibo.config import raise_error from qibo.models import Circuit from qibo.transpiler._exceptions import PlacementError from qibo.transpiler.abstract import Placer, Router +from qibo.transpiler.asserts import assert_placement from qibo.transpiler.router import _find_connected_qubit -def assert_placement( - circuit: Circuit, layout: dict, connectivity: nx.Graph = None -) -> bool: - """Check if layout is in the correct form and matches the number of qubits of the circuit. - - Args: - circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check. - layout (dict): physical to logical qubit mapping. - connectivity (:class:`networkx.Graph`, optional): Chip connectivity. - This argument is necessary if the layout is applied to a subset of - qubits of the original connectivity graph. Defaults to ``None``. - """ - assert_mapping_consistency(layout=layout, connectivity=connectivity) - if circuit.nqubits > len(layout): - raise_error( - PlacementError, - "Layout can't be used on circuit. The circuit requires more qubits.", - ) - if circuit.nqubits < len(layout): - raise_error( - PlacementError, - "Layout can't be used on circuit. " - + "Ancillary extra qubits need to be added to the circuit.", - ) - - -def assert_mapping_consistency(layout: dict, connectivity: nx.Graph = None): - """Check if layout is in the correct form. - - Args: - layout (dict): physical to logical qubit mapping. - connectivity (:class:`networkx.Graph`, optional): Chip connectivity. - This argument is necessary if the layout is applied to a subset of - qubits of the original connectivity graph. Defaults to ``None``. - """ - values = sorted(layout.values()) - physical_qubits = list(layout) - nodes = ( - list(range(len(values))) if connectivity is None else list(connectivity.nodes) - ) - ref_keys = ( - ["q" + str(i) for i in nodes] if isinstance(physical_qubits[0], str) else nodes - ) - if sorted(physical_qubits) != sorted(ref_keys): - raise_error( - PlacementError, - "Some physical qubits in the layout may be missing or duplicated.", - ) - if values != list(range(len(values))): - raise_error( - PlacementError, - "Some logical qubits in the layout may be missing or duplicated.", - ) - - def _find_gates_qubits_pairs(circuit: Circuit): """Helper method for :meth:`qibo.transpiler.placer`. Translate circuit into a list of pairs of qubits to be used by the router and placer. @@ -99,17 +45,12 @@ class StarConnectivityPlacer(Placer): q Args: - connectivity (:class:`networkx.Graph`): chip connectivity, not used for this transpiler. - middle_qubit (int, optional): qubit id of the qubit that is in the middle of the star. + connectivity (:class:`networkx.Graph`): star connectivity graph. """ - def __init__(self, connectivity=None, middle_qubit: int = 2): - self.middle_qubit = middle_qubit - if connectivity is not None: # pragma: no cover - log.warning( - "StarConnectivityRouter does not use the connectivity graph." - "The connectivity graph will be ignored." - ) + def __init__(self, connectivity: Optional[nx.Graph] = None): + self.connectivity = connectivity + self.middle_qubit = None def __call__(self, circuit: Circuit): """Apply the transpiler transformation on a given circuit. @@ -117,14 +58,12 @@ def __call__(self, circuit: Circuit): Args: circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform. Only single qubit gates and two qubits gates are supported by the router. - - Returns: - dict: physical to logical qubit mapping. """ + assert_placement(circuit, self.connectivity) + self._check_star_connectivity() - # find the number of qubits for hardware circuit - nqubits = max(circuit.nqubits, self.middle_qubit + 1) - hardware_qubits = list(range(nqubits)) + middle_qubit_idx = circuit.wire_names.index(self.middle_qubit) + wire_names = circuit.wire_names.copy() for i, gate in enumerate(circuit.queue): if len(gate.qubits) > 2: @@ -133,118 +72,35 @@ def __call__(self, circuit: Circuit): "Gates targeting more than 2 qubits are not supported", ) if len(gate.qubits) == 2: - if self.middle_qubit not in gate.qubits: + if middle_qubit_idx not in gate.qubits: new_middle = _find_connected_qubit( gate.qubits, circuit.queue[i + 1 :], - hardware_qubits, error=PlacementError, + mapping=list(range(circuit.nqubits)), ) - hardware_qubits[self.middle_qubit], hardware_qubits[new_middle] = ( - new_middle, - self.middle_qubit, + + ( + wire_names[middle_qubit_idx], + wire_names[new_middle], + ) = ( + wire_names[new_middle], + wire_names[middle_qubit_idx], ) break - return dict(zip(["q" + str(i) for i in range(nqubits)], hardware_qubits)) - - -class Trivial(Placer): - """Place qubits according to the following notation: - - .. math:: - \\{\\textup{"q0"} : 0, \\textup{"q1"} : 1, ..., \\textup{"qn"} : n}. + circuit.wire_names = wire_names - Args: - connectivity (networkx.Graph, optional): chip connectivity. - """ - - def __init__(self, connectivity: nx.Graph = None): - self.connectivity = connectivity - - def __call__(self, circuit: Circuit): - """Find the trivial placement for the circuit. - - Args: - circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled. - - Returns: - (dict): physical to logical qubit mapping. - """ - if self.connectivity is not None: - if self.connectivity.number_of_nodes() != circuit.nqubits: + def _check_star_connectivity(self): + """Check if the connectivity graph is a star graph.""" + for node in self.connectivity.nodes: + if self.connectivity.degree(node) == 4: + self.middle_qubit = node + elif self.connectivity.degree(node) != 1: raise_error( - PlacementError, - "The number of nodes of the connectivity graph must match " - + "the number of qubits in the circuit", - ) - trivial_layout = dict( - zip( - ["q" + str(i) for i in list(self.connectivity.nodes())], - range(circuit.nqubits), - ) - ) - else: - trivial_layout = dict( - zip( - ["q" + str(i) for i in range(circuit.nqubits)], - range(circuit.nqubits), - ) - ) - return trivial_layout - - -class Custom(Placer): - """Define a custom initial qubit mapping. - - Args: - map (list or dict): physical to logical qubit mapping. - Examples: :math:`[1,2,0]` or - :math:`{\\textup{"q0"}: 1, \\textup{"q1"}: 2, \\textup{"q2"}:0}` - to assign the physical qubits :math:`\\{0, 1, 2\\}` - to the logical qubits :math:`[1, 2, 0]`. - connectivity (:class:`networkx.Graph`, optional): chip connectivity. - This argument is necessary if the layout applied to a subset of - qubits of the original connectivity graph. Defaults to ``None``. - """ - - def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph = None): - self.connectivity = connectivity - self.initial_map = initial_map - - def __call__(self, circuit=None): - """Return the custom placement if it can be applied to the given circuit (if given). - - Args: - circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled. - - Returns: - (dict): physical to logical qubit mapping. - """ - if isinstance(self.initial_map, dict): - pass - elif isinstance(self.initial_map, list): - if self.connectivity is not None: - self.initial_map = dict( - zip( - ["q" + str(i) for i in self.connectivity.nodes()], - self.initial_map, - ) + ValueError, + "This connectivity graph is not a star graph.", ) - else: - self.initial_map = dict( - zip( - ["q" + str(i) for i in range(len(self.initial_map))], - self.initial_map, - ) - ) - else: - raise_error(TypeError, "Use dict or list to define mapping.") - if circuit is not None: - assert_placement(circuit, self.initial_map, connectivity=self.connectivity) - else: - assert_mapping_consistency(self.initial_map, connectivity=self.connectivity) - return self.initial_map class Subgraph(Placer): @@ -258,7 +114,7 @@ class Subgraph(Placer): connectivity (:class:`networkx.Graph`): chip connectivity. """ - def __init__(self, connectivity: nx.Graph): + def __init__(self, connectivity: Optional[nx.Graph] = None): self.connectivity = connectivity def __call__(self, circuit: Circuit): @@ -267,10 +123,8 @@ def __call__(self, circuit: Circuit): Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled. - - Returns: - (dict): physical to logical qubit mapping. """ + assert_placement(circuit, self.connectivity) gates_qubits_pairs = _find_gates_qubits_pairs(circuit) if len(gates_qubits_pairs) < 3: raise_error( @@ -301,9 +155,7 @@ def __call__(self, circuit: Circuit): ): break - sorted_result = dict(sorted(result.mapping.items())) - - return {"q" + str(k): v for k, v in sorted_result.items()} + circuit.wire_names = sorted(result.mapping, key=lambda k: result.mapping[k]) class Random(Placer): @@ -320,7 +172,9 @@ class Random(Placer): initializes a generator with a random seed. Defaults to ``None``. """ - def __init__(self, connectivity, samples: int = 100, seed=None): + def __init__( + self, connectivity: Optional[nx.Graph] = None, samples: int = 100, seed=None + ): self.connectivity = connectivity self.samples = samples self.seed = seed @@ -330,15 +184,12 @@ def __call__(self, circuit): Args: circuit (:class:`qibo.models.circuit.Circuit`): Circuit to be transpiled. - - Returns: - (dict): physical-to-logical qubit mapping. """ + assert_placement(circuit, self.connectivity) _, local_state = _check_backend_and_local_state(self.seed, backend=None) gates_qubits_pairs = _find_gates_qubits_pairs(circuit) nodes = self.connectivity.number_of_nodes() keys = list(self.connectivity.nodes()) - dict_keys = ["q" + str(i) for i in keys] final_mapping = dict(zip(keys, range(nodes))) final_graph = nx.relabel_nodes(self.connectivity, final_mapping) @@ -351,16 +202,17 @@ def __call__(self, circuit): cost = self._cost(graph, gates_qubits_pairs) if cost == 0: - final_layout = dict(zip(dict_keys, list(mapping.values()))) - return dict(sorted(final_layout.items())) + final_layout = dict(zip(keys, list(mapping.values()))) + circuit.wire_names = sorted(final_layout, key=final_layout.get) + return if cost < final_cost: final_graph = graph final_mapping = mapping final_cost = cost - final_layout = dict(zip(dict_keys, list(final_mapping.values()))) - return dict(sorted(final_layout.items())) + final_layout = dict(zip(keys, list(final_mapping.values()))) + circuit.wire_names = sorted(final_layout, key=final_layout.get) def _cost(self, graph: nx.Graph, gates_qubits_pairs: list): """ @@ -405,8 +257,8 @@ class ReverseTraversal(Placer): def __init__( self, - connectivity: nx.Graph, routing_algorithm: Router, + connectivity: Optional[nx.Graph] = None, depth: Optional[int] = None, ): self.connectivity = connectivity @@ -418,17 +270,11 @@ def __call__(self, circuit: Circuit): Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled. - - Returns: - (dict): physical to logical qubit mapping. """ - initial_placer = Trivial(self.connectivity) - initial_placement = initial_placer(circuit=circuit) + assert_placement(circuit, self.connectivity) self.routing_algorithm.connectivity = self.connectivity new_circuit = self._assemble_circuit(circuit) - final_placement = self._routing_step(initial_placement, new_circuit) - - return final_placement + self._routing_step(new_circuit) def _assemble_circuit(self, circuit: Circuit): """Assemble a single circuit to apply Reverse Traversal placement based on depth. @@ -461,20 +307,19 @@ def _assemble_circuit(self, circuit: Circuit): gates_qubits_pairs.reverse() assembled_gates_qubits_pairs += gates_qubits_pairs[0:remainder] - new_circuit = Circuit(circuit.nqubits) + new_circuit = Circuit(circuit.nqubits, wire_names=circuit.wire_names) for qubits in assembled_gates_qubits_pairs: # As only the connectivity is important here we can replace everything with CZ gates new_circuit.add(gates.CZ(qubits[0], qubits[1])) return new_circuit.invert() - def _routing_step(self, layout: dict, circuit: Circuit): + def _routing_step(self, circuit: Circuit): """Perform routing of the circuit. Args: - layout (dict): intial qubit layout. circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed. """ - _, final_mapping = self.routing_algorithm(circuit, layout) + _, final_mapping = self.routing_algorithm(circuit) return final_mapping diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py index b1aad8fc69..704e4435b8 100644 --- a/src/qibo/transpiler/router.py +++ b/src/qibo/transpiler/router.py @@ -6,62 +6,14 @@ import numpy as np from qibo import gates -from qibo.config import log, raise_error +from qibo.config import raise_error from qibo.models import Circuit from qibo.transpiler._exceptions import ConnectivityError from qibo.transpiler.abstract import Router +from qibo.transpiler.asserts import assert_placement from qibo.transpiler.blocks import Block, CircuitBlocks -def assert_connectivity(connectivity: nx.Graph, circuit: Circuit): - """Assert if a circuit can be executed on Hardware. - - No gates acting on more than two qubits. - All two-qubit operations can be performed on hardware. - - Args: - circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check. - connectivity (:class:`networkx.Graph`): chip connectivity. - """ - if list(connectivity.nodes) != list(range(connectivity.number_of_nodes())): - node_mapping = {node: i for i, node in enumerate(connectivity.nodes)} - new_connectivity = nx.Graph() - new_connectivity.add_edges_from( - [(node_mapping[u], node_mapping[v]) for u, v in connectivity.edges] - ) - connectivity = new_connectivity - for gate in circuit.queue: - if len(gate.qubits) > 2 and not isinstance(gate, gates.M): - raise_error(ConnectivityError, f"{gate.name} acts on more than two qubits.") - if len(gate.qubits) == 2: - # physical_qubits = tuple(sorted((circuit.wire_names[gate.qubits[0]], circuit.wire_names[gate.qubits[1]]))) - physical_qubits = tuple(sorted(gate.qubits)) # for q_i naming - if physical_qubits not in connectivity.edges: - raise_error( - ConnectivityError, - f"The circuit does not respect the connectivity. {gate.name} acts on {physical_qubits} but only the following qubits are directly connected: {connectivity.edges}.", - ) - - -def _relabel_connectivity(connectivity, layout): - """Relabels the connectivity graph using the passed layout. - - Args: - connectivity (nx.Graph): input connectivity. - layout (dict): input qubit layout. - Returns: - (dict) the updated connectivity. - """ - node_mapping = {} - layout = dict( - sorted(layout.items(), key=lambda item: int(item[0][1:])) - ) # for q_i naming - for i, node in enumerate(list(layout.keys())): - node_mapping[int(node[1:])] = i # for q_i naming - new_connectivity = nx.relabel_nodes(connectivity, node_mapping) - return new_connectivity - - class StarConnectivityRouter(Router): """Transforms an arbitrary circuit to one that can be executed on hardware. @@ -76,91 +28,87 @@ class StarConnectivityRouter(Router): by adding SWAP gates when needed. Args: - connectivity (:class:`networkx.Graph`): chip connectivity, not used for this transpiler. - middle_qubit (int, optional): qubit id of the qubit that is in the middle of the star. + connectivity (:class:`networkx.Graph`): star connectivity graph. """ - def __init__(self, connectivity=None, middle_qubit: int = 2): - self.middle_qubit = middle_qubit - if connectivity is not None: # pragma: no cover - log.warning( - "StarConnectivityRouter does not use the connectivity graph." - "The connectivity graph will be ignored." - ) + def __init__(self, connectivity: Optional[nx.Graph] = None): + self.connectivity = connectivity + self.middle_qubit = None - def __call__(self, circuit: Circuit, initial_layout: dict): + def __call__(self, circuit: Circuit): """Apply the transpiler transformation on a given circuit. Args: circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform. Only single qubit gates and two qubits gates are supported by the router. - initial_layout (dict): initial physical-to-logical qubit mapping, - use `qibo.transpiler.placer.StarConnectivityPlacer` for better performance. - - Returns: - (:class:`qibo.models.circuit.Circuit`, list): circuit that performs the same operation - as the original but respects the hardware connectivity, - and list that maps logical to hardware qubits. """ + self._check_star_connectivity() + assert_placement(circuit, self.connectivity) - middle_qubit = self.middle_qubit - nqubits = max(circuit.nqubits, middle_qubit + 1) - # new circuit object that will be compatible with hardware connectivity - new = Circuit(nqubits) - # list to maps logical to hardware qubits - hardware_qubits = list(initial_layout.values()) + middle_qubit_idx = circuit.wire_names.index(self.middle_qubit) + nqubits = circuit.nqubits + new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names) + l2p = list(range(nqubits)) for i, gate in enumerate(circuit.queue): - # map gate qubits to hardware - qubits = tuple(hardware_qubits.index(q) for q in gate.qubits) + routed_qubits = [l2p[q] for q in gate.qubits] + if isinstance(gate, gates.M): - new_gate = gates.M(*qubits, **gate.init_kwargs) + new_gate = gates.M(*routed_qubits, **gate.init_kwargs) new_gate.result = gate.result new.add(new_gate) continue - if len(qubits) > 2: + if len(routed_qubits) > 2: raise_error( ConnectivityError, "Gates targeting more than two qubits are not supported.", ) - if len(qubits) == 2 and middle_qubit not in qubits: + if len(routed_qubits) == 2 and middle_qubit_idx not in routed_qubits: # find which qubit should be moved new_middle = _find_connected_qubit( - qubits, + routed_qubits, circuit.queue[i + 1 :], - hardware_qubits, error=ConnectivityError, + mapping=l2p, ) - # update hardware qubits according to the swap - hardware_qubits[middle_qubit], hardware_qubits[new_middle] = ( - hardware_qubits[new_middle], - hardware_qubits[middle_qubit], - ) - new.add(gates.SWAP(middle_qubit, new_middle)) - # update gate qubits according to the new swap - qubits = tuple(hardware_qubits.index(q) for q in gate.qubits) + + new.add(gates.SWAP(new_middle, middle_qubit_idx)) + idx1, idx2 = l2p.index(middle_qubit_idx), l2p.index(new_middle) + l2p[idx1], l2p[idx2] = l2p[idx2], l2p[idx1] + + routed_qubits = [l2p[q] for q in gate.qubits] # add gate to the hardware circuit if isinstance(gate, gates.Unitary): # gates.Unitary requires matrix as first argument matrix = gate.init_args[0] - new.add(gate.__class__(matrix, *qubits, **gate.init_kwargs)) + new.add(gate.__class__(matrix, *routed_qubits, **gate.init_kwargs)) else: - new.add(gate.__class__(*qubits, **gate.init_kwargs)) - hardware_qubits_keys = ["q" + str(i) for i in range(5)] - return new, dict(zip(hardware_qubits_keys, hardware_qubits)) + new.add(gate.__class__(*routed_qubits, **gate.init_kwargs)) + return new, {circuit.wire_names[i]: l2p[i] for i in range(nqubits)} + + def _check_star_connectivity(self): + """Check if the connectivity graph is a star graph.""" + for node in self.connectivity.nodes: + if self.connectivity.degree(node) == 4: + self.middle_qubit = node + elif self.connectivity.degree(node) != 1: + raise_error( + ValueError, + "This connectivity graph is not a star graph.", + ) -def _find_connected_qubit(qubits, queue, hardware_qubits, error): +def _find_connected_qubit(qubits, queue, error, mapping): """Helper method for :meth:`qibo.transpiler.router.StarConnectivityRouter` and :meth:`qibo.transpiler.router.StarConnectivityPlacer`. Finds which qubit should be mapped to hardware middle qubit by looking at the two-qubit gates that follow. """ - possible_qubits = set(qubits) + possible_qubits = {qubits[0], qubits[1]} for next_gate in queue: if len(next_gate.qubits) > 2: raise_error( @@ -168,11 +116,13 @@ def _find_connected_qubit(qubits, queue, hardware_qubits, error): "Gates targeting more than 2 qubits are not supported", ) if len(next_gate.qubits) == 2: - possible_qubits &= {hardware_qubits.index(q) for q in next_gate.qubits} + possible_qubits &= { + mapping[next_gate.qubits[0]], + mapping[next_gate.qubits[1]], + } - if not possible_qubits: + if len(possible_qubits) == 0: return qubits[0] - if len(possible_qubits) == 1: return possible_qubits.pop() @@ -185,7 +135,6 @@ class CircuitMap: Also implements the initial two-qubit block decompositions. Args: - initial_layout (dict): initial physical to logical qubit mapping. circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed. blocks (:class:`qibo.transpiler.blocks.CircuitBlocks`, optional): circuit block representation. If ``None``, the blocks will be computed from the circuit. @@ -194,7 +143,6 @@ class CircuitMap: def __init__( self, - initial_layout: Optional[dict] = None, circuit: Optional[Circuit] = None, blocks: Optional[CircuitBlocks] = None, temp: Optional[bool] = False, @@ -204,23 +152,21 @@ def __init__( self._temporary = temp if self._temporary: return - elif circuit is None: + if circuit is None: raise_error(ValueError, "Circuit must be provided.") - if blocks is not None: self.circuit_blocks = blocks else: self.circuit_blocks = CircuitBlocks(circuit, index_names=True) - self._nqubits = circuit.nqubits - self._routed_blocks = CircuitBlocks(Circuit(circuit.nqubits)) + self.nqubits = circuit.nqubits + self._routed_blocks = CircuitBlocks( + Circuit(circuit.nqubits, wire_names=circuit.wire_names) + ) self._swaps = 0 - if initial_layout is None: - return - - self.wire_names = list(initial_layout.keys()) - self.physical_to_logical = list(initial_layout.values()) + self.wire_names = circuit.wire_names.copy() + self.physical_to_logical = list(range(self.nqubits)) @property def physical_to_logical(self): @@ -302,7 +248,7 @@ def routed_circuit(self, circuit_kwargs: Optional[dict] = None): def final_layout(self): """Returns the final physical-logical qubits mapping.""" - return {self.wire_names[i]: self._p2l[i] for i in range(self._nqubits)} + return {self.wire_names[i]: self._l2p[i] for i in range(self.nqubits)} def update(self, logical_swap: tuple): """Updates the qubit mapping after applying a ``SWAP`` @@ -368,7 +314,9 @@ class ShortestPaths(Router): If ``None``, defaults to :math:`42`. Defaults to ``None``. """ - def __init__(self, connectivity: nx.Graph, seed: Optional[int] = None): + def __init__( + self, connectivity: Optional[nx.Graph] = None, seed: Optional[int] = None + ): self.connectivity = connectivity self._front_layer = None self.circuit_map = None @@ -384,19 +332,19 @@ def added_swaps(self): """Returns the number of SWAP gates added to the circuit during routing.""" return self.circuit_map._swaps - def __call__(self, circuit: Circuit, initial_layout: dict): + def __call__(self, circuit: Circuit): """Circuit connectivity matching. Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be matched to hardware connectivity. - initial_layout (dict): initial physical-to-logical qubit mapping Returns: (:class:`qibo.models.circuit.Circuit`, dict): circut mapped to hardware topology, and final physical-to-logical qubit mapping. """ - self._preprocessing(circuit=circuit, initial_layout=initial_layout) + assert_placement(circuit, self.connectivity) + self._preprocessing(circuit=circuit) while self._dag.number_of_nodes() != 0: execute_block_list = self._check_execution() if execute_block_list is not None: @@ -405,7 +353,6 @@ def __call__(self, circuit: Circuit, initial_layout: dict): self._find_new_mapping() circuit_kwargs = circuit.init_kwargs - circuit_kwargs["wire_names"] = list(initial_layout.keys()) routed_circuit = self.circuit_map.routed_circuit(circuit_kwargs=circuit_kwargs) if self._final_measurements is not None: routed_circuit = self._append_final_measurements( @@ -490,7 +437,7 @@ def _compute_cost(self, candidate: tuple): (list, int): best path to move qubits and qubit meeting point in the path. """ temporary_circuit = CircuitMap( - circuit=Circuit(self.circuit_map._nqubits), + circuit=Circuit(self.circuit_map.nqubits), blocks=deepcopy(self.circuit_map.circuit_blocks), ) @@ -573,7 +520,7 @@ def _update_front_layer(self): node[0] for node in self._dag.nodes(data="layer") if node[1] == 0 ] - def _preprocessing(self, circuit: Circuit, initial_layout: dict): + def _preprocessing(self, circuit: Circuit): """The following objects will be initialised: - circuit: class to represent circuit and to perform logical-physical qubit mapping. - _final_measurements: measurement gates at the end of the circuit. @@ -581,14 +528,13 @@ def _preprocessing(self, circuit: Circuit, initial_layout: dict): Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be preprocessed. - initial_layout (dict): initial physical-to-logical qubit mapping. """ - - self.connectivity = _relabel_connectivity(self.connectivity, initial_layout) - + self.connectivity = nx.relabel_nodes( + self.connectivity, {v: i for i, v in enumerate(circuit.wire_names)} + ) copied_circuit = circuit.copy(deep=True) self._final_measurements = self._detach_final_measurements(copied_circuit) - self.circuit_map = CircuitMap(initial_layout, copied_circuit) + self.circuit_map = CircuitMap(copied_circuit) self._dag = _create_dag(self.circuit_map.blocks_logical_qubits_pairs()) self._update_front_layer() @@ -657,7 +603,7 @@ class Sabre(Router): def __init__( self, - connectivity: nx.Graph, + connectivity: Optional[nx.Graph] = None, lookahead: int = 2, decay_lookahead: float = 0.6, delta: float = 0.001, @@ -679,17 +625,17 @@ def __init__( self._temp_added_swaps = [] random.seed(seed) - def __call__(self, circuit: Circuit, initial_layout: dict): + def __call__(self, circuit: Circuit): """Route the circuit. Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed. - initial_layout (dict): initial physical to logical qubit mapping. Returns: (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout. """ - self._preprocessing(circuit=circuit, initial_layout=initial_layout) + assert_placement(circuit, self.connectivity) + self._preprocessing(circuit=circuit) longest_path = np.max(self._dist_matrix) while self._dag.number_of_nodes() != 0: @@ -711,7 +657,6 @@ def __call__(self, circuit: Circuit, initial_layout: dict): self._shortest_path_routing() circuit_kwargs = circuit.init_kwargs - circuit_kwargs["wire_names"] = list(initial_layout.keys()) routed_circuit = self.circuit_map.routed_circuit(circuit_kwargs=circuit_kwargs) if self._final_measurements is not None: routed_circuit = self._append_final_measurements( @@ -725,7 +670,7 @@ def added_swaps(self): """Returns the number of SWAP gates added to the circuit during routing.""" return self.circuit_map._swaps - def _preprocessing(self, circuit: Circuit, initial_layout: dict): + def _preprocessing(self, circuit: Circuit): """The following objects will be initialised: - circuit: class to represent circuit and to perform logical-physical qubit mapping. - _final_measurements: measurement gates at the end of the circuit. @@ -738,14 +683,15 @@ def _preprocessing(self, circuit: Circuit, initial_layout: dict): Args: circuit (:class:`qibo.models.circuit.Circuit`): circuit to be preprocessed. - initial_layout (dict): initial physical-to-logical qubit mapping. """ - self.connectivity = _relabel_connectivity(self.connectivity, initial_layout) + self.connectivity = nx.relabel_nodes( + self.connectivity, {v: i for i, v in enumerate(circuit.wire_names)} + ) copied_circuit = circuit.copy(deep=True) self._final_measurements = self._detach_final_measurements(copied_circuit) - self.circuit_map = CircuitMap(initial_layout, copied_circuit) + self.circuit_map = CircuitMap(copied_circuit) self._dist_matrix = nx.floyd_warshall_numpy(self.connectivity) self._dag = _create_dag(self.circuit_map.blocks_logical_qubits_pairs()) self._memory_map = [] @@ -977,7 +923,7 @@ def _create_dag(gates_qubits_pairs: list): dag = nx.DiGraph() dag.add_nodes_from(range(len(gates_qubits_pairs))) - for i in range(len(gates_qubits_pairs)): + for i, _ in enumerate(gates_qubits_pairs): dag.nodes[i]["qubits"] = gates_qubits_pairs[i] # Find all successors @@ -986,7 +932,7 @@ def _create_dag(gates_qubits_pairs: list): saturated_qubits = [] for next_idx, next_gate in enumerate(gates_qubits_pairs[idx + 1 :]): for qubit in gate: - if (qubit in next_gate) and (not qubit in saturated_qubits): + if (qubit in next_gate) and (qubit not in saturated_qubits): saturated_qubits.append(qubit) connectivity_list.append((idx, next_idx + idx + 1)) if len(saturated_qubits) >= 2: diff --git a/src/qibo/transpiler/unroller.py b/src/qibo/transpiler/unroller.py index 17e2e385aa..2e875311fd 100644 --- a/src/qibo/transpiler/unroller.py +++ b/src/qibo/transpiler/unroller.py @@ -125,39 +125,6 @@ def __call__(self, circuit: Circuit): return translated_circuit -def assert_decomposition( - circuit: Circuit, - native_gates: NativeGates, -): - """Checks if a circuit has been correctly decomposed into native gates. - - Args: - circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check. - native_gates (:class:`qibo.transpiler.unroller.NativeGates`): - native gates in the transpiled circuit. - """ - for gate in circuit.queue: - if isinstance(gate, gates.M): - continue - if len(gate.qubits) <= 2: - try: - native_type_gate = NativeGates.from_gate(gate) - if not native_type_gate & native_gates: - raise_error( - DecompositionError, - f"{gate.name} is not a native gate.", - ) - except ValueError: - raise_error( - DecompositionError, - f"{gate.name} is not a native gate.", - ) - else: - raise_error( - DecompositionError, f"{gate.name} acts on more than two qubits." - ) - - def translate_gate( gate, native_gates: NativeGates, diff --git a/tests/conftest.py b/tests/conftest.py index a5029ddbe8..a98b9de50f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ import sys +import networkx as nx import pytest from qibo.backends import _Global, construct_backend @@ -81,6 +82,40 @@ def clear(): _Global._transpiler = None +@pytest.fixture +def star_connectivity(): + def _star_connectivity(names=list(range(5)), middle_qubit_idx=2): + chip = nx.Graph() + chip.add_nodes_from(names) + graph_list = [ + (names[i], names[middle_qubit_idx]) + for i in range(len(names)) + if i != middle_qubit_idx + ] + chip.add_edges_from(graph_list) + return chip + + return _star_connectivity + + +@pytest.fixture +def grid_connectivity(): + def _grid_connectivity(names=list(range(5))): + chip = nx.Graph() + chip.add_nodes_from(names) + graph_list = [ + (names[0], names[1]), + (names[1], names[2]), + (names[2], names[3]), + (names[3], names[0]), + (names[0], names[4]), + ] + chip.add_edges_from(graph_list) + return chip + + return _grid_connectivity + + def pytest_generate_tests(metafunc): module_name = metafunc.module.__name__ diff --git a/tests/test_backends.py b/tests/test_backends.py index 85fb18f3a3..383fdb7c17 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -113,19 +113,17 @@ def test_construct_backend(backend): def test_list_available_backends(): - tensorflow = False if platform.system() == "Windows" else True qulacs = ( False if platform.system() == "Darwin" and sys.version_info[1] == 9 else True ) available_backends = { "numpy": True, - "pytorch": True, "qulacs": qulacs, "qibojit": {"numba": True, "cupy": False, "cuquantum": False}, "qibolab": False, "qibo-cloud-backends": False, "qibotn": {"cutensornet": False, "qutensornet": True}, - "qiboml": {"tensorflow": tensorflow}, + "qiboml": {"tensorflow": False, "pytorch": True}, } assert available_backends == list_available_backends( "qibojit", "qibolab", "qibo-cloud-backends", "qibotn", "qiboml" diff --git a/tests/test_backends_global.py b/tests/test_backends_global.py index 99c1f9d450..dc0b6dfeaa 100644 --- a/tests/test_backends_global.py +++ b/tests/test_backends_global.py @@ -128,9 +128,9 @@ def test_set_get_transpiler(): transpiler = Passes( connectivity=connectivity, passes=[ - Preprocessing(connectivity), - Random(connectivity, seed=0), - Sabre(connectivity), + Preprocessing(), + Random(seed=0), + Sabre(), Unroller(NativeGates.default()), ], ) @@ -171,8 +171,13 @@ def natives(self): _Global._backend = backend transpiler = _Global.transpiler() - assert list(transpiler.connectivity.nodes) == [0, 1, 2, 3, 4] - assert list(transpiler.connectivity.edges) == [(0, 1), (1, 2), (2, 3), (3, 4)] + assert list(transpiler.connectivity.nodes) == ["A1", "A2", "A3", "A4", "A5"] + assert list(transpiler.connectivity.edges) == [ + ("A1", "A2"), + ("A2", "A3"), + ("A3", "A4"), + ("A4", "A5"), + ] assert ( NativeGates.CZ in transpiler.native_gates and NativeGates.GPI2 in transpiler.native_gates diff --git a/tests/test_backends_torch_gradients.py b/tests/test_backends_torch_gradients.py deleted file mode 100644 index 9dcd0f032a..0000000000 --- a/tests/test_backends_torch_gradients.py +++ /dev/null @@ -1,85 +0,0 @@ -import sys - -import numpy as np -import pytest - -from qibo import Circuit, gates -from qibo.backends import PyTorchBackend, construct_backend -from qibo.quantum_info import infidelity - - -def test_torch_gradients(): - backend = PyTorchBackend() - backend.np.manual_seed(42) - nepochs = 400 - optimizer = backend.np.optim.Adam - target_state = backend.np.rand(4, dtype=backend.np.complex128) - target_state = target_state / backend.np.norm(target_state) - params = backend.np.rand(4, dtype=backend.np.float64, requires_grad=True) - circuit = Circuit(2) - circuit.add(gates.RX(0, params[0])) - circuit.add(gates.RY(1, params[1])) - circuit.add(gates.U2(1, params[2], params[3])) - - initial_params = params.clone() - initial_loss = infidelity( - target_state, backend.execute_circuit(circuit).state(), backend=backend - ) - - optimizer = optimizer([params], lr=0.01) - for _ in range(nepochs): - optimizer.zero_grad() - circuit.set_parameters(params) - final_state = backend.execute_circuit(circuit).state() - loss = infidelity(target_state, final_state, backend=backend) - loss.backward() - grad = params.grad.clone().norm() - optimizer.step() - - assert initial_loss > loss - assert initial_params[0] != params[0] - assert grad.item() < 10e-3 - - -@pytest.mark.skipif( - sys.platform != "linux", reason="Tensorflow available only when testing on linux." -) -def test_torch_tensorflow_gradients(): - - backend = PyTorchBackend() - tf_backend = construct_backend(backend="qiboml", platform="tensorflow") - - target_state = backend.np.tensor([0.0, 1.0], dtype=backend.np.complex128) - param = backend.np.tensor([0.1], dtype=backend.np.float64, requires_grad=True) - circuit = Circuit(1) - circuit.add(gates.RX(0, param[0])) - - optimizer = backend.np.optim.SGD - optimizer = optimizer([param], lr=1) - circuit.set_parameters(param) - final_state = backend.execute_circuit(circuit).state() - loss = infidelity(target_state, final_state, backend=backend) - loss.backward() - torch_param_grad = param.grad.clone().item() - optimizer.step() - torch_param = param.clone().item() - - target_state = tf_backend.tf.constant([0.0, 1.0], dtype=tf_backend.tf.complex128) - param = tf_backend.tf.Variable([0.1], dtype=tf_backend.tf.float64) - circuit = Circuit(1) - circuit.add(gates.RX(0, param[0])) - - optimizer = tf_backend.tf.optimizers.SGD(learning_rate=1.0) - - with tf_backend.tf.GradientTape() as tape: - circuit.set_parameters(param) - final_state = tf_backend.execute_circuit(circuit).state() - loss = infidelity(target_state, final_state, backend=tf_backend) - - grads = tape.gradient(loss, [param]) - tf_param_grad = grads[0].numpy()[0] - optimizer.apply_gradients(zip(grads, [param])) - tf_param = param.numpy()[0] - - assert np.allclose(torch_param_grad, tf_param_grad, atol=1e-7, rtol=1e-7) - assert np.allclose(torch_param, tf_param, atol=1e-7, rtol=1e-7) diff --git a/tests/test_hamiltonians.py b/tests/test_hamiltonians.py index 1c41f3fccb..8038f50a32 100644 --- a/tests/test_hamiltonians.py +++ b/tests/test_hamiltonians.py @@ -69,10 +69,10 @@ def transformation_d(a, b, use_eye=False): H2 = hamiltonians.XXZ(nqubits=2, delta=1, backend=backend) mH1, mH2 = backend.to_numpy(H1.matrix), backend.to_numpy(H2.matrix) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) mH1 = random_sparse_matrix(backend, 64, sparse_type=sparse_type) mH2 = random_sparse_matrix(backend, 64, sparse_type=sparse_type) @@ -99,10 +99,10 @@ def test_hamiltonian_addition(backend, sparse_type): H1 = hamiltonians.Y(nqubits=3, backend=backend) H2 = hamiltonians.TFIM(nqubits=3, h=1.0, backend=backend) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) H1 = hamiltonians.Hamiltonian( 6, random_sparse_matrix(backend, 64, sparse_type=sparse_type), @@ -147,10 +147,10 @@ def test_hamiltonian_operation_errors(backend): @pytest.mark.parametrize("sparse_type", [None, "coo", "csr", "csc", "dia"]) def test_hamiltonian_matmul(backend, sparse_type): """Test matrix multiplication between Hamiltonians.""" - if backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) if sparse_type is None: nqubits = 3 H1 = hamiltonians.TFIM(nqubits, h=1.0, backend=backend) @@ -191,10 +191,10 @@ def test_hamiltonian_matmul_states(backend, sparse_type): nqubits = 3 H = hamiltonians.TFIM(nqubits, h=1.0, backend=backend) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) nqubits = 3 nstates = 2**nqubits matrix = random_sparse_matrix(backend, nstates, sparse_type) @@ -228,10 +228,10 @@ def test_hamiltonian_expectation(backend, dense, density_matrix, sparse_type): if sparse_type is None: h = hamiltonians.XXZ(nqubits=3, delta=0.5, dense=dense, backend=backend) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) h = hamiltonians.Hamiltonian( 6, random_sparse_matrix(backend, 64, sparse_type), backend=backend ) @@ -323,10 +323,10 @@ def test_hamiltonian_eigenvalues(backend, dtype, sparse_type, dense): if sparse_type is None: H1 = hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense, backend=backend) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) from scipy import sparse H1 = hamiltonians.XXZ(nqubits=5, delta=0.5, backend=backend) @@ -400,10 +400,10 @@ def test_hamiltonian_ground_state(backend, sparse_type, dense): if sparse_type is None: H = hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense, backend=backend) else: - if backend.platform == "tensorflow": - pytest.skip("Tensorflow does not support operations with sparse matrices.") - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") + if backend.platform in ["tensorflow", "pytorch"]: + pytest.skip( + "Tensorflow and Pytorch do not support operations with sparse matrices." + ) from scipy import sparse H = hamiltonians.XXZ(nqubits=5, delta=0.5, backend=backend) @@ -432,12 +432,10 @@ def construct_hamiltonian(): if sparse_type is None: return hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense, backend=backend) else: - if backend.platform == "tensorflow": + if backend.platform in ["tensorflow", "pytorch"]: pytest.skip( - "Tensorflow does not support operations with sparse matrices." + "Tensorflow and Pytorch do not support operations with sparse matrices." ) - elif backend.name == "pytorch": - pytest.skip("Pytorch does not support operations with sparse matrices.") from scipy import sparse ham = hamiltonians.XXZ(nqubits=5, delta=0.5, backend=backend) diff --git a/tests/test_measurements.py b/tests/test_measurements.py index 56a1e79b2a..d781760892 100644 --- a/tests/test_measurements.py +++ b/tests/test_measurements.py @@ -434,7 +434,7 @@ def test_measurement_basis(backend, nqubits, outcome): def test_measurement_basis_list(backend): - c = Circuit(4) + c = Circuit(4, wire_names=["q0", "q1", "q2", "q3"]) c.add(gates.H(0)) c.add(gates.X(2)) c.add(gates.H(2)) diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py index c6a72a39ff..b2b2ca904d 100644 --- a/tests/test_models_circuit.py +++ b/tests/test_models_circuit.py @@ -6,6 +6,7 @@ import pytest from qibo import Circuit, gates +from qibo.models.circuit import _resolve_qubits from qibo.models.utils import initialize @@ -48,6 +49,44 @@ def test_circuit_init(): assert c.nqubits == 2 +def test_resolve_qubits(): + nqubits, wire_names = _resolve_qubits(3, None) + assert nqubits == 3 and wire_names is None + nqubits, wire_names = _resolve_qubits(3, ["a", "b", "c"]) + assert nqubits == 3 and wire_names == ["a", "b", "c"] + nqubits, wire_names = _resolve_qubits(["a", "b", "c"], None) + assert nqubits == 3 and wire_names == ["a", "b", "c"] + nqubits, wire_names = _resolve_qubits(None, ["x", "y", "z"]) + assert nqubits == 3 and wire_names == ["x", "y", "z"] + + with pytest.raises(ValueError): + _resolve_qubits(None, None) + with pytest.raises(ValueError): + _resolve_qubits(3, ["a", "b"]) + with pytest.raises(ValueError): + _resolve_qubits(["a", "b", "c"], ["x", "y"]) + + +def test_circuit_init_resolve_qubits(): + a = Circuit(3) + assert a.nqubits == 3 and a.wire_names == [0, 1, 2] + b = Circuit(3, wire_names=["a", "b", "c"]) + assert b.nqubits == 3 and b.wire_names == ["a", "b", "c"] + c = Circuit(["a", "b", "c"]) + assert c.nqubits == 3 and c.wire_names == ["a", "b", "c"] + d = Circuit(wire_names=["x", "y", "z"]) + assert d.nqubits == 3 and d.wire_names == ["x", "y", "z"] + + +def test_circuit_init_resolve_qubits_err(): + with pytest.raises(ValueError): + a = Circuit() + with pytest.raises(ValueError): + b = Circuit(3, wire_names=["a", "b"]) + with pytest.raises(ValueError): + c = Circuit(["a", "b", "c"], wire_names=["x", "y"]) + + def test_eigenstate(backend): nqubits = 3 c = Circuit(nqubits) @@ -625,7 +664,7 @@ def test_circuit_draw(): "q3: ─────────o──|───────o──|────o──|──H─U1───|─x─\n" "q4: ────────────o──────────o───────o────o──H─x───" ) - circuit = Circuit(5) + circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): @@ -636,17 +675,19 @@ def test_circuit_draw(): assert str(circuit) == ref -def test_circuit_wire_names_errors(): +def test_circuit_wire_names(): + circuit = Circuit(5) + assert circuit.wire_names == [0, 1, 2, 3, 4] + assert circuit._wire_names == None + + circuit.wire_names = ["a", "b", "c", "d", "e"] + assert circuit.wire_names == ["a", "b", "c", "d", "e"] + assert circuit._wire_names == ["a", "b", "c", "d", "e"] + with pytest.raises(TypeError): - circuit = Circuit(5, wire_names=1) - with pytest.raises(ValueError): - circuit = Circuit(5, wire_names=["a", "b", "c"]) + circuit.wire_names = 5 with pytest.raises(ValueError): - circuit = Circuit(2, wire_names={"q0": "1", "q1": "2", "q2": "3"}) - with pytest.raises(ValueError): - circuit = Circuit(2, wire_names={"q0": "1", "q1": 2}) - with pytest.raises(ValueError): - circuit = Circuit(2, wire_names=["1", 2]) + circuit.wire_names = ["a", "b", "c", "d"] def test_circuit_draw_wire_names(): @@ -669,6 +710,24 @@ def test_circuit_draw_wire_names(): assert str(circuit) == ref +def test_circuit_draw_wire_names_int(): + ref = ( + "2133: ─H─U1─U1─U1─U1───────────────────────────x───\n" + + "8 : ───o──|──|──|──H─U1─U1─U1────────────────|─x─\n" + + "2319: ──────o──|──|────o──|──|──H─U1─U1────────|─|─\n" + + "0 : ─────────o──|───────o──|────o──|──H─U1───|─x─\n" + + "1908: ────────────o──────────o───────o────o──H─x───" + ) + circuit = Circuit(5, wire_names=[2133, 8, 2319, 0, 1908]) + for i1 in range(5): + circuit.add(gates.H(i1)) + for i2 in range(i1 + 1, 5): + circuit.add(gates.CU1(i2, i1, theta=0)) + circuit.add(gates.SWAP(0, 4)) + circuit.add(gates.SWAP(1, 3)) + assert str(circuit) == ref + + def test_circuit_draw_line_wrap(capsys): """Test circuit text draw with line wrap.""" ref_line_wrap_50 = ( @@ -705,7 +764,7 @@ def test_circuit_draw_line_wrap(capsys): + "q4: ... ───" ) - circuit = Circuit(5) + circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): @@ -766,7 +825,7 @@ def test_circuit_draw_line_wrap_names(capsys): + "q4: ... ───" ) - circuit = Circuit(5, wire_names={"q1": "a"}) + circuit = Circuit(5, wire_names=["q0", "a", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): @@ -795,7 +854,7 @@ def test_circuit_draw_line_wrap_names(capsys): def test_circuit_draw_channels(capsys, legend): """Check that channels are drawn correctly.""" - circuit = Circuit(2, density_matrix=True) + circuit = Circuit(2, density_matrix=True, wire_names=["q0", "q1"]) circuit.add(gates.H(0)) circuit.add(gates.PauliNoiseChannel(0, list(zip(["X", "Z"], [0.1, 0.2])))) circuit.add(gates.H(1)) @@ -832,7 +891,7 @@ def test_circuit_draw_callbacks(capsys, legend): from qibo.callbacks import EntanglementEntropy entropy = EntanglementEntropy([0]) - c = Circuit(2) + c = Circuit(2, wire_names=["q0", "q1"]) c.add(gates.CallbackGate(entropy)) c.add(gates.H(0)) c.add(gates.CallbackGate(entropy)) @@ -863,7 +922,7 @@ def test_circuit_draw_labels(): + "q3: ─────────o──|───────o──|────o──|──H─G4───|─x─\n" + "q4: ────────────o──────────o───────o────o──H─x───" ) - circuit = Circuit(5) + circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): @@ -884,7 +943,7 @@ def test_circuit_draw_names(capsys): + "q3: ─────────o──|───────o──|────o──|──H─cx───|─x─\n" + "q4: ────────────o──────────o───────o────o──H─x───" ) - circuit = Circuit(5) + circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): diff --git a/tests/test_models_circuit_fuse.py b/tests/test_models_circuit_fuse.py index 22e9c74f0e..ae90d42b02 100644 --- a/tests/test_models_circuit_fuse.py +++ b/tests/test_models_circuit_fuse.py @@ -228,7 +228,7 @@ def test_fused_gate_draw(): "q3: ───────────────o──|───────────o──|──[─o──H─]─|──[─U1───]─|─x─\n" "q4: ──────────────────o──────────────o───────────o──[─o──H─]─x───" ) - circuit = Circuit(5) + circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"]) for i1 in range(5): circuit.add(gates.H(i1)) for i2 in range(i1 + 1, 5): diff --git a/tests/test_models_variational.py b/tests/test_models_variational.py index 1c49f4bacf..08031b853f 100644 --- a/tests/test_models_variational.py +++ b/tests/test_models_variational.py @@ -109,13 +109,11 @@ def myloss(parameters, circuit, target): def test_vqe(backend, method, options, compile, filename): """Performs a VQE circuit minimization test.""" if (method == "sgd" or compile) and ( - (backend.name != "pytorch") or (backend.platform != "tensorflow") + backend.platform not in ["tensorflow", "pytorch"] ): pytest.skip("Skipping SGD test for unsupported backend.") - if method != "sgd" and backend.name == "pytorch": - pytest.skip("Skipping scipy optimizers for pytorch.") - if method != "sgd" and backend.platform == "tensorflow": - pytest.skip("Skipping scipy optimizers for tensorflow.") + if method != "sgd" and (backend.platform in ["tensorflow", "pytorch"]): + pytest.skip("Skipping scipy optimizers for pytorch and tensorflow.") n_threads = backend.nthreads backend.set_threads(1) nqubits = 3 @@ -138,7 +136,7 @@ def test_vqe(backend, method, options, compile, filename): initial_parameters = backend.cast( np.random.uniform(0, 2 * np.pi, 2 * nqubits * layers + nqubits), dtype="float64" ) - if backend.name == "pytorch": + if backend.platform == "pytorch": initial_parameters.requires_grad = True v = VQE(circuit, hamiltonian) @@ -281,14 +279,14 @@ def test_qaoa_errors(backend): @pytest.mark.parametrize(test_names, test_values) def test_qaoa_optimization(backend, method, options, dense, filename): - if (method == "sgd") and (backend.name not in ["tensorflow", "pytorch"]): + if (method == "sgd") and (backend.platform not in ["tensorflow", "pytorch"]): pytest.skip("Skipping SGD test for unsupported backend.") - if method != "sgd" and backend.name in ("tensorflow", "pytorch"): + if method != "sgd" and backend.platform in ("tensorflow", "pytorch"): pytest.skip("Skipping scipy optimizers for tensorflow and pytorch.") h = XXZ(3, dense=dense, backend=backend) qaoa = QAOA(h) initial_p = backend.cast([0.05, 0.06, 0.07, 0.08], dtype="float64") - if backend.name == "pytorch": + if backend.platform == "pytorch": initial_p.requires_grad = True best, params, _ = qaoa.minimize(initial_p, method=method, options=options) if filename is not None: diff --git a/tests/test_quantum_info_metrics.py b/tests/test_quantum_info_metrics.py index fa9595650c..2819d9242a 100644 --- a/tests/test_quantum_info_metrics.py +++ b/tests/test_quantum_info_metrics.py @@ -394,7 +394,7 @@ def test_frame_potential(backend, nqubits, power_t, samples): @pytest.mark.parametrize("return_complex", [False, True]) @pytest.mark.parametrize("nqubits", [4, 8]) def test_qfim(backend, nqubits, return_complex, params_flag): - if backend.name == "pytorch" or backend.platform == "tensorflow": + if backend.platform in ["tensorflow", "pytorch"]: # QFIM from https://arxiv.org/abs/2405.20408 is known analytically data = np.random.rand(nqubits) data = backend.cast(data, dtype=data.dtype) diff --git a/tests/test_quantum_info_operations.py b/tests/test_quantum_info_operations.py index ec1075e73d..a8b119637c 100644 --- a/tests/test_quantum_info_operations.py +++ b/tests/test_quantum_info_operations.py @@ -260,8 +260,8 @@ def test_singular_value_decomposition(backend): S_sorted = backend.sort(S) coeffs_sorted = backend.sort(coeffs) - if backend.name == "pytorch": - S_sorted, coeffs_sorted = S_sorted[0], coeffs_sorted[0] + # if backend.platform == "pytorch": + # S_sorted, coeffs_sorted = S_sorted[0], coeffs_sorted[0] backend.assert_allclose(S_sorted, coeffs_sorted) diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index b362f6fef3..a1eb888257 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -173,7 +173,8 @@ def test_random_unitary(backend, measure): matrix = random_unitary(dims, measure=measure, backend=backend) matrix_dagger = backend.conj(matrix).T matrix_inv = ( - backend.inverse(matrix) if backend.name == "pytorch" else np.linalg.inv(matrix) + backend.inverse(matrix) + # backend.inverse(matrix) if backend.platform == "pytorch" else np.linalg.inv(matrix) ) norm = float( backend.calculate_norm_density_matrix(matrix_inv - matrix_dagger, order=2) diff --git a/tests/test_tomography_gate_set_tomography.py b/tests/test_tomography_gate_set_tomography.py index d6d2ffd2df..be0c4d4fc6 100644 --- a/tests/test_tomography_gate_set_tomography.py +++ b/tests/test_tomography_gate_set_tomography.py @@ -261,7 +261,7 @@ def test_GST_non_invertible_matrix(): matrices = GST(gate_set=[], pauli_liouville=True, gauge_matrix=T) -def test_GST_with_transpiler(backend): +def test_GST_with_transpiler(backend, star_connectivity): import networkx as nx target_gates = [gates.SX(0), gates.Z(0), gates.CNOT(0, 1)] @@ -276,18 +276,15 @@ def test_GST_with_transpiler(backend): transpiler=None, ) # define transpiler - connectivity = nx.Graph() - # star connectivity - connectivity.add_edges_from([(0, 2), (1, 2), (2, 3), (2, 4)]) + connectivity = star_connectivity() transpiler = Passes( connectivity=connectivity, passes=[ - Preprocessing(connectivity), - Random(connectivity), - Sabre(connectivity), + Preprocessing(), + Random(), + Sabre(), Unroller(NativeGates.default(), backend=backend), ], - int_qubit_names=True, ) # transpiled GST T_empty_1q, T_empty_2q, *T_approx_gates = GST( diff --git a/tests/test_transpiler_asserts.py b/tests/test_transpiler_asserts.py new file mode 100644 index 0000000000..8b0b268003 --- /dev/null +++ b/tests/test_transpiler_asserts.py @@ -0,0 +1,151 @@ +import pytest + +from qibo import gates +from qibo.models.circuit import Circuit +from qibo.transpiler._exceptions import ( + ConnectivityError, + DecompositionError, + PlacementError, + TranspilerPipelineError, +) +from qibo.transpiler.asserts import ( + assert_circuit_equivalence, + assert_connectivity, + assert_decomposition, + assert_placement, +) +from qibo.transpiler.pipeline import restrict_connectivity_qubits +from qibo.transpiler.unroller import NativeGates + + +def test_assert_circuit_equivalence_equal(): + circ1 = Circuit(2) + circ2 = Circuit(2) + circ1.add(gates.X(0)) + circ1.add(gates.CZ(0, 1)) + circ2.add(gates.X(0)) + circ2.add(gates.CZ(0, 1)) + final_map = {0: 0, 1: 1} + assert_circuit_equivalence(circ1, circ2, final_map=final_map) + + +def test_assert_circuit_equivalence_swap(): + circ1 = Circuit(2) + circ2 = Circuit(2) + circ1.add(gates.X(0)) + circ2.add(gates.SWAP(0, 1)) + circ2.add(gates.X(1)) + final_map = {0: 1, 1: 0} + assert_circuit_equivalence(circ1, circ2, final_map=final_map) + + +def test_assert_circuit_equivalence_false(): + circ1 = Circuit(2) + circ2 = Circuit(2) + circ1.add(gates.X(0)) + circ2.add(gates.SWAP(0, 1)) + circ2.add(gates.X(1)) + final_map = {0: 0, 1: 1} + with pytest.raises(TranspilerPipelineError): + assert_circuit_equivalence(circ1, circ2, final_map=final_map) + + +def test_assert_placement_true(star_connectivity): + circuit = Circuit(5) + assert_placement(circuit, connectivity=star_connectivity()) + + +@pytest.mark.parametrize( + "qubits, names", [(1, ["A", "B", "C", "D", "E"]), (10, ["A", "B", "C", "D", "E"])] +) +def test_assert_placement_false(qubits, names, star_connectivity): + connectivity = star_connectivity() + circuit = Circuit(5) + circuit.nqubits = qubits + circuit._wire_names = names + with pytest.raises(PlacementError): + assert_placement(circuit, connectivity) + + connectivity = None + with pytest.raises(ValueError): + assert_placement(circuit, connectivity) + + +@pytest.mark.parametrize("qubits", [10, 1]) +def test_assert_placement_error(qubits, star_connectivity): + connectivity = star_connectivity() + circuit = Circuit(qubits) + with pytest.raises(PlacementError): + assert_placement(circuit, connectivity) + + +@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]]) +def test_assert_placement_restricted(names, star_connectivity): + connectivity = star_connectivity(names) + on_qubit = [names[0], names[2]] + circuit = Circuit(2, wire_names=on_qubit) + restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit) + assert_placement(circuit, restricted_connectivity) + + +@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]]) +def test_assert_placement_restricted_error(names, star_connectivity): + connectivity = star_connectivity(names) + on_qubit = [names[0], names[2]] + circuit = Circuit(2, wire_names=[names[3], names[4]]) + restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit) + with pytest.raises(PlacementError): + assert_placement(circuit, restricted_connectivity) + + +def test_assert_decomposition(): + circuit = Circuit(2) + circuit.add(gates.CZ(0, 1)) + circuit.add(gates.Z(0)) + circuit.add(gates.M(1)) + assert_decomposition(circuit, native_gates=NativeGates.default()) + + +def test_assert_decomposition_fail_1q(): + circuit = Circuit(1) + circuit.add(gates.X(0)) + with pytest.raises(DecompositionError): + assert_decomposition(circuit, native_gates=NativeGates.default()) + + +@pytest.mark.parametrize("gate", [gates.CNOT(0, 1), gates.iSWAP(0, 1)]) +def test_assert_decomposition_fail_2q(gate): + circuit = Circuit(2) + circuit.add(gate) + with pytest.raises(DecompositionError): + assert_decomposition(circuit, native_gates=NativeGates.default()) + + +def test_assert_decomposition_fail_3q(): + circuit = Circuit(3) + circuit.add(gates.TOFFOLI(0, 1, 2)) + with pytest.raises(DecompositionError): + assert_decomposition(circuit, native_gates=NativeGates.default()) + + +def test_assert_connectivity(star_connectivity): + names = ["A", "B", "C", "D", "E"] + circuit = Circuit(5, wire_names=names) + circuit.add(gates.CZ(0, 2)) + circuit.add(gates.CZ(1, 2)) + circuit.add(gates.CZ(2, 1)) + assert_connectivity(star_connectivity(names), circuit) + + +def test_assert_connectivity_false(star_connectivity): + circuit = Circuit(5) + circuit.add(gates.CZ(0, 1)) + with pytest.raises(ConnectivityError): + assert_connectivity(star_connectivity(), circuit) + + +def test_assert_connectivity_3q(star_connectivity): + circuit = Circuit(5) + circuit.add(gates.TOFFOLI(0, 1, 2)) + with pytest.raises(ConnectivityError): + assert_connectivity(star_connectivity(), circuit) diff --git a/tests/test_transpiler_decompositions.py b/tests/test_transpiler_decompositions.py index 9fcb32daa4..e906ea953f 100644 --- a/tests/test_transpiler_decompositions.py +++ b/tests/test_transpiler_decompositions.py @@ -5,7 +5,8 @@ from qibo.backends import NumpyBackend from qibo.models import Circuit from qibo.quantum_info.random_ensembles import random_unitary -from qibo.transpiler.unroller import NativeGates, assert_decomposition, translate_gate +from qibo.transpiler.asserts import assert_decomposition +from qibo.transpiler.unroller import NativeGates, translate_gate default_natives = NativeGates.Z | NativeGates.RZ | NativeGates.M | NativeGates.I diff --git a/tests/test_transpiler_optimizer.py b/tests/test_transpiler_optimizer.py index 171c7516d4..500f507178 100644 --- a/tests/test_transpiler_optimizer.py +++ b/tests/test_transpiler_optimizer.py @@ -6,22 +6,18 @@ from qibo.transpiler.optimizer import Preprocessing, Rearrange -def star_connectivity(): - chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(i, 2) for i in range(5) if i != 2] - chip.add_edges_from(graph_list) - return chip - - -def test_preprocessing_error(): +def test_preprocessing_error(star_connectivity): circ = Circuit(7) preprocesser = Preprocessing(connectivity=star_connectivity()) with pytest.raises(ValueError): new_circuit = preprocesser(circuit=circ) + circ = Circuit(5, wire_names=[0, 1, 2, "q3", "q4"]) + with pytest.raises(ValueError): + new_circuit = preprocesser(circuit=circ) + -def test_preprocessing_same(): +def test_preprocessing_same(star_connectivity): circ = Circuit(5) circ.add(gates.CNOT(0, 1)) preprocesser = Preprocessing(connectivity=star_connectivity()) @@ -29,7 +25,7 @@ def test_preprocessing_same(): assert new_circuit.ngates == 1 -def test_preprocessing_add(): +def test_preprocessing_add(star_connectivity): circ = Circuit(3) circ.add(gates.CNOT(0, 1)) preprocesser = Preprocessing(connectivity=star_connectivity()) diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py index bfa13f9e4d..a8e43bc6aa 100644 --- a/tests/test_transpiler_pipeline.py +++ b/tests/test_transpiler_pipeline.py @@ -5,23 +5,17 @@ from qibo import gates from qibo.models import Circuit from qibo.transpiler._exceptions import ConnectivityError, TranspilerPipelineError +from qibo.transpiler.asserts import assert_circuit_equivalence, assert_transpiling from qibo.transpiler.optimizer import Preprocessing -from qibo.transpiler.pipeline import ( - Passes, - assert_circuit_equivalence, - assert_transpiling, - restrict_connectivity_qubits, -) -from qibo.transpiler.placer import Random, ReverseTraversal, Trivial +from qibo.transpiler.pipeline import Passes, restrict_connectivity_qubits +from qibo.transpiler.placer import Random, ReverseTraversal from qibo.transpiler.router import Sabre, ShortestPaths from qibo.transpiler.unroller import NativeGates, Unroller -def generate_random_circuit(nqubits, ngates, seed=None): - """Generate random circuits one-qubit rotations and CZ gates.""" - if seed is not None: # pragma: no cover - np.random.seed(seed) - +def generate_random_circuit(nqubits, ngates, names=None, seed=42): + """Generate a random circuit with RX and CZ gates.""" + np.random.seed(seed) one_qubit_gates = [gates.RX, gates.RY, gates.RZ, gates.X, gates.Y, gates.Z, gates.H] two_qubit_gates = [ gates.CNOT, @@ -34,7 +28,7 @@ def generate_random_circuit(nqubits, ngates, seed=None): ] n1, n2 = len(one_qubit_gates), len(two_qubit_gates) n = n1 + n2 if nqubits > 1 else n1 - circuit = Circuit(nqubits) + circuit = Circuit(nqubits, wire_names=names) for _ in range(ngates): igate = int(np.random.randint(0, n)) if igate >= n1: @@ -47,120 +41,58 @@ def generate_random_circuit(nqubits, ngates, seed=None): gate = one_qubit_gates[igate] if issubclass(gate, gates.ParametrizedGate): theta = 2 * np.pi * np.random.random() - circuit.add(gate(*q, theta=theta)) + circuit.add(gate(*q, theta=theta, trainable=False)) else: circuit.add(gate(*q)) return circuit -def star_connectivity(): - chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(i, 2) for i in range(5) if i != 2] - chip.add_edges_from(graph_list) - return chip - - -def test_restrict_qubits_error_no_subset(): +def test_restrict_qubits_error_no_subset(star_connectivity): with pytest.raises(ConnectivityError) as excinfo: - restrict_connectivity_qubits(star_connectivity(), [1, 2, 6]) + restrict_connectivity_qubits(star_connectivity(), [0, 1, 5]) assert "Some qubits are not in the original connectivity." in str(excinfo.value) -def test_restrict_qubits_error_not_connected(): +def test_restrict_qubits_error_not_connected(star_connectivity): with pytest.raises(ConnectivityError) as excinfo: - restrict_connectivity_qubits(star_connectivity(), [1, 3]) + restrict_connectivity_qubits(star_connectivity(), [0, 1]) assert "New connectivity graph is not connected." in str(excinfo.value) -def test_restrict_qubits(): - new_connectivity = restrict_connectivity_qubits(star_connectivity(), [1, 2, 3]) - assert list(new_connectivity.nodes) == [1, 2, 3] - assert list(new_connectivity.edges) == [(1, 2), (2, 3)] - - -@pytest.mark.parametrize("ngates", [5, 10, 50]) -def test_pipeline_default(ngates): - circ = generate_random_circuit(nqubits=5, ngates=ngates) - default_transpiler = Passes(passes=None, connectivity=star_connectivity()) - transpiled_circ, final_layout = default_transpiler(circ) - initial_layout = default_transpiler.get_initial_layout() - assert_transpiling( - original_circuit=circ, - transpiled_circuit=transpiled_circ, - connectivity=star_connectivity(), - initial_layout=initial_layout, - final_layout=final_layout, - native_gates=NativeGates.default(), - check_circuit_equivalence=False, +def test_restrict_qubits(star_connectivity): + new_connectivity = restrict_connectivity_qubits( + star_connectivity(["A", "B", "C", "D", "E"]), ["A", "B", "C"] ) - - -def test_assert_circuit_equivalence_equal(): - circ1 = Circuit(2) - circ2 = Circuit(2) - circ1.add(gates.X(0)) - circ1.add(gates.CZ(0, 1)) - circ2.add(gates.X(0)) - circ2.add(gates.CZ(0, 1)) - final_map = {"q0": 0, "q1": 1} - assert_circuit_equivalence(circ1, circ2, final_map=final_map) - - -def test_assert_circuit_equivalence_swap(): - circ1 = Circuit(2) - circ2 = Circuit(2) - circ1.add(gates.X(0)) - circ2.add(gates.SWAP(0, 1)) - circ2.add(gates.X(1)) - final_map = {"q0": 1, "q1": 0} - assert_circuit_equivalence(circ1, circ2, final_map=final_map) - - -def test_assert_circuit_equivalence_false(): - circ1 = Circuit(2) - circ2 = Circuit(2) - circ1.add(gates.X(0)) - circ2.add(gates.SWAP(0, 1)) - circ2.add(gates.X(1)) - final_map = {"q0": 0, "q1": 1} - with pytest.raises(TranspilerPipelineError): - assert_circuit_equivalence(circ1, circ2, final_map=final_map) - - -def test_int_qubit_names(): - circ = Circuit(2) - final_map = {i: i for i in range(5)} - default_transpiler = Passes( - passes=None, connectivity=star_connectivity(), int_qubit_names=True - ) - _, final_layout = default_transpiler(circ) - assert final_map == final_layout + assert list(new_connectivity.nodes) == ["A", "B", "C"] + assert list(new_connectivity.edges) == [("A", "C"), ("B", "C")] def test_assert_circuit_equivalence_wrong_nqubits(): circ1 = Circuit(1) circ2 = Circuit(2) - final_map = {"q0": 0, "q1": 1} + final_map = {0: 0, 1: 1} with pytest.raises(ValueError): assert_circuit_equivalence(circ1, circ2, final_map=final_map) -def test_error_connectivity(): - with pytest.raises(TranspilerPipelineError): - default_transpiler = Passes(passes=None, connectivity=None) - - @pytest.mark.parametrize("qubits", [3, 5]) -def test_is_satisfied(qubits): - default_transpiler = Passes(passes=None, connectivity=star_connectivity()) - circuit = Circuit(qubits) +def test_is_satisfied(qubits, star_connectivity): + default_transpiler = Passes( + passes=None, connectivity=star_connectivity(), on_qubits=list(range(qubits)) + ) + circuit = Circuit(qubits, wire_names=list(range(qubits))) circuit.add(gates.CZ(0, 2)) circuit.add(gates.Z(0)) assert default_transpiler.is_satisfied(circuit) -def test_is_satisfied_false_decomposition(): +def test_is_satisfied_false_placement(star_connectivity): + default_transpiler = Passes(passes=None, connectivity=star_connectivity()) + circuit = Circuit(5, wire_names=["A", "B", "C", "D", "E"]) + assert not default_transpiler.is_satisfied(circuit) + + +def test_is_satisfied_false_decomposition(star_connectivity): default_transpiler = Passes(passes=None, connectivity=star_connectivity()) circuit = Circuit(5) circuit.add(gates.CZ(0, 2)) @@ -168,7 +100,7 @@ def test_is_satisfied_false_decomposition(): assert not default_transpiler.is_satisfied(circuit) -def test_is_satisfied_false_connectivity(): +def test_is_satisfied_false_connectivity(star_connectivity): default_transpiler = Passes(passes=None, connectivity=star_connectivity()) circuit = Circuit(5) circuit.add(gates.CZ(0, 1)) @@ -176,104 +108,76 @@ def test_is_satisfied_false_connectivity(): assert not default_transpiler.is_satisfied(circuit) -@pytest.mark.parametrize("qubits", [2, 5]) -@pytest.mark.parametrize("gates", [5, 20]) -@pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal]) -@pytest.mark.parametrize("routing", [ShortestPaths, Sabre]) -def test_custom_passes(placer, routing, gates, qubits): - circ = generate_random_circuit(nqubits=qubits, ngates=gates) +@pytest.mark.parametrize("nqubits", [2, 3, 5]) +@pytest.mark.parametrize("ngates", [5, 20]) +@pytest.mark.parametrize("placer", [Random, ReverseTraversal]) +@pytest.mark.parametrize("router", [ShortestPaths, Sabre]) +def test_custom_passes(placer, router, ngates, nqubits, star_connectivity): + connectivity = star_connectivity() + circ = generate_random_circuit(nqubits=nqubits, ngates=ngates) custom_passes = [] - custom_passes.append(Preprocessing(connectivity=star_connectivity())) + custom_passes.append(Preprocessing()) if placer == ReverseTraversal: custom_passes.append( placer( - connectivity=star_connectivity(), - routing_algorithm=routing(connectivity=star_connectivity()), + routing_algorithm=router(), ) ) else: - custom_passes.append(placer(connectivity=star_connectivity())) - custom_passes.append(routing(connectivity=star_connectivity())) + custom_passes.append(placer()) + custom_passes.append(router()) custom_passes.append(Unroller(native_gates=NativeGates.default())) custom_pipeline = Passes( - custom_passes, - connectivity=star_connectivity(), + passes=custom_passes, + connectivity=connectivity, native_gates=NativeGates.default(), ) transpiled_circ, final_layout = custom_pipeline(circ) - initial_layout = custom_pipeline.get_initial_layout() assert_transpiling( original_circuit=circ, transpiled_circuit=transpiled_circ, - connectivity=star_connectivity(), - initial_layout=initial_layout, + connectivity=connectivity, final_layout=final_layout, native_gates=NativeGates.default(), ) -@pytest.mark.parametrize("gates", [5, 20]) -@pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal]) +@pytest.mark.parametrize("ngates", [5, 20]) +@pytest.mark.parametrize("placer", [Random, ReverseTraversal]) @pytest.mark.parametrize("routing", [ShortestPaths, Sabre]) -def test_custom_passes_restrict(gates, placer, routing): - circ = generate_random_circuit(nqubits=3, ngates=gates) +@pytest.mark.parametrize("restrict_names", [[1, 2, 3], [0, 2, 4], [4, 2, 3]]) +def test_custom_passes_restrict( + ngates, placer, routing, restrict_names, star_connectivity +): + connectivity = star_connectivity() + circ = generate_random_circuit(nqubits=3, ngates=ngates, names=restrict_names) custom_passes = [] - custom_passes.append(Preprocessing(connectivity=star_connectivity())) + custom_passes.append(Preprocessing()) if placer == ReverseTraversal: custom_passes.append( placer( - connectivity=star_connectivity(), - routing_algorithm=routing(connectivity=star_connectivity()), + routing_algorithm=routing(), ) ) else: - custom_passes.append(placer(connectivity=star_connectivity())) - custom_passes.append(routing(connectivity=star_connectivity())) + custom_passes.append(placer()) + custom_passes.append(routing()) custom_passes.append(Unroller(native_gates=NativeGates.default())) custom_pipeline = Passes( - custom_passes, - connectivity=star_connectivity(), + passes=custom_passes, + connectivity=connectivity, native_gates=NativeGates.default(), - on_qubits=[1, 2, 3], + on_qubits=restrict_names, ) transpiled_circ, final_layout = custom_pipeline(circ) - initial_layout = custom_pipeline.get_initial_layout() assert_transpiling( original_circuit=circ, transpiled_circuit=transpiled_circ, - connectivity=restrict_connectivity_qubits(star_connectivity(), [1, 2, 3]), - initial_layout=initial_layout, + connectivity=restrict_connectivity_qubits(star_connectivity(), restrict_names), final_layout=final_layout, native_gates=NativeGates.default(), ) - assert transpiled_circ.wire_names == ["q1", "q2", "q3"] - - -def test_custom_passes_multiple_placer(): - custom_passes = [] - custom_passes.append(Random(connectivity=star_connectivity())) - custom_passes.append(Trivial(connectivity=star_connectivity())) - custom_pipeline = Passes( - custom_passes, - connectivity=star_connectivity(), - native_gates=NativeGates.default(), - ) - circ = generate_random_circuit(nqubits=5, ngates=20) - with pytest.raises(TranspilerPipelineError): - transpiled_circ, final_layout = custom_pipeline(circ) - - -def test_custom_passes_no_placer(): - custom_passes = [] - custom_passes.append(ShortestPaths(connectivity=star_connectivity())) - custom_pipeline = Passes( - custom_passes, - connectivity=star_connectivity(), - native_gates=NativeGates.default(), - ) - circ = generate_random_circuit(nqubits=5, ngates=20) - with pytest.raises(TranspilerPipelineError): - transpiled_circ, final_layout = custom_pipeline(circ) + assert set(transpiled_circ.wire_names) == set(restrict_names) def test_custom_passes_wrong_pass(): @@ -281,32 +185,30 @@ def test_custom_passes_wrong_pass(): custom_pipeline = Passes(passes=custom_passes, connectivity=None) circ = generate_random_circuit(nqubits=5, ngates=5) with pytest.raises(TranspilerPipelineError): - transpiled_circ, final_layout = custom_pipeline(circ) + custom_pipeline(circ) -def test_int_qubit_names(): - connectivity = star_connectivity() +def test_int_qubit_names(star_connectivity): + names = [980, 123, 45, 9, 210464] + connectivity = star_connectivity(names) transpiler = Passes( connectivity=connectivity, passes=[ - Preprocessing(connectivity), - Random(connectivity, seed=0), - Sabre(connectivity), + Preprocessing(), + Random(seed=0), + Sabre(), Unroller(NativeGates.default()), ], - int_qubit_names=True, ) - circuit = Circuit(1) + circuit = Circuit(1, wire_names=[123]) circuit.add(gates.I(0)) circuit.add(gates.H(0)) circuit.add(gates.M(0)) transpiled_circuit, final_map = transpiler(circuit) - initial_layout = transpiler.get_initial_layout() assert_transpiling( original_circuit=circuit, transpiled_circuit=transpiled_circuit, connectivity=connectivity, - initial_layout=initial_layout, final_layout=final_map, native_gates=NativeGates.default(), ) diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py index 6855a7eeac..13fef50904 100644 --- a/tests/test_transpiler_placer.py +++ b/tests/test_transpiler_placer.py @@ -3,98 +3,26 @@ from qibo import gates from qibo.models import Circuit -from qibo.transpiler._exceptions import PlacementError +from qibo.transpiler._exceptions import PlacementError, TranspilerPipelineError +from qibo.transpiler.asserts import assert_placement from qibo.transpiler.pipeline import restrict_connectivity_qubits from qibo.transpiler.placer import ( - Custom, Random, ReverseTraversal, StarConnectivityPlacer, Subgraph, - Trivial, _find_gates_qubits_pairs, - assert_mapping_consistency, - assert_placement, ) from qibo.transpiler.router import ShortestPaths -def star_connectivity(): - chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(i, 2) for i in range(5) if i != 2] - chip.add_edges_from(graph_list) - return chip - - -def star_circuit(): - circuit = Circuit(5) +def star_circuit(names=[0, 1, 2, 3, 4]): + circuit = Circuit(5, wire_names=names) for i in range(1, 5): circuit.add(gates.CNOT(i, 0)) return circuit -@pytest.mark.parametrize("connectivity", [star_connectivity(), None]) -@pytest.mark.parametrize( - "layout", - [{"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}], -) -def test_assert_placement_true(layout, connectivity): - circuit = Circuit(5) - assert_placement(circuit, layout, connectivity=connectivity) - - -@pytest.mark.parametrize("qubits", [5, 3]) -@pytest.mark.parametrize( - "layout", [{"q0": 0, "q1": 1, "q2": 2, "q3": 3}, {"q0": 0, "q0": 1, "q2": 2}] -) -def test_assert_placement_false(qubits, layout): - circuit = Circuit(qubits) - with pytest.raises(PlacementError): - assert_placement(circuit, layout) - - -@pytest.mark.parametrize( - "layout", - [{"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}], -) -def test_mapping_consistency(layout): - assert_mapping_consistency(layout) - - -@pytest.mark.parametrize( - "layout", - [ - {"q0": 0, "q1": 0, "q2": 1, "q3": 4, "q4": 3}, - {"q0": 0, "q1": 2, "q0": 1, "q3": 4, "q4": 3}, - ], -) -def test_mapping_consistency_error(layout): - with pytest.raises(PlacementError): - assert_mapping_consistency(layout) - - -def test_mapping_consistency_restricted(): - layout = {"q0": 0, "q2": 1} - connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2]) - assert_mapping_consistency(layout, restricted_connectivity) - - -@pytest.mark.parametrize( - "layout", - [ - {"q0": 0, "q2": 2}, - {"q0": 0, "q1": 1}, - ], -) -def test_mapping_consistency_restricted_error(layout): - connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2]) - with pytest.raises(PlacementError): - assert_mapping_consistency(layout, restricted_connectivity) - - def test_gates_qubits_pairs(): circuit = Circuit(5) circuit.add(gates.CNOT(0, 1)) @@ -111,99 +39,13 @@ def test_gates_qubits_pairs_error(): gates_qubits_pairs = _find_gates_qubits_pairs(circuit) -def test_trivial(): - circuit = Circuit(5) - connectivity = star_connectivity() - placer = Trivial(connectivity=connectivity) - layout = placer(circuit) - assert layout == {"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4} - assert_placement(circuit, layout) - - -def test_trivial_restricted(): - circuit = Circuit(2) - connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2]) - placer = Trivial(connectivity=restricted_connectivity) - layout = placer(circuit) - assert layout == {"q0": 0, "q2": 1} - assert_placement( - circuit=circuit, layout=layout, connectivity=restricted_connectivity - ) - - -def test_trivial_error(): - circuit = Circuit(4) - connectivity = star_connectivity() - placer = Trivial(connectivity=connectivity) - with pytest.raises(PlacementError): - layout = placer(circuit) - - -@pytest.mark.parametrize( - "custom_layout", [[4, 3, 2, 1, 0], {"q0": 4, "q1": 3, "q2": 2, "q3": 1, "q4": 0}] -) -@pytest.mark.parametrize("give_circuit", [True, False]) -@pytest.mark.parametrize("give_connectivity", [True, False]) -def test_custom(custom_layout, give_circuit, give_connectivity): - if give_circuit: - circuit = Circuit(5) - else: - circuit = None - if give_connectivity: - connectivity = star_connectivity() - else: - connectivity = None - placer = Custom(connectivity=connectivity, initial_map=custom_layout) - layout = placer(circuit) - assert layout == {"q0": 4, "q1": 3, "q2": 2, "q3": 1, "q4": 0} - - -@pytest.mark.parametrize("custom_layout", [[1, 0], {"q0": 1, "q2": 0}]) -def test_custom_restricted(custom_layout): - circuit = Circuit(2) - connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2]) - placer = Custom(connectivity=restricted_connectivity, initial_map=custom_layout) - layout = placer(circuit) - assert layout == {"q0": 1, "q2": 0} - assert_placement( - circuit=circuit, layout=layout, connectivity=restricted_connectivity - ) - - -def test_custom_error_circuit(): - circuit = Circuit(3) - custom_layout = [4, 3, 2, 1, 0] - connectivity = star_connectivity() - placer = Custom(connectivity=connectivity, initial_map=custom_layout) - with pytest.raises(PlacementError): - layout = placer(circuit) - - -def test_custom_error_no_circuit(): - connectivity = star_connectivity() - custom_layout = {"q0": 4, "q1": 3, "q2": 2, "q3": 0, "q4": 0} - placer = Custom(connectivity=connectivity, initial_map=custom_layout) - with pytest.raises(PlacementError): - layout = placer() - - -def test_custom_error_type(): - circuit = Circuit(5) - connectivity = star_connectivity() - layout = 1 - placer = Custom(connectivity=connectivity, initial_map=layout) - with pytest.raises(TypeError): - layout = placer(circuit) - - -def test_subgraph_perfect(): +def test_subgraph_perfect(star_connectivity): connectivity = star_connectivity() placer = Subgraph(connectivity=connectivity) - layout = placer(star_circuit()) - assert layout["q2"] == 0 - assert_placement(star_circuit(), layout) + circuit = star_circuit() + placer(circuit) + assert circuit.wire_names[0] == 2 + assert_placement(circuit, connectivity) def imperfect_circuit(): @@ -220,23 +62,24 @@ def imperfect_circuit(): return circuit -def test_subgraph_non_perfect(): +def test_subgraph_non_perfect(star_connectivity): connectivity = star_connectivity() placer = Subgraph(connectivity=connectivity) - layout = placer(imperfect_circuit()) - assert_placement(imperfect_circuit(), layout) + circuit = imperfect_circuit() + placer(circuit) + assert_placement(circuit, connectivity) -def test_subgraph_error(): +def test_subgraph_error(star_connectivity): connectivity = star_connectivity() placer = Subgraph(connectivity=connectivity) circuit = Circuit(5) with pytest.raises(ValueError): - layout = placer(circuit) + placer(circuit) -def test_subgraph_restricted(): - circuit = Circuit(4) +def test_subgraph_restricted(star_connectivity): + circuit = Circuit(4, wire_names=[0, 2, 3, 4]) circuit.add(gates.CNOT(0, 3)) circuit.add(gates.CNOT(0, 1)) circuit.add(gates.CNOT(3, 2)) @@ -246,66 +89,57 @@ def test_subgraph_restricted(): connectivity = star_connectivity() restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4]) placer = Subgraph(connectivity=restricted_connectivity) - layout = placer(circuit) - assert_placement( - circuit=circuit, layout=layout, connectivity=restricted_connectivity - ) + placer(circuit) + assert_placement(circuit, restricted_connectivity) @pytest.mark.parametrize("reps", [1, 10, 100]) -def test_random(reps): - connectivity = star_connectivity() +@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]]) +def test_random(reps, names, star_connectivity): + connectivity = star_connectivity(names) placer = Random(connectivity=connectivity, samples=reps) - layout = placer(star_circuit()) - assert_placement(star_circuit(), layout) - - -def test_random_perfect(): - circ = Circuit(5) - circ.add(gates.CZ(0, 1)) - connectivity = star_connectivity() - placer = Random(connectivity=connectivity, samples=1000) - layout = placer(circ) - assert_placement(star_circuit(), layout) + circuit = star_circuit(names=names) + placer(circuit) + assert_placement(circuit, connectivity) -def test_random_restricted(): - circuit = Circuit(4) +def test_random_restricted(star_connectivity): + names = [0, 1, 2, 3, 4] + circuit = Circuit(4, wire_names=[0, 2, 3, 4]) circuit.add(gates.CNOT(1, 3)) circuit.add(gates.CNOT(2, 1)) circuit.add(gates.CNOT(3, 2)) circuit.add(gates.CNOT(2, 1)) circuit.add(gates.CNOT(1, 2)) circuit.add(gates.CNOT(3, 1)) - connectivity = star_connectivity() + connectivity = star_connectivity(names) restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4]) placer = Random(connectivity=restricted_connectivity, samples=100) - layout = placer(circuit) - assert_placement( - circuit=circuit, layout=layout, connectivity=restricted_connectivity - ) + placer(circuit) + assert_placement(circuit, restricted_connectivity) -@pytest.mark.parametrize("gates", [None, 5, 13]) -def test_reverse_traversal(gates): - circuit = star_circuit() - connectivity = star_connectivity() +@pytest.mark.parametrize("ngates", [None, 5, 13]) +@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]]) +def test_reverse_traversal(ngates, names, star_connectivity): + circuit = star_circuit(names=names) + connectivity = star_connectivity(names=names) routing = ShortestPaths(connectivity=connectivity) - placer = ReverseTraversal(connectivity, routing, depth=gates) - layout = placer(circuit) - assert_placement(circuit, layout) + placer = ReverseTraversal(routing, connectivity, depth=ngates) + placer(circuit) + assert_placement(circuit, connectivity) -def test_reverse_traversal_no_gates(): +def test_reverse_traversal_no_gates(star_connectivity): connectivity = star_connectivity() routing = ShortestPaths(connectivity=connectivity) - placer = ReverseTraversal(connectivity, routing, depth=10) + placer = ReverseTraversal(routing, connectivity, depth=10) circuit = Circuit(5) with pytest.raises(ValueError): - layout = placer(circuit) + placer(circuit) -def test_reverse_traversal_restricted(): +def test_reverse_traversal_restricted(star_connectivity): circuit = Circuit(4) circuit.add(gates.CNOT(1, 3)) circuit.add(gates.CNOT(2, 1)) @@ -314,34 +148,42 @@ def test_reverse_traversal_restricted(): circuit.add(gates.CNOT(1, 2)) circuit.add(gates.CNOT(3, 1)) connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4]) + restrict_names = [0, 2, 3, 4] + restricted_connectivity = restrict_connectivity_qubits(connectivity, restrict_names) + circuit.wire_names = restrict_names routing = ShortestPaths(connectivity=restricted_connectivity) placer = ReverseTraversal( connectivity=restricted_connectivity, routing_algorithm=routing, depth=5 ) - layout = placer(circuit) - assert_placement( - circuit=circuit, layout=layout, connectivity=restricted_connectivity - ) + placer(circuit) + assert_placement(circuit, restricted_connectivity) -def test_star_connectivity_placer(): - circ = Circuit(3) +def test_star_connectivity_placer(star_connectivity): + circ = Circuit(5) circ.add(gates.CZ(0, 1)) circ.add(gates.CZ(1, 2)) circ.add(gates.CZ(0, 2)) - placer = StarConnectivityPlacer(middle_qubit=2) - layout = placer(circ) - assert_placement(circ, layout) - assert layout == {"q0": 0, "q1": 2, "q2": 1} + connectivity = star_connectivity() + placer = StarConnectivityPlacer(connectivity) + placer(circ) + assert_placement(circ, connectivity) + assert circ.wire_names == [0, 2, 1, 3, 4] @pytest.mark.parametrize("first", [True, False]) -def test_star_connectivity_placer_error(first): - circ = Circuit(3) +def test_star_connectivity_placer_error(first, star_connectivity): + circ = Circuit(5) if first: circ.add(gates.CZ(0, 1)) circ.add(gates.TOFFOLI(0, 1, 2)) - placer = StarConnectivityPlacer(middle_qubit=2) + connectivity = star_connectivity() + placer = StarConnectivityPlacer(connectivity) with pytest.raises(PlacementError): - layout = placer(circ) + placer(circ) + + chip = nx.Graph() + chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)]) + with pytest.raises(ValueError): + placer = StarConnectivityPlacer(chip) + placer(circ) diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py index 80b0e72aa3..06899e78d3 100644 --- a/tests/test_transpiler_router.py +++ b/tests/test_transpiler_router.py @@ -9,61 +9,48 @@ from qibo.models import Circuit from qibo.quantum_info.random_ensembles import random_unitary from qibo.transpiler._exceptions import ConnectivityError -from qibo.transpiler.blocks import Block -from qibo.transpiler.optimizer import Preprocessing -from qibo.transpiler.pipeline import ( +from qibo.transpiler.asserts import ( + _transpose_qubits, assert_circuit_equivalence, - restrict_connectivity_qubits, -) -from qibo.transpiler.placer import ( - Custom, - Random, - StarConnectivityPlacer, - Subgraph, - Trivial, + assert_connectivity, assert_placement, ) +from qibo.transpiler.pipeline import restrict_connectivity_qubits +from qibo.transpiler.placer import Random, StarConnectivityPlacer, Subgraph from qibo.transpiler.router import ( CircuitMap, Sabre, ShortestPaths, StarConnectivityRouter, - assert_connectivity, ) -def star_connectivity(middle_qubit=2): - chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(i, middle_qubit) for i in range(5) if i != middle_qubit] - chip.add_edges_from(graph_list) - return chip - - -def grid_connectivity(): +def line_connectivity(n, names=None): + if names is None: + names = list(range(n)) chip = nx.Graph() - chip.add_nodes_from(list(range(5))) - graph_list = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 4)] + chip.add_nodes_from(names) + graph_list = [(names[i], names[i + 1]) for i in range(n - 1)] chip.add_edges_from(graph_list) return chip -def line_connectivity(n): - chip = nx.Graph() - chip.add_nodes_from(list(range(n))) - graph_list = [(i, i + 1) for i in range(n - 1)] - chip.add_edges_from(graph_list) - return chip - - -def generate_random_circuit(nqubits, ngates, seed=42): +def generate_random_circuit(nqubits, ngates, names=None, seed=42): """Generate a random circuit with RX and CZ gates.""" np.random.seed(seed) - one_qubit_gates = [gates.RX, gates.RY, gates.RZ] - two_qubit_gates = [gates.CZ, gates.CNOT, gates.SWAP] + one_qubit_gates = [gates.RX, gates.RY, gates.RZ, gates.X, gates.Y, gates.Z, gates.H] + two_qubit_gates = [ + gates.CNOT, + gates.CZ, + gates.SWAP, + gates.iSWAP, + gates.CRX, + gates.CRY, + gates.CRZ, + ] n1, n2 = len(one_qubit_gates), len(two_qubit_gates) n = n1 + n2 if nqubits > 1 else n1 - circuit = Circuit(nqubits) + circuit = Circuit(nqubits, wire_names=names) for _ in range(ngates): igate = int(np.random.randint(0, n)) if igate >= n1: @@ -89,9 +76,9 @@ def star_circuit(): return circuit -def matched_circuit(): +def matched_circuit(names): """Return a simple circuit that can be executed on star connectivity""" - circuit = Circuit(5) + circuit = Circuit(5, wire_names=names) circuit.add(gates.CZ(0, 2)) circuit.add(gates.CZ(1, 2)) circuit.add(gates.Z(1)) @@ -100,111 +87,138 @@ def matched_circuit(): return circuit -def test_assert_connectivity(): - assert_connectivity(star_connectivity(), matched_circuit()) +def test_bell_state_3q(): + circuit = Circuit(3) + circuit.add(gates.H(0)) + circuit.add(gates.CNOT(0, 2)) + circuit.add(gates.X(0)) + circuit.add(gates.M(0, 1, 2)) + c = circuit.copy() + connectivity = line_connectivity(3, None) + router = Sabre(connectivity=connectivity) + routed_circuit, final_map = router(c) -def test_assert_connectivity_false(): - circuit = Circuit(5) - circuit.add(gates.CZ(0, 1)) - with pytest.raises(ConnectivityError): - assert_connectivity(star_connectivity(), circuit) + backend = NumpyBackend() + state = np.array([1, 0, 0, 0, 0, 0, 0, 0]) + original_state = backend.execute_circuit(circuit, state).state() + target_state = backend.execute_circuit(routed_circuit, state).state() + target_state = _transpose_qubits(target_state, list(final_map.values())) + assert np.all(np.isclose(np.real(original_state), np.real(target_state))) -def test_assert_connectivity_3q(): - circuit = Circuit(5) - circuit.add(gates.TOFFOLI(0, 1, 2)) - with pytest.raises(ConnectivityError): - assert_connectivity(star_connectivity(), circuit) +@pytest.mark.parametrize("ngates", [5, 25]) +def test_random_circuits_5q(ngates, star_connectivity): + connectivity = star_connectivity() + placer = Random(connectivity) + transpiler = ShortestPaths(connectivity) + circuit = generate_random_circuit(nqubits=5, ngates=ngates) + original_circuit = circuit.copy() + placer(circuit) + transpiled_circuit, final_qubit_map = transpiler(circuit) + + assert transpiler.added_swaps >= 0 + assert_connectivity(connectivity, transpiled_circuit) + assert_placement(transpiled_circuit, connectivity) + assert ngates + transpiler.added_swaps == transpiled_circuit.ngates + assert_circuit_equivalence( + original_circuit=original_circuit, + transpiled_circuit=transpiled_circuit, + final_map=final_qubit_map, + ) + + +@pytest.mark.parametrize("ngates", [5, 25]) +def test_random_circuits_5q_grid(ngates, grid_connectivity): + connectivity = grid_connectivity() + placer = Random(connectivity) + transpiler = ShortestPaths(connectivity) + + circuit = generate_random_circuit(nqubits=5, ngates=ngates) + original_circuit = circuit.copy() + placer(circuit) + transpiled_circuit, final_qubit_map = transpiler(circuit) -@pytest.mark.parametrize("gates", [5, 25]) -@pytest.mark.parametrize("placer", [Trivial, Random]) -@pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()]) -def test_random_circuits_5q(gates, placer, connectivity): - placer = placer(connectivity=connectivity) - layout_circ = Circuit(5) - initial_layout = placer(layout_circ) - transpiler = ShortestPaths(connectivity=connectivity) - circuit = generate_random_circuit(nqubits=5, ngates=gates) - transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout) assert transpiler.added_swaps >= 0 assert_connectivity(connectivity, transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) - assert gates + transpiler.added_swaps == transpiled_circuit.ngates - qubit_matcher = Preprocessing(connectivity=connectivity) - new_circuit = qubit_matcher(circuit=circuit) + assert_placement(transpiled_circuit, connectivity) + assert ngates + transpiler.added_swaps == transpiled_circuit.ngates assert_circuit_equivalence( - original_circuit=new_circuit, + original_circuit=original_circuit, transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) -def test_random_circuits_15q_50g(): - nqubits, ngates = 15, 50 - connectivity = line_connectivity(nqubits) +@pytest.mark.parametrize("nqubits", [11, 12, 13, 14, 15]) +@pytest.mark.parametrize("ngates", [30, 50]) +def test_random_circuits_15q_50g(nqubits, ngates): + connectivity = line_connectivity(nqubits, None) placer = Random(connectivity=connectivity) - layout_circ = Circuit(nqubits) - initial_layout = placer(layout_circ) transpiler = Sabre(connectivity=connectivity) circuit = generate_random_circuit(nqubits=nqubits, ngates=ngates) - transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout) + original_circuit = circuit.copy() + + placer(circuit) + transpiled_circuit, final_qubit_map = transpiler(circuit) + assert transpiler.added_swaps >= 0 assert_connectivity(connectivity, transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) + assert_placement(transpiled_circuit, connectivity) assert ngates + transpiler.added_swaps == transpiled_circuit.ngates - qubit_matcher = Preprocessing(connectivity=connectivity) - new_circuit = qubit_matcher(circuit=circuit) assert_circuit_equivalence( - original_circuit=new_circuit, + original_circuit=original_circuit, transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) -def test_star_circuit(): - placer = Subgraph(star_connectivity()) - initial_layout = placer(star_circuit()) - transpiler = ShortestPaths(connectivity=star_connectivity()) - transpiled_circuit, final_qubit_map = transpiler(star_circuit(), initial_layout) +def test_star_circuit(star_connectivity): + connectivity = star_connectivity() + circuit = star_circuit() + placer = Subgraph(connectivity=connectivity) + transpiler = ShortestPaths(connectivity=connectivity) + + placer(circuit) + transpiled_circuit, final_qubit_map = transpiler(circuit) + assert transpiler.added_swaps == 0 assert_connectivity(star_connectivity(), transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) + assert_placement(transpiled_circuit, connectivity) assert_circuit_equivalence( original_circuit=star_circuit(), transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) -def test_star_circuit_custom_map(): - placer = Custom(initial_map=[1, 0, 2, 3, 4], connectivity=star_connectivity()) - initial_layout = placer() - transpiler = ShortestPaths(connectivity=star_connectivity()) - transpiled_circuit, final_qubit_map = transpiler(star_circuit(), initial_layout) +def test_star_circuit_custom_map(star_connectivity): + connectivity = star_connectivity() + circuit = star_circuit() + circuit.wire_names = [1, 0, 2, 3, 4] + transpiler = ShortestPaths(connectivity=connectivity) + transpiled_circuit, final_qubit_map = transpiler(circuit) + assert transpiler.added_swaps == 1 assert_connectivity(star_connectivity(), transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) + assert_placement(transpiled_circuit, connectivity) assert_circuit_equivalence( original_circuit=star_circuit(), transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) -def test_routing_with_measurements(): - placer = Trivial(connectivity=star_connectivity()) +def test_routing_with_measurements(star_connectivity): + connectivity = star_connectivity() circuit = Circuit(5) circuit.add(gates.CNOT(0, 1)) circuit.add(gates.M(0, 2, 3)) - initial_layout = placer(circuit=circuit) - transpiler = ShortestPaths(connectivity=star_connectivity()) - transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout) + + transpiler = ShortestPaths(connectivity) + transpiled_circuit, final_qubit_map = transpiler(circuit) + assert transpiled_circuit.ngates == 3 measured_qubits = transpiled_circuit.queue[2].qubits assert measured_qubits == (0, 1, 3) @@ -212,37 +226,26 @@ def test_routing_with_measurements(): original_circuit=circuit, transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) def test_sabre_looping(): # Setup where the looping occurs - # Line connectivity, gates with gate_array, Trivial placer + # Line connectivity, gates with gate_array + + connectivity = line_connectivity(10, None) gate_array = [(7, 2), (6, 0), (5, 6), (4, 8), (3, 5), (9, 1)] loop_circ = Circuit(10) for qubits in gate_array: loop_circ.add(gates.CZ(*qubits)) - chip = nx.Graph() - chip.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - chip.add_edges_from( - [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)] - ) - - placer = Trivial(connectivity=chip) - initial_layout = placer(loop_circ) router_no_threshold = Sabre( - connectivity=chip, swap_threshold=np.inf + connectivity=connectivity, swap_threshold=np.inf ) # Without reset - router_threshold = Sabre(connectivity=chip) # With reset + router_threshold = Sabre(connectivity=connectivity) # With reset - routed_no_threshold, final_mapping_no_threshold = router_no_threshold( - loop_circ, initial_layout=initial_layout - ) - routed_threshold, final_mapping_threshold = router_threshold( - loop_circ, initial_layout=initial_layout - ) + routed_no_threshold, final_mapping_no_threshold = router_no_threshold(loop_circ) + routed_threshold, final_mapping_threshold = router_threshold(loop_circ) count_no_threshold = router_no_threshold.added_swaps count_threshold = router_threshold.added_swaps @@ -252,13 +255,11 @@ def test_sabre_looping(): original_circuit=loop_circ, transpiled_circuit=routed_no_threshold, final_map=final_mapping_no_threshold, - initial_map=initial_layout, ) assert_circuit_equivalence( original_circuit=loop_circ, transpiled_circuit=routed_threshold, final_map=final_mapping_threshold, - initial_map=initial_layout, ) @@ -269,18 +270,11 @@ def test_sabre_shortest_path_routing(): for qubits in gate_array: loop_circ.add(gates.CZ(*qubits)) - # line connectivity - chip = nx.Graph() - chip.add_nodes_from(range(10)) - chip.add_edges_from( - [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)] - ) + connectivity = line_connectivity(10, None) - placer = Trivial(connectivity=chip) - initial_layout = placer(loop_circ) - router = Sabre(connectivity=chip) + router = Sabre(connectivity) - router._preprocessing(circuit=loop_circ, initial_layout=initial_layout) + router._preprocessing(circuit=loop_circ) router._shortest_path_routing() # q2 should be moved adjacent to q8 gate_28 = router.circuit_map.circuit_blocks.block_list[2] @@ -300,14 +294,15 @@ def test_circuit_map(): circ.add(gates.CZ(1, 2)) circ.add(gates.CZ(0, 1)) circ.add(gates.CZ(2, 3)) - initial_layout = {"q0": 2, "q1": 0, "q2": 1, "q3": 3} - circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ) + circ.wire_names = ["q1", "q2", "q0", "q3"] + + circuit_map = CircuitMap(circuit=circ) block_list = circuit_map.circuit_blocks # test blocks_qubits_pairs assert circuit_map.blocks_logical_qubits_pairs() == [(0, 1), (1, 2), (0, 1), (2, 3)] # test execute_block and routed_circuit circuit_map.execute_block(block_list.search_by_index(0)) - routed_circuit = circuit_map.routed_circuit() + routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs) assert isinstance(routed_circuit.queue[0], gates.H) assert len(routed_circuit.queue) == 4 qubits = routed_circuit.queue[2].qubits @@ -318,7 +313,7 @@ def test_circuit_map(): # test update 1 circuit_map.update((0, 2)) - routed_circuit = circuit_map.routed_circuit() + routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs) assert isinstance(routed_circuit.queue[4], gates.SWAP) qubits = routed_circuit.queue[4].qubits assert ( @@ -326,12 +321,12 @@ def test_circuit_map(): and routed_circuit.wire_names[qubits[1]] == "q0" ) assert circuit_map._swaps == 1 - assert circuit_map.physical_to_logical == [0, 2, 1, 3] - assert circuit_map.logical_to_physical == [0, 2, 1, 3] + assert circuit_map.physical_to_logical == [2, 1, 0, 3] + assert circuit_map.logical_to_physical == [2, 1, 0, 3] # test update 2 circuit_map.update((1, 2)) - routed_circuit = circuit_map.routed_circuit() + routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs) assert isinstance(routed_circuit.queue[5], gates.SWAP) qubits = routed_circuit.queue[5].qubits assert ( @@ -339,14 +334,14 @@ def test_circuit_map(): and routed_circuit.wire_names[qubits[1]] == "q1" ) assert circuit_map._swaps == 2 - assert circuit_map.physical_to_logical == [0, 1, 2, 3] - assert circuit_map.logical_to_physical == [0, 1, 2, 3] + assert circuit_map.physical_to_logical == [1, 2, 0, 3] + assert circuit_map.logical_to_physical == [2, 0, 1, 3] - # # test execute_block after multiple swaps + # test execute_block after multiple swaps circuit_map.execute_block(block_list.search_by_index(1)) circuit_map.execute_block(block_list.search_by_index(2)) circuit_map.execute_block(block_list.search_by_index(3)) - routed_circuit = circuit_map.routed_circuit() + routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs) assert isinstance(routed_circuit.queue[6], gates.CZ) qubits = routed_circuit.queue[6].qubits @@ -366,83 +361,112 @@ def test_circuit_map(): ) assert len(circuit_map.circuit_blocks()) == 0 # test final layout - assert circuit_map.final_layout() == {"q0": 0, "q1": 1, "q2": 2, "q3": 3} + assert circuit_map.final_layout() == {"q0": 1, "q1": 2, "q2": 0, "q3": 3} -def test_sabre_matched(): - placer = Trivial() - layout_circ = Circuit(5) - initial_layout = placer(layout_circ) - router = Sabre(connectivity=star_connectivity()) - routed_circuit, final_map = router( - circuit=matched_circuit(), initial_layout=initial_layout - ) +@pytest.mark.parametrize( + "names", + [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]], +) +def test_sabre_matched(names, star_connectivity): + connectivity = star_connectivity(names=names) + circuit = matched_circuit(names) + original_circuit = circuit.copy() + + router = Sabre(connectivity=connectivity) + routed_circuit, final_map = router(circuit) + assert router.added_swaps == 0 - assert final_map == {"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4} - assert_connectivity(circuit=routed_circuit, connectivity=star_connectivity()) + assert_connectivity(circuit=routed_circuit, connectivity=connectivity) assert_circuit_equivalence( - original_circuit=matched_circuit(), + original_circuit=original_circuit, transpiled_circuit=routed_circuit, final_map=final_map, - initial_map=initial_layout, ) @pytest.mark.parametrize("seed", [42]) -def test_sabre_simple(seed): - placer = Trivial() +def test_sabre_simple(seed, star_connectivity): + connectivity = star_connectivity() circ = Circuit(5) circ.add(gates.CZ(0, 1)) - initial_layout = placer(circ) - router = Sabre(connectivity=star_connectivity(), seed=seed) - routed_circuit, final_map = router(circuit=circ, initial_layout=initial_layout) + original_circuit = circ.copy() + + router = Sabre(connectivity=connectivity, seed=seed) + routed_circuit, final_map = router(circ) + assert router.added_swaps == 1 - assert final_map == {"q0": 2, "q1": 1, "q2": 0, "q3": 3, "q4": 4} + assert final_map == {0: 2, 1: 1, 2: 0, 3: 3, 4: 4} assert routed_circuit.queue[0].qubits == (0, 2) assert isinstance(routed_circuit.queue[0], gates.SWAP) assert isinstance(routed_circuit.queue[1], gates.CZ) - assert_connectivity(circuit=routed_circuit, connectivity=star_connectivity()) + assert_connectivity(circuit=routed_circuit, connectivity=connectivity) assert_circuit_equivalence( - original_circuit=circ, + original_circuit=original_circuit, transpiled_circuit=routed_circuit, final_map=final_map, - initial_map=initial_layout, ) @pytest.mark.parametrize("n_gates", [10, 40]) @pytest.mark.parametrize("look", [0, 5]) @pytest.mark.parametrize("decay", [0.5, 1.0]) -@pytest.mark.parametrize("placer", [Trivial, Random]) -@pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()]) -def test_sabre_random_circuits(n_gates, look, decay, placer, connectivity): - placer = placer(connectivity=connectivity) - layout_circ = Circuit(5) - initial_layout = placer(layout_circ) - router = Sabre(connectivity=connectivity, lookahead=look, decay_lookahead=decay) +def test_sabre_random_circuits(n_gates, look, decay, star_connectivity): + connectivity = star_connectivity() circuit = generate_random_circuit(nqubits=5, ngates=n_gates) measurement = gates.M(*range(5)) circuit.add(measurement) - transpiled_circuit, final_qubit_map = router(circuit, initial_layout) + original_circuit = circuit.copy() + placer = Random(connectivity) + router = Sabre(connectivity, lookahead=look, decay_lookahead=decay) + + placer(circuit) + transpiled_circuit, final_qubit_map = router(circuit) + assert router.added_swaps >= 0 assert_connectivity(connectivity, transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) + assert_placement(transpiled_circuit, connectivity) assert n_gates + router.added_swaps + 1 == transpiled_circuit.ngates assert_circuit_equivalence( - original_circuit=circuit, + original_circuit=original_circuit, + transpiled_circuit=transpiled_circuit, + final_map=final_qubit_map, + ) + assert transpiled_circuit.queue[-1].register_name == measurement.register_name + + +@pytest.mark.parametrize("n_gates", [10, 40]) +@pytest.mark.parametrize("look", [0, 5]) +@pytest.mark.parametrize("decay", [0.5, 1.0]) +def test_sabre_random_circuits_grid(n_gates, look, decay, grid_connectivity): + connectivity = grid_connectivity() + circuit = generate_random_circuit(nqubits=5, ngates=n_gates) + measurement = gates.M(*range(5)) + circuit.add(measurement) + original_circuit = circuit.copy() + placer = Random(connectivity) + router = Sabre(connectivity, lookahead=look, decay_lookahead=decay) + + placer(circuit) + transpiled_circuit, final_qubit_map = router(circuit) + + assert router.added_swaps >= 0 + assert_connectivity(connectivity, transpiled_circuit) + assert_placement(transpiled_circuit, connectivity) + assert n_gates + router.added_swaps + 1 == transpiled_circuit.ngates + assert_circuit_equivalence( + original_circuit=original_circuit, transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) assert transpiled_circuit.queue[-1].register_name == measurement.register_name -def test_sabre_memory_map(): - placer = Trivial() +def test_sabre_memory_map(star_connectivity): + connectivity = star_connectivity() layout_circ = Circuit(5) - initial_layout = placer(layout_circ) - router = Sabre(connectivity=star_connectivity()) - router._preprocessing(circuit=star_circuit(), initial_layout=initial_layout) + router = Sabre(connectivity=connectivity) + router._preprocessing(circuit=star_circuit()) router._memory_map = [[1, 0, 2, 3, 4]] value = router._compute_cost((0, 1)) assert value == float("inf") @@ -458,53 +482,65 @@ def test_sabre_intermediate_measurements(): connectivity.add_nodes_from([0, 1, 2]) connectivity.add_edges_from([(0, 1), (1, 2)]) router = Sabre(connectivity=connectivity) - initial_layout = {"q0": 0, "q1": 1, "q2": 2} - routed_circ, _ = router(circuit=circ, initial_layout=initial_layout) + routed_circ, _ = router(circuit=circ) assert routed_circ.queue[3].register_name == measurement.register_name @pytest.mark.parametrize("router_algorithm", [Sabre, ShortestPaths]) -def test_restrict_qubits(router_algorithm): +def test_restrict_qubits(router_algorithm, star_connectivity): circ = Circuit(3) circ.add(gates.CZ(0, 1)) circ.add(gates.CZ(0, 2)) circ.add(gates.CZ(2, 1)) - initial_layout = {"q0": 0, "q2": 2, "q3": 1} - connectivity = star_connectivity() - restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3]) + circ.wire_names = ["q0", "q3", "q2"] + connectivity = star_connectivity(["q0", "q1", "q2", "q3", "q4"]) + restricted_connectivity = restrict_connectivity_qubits( + connectivity, ["q0", "q2", "q3"] + ) router = router_algorithm(connectivity=restricted_connectivity) - routed_circ, final_layout = router(circuit=circ, initial_layout=initial_layout) + routed_circ, final_layout = router(circuit=circ) assert_circuit_equivalence( original_circuit=circ, transpiled_circuit=routed_circ, final_map=final_layout, - initial_map=initial_layout, ) assert_connectivity(restricted_connectivity, routed_circ) - assert_placement(routed_circ, final_layout, connectivity=restricted_connectivity) - assert routed_circ.wire_names == ["q0", "q2", "q3"] + assert_placement(routed_circ, connectivity=restricted_connectivity) + assert routed_circ.wire_names == ["q0", "q3", "q2"] -def test_star_error_multi_qubit(): - circuit = Circuit(3) +def test_star_error_multi_qubit(star_connectivity): + circuit = Circuit(5) circuit.add(gates.TOFFOLI(0, 1, 2)) - transpiler = StarConnectivityRouter(middle_qubit=2) + connectivity = star_connectivity(middle_qubit_idx=2) + transpiler = StarConnectivityRouter(connectivity) with pytest.raises(ConnectivityError): - transpiled, hardware_qubits = transpiler( - initial_layout={"q0": 0, "q1": 1, "q2": 2}, circuit=circuit - ) + transpiled, hardware_qubits = transpiler(circuit=circuit) + + chip = nx.Graph() + chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)]) + with pytest.raises(ValueError): + router = StarConnectivityRouter(chip) + _, _ = router(circuit=circuit) -@pytest.mark.parametrize("nqubits", [1, 3, 5]) +# @pytest.mark.parametrize("nqubits", [1, 3, 5]) +@pytest.mark.parametrize("nqubits", [5]) @pytest.mark.parametrize("middle_qubit", [0, 2, 4]) @pytest.mark.parametrize("depth", [2, 10]) @pytest.mark.parametrize("measurements", [True, False]) @pytest.mark.parametrize("unitaries", [True, False]) -def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries): +@pytest.mark.parametrize( + "names", + [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]], +) +def test_star_router( + nqubits, depth, middle_qubit, measurements, unitaries, names, star_connectivity +): unitary_dim = min(2, nqubits) - connectivity = star_connectivity(middle_qubit) + connectivity = star_connectivity(names=names, middle_qubit_idx=middle_qubit) if unitaries: - circuit = Circuit(nqubits) + circuit = Circuit(nqubits, wire_names=names) pairs = list(itertools.combinations(range(nqubits), unitary_dim)) for _ in range(depth): qubits = pairs[int(np.random.randint(len(pairs)))] @@ -514,32 +550,28 @@ def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries): ) ) else: - circuit = generate_random_circuit(nqubits, depth) + circuit = generate_random_circuit(nqubits, depth, names) if measurements: circuit.add(gates.M(0)) - transpiler = StarConnectivityRouter(middle_qubit=middle_qubit) - placer = StarConnectivityPlacer(middle_qubit=middle_qubit) - initial_layout = placer(circuit=circuit) - transpiled_circuit, final_qubit_map = transpiler( - circuit=circuit, initial_layout=initial_layout - ) + original_circuit = circuit.copy() + transpiler = StarConnectivityRouter(connectivity) + placer = StarConnectivityPlacer(connectivity) + + placer(circuit) + transpiled_circuit, final_qubit_map = transpiler(circuit) assert_connectivity(connectivity, transpiled_circuit) - assert_placement(transpiled_circuit, final_qubit_map) - matched_original = Circuit(max(circuit.nqubits, middle_qubit + 1)) - for gate in circuit.queue: - matched_original.add(gate) + assert_placement(transpiled_circuit, connectivity) assert_circuit_equivalence( - original_circuit=matched_original, + original_circuit=original_circuit, transpiled_circuit=transpiled_circuit, final_map=final_qubit_map, - initial_map=initial_layout, ) def test_undo(): circ = Circuit(4) - initial_layout = {"q0": 0, "q1": 1, "q2": 2, "q3": 3} - circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ) + circ.wire_names = ["q0", "q1", "q2", "q3"] + circuit_map = CircuitMap(circuit=circ) # Two SWAP gates are added circuit_map.update((1, 2)) @@ -572,8 +604,8 @@ def test_circuitmap_no_circuit(): def test_logical_to_physical_setter(): circ = Circuit(4) - initial_layout = {"q0": 0, "q1": 3, "q2": 2, "q3": 1} - circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ) + circ.wire_names = ["q0", "q3", "q2", "q1"] + circuit_map = CircuitMap(circuit=circ) circuit_map.logical_to_physical = [2, 0, 1, 3] assert circuit_map.logical_to_physical == [2, 0, 1, 3] assert circuit_map.physical_to_logical == [1, 2, 0, 3] diff --git a/tests/test_transpiler_unitary_decompositions.py b/tests/test_transpiler_unitary_decompositions.py index 36f8b63647..530c3b4784 100644 --- a/tests/test_transpiler_unitary_decompositions.py +++ b/tests/test_transpiler_unitary_decompositions.py @@ -3,7 +3,6 @@ from scipy.linalg import expm from qibo import Circuit, gates, matrices -from qibo.config import PRECISION_TOL from qibo.quantum_info.linalg_operations import partial_trace from qibo.quantum_info.metrics import purity from qibo.quantum_info.random_ensembles import random_unitary diff --git a/tests/test_transpiler_unroller.py b/tests/test_transpiler_unroller.py index e09147b179..181a348e82 100644 --- a/tests/test_transpiler_unroller.py +++ b/tests/test_transpiler_unroller.py @@ -3,12 +3,8 @@ from qibo import gates from qibo.models import Circuit from qibo.transpiler._exceptions import DecompositionError -from qibo.transpiler.unroller import ( - NativeGates, - Unroller, - assert_decomposition, - translate_gate, -) +from qibo.transpiler.asserts import assert_decomposition +from qibo.transpiler.unroller import NativeGates, Unroller, translate_gate def test_native_gates_from_gatelist(): @@ -43,36 +39,6 @@ def test_translate_gate_error_2q(): translate_gate(gates.CZ(0, 1), natives) -def test_assert_decomposition(): - circuit = Circuit(2) - circuit.add(gates.CZ(0, 1)) - circuit.add(gates.Z(0)) - circuit.add(gates.M(1)) - assert_decomposition(circuit, native_gates=NativeGates.default()) - - -def test_assert_decomposition_fail_1q(): - circuit = Circuit(1) - circuit.add(gates.X(0)) - with pytest.raises(DecompositionError): - assert_decomposition(circuit, native_gates=NativeGates.default()) - - -@pytest.mark.parametrize("gate", [gates.CNOT(0, 1), gates.iSWAP(0, 1)]) -def test_assert_decomposition_fail_2q(gate): - circuit = Circuit(2) - circuit.add(gate) - with pytest.raises(DecompositionError): - assert_decomposition(circuit, native_gates=NativeGates.default()) - - -def test_assert_decomposition_fail_3q(): - circuit = Circuit(3) - circuit.add(gates.TOFFOLI(0, 1, 2)) - with pytest.raises(DecompositionError): - assert_decomposition(circuit, native_gates=NativeGates.default()) - - @pytest.mark.parametrize( "natives_2q", [NativeGates.CZ, NativeGates.iSWAP, NativeGates.CZ | NativeGates.iSWAP], @@ -146,8 +112,8 @@ def test_temp_cnot_decomposition(): glist = [gates.GPI2, gates.RZ, gates.Z, gates.M, gates.CNOT] native_gates = NativeGates(0).from_gatelist(glist) - custom_pipeline = Passes([Unroller(native_gates=native_gates)]) - transpiled_circuit, _ = custom_pipeline(circ) + unroller = Unroller(native_gates=native_gates) + transpiled_circuit = unroller(circ) # H assert transpiled_circuit.queue[0].name == "z"