diff --git a/.all-contributorsrc b/.all-contributorsrc index 610c8223..a625ed92 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -240,6 +240,96 @@ "contributions": [ "example" ] + }, + { + "login": "FelixXu35", + "name": "Felix Xu", + "avatar_url": "https://avatars.githubusercontent.com/u/61252303?v=4", + "profile": "https://www.linkedin.com/in/felix-xu-16a153196/", + "contributions": [ + "tutorial", + "code", + "test" + ] + }, + { + "login": "hongyehu", + "name": "Hong-Ye Hu", + "avatar_url": "https://avatars.githubusercontent.com/u/50563225?v=4", + "profile": "https://scholar.harvard.edu/hongyehu/home", + "contributions": [ + "doc" + ] + }, + { + "login": "PeilinZHENG", + "name": "peilin", + "avatar_url": "https://avatars.githubusercontent.com/u/45784888?v=4", + "profile": "https://github.com/PeilinZHENG", + "contributions": [ + "tutorial", + "code", + "test", + "doc" + ] + }, + { + "login": "EmilianoG-byte", + "name": "Cristian Emiliano Godinez Ramirez", + "avatar_url": "https://avatars.githubusercontent.com/u/57567043?v=4", + "profile": "https://emilianog-byte.github.io", + "contributions": [ + "code", + "test" + ] + }, + { + "login": "ztzhu1", + "name": "ztzhu", + "avatar_url": "https://avatars.githubusercontent.com/u/111620128?v=4", + "profile": "https://github.com/ztzhu1", + "contributions": [ + "code" + ] + }, + { + "login": "royess", + "name": "Rabqubit", + "avatar_url": "https://avatars.githubusercontent.com/u/31059422?v=4", + "profile": "https://github.com/royess", + "contributions": [ + "example" + ] + }, + { + "login": "king-p3nguin", + "name": "Kazuki Tsuoka", + "avatar_url": "https://avatars.githubusercontent.com/u/103920010?v=4", + "profile": "https://github.com/king-p3nguin", + "contributions": [ + "code", + "test", + "doc", + "example" + ] + }, + { + "login": "Gopal-Dahale", + "name": "Gopal Ramesh Dahale", + "avatar_url": "https://avatars.githubusercontent.com/u/49199003?v=4", + "profile": "https://gopal-dahale.github.io/", + "contributions": [ + "example" + ] + }, + { + "login": "AbdullahKazi500", + "name": "Chanandellar Bong", + "avatar_url": "https://avatars.githubusercontent.com/u/75779966?v=4", + "profile": "https://github.com/AbdullahKazi500", + "contributions": [ + "example" + ] } ], "contributorsPerLine": 6, @@ -247,5 +337,6 @@ "repoType": "github", "repoHost": "https://github.com", "projectName": "tensorcircuit", - "projectOwner": "tencent-quantum-lab" + "projectOwner": "tencent-quantum-lab", + "commitType": "docs" } diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a0a7dff..964f9d67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04, macos-latest] # macos-latest disabled to save quota - python-version: [3.8] + python-version: ["3.10"] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/nightly_release.yml b/.github/workflows/nightly_release.yml index ce62cc9c..8a1dbda8 100644 --- a/.github/workflows/nightly_release.yml +++ b/.github/workflows/nightly_release.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: "3.10" cache: "pip" - name: install dependencies run: | diff --git a/.gitignore b/.gitignore index c1649c55..c21b5efb 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ examples/Unified AD model.ipynb docs/source/locale/zh/LC_MESSAGES/textbook.po docs/source/locale/zh/LC_MESSAGES/whitepapertoc_cn.po docs/source/locale/zh/LC_MESSAGES/textbooktoc.po +test.qasm diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..2acb1049 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +formats: + - pdf + +# Set the version of Python and other tools you might need +build: + os: ubuntu-20.04 + tools: + python: "3.8" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: requirements/requirements-rtd.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e40c05..3f072c9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,134 @@ ## Unreleased +### Added + +- Add support for parameter expression in qiskit translation + +## 0.12.0 + +### Added + +- Add translation of r gate from qiskit + +- Add `det` method at backends + +- Add fermion Gaussian state simulator in `fgs.py` + +- Add `partial_transpose` and `entanglement_negativity` method in `quantum.py` + +- Add `reduced_wavefunction` method in `quantum.py` to get reduced pure state + +### Changed + +- move ensemble module to applications/ai (breaking changes) + +- tc2qiskit now record qiskit measure with incremental clbit from 0 + +### Fixed + +- Support degenerate eigenvalue for jax backend `eigh` method when using AD + +- Fixed `cu` gate translation from qiskit to avoid qiskit bug + +- Fixed jax refactoring (0.4.24) where SVD and QR return a namedtuple instead of a tuple + +- Fix qiskit<1.0 and tf<2.16 + +## 0.11.0 + +### Added + +- Add multiple GPU VQE examples using jax pmap + +- Add `with_prob` option to `general_kraus` so that the probability of each option can be returned together + +- Add benchmark example showcasing new way of implementing matrix product using vmap + +- Add keras3 example showcasing integration with tc + +- Add circuit copy method that avoid shallow copy issue `Circuit.copy()` + +- Add end to end infrastructures and methods for classical shadow in `shadows.py` + +- Add classical shadow tutorial + +- Add NN-VQE tutorial + +### Fixed + +- improve the `adaptive_vmap` to support internal jit and pytree output + +- fix `pauli_gates` dtype unchange issue when set new dtype (not recommend to use this attr anymore) + +- fix rem `apply_correction` bug when non-numpy backend is set + +- fix tf warning for `cast` with higher version of tf + +### Changed + +- The static method `BaseCircuit.copy` is renamed as `BaseCircuit.copy_nodes` (breaking changes) + +## 0.10.0 + +### Added + +- `c.measure_instruction(*qubits)` now supports multiple ints specified at the same time + +- `c.expectation_ps()` now also supports `ps` argument directly (pauli structures) + +- Add tc version print in `tc.about()` method + +- tc now supports fancy batch indexing for gates, e.g. `c.rxx([0, 1, 2], [1, 2, 3], theta=K.ones([3]))` + +- Task management via group tag (when `submit_task` and `list_tasks`) + +- `batch_expectation_ps` now supports local device without topology and thus unify the interface for numerical exact simulation, numerical simulation with measurement shots and QPU experiments + +- introduce two stage compiling for `batch_expectation_ps` to save some compiling overhead + +- Add experimental support for ODE backend pulse level control simulation/analog quantum computing + +- make the pulse level control support differentiating the end time + +- Add new qem module with qem methods: zne, dd and rc + +### Fixed + +- `tc.results.counts.plot_histogram` now can dispatch kws to corresponding qiskit method + +- New implementation for `c.inverse()` to partially avoid unrecognized gate name issue + +- Fixed bug for `batch_expectation_ps` for jax backend + +- Partially fix the SVD numerical stability bug on tf backend when using `MPSCircuit` + +- List syntax for gate now supports range + +## 0.9.1 + +### Added + +- Add `tc.TorchHardwarLayer` for shortcut layer construction of quantum hardware experiments + +- Add cotengra contractor setup shortcut + +- Add simplecompiler module to assite qiskit compile for better performance when targeting rz native basis + +### Changed + +- Add compiler and cloud namespace to the global tensorcircuit namespace + +- Refactor composed compiler pipeline interface to include simple_compiler, using `DefaultCompiler` for now (breaking) + +- Refactor `batch_submit_template` wrapper to make it a standard abstraction layer between tc cloud infras and `batch_expectation_ps` abstraction, providing another way to adpot other cloud providers with only `batch_submit_template` implemented + +### Fixed + +- `submit_task` return (list of dict vs dict) follows the data type of provided circuit instead of the number of circuits + +- Fix qubit mapping related bug when using `batch_expectation_ps` or `simple_compile` + ## 0.9.0 ### Added diff --git a/LICENSE b/LICENSE index d6456956..253d6ac1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,202 +1,65 @@ +Tencent is pleased to support the open source community by making tensorcircuit available. - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Copyright (C) 2025 THL A29 Limited, a Tencent company. All rights reserved. + +tensorcircuit is licensed under the Apache License Version 2.0. + + +Terms of the Apache License Version 2.0: +-------------------------------------------------------------------- +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index 848de62c..c46b54c7 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,15 @@

English | 简体中文

-TensorCircuit is the next generation of quantum circuit simulators with support for automatic differentiation, just-in-time compiling, hardware acceleration, and vectorized parallelism. +TensorCircuit is the next generation of quantum software framework with support for automatic differentiation, just-in-time compiling, hardware acceleration, and vectorized parallelism. -TensorCircuit is built on top of modern machine learning frameworks and is machine learning backend agnostic. It is specifically suitable for highly efficient simulations of quantum-classical hybrid paradigm and variational quantum algorithms. +TensorCircuit is built on top of modern machine learning frameworks: Jax, TensorFlow, and PyTorch. It is specifically suitable for highly efficient simulations of quantum-classical hybrid paradigm and variational quantum algorithms in ideal, noisy and approximate cases. It also supports real quantum hardware access and provides CPU/GPU/QPU hybrid deployment solutions since v0.9. ## Getting Started -Please begin with [Quick Start](/docs/source/quickstart.rst). +Please begin with [Quick Start](/docs/source/quickstart.rst) in the [full documentation](https://tensorcircuit.readthedocs.io/). -For more information and introductions, please refer to helpful [example scripts](/examples) and [full documentation](https://tensorcircuit.readthedocs.io/). API docstrings and test cases in [tests](/tests) are also informative. +For more information on software usage, sota algorithm implementation and engineer paradigm demonstration, please refer to 70+ [example scripts](/examples) and 30+ [tutorial notebooks](https://tensorcircuit.readthedocs.io/en/latest/#tutorials). API docstrings and test cases in [tests](/tests) are also informative. The following are some minimal demos. @@ -76,6 +76,57 @@ theta = tc.array_to_tensor(1.0) print(g(theta)) ``` +
+ More highlight features for TensorCircuit (click for details) + +- Sparse Hamiltonian generation and expectation evaluation: + +```python +n = 6 +pauli_structures = [] +weights = [] +for i in range(n): + pauli_structures.append(tc.quantum.xyz2ps({"z": [i, (i + 1) % n]}, n=n)) + weights.append(1.0) +for i in range(n): + pauli_structures.append(tc.quantum.xyz2ps({"x": [i]}, n=n)) + weights.append(-1.0) +h = tc.quantum.PauliStringSum2COO(pauli_structures, weights) +print(h) +# BCOO(complex64[64, 64], nse=448) +c = tc.Circuit(n) +c.h(range(n)) +energy = tc.templates.measurements.operator_expectation(c, h) +# -6 +``` + +- Large-scale simulation with tensor network engine + +```python +# tc.set_contractor("cotengra-30-10") +n=500 +c = tc.Circuit(n) +c.h(0) +c.cx(range(n-1), range(1, n)) +c.expectation_ps(z=[0, n-1], reuse=False) +``` + +- Density matrix simulator and quantum info quantities + +```python +c = tc.DMCircuit(2) +c.h(0) +c.cx(0, 1) +c.depolarizing(1, px=0.1, py=0.1, pz=0.1) +dm = c.state() +print(tc.quantum.entropy(dm)) +print(tc.quantum.entanglement_entropy(dm, [0])) +print(tc.quantum.entanglement_negativity(dm, [0])) +print(tc.quantum.log_negativity(dm, [0])) +``` + +
+ ## Install The package is written in pure Python and can be obtained via pip as: @@ -90,14 +141,7 @@ We recommend you install this package with tensorflow also installed as: pip install tensorcircuit[tensorflow] ``` -Other optional dependencies include `[torch]`, `[jax]` and `[qiskit]`. - -For the nightly build of tensorcircuit with new features, try: - -```python -pip uninstall tensorcircuit -pip install tensorcircuit-nightly -``` +Other optional dependencies include `[torch]`, `[jax]`, `[qiskit]` and `[cloud]`. We also have [Docker support](/docker). @@ -105,7 +149,9 @@ We also have [Docker support](/docker). - Tensor network simulation engine based -- JIT, AD, vectorized parallelism compatible, GPU support +- JIT, AD, vectorized parallelism compatible + +- GPU support, quantum device access support, hybrid deployment support - Efficiency @@ -115,30 +161,93 @@ We also have [Docker support](/docker). - Elegance - - Flexibility: customized contraction, multiple ML backend/interface choices, multiple dtype precisions + - Flexibility: customized contraction, multiple ML backend/interface choices, multiple dtype precisions, multiple QPU providers - API design: quantum for humans, less code, more power +- Batteries included + +
+ Tons of amazing features and built in tools for research (click for details) + + - Support **super large circuit simulation** using tensor network engine. + + - Support **noisy simulation** with both Monte Carlo and density matrix (tensor network powered) modes. + + - Support **approximate simulation** with MPS-TEBD modes. + + - Support **analog/digital hybrid simulation** (time dependent Hamiltonian evolution, **pulse** level simulation) with neural ode modes. + + - Support **Fermion Gaussian state** simulation with expectation, entanglement, measurement, ground state, real and imaginary time evolution. + + - Support **qudits simulation**. + + - Support **parallel** quantum circuit evaluation across **multiple GPUs**. + + - Highly customizable **noise model** with gate error and scalable readout error. + + - Support for **non-unitary** gate and post-selection simulation. + + - Support **real quantum devices access** from different providers. + + - **Scalable readout error mitigation** native to both bitstring and expectation level with automatic qubit mapping consideration. + + - **Advanced quantum error mitigation methods** and pipelines such as ZNE, DD, RC, etc. + + - Support **MPS/MPO** as representations for input states, quantum gates and observables to be measured. + + - Support **vectorized parallelism** on circuit inputs, circuit parameters, circuit structures, circuit measurements and these vectorization can be nested. + + - Gradients can be obtained with both **automatic differenation** and parameter shift (vmap accelerated) modes. + + - **Machine learning interface/layer/model** abstraction in both TensorFlow and PyTorch for both numerical simulation and real QPU experiments. + + - Circuit sampling supports both final state sampling and perfect sampling from tensor networks. + + - Light cone reduction support for local expectation calculation. + + - Highly customizable tensor network contraction path finder with opteinsum interface. + + - Observables are supported in measurement, sparse matrix, dense matrix and MPO format. + + - Super fast weighted sum Pauli string Hamiltonian matrix generation. + + - Reusable common circuit/measurement/problem templates and patterns. + + - Jittable classical shadow infrastructures. + + - SOTA quantum algorithm and model implementations. + + - Support hybrid workflows and pipelines with CPU/GPU/QPU hardware from local/cloud/hpc resources using tf/torch/jax/cupy/numpy frameworks all at the same time. + +
+ ## Contributing ### Status -This project is released by [Tencent Quantum Lab](https://quantum.tencent.com/) and is created and maintained by [Shi-Xin Zhang](https://github.com/refraction-ray) with current core authors [Shi-Xin Zhang](https://github.com/refraction-ray) and [Yu-Qin Chen](https://github.com/yutuer21). We also thank [contributions](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors) from the lab and the open source community. +This project is created and maintained by [Shi-Xin Zhang](https://github.com/refraction-ray) with current core authors [Shi-Xin Zhang](https://github.com/refraction-ray) and [Yu-Qin Chen](https://github.com/yutuer21). We also thank [contributions](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors) from the open source community. ### Citation -If this project helps in your research, please cite our software whitepaper published in Quantum: +If this project helps in your research, please cite our software whitepaper to acknowledge the work put into the development of TensorCircuit. -[TensorCircuit: a Quantum Software Framework for the NISQ Era](https://quantum-journal.org/papers/q-2023-02-02-912/) +[TensorCircuit: a Quantum Software Framework for the NISQ Era](https://quantum-journal.org/papers/q-2023-02-02-912/) (published in Quantum) which is also a good introduction to the software. +Research works citing TensorCircuit can be highlighted in [Research and Applications section](https://github.com/tencent-quantum-lab/tensorcircuit#research-and-applications). + ### Guidelines For contribution guidelines and notes, see [CONTRIBUTING](/CONTRIBUTING.md). We welcome [issues](https://github.com/tencent-quantum-lab/tensorcircuit/issues), [PRs](https://github.com/tencent-quantum-lab/tensorcircuit/pulls), and [discussions](https://github.com/tencent-quantum-lab/tensorcircuit/discussions) from everyone, and these are all hosted on GitHub. +### License + +TensorCircuit is open source, released under the Apache License, Version 2.0. + ### Contributors @@ -173,6 +282,17 @@ We welcome [issues](https://github.com/tencent-quantum-lab/tensorcircuit/issues) 隐公观鱼
隐公观鱼

💻 ⚠️ WiuYuan
WiuYuan

💡 + Felix Xu
Felix Xu

💻 ⚠️ + Hong-Ye Hu
Hong-Ye Hu

📖 + peilin
peilin

💻 ⚠️ 📖 + Cristian Emiliano Godinez Ramirez
Cristian Emiliano Godinez Ramirez

💻 ⚠️ + + + ztzhu
ztzhu

💻 + Rabqubit
Rabqubit

💡 + Kazuki Tsuoka
Kazuki Tsuoka

💻 ⚠️ 📖 💡 + Gopal Ramesh Dahale
Gopal Ramesh Dahale

💡 + Chanandellar Bong
Chanandellar Bong

💡 @@ -194,19 +314,92 @@ We welcome [issues](https://github.com/tencent-quantum-lab/tensorcircuit/issues) ### DQAS For the application of Differentiable Quantum Architecture Search, see [applications](/tensorcircuit/applications). -Reference paper: https://arxiv.org/pdf/2010.08561.pdf (published in QST). + +Reference paper: https://arxiv.org/abs/2010.08561 (published in QST). ### VQNHE For the application of Variational Quantum-Neural Hybrid Eigensolver, see [applications](/tensorcircuit/applications). -Reference paper: https://arxiv.org/pdf/2106.05105.pdf (published in PRL) and https://arxiv.org/pdf/2112.10380.pdf. -### VQEX - MBL +Reference paper: https://arxiv.org/abs/2106.05105 (published in PRL) and https://arxiv.org/abs/2112.10380 (published in AQT). + +### VQEX-MBL For the application of VQEX on MBL phase identification, see the [tutorial](/docs/source/tutorials/vqex_mbl.ipynb). -Reference paper: https://arxiv.org/pdf/2111.13719.pdf (published in PRB). -### Stark - DTC +Reference paper: https://arxiv.org/abs/2111.13719 (published in PRB). + +### Stark-DTC For the numerical demosntration of discrete time crystal enabled by Stark many-body localization, see the Floquet simulation [demo](/examples/timeevolution_trotter.py). -Reference paper: https://arxiv.org/pdf/2208.02866.pdf (published in PRL). + +Reference paper: https://arxiv.org/abs/2208.02866 (published in PRL). + +### RA-Training + +For the numerical simulation of variational quantum algorithm training using random gate activation strategy by us, see the [project repo](https://github.com/ls-iastu/RAtraining). + +Reference paper: https://arxiv.org/abs/2303.08154 (published in PRR as a Letter). + +### TenCirChem + +[TenCirChem](https://github.com/tencent-quantum-lab/TenCirChem) is an efficient and versatile quantum computation package for molecular properties. TenCirChem is based on TensorCircuit and is optimized for chemistry applications. + +Reference paper: https://arxiv.org/abs/2303.10825 (published in JCTC). + +### EMQAOA-DARBO + +For the numerical simulation and hardware experiments with error mitigation on QAOA, see the [project repo](https://github.com/sherrylixuecheng/EMQAOA-DARBO). + +Reference paper: https://arxiv.org/abs/2303.14877 (published in Communications Physics). + +### NN-VQA + +For the setup and simulation code of neural network encoded variational quantum eigensolver, see the [demo](/docs/source/tutorials/nnvqe.ipynb). + +Reference paper: https://arxiv.org/abs/2308.01068 (published in PRApplied). + +### More works + +
+ More research works and code projects using TensorCircuit (click for details) + +- Neural Predictor based Quantum Architecture Search: https://arxiv.org/abs/2103.06524 (published in Machine Learning: Science and Technology). + +- Quantum imaginary-time control for accelerating the ground-state preparation: https://arxiv.org/abs/2112.11782 (published in PRR). + +- Efficient Quantum Simulation of Electron-Phonon Systems by Variational Basis State Encoder: https://arxiv.org/abs/2301.01442 (published in PRR). + +- Variational Quantum Simulations of Finite-Temperature Dynamical Properties via Thermofield Dynamics: https://arxiv.org/abs/2206.05571. + +- Understanding quantum machine learning also requires rethinking generalization: https://arxiv.org/abs/2306.13461 (published in Nature Communications). + +- Decentralized Quantum Federated Learning for Metaverse: Analysis, Design and Implementation: https://arxiv.org/abs/2306.11297. Code: https://github.com/s222416822/BQFL. + +- Non-IID quantum federated learning with one-shot communication complexity: https://arxiv.org/abs/2209.00768 (published in Quantum Machine Intelligence). Code: https://github.com/JasonZHM/quantum-fed-infer. + +- Quantum generative adversarial imitation learning: https://doi.org/10.1088/1367-2630/acc605 (published in New Journal of Physics). + +- GSQAS: Graph Self-supervised Quantum Architecture Search: https://arxiv.org/abs/2303.12381 (published in Physica A: Statistical Mechanics and its Applications). + +- Practical advantage of quantum machine learning in ghost imaging: https://www.nature.com/articles/s42005-023-01290-1 (published in Communications Physics). + +- Zero and Finite Temperature Quantum Simulations Powered by Quantum Magic: https://arxiv.org/abs/2308.11616. + +- Comparison of Quantum Simulators for Variational Quantum Search: A Benchmark Study: https://arxiv.org/abs/2309.05924. + +- Statistical analysis of quantum state learning process in quantum neural networks: https://arxiv.org/abs/2309.14980 (published in NeurIPS). + +- Generative quantum machine learning via denoising diffusion probabilistic models: https://arxiv.org/abs/2310.05866 (published in PRL). + +- Quantum imaginary time evolution and quantum annealing meet topological sector optimization: https://arxiv.org/abs/2310.04291. + +- Google Summer of Code 2023 Projects (QML4HEP): https://github.com/ML4SCI/QMLHEP, https://github.com/Gopal-Dahale/qgnn-hep, https://github.com/salcc/QuantumTransformers. + +- Absence of barren plateaus in finite local-depth circuits with long-range entanglement: https://arxiv.org/abs/2311.01393 (published in PRL). + +- Non-Markovianity benefits quantum dynamics simulation: https://arxiv.org/abs/2311.17622. + +
+ +If you want to highlight your research work or projects here, feel free to add by opening PR. diff --git a/README_cn.md b/README_cn.md index d22b37fd..8137eb85 100644 --- a/README_cn.md +++ b/README_cn.md @@ -25,15 +25,17 @@

English | 简体中文

-TensorCircuit 是下一代量子电路模拟器,支持自动微分、即时编译、硬件加速和向量并行化。 +TensorCircuit 是下一代量子软件框架,完美支持自动微分、即时编译、硬件加速和向量并行化。 -TensorCircuit 建立在现代机器学习框架之上,并且与机器学习后端无关。 它特别适用于量子经典混合范式和变分量子算法的高效模拟。 +TensorCircuit 建立在现代机器学习框架 Jax, TensorFlow, PyTorch 之上,支持机器学习后端无关的统一界面。 其特别适用于理想情况、含噪声情况及可控近似情况下,大规模量子经典混合范式和变分量子算法的高效模拟。 + +TensorCircuit 现在支持真实量子硬件连接和实验,并提供优雅的 CPU/GPU/QPU 混合部署训练方案(v0.9+)。 ## 入门 -请从 [快速上手](/docs/source/quickstart.rst) 和 [Jupyter 教程](/docs/source/tutorials) 开始。 +请从 [完整文档](https://tensorcircuit.readthedocs.io/zh/latest/) 中的 [快速上手](/docs/source/quickstart.rst) 开始。 -有关更多信息和介绍,请参阅有用的 [示例脚本](/examples) 和 [完整文档](https://tensorcircuit.readthedocs.io/zh/latest/)。 [测试](/tests) 中的 API docstring 和测试用例也提供了丰富的信息。 +有关软件用法,算法实现和工程范式演示的更多信息和介绍,请参阅 70+ [示例脚本](/examples) 和 30+ [案例教程](https://tensorcircuit.readthedocs.io/zh/latest/#tutorials)。 [测试](/tests) 用例和 API docstring 也提供了丰富的使用信息。 以下是一些最简易的演示。 @@ -50,7 +52,7 @@ print(c.expectation_ps(z=[0, 1])) print(c.sample(allow_state=True, batch=1024, format="count_dict_bin")) ``` -- 运行时特性定制: +- 运行时特性设置: ```python tc.set_backend("tensorflow") @@ -86,7 +88,7 @@ pip install tensorcircuit pip install tensorcircuit[tensorflow] ``` -其他安装选项包括: `[torch]`, `[jax]` and `[qiskit]`。 +其他安装选项包括: `[torch]`, `[jax]`, `[qiskit]` 和 `[cloud]`。 此外我们有每日发布的最新版本 pip package,可以尝鲜开发的最新功能,请通过以下方式安装: @@ -101,7 +103,9 @@ pip install tensorcircuit-nightly - 基于张量网络模拟引擎 -- 即时编译、自动微分、向量并行化兼容,GPU 支持 +- 即时编译、自动微分、向量并行化兼容 + +- GPU 支持、量子硬件支持、混合部署方案支持 - 效率 @@ -111,7 +115,7 @@ pip install tensorcircuit-nightly - 优雅 - - 灵活性:自定义张量收缩、多种 ML 后端/接口选择、多种数值精度 + - 灵活性:自定义张量收缩、多种 ML 后端/接口选择、多种数值精度、多种量子硬件 - API 设计:人类可理解的量子,更少的代码,更多的可能 @@ -119,11 +123,11 @@ pip install tensorcircuit-nightly ### 现况 -该项目由[腾讯量子实验室](https://quantum.tencent.com/)发布,由 [Shi-Xin Zhang](https://github.com/refraction-ray) 创造并维护。当前核心作者包括 [Shi-Xin Zhang](https://github.com/refraction-ray) 和 [Yu-Qin Chen](https://github.com/yutuer21)。我们也感谢来自实验室和开源社区的[贡献](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors)。 +该项目由 [Shi-Xin Zhang](https://github.com/refraction-ray) 创造并维护。当前核心作者包括 [Shi-Xin Zhang](https://github.com/refraction-ray) 和 [Yu-Qin Chen](https://github.com/yutuer21)。我们也感谢来自开源社区的[贡献](https://github.com/tencent-quantum-lab/tensorcircuit/graphs/contributors)。 ### 引用 -如果该软件对您的研究有帮助, 请引用我们发表在 Quantum 期刊的白皮书文章: +如果该软件对您的研究有帮助, 请引用我们发表在 Quantum 期刊的白皮书文章来支持我们的研发付出。 [TensorCircuit: a Quantum Software Framework for the NISQ Era](https://quantum-journal.org/papers/q-2023-02-02-912/). @@ -133,24 +137,56 @@ pip install tensorcircuit-nightly 我们欢迎大家提出 [issues](https://github.com/tencent-quantum-lab/tensorcircuit/issues), [PR](https://github.com/tencent-quantum-lab/tensorcircuit/pulls), 和 [讨论](https://github.com/tencent-quantum-lab/tensorcircuit/discussions),这些都托管在 GitHub 上。 +### 协议 + +TensorCircuit 是基于 Apache License 2.0 的开源软件。 + ## 研究和应用 ### DQAS 可微量子架构搜索的应用见 [应用](/tensorcircuit/applications)。 -参考论文:https://arxiv.org/pdf/2010.08561.pdf (QST)。 + +参考论文:https://arxiv.org/abs/2010.08561 (QST)。 ### VQNHE 关于变分量子神经混合本征求解器的应用,请参见 [应用](tensorcircuit/applications)。 -参考论文:https://arxiv.org/pdf/2106.05105.pdf (PRL) 和 https://arxiv.org/pdf/2112.10380.pdf 。 -### VQEX - MBL +参考论文:https://arxiv.org/abs/2106.05105 (PRL) 和 https://arxiv.org/abs/2112.10380 。 + +### VQEX-MBL VQEX 在 MBL 相位识别上的应用见 [教程](/docs/source/tutorials/vqex_mbl.ipynb)。 -参考论文: https://arxiv.org/pdf/2111.13719.pdf (PRB)。 -### Stark - DTC +参考论文: https://arxiv.org/abs/2111.13719 (PRB)。 + +### Stark-DTC + +数值验证 Stark 多体局域化稳定的离散时间晶体,类似的 Floquet 系统模拟请参考 [例子](/examples/timeevolution_trotter.py)。 + +参考论文: https://arxiv.org/abs/2208.02866 (PRL)。 + +### RA-Training + +利用我们提出的随机量子门激活策略训练优化变分量子算法的实现请参考 [项目](https://github.com/ls-iastu/RAtraining). + +参考论文: https://arxiv.org/abs/2303.08154。 + +### TenCirChem + +[TenCirChem](https://github.com/tencent-quantum-lab/TenCirChem) 是高效的,专注于处理和计算分子性质的量子计算软件。其基于 TensorCircuit 并为量子化学任务进行了专门的优化。 + +参考论文: https://arxiv.org/abs/2303.10825 (JCTC)。 + +### EMQAOA-DARBO + +数值模拟和带错误消除的真实量子硬件实验验证 QAOA 优化的代码请参考 [项目](https://github.com/sherrylixuecheng/EMQAOA-DARBO)。 + +参考论文: https://arxiv.org/abs/2303.14877。 + +### NN-VQA + +关于神经网络编码的变分量子算法的实现和工作流, 见 [教程](/docs/source/tutorials/nnvqe.ipynb)。 -数值验证 Stark 多体局域化稳定的离散时间晶体,类似的 Floquet 系统模拟请参考 [例子](/examples/timeevolution_trotter.py). -参考论文: https://arxiv.org/pdf/2208.02866.pdf (PRL). +参考论文: https://arxiv.org/abs/2308.01068。 diff --git a/check_all.sh b/check_all.sh old mode 100755 new mode 100644 diff --git a/docker/Dockerfile_v2 b/docker/Dockerfile_v2 new file mode 100644 index 00000000..9f2f4523 --- /dev/null +++ b/docker/Dockerfile_v2 @@ -0,0 +1,37 @@ +FROM nvidia/cuda:11.7.1-cudnn8-devel-ubuntu20.04 +# nvidia/cuda:11.6.0-cudnn8-devel-ubuntu20.04 + +RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ + wget \ + git \ + vim \ + pandoc + +RUN wget -q -P /tmp \ + https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \ + && bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda \ + && rm /tmp/Miniconda3-latest-Linux-x86_64.sh + +ENV PATH="/opt/conda/bin:$PATH" + +RUN conda install -y \ + pip \ + python=3.10 + +COPY requirements/requirements-docker-v2.txt /requirements-docker-v2.txt + +# RUN pip install -r /requirements-docker-v2.txt -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html +RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r /requirements-docker-v2.txt -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html + +# RUN pip install nvidia-cudnn-cu11==8.6.0.163 ray +RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple nvidia-cudnn-cu11==8.6.0.163 ray + +RUN pip install tensorcircuit + +# requirements conflict for ray +# jax must have cudnn>8.6 otherwise fail when init array on gpu, +# while torch insists cudnn 8.5 in setup but 8.6 can also work for torch + +RUN echo export TF_CPP_MIN_LOG_LEVEL=3 >> ~/.bashrc + +CMD ["/bin/bash"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 4b011c1b..1c5aea0d 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,22 +4,26 @@ Run the following command to build the docker for tensorcircuit at parent path: sudo docker build . -f docker/Dockerfile -t tensorcircuit ``` -One can also pull the [official image](https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit) from DockerHub as +Since v0.10 we introduce new docker env based on ubuntu20.04+cuda11.7+py3.10 (+ pip installed tensorcircuit package), build the new docker use ```bash -sudo docker pull tensorcircuit/tensorcircuit +sudo docker build . -f docker/Dockerfile_v2 -t tensorcircuit ``` +One can also pull the [official image](https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit) from DockerHub as + +```bash +sudo docker pull tensorcircuit/tensorcircuit +``` Run the docker container by the following command: ```bash sudo docker run -it --network host --gpus all tensorcircuit -# if one also wants mount local source code, also add args `-v "$(pwd)":/app` +# if one also wants to mount local source code, also add args `-v "$(pwd)":/root` -# for old dockerfile with no runtime env setting -# sudo docker run -it --network host -e LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-11.0/targets/x86_64-linux/lib -e PYTHONPATH=/app -v "$(pwd)":/app --gpus all tensorcircuit +# using tensorcircuit/tensorcircuit:latest to run the prebuild docker image from dockerhub ``` -`export TF_CPP_MIN_LOG_LEVEL=3` maybe necessary since jax suprisingly frequently complain about ptxas version problem. And `export CUDA_VISIBLE_DEVICES=-1` if you want to test only on CPU. +`export CUDA_VISIBLE_DEVICES=-1` if you want to test only on CPU. diff --git a/docs/source/api/about.rst b/docs/source/api/about.rst index 8f7bbf76..e065f1eb 100644 --- a/docs/source/api/about.rst +++ b/docs/source/api/about.rst @@ -1,5 +1,5 @@ tensorcircuit.about -================================================== +================================================================================ .. automodule:: tensorcircuit.about :members: :undoc-members: diff --git a/docs/source/api/abstractcircuit.rst b/docs/source/api/abstractcircuit.rst index 2caf0af1..3d67a499 100644 --- a/docs/source/api/abstractcircuit.rst +++ b/docs/source/api/abstractcircuit.rst @@ -1,5 +1,5 @@ tensorcircuit.abstractcircuit -================================================== +================================================================================ .. automodule:: tensorcircuit.abstractcircuit :members: :undoc-members: diff --git a/docs/source/api/applications.rst b/docs/source/api/applications.rst index ad329ccf..85c31126 100644 --- a/docs/source/api/applications.rst +++ b/docs/source/api/applications.rst @@ -1,9 +1,13 @@ tensorcircuit.applications -================================================== +================================================================================ .. toctree:: + applications/ai.rst applications/dqas.rst + applications/finance.rst applications/graphdata.rst applications/layers.rst + applications/optimization.rst + applications/physics.rst applications/utils.rst applications/vags.rst applications/van.rst diff --git a/docs/source/api/applications/ai.rst b/docs/source/api/applications/ai.rst new file mode 100644 index 00000000..96a22cdb --- /dev/null +++ b/docs/source/api/applications/ai.rst @@ -0,0 +1,4 @@ +tensorcircuit.applications.ai +================================================================================ +.. toctree:: + ai/ensemble.rst \ No newline at end of file diff --git a/docs/source/api/applications/ai/ensemble.rst b/docs/source/api/applications/ai/ensemble.rst new file mode 100644 index 00000000..0173ac00 --- /dev/null +++ b/docs/source/api/applications/ai/ensemble.rst @@ -0,0 +1,7 @@ +tensorcircuit.applications.ai.ensemble +================================================================================ +.. automodule:: tensorcircuit.applications.ai.ensemble + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/applications/dqas.rst b/docs/source/api/applications/dqas.rst index 32457e1f..73cacd43 100644 --- a/docs/source/api/applications/dqas.rst +++ b/docs/source/api/applications/dqas.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.dqas -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.dqas :members: :undoc-members: diff --git a/docs/source/api/applications/finance.rst b/docs/source/api/applications/finance.rst new file mode 100644 index 00000000..d3302b31 --- /dev/null +++ b/docs/source/api/applications/finance.rst @@ -0,0 +1,4 @@ +tensorcircuit.applications.finance +================================================================================ +.. toctree:: + finance/portfolio.rst \ No newline at end of file diff --git a/docs/source/api/applications/finance/portfolio.rst b/docs/source/api/applications/finance/portfolio.rst new file mode 100644 index 00000000..993b5754 --- /dev/null +++ b/docs/source/api/applications/finance/portfolio.rst @@ -0,0 +1,7 @@ +tensorcircuit.applications.finance.portfolio +================================================================================ +.. automodule:: tensorcircuit.applications.finance.portfolio + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/applications/graphdata.rst b/docs/source/api/applications/graphdata.rst index 22e1af13..44851513 100644 --- a/docs/source/api/applications/graphdata.rst +++ b/docs/source/api/applications/graphdata.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.graphdata -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.graphdata :members: :undoc-members: diff --git a/docs/source/api/applications/layers.rst b/docs/source/api/applications/layers.rst index 69303e98..d4f49e81 100644 --- a/docs/source/api/applications/layers.rst +++ b/docs/source/api/applications/layers.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.layers -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.layers :members: :undoc-members: diff --git a/docs/source/api/applications/optimization.rst b/docs/source/api/applications/optimization.rst new file mode 100644 index 00000000..87a0ffbb --- /dev/null +++ b/docs/source/api/applications/optimization.rst @@ -0,0 +1,7 @@ +tensorcircuit.applications.optimization +================================================================================ +.. automodule:: tensorcircuit.applications.optimization + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/applications/physics.rst b/docs/source/api/applications/physics.rst new file mode 100644 index 00000000..98d1a2ed --- /dev/null +++ b/docs/source/api/applications/physics.rst @@ -0,0 +1,5 @@ +tensorcircuit.applications.physics +================================================================================ +.. toctree:: + physics/baseline.rst + physics/fss.rst \ No newline at end of file diff --git a/docs/source/api/applications/physics/baseline.rst b/docs/source/api/applications/physics/baseline.rst new file mode 100644 index 00000000..2ac581ba --- /dev/null +++ b/docs/source/api/applications/physics/baseline.rst @@ -0,0 +1,7 @@ +tensorcircuit.applications.physics.baseline +================================================================================ +.. automodule:: tensorcircuit.applications.physics.baseline + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/applications/physics/fss.rst b/docs/source/api/applications/physics/fss.rst new file mode 100644 index 00000000..d65cd6c1 --- /dev/null +++ b/docs/source/api/applications/physics/fss.rst @@ -0,0 +1,7 @@ +tensorcircuit.applications.physics.fss +================================================================================ +.. automodule:: tensorcircuit.applications.physics.fss + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/applications/utils.rst b/docs/source/api/applications/utils.rst index d4549700..4114e7d8 100644 --- a/docs/source/api/applications/utils.rst +++ b/docs/source/api/applications/utils.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.utils -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.utils :members: :undoc-members: diff --git a/docs/source/api/applications/vags.rst b/docs/source/api/applications/vags.rst index 5b951bd3..af0f451f 100644 --- a/docs/source/api/applications/vags.rst +++ b/docs/source/api/applications/vags.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.vags -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.vags :members: :undoc-members: diff --git a/docs/source/api/applications/van.rst b/docs/source/api/applications/van.rst index 463e44d2..5c90f2e5 100644 --- a/docs/source/api/applications/van.rst +++ b/docs/source/api/applications/van.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.van -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.van :members: :undoc-members: diff --git a/docs/source/api/applications/vqes.rst b/docs/source/api/applications/vqes.rst index e3c775e5..d868c634 100644 --- a/docs/source/api/applications/vqes.rst +++ b/docs/source/api/applications/vqes.rst @@ -1,5 +1,5 @@ tensorcircuit.applications.vqes -================================================== +================================================================================ .. automodule:: tensorcircuit.applications.vqes :members: :undoc-members: diff --git a/docs/source/api/backends.rst b/docs/source/api/backends.rst index 4504e569..cfc63bec 100644 --- a/docs/source/api/backends.rst +++ b/docs/source/api/backends.rst @@ -1,5 +1,5 @@ tensorcircuit.backends -================================================== +================================================================================ .. toctree:: backends/backend_factory.rst backends/cupy_backend.rst diff --git a/docs/source/api/backends/backend_factory.rst b/docs/source/api/backends/backend_factory.rst index 8864abfe..6df6374e 100644 --- a/docs/source/api/backends/backend_factory.rst +++ b/docs/source/api/backends/backend_factory.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.backend_factory -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.backend_factory :members: :undoc-members: diff --git a/docs/source/api/backends/cupy_backend.rst b/docs/source/api/backends/cupy_backend.rst index 743fe8f3..1e2421eb 100644 --- a/docs/source/api/backends/cupy_backend.rst +++ b/docs/source/api/backends/cupy_backend.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.cupy_backend -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.cupy_backend :members: :undoc-members: diff --git a/docs/source/api/backends/jax_backend.rst b/docs/source/api/backends/jax_backend.rst index e0dfe7c3..209409bc 100644 --- a/docs/source/api/backends/jax_backend.rst +++ b/docs/source/api/backends/jax_backend.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.jax_backend -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.jax_backend :members: :undoc-members: diff --git a/docs/source/api/backends/numpy_backend.rst b/docs/source/api/backends/numpy_backend.rst index af19d26b..735f969f 100644 --- a/docs/source/api/backends/numpy_backend.rst +++ b/docs/source/api/backends/numpy_backend.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.numpy_backend -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.numpy_backend :members: :undoc-members: diff --git a/docs/source/api/backends/pytorch_backend.rst b/docs/source/api/backends/pytorch_backend.rst index df2712c6..0d10f664 100644 --- a/docs/source/api/backends/pytorch_backend.rst +++ b/docs/source/api/backends/pytorch_backend.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.pytorch_backend -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.pytorch_backend :members: :undoc-members: diff --git a/docs/source/api/backends/tensorflow_backend.rst b/docs/source/api/backends/tensorflow_backend.rst index 52663b1a..a595418e 100644 --- a/docs/source/api/backends/tensorflow_backend.rst +++ b/docs/source/api/backends/tensorflow_backend.rst @@ -1,5 +1,5 @@ tensorcircuit.backends.tensorflow_backend -================================================== +================================================================================ .. automodule:: tensorcircuit.backends.tensorflow_backend :members: :undoc-members: diff --git a/docs/source/api/basecircuit.rst b/docs/source/api/basecircuit.rst index 6b014bb1..79c2636e 100644 --- a/docs/source/api/basecircuit.rst +++ b/docs/source/api/basecircuit.rst @@ -1,5 +1,5 @@ tensorcircuit.basecircuit -================================================== +================================================================================ .. automodule:: tensorcircuit.basecircuit :members: :undoc-members: diff --git a/docs/source/api/channels.rst b/docs/source/api/channels.rst index 3a7cf3af..d9d6fd00 100644 --- a/docs/source/api/channels.rst +++ b/docs/source/api/channels.rst @@ -1,5 +1,5 @@ tensorcircuit.channels -================================================== +================================================================================ .. automodule:: tensorcircuit.channels :members: :undoc-members: diff --git a/docs/source/api/circuit.rst b/docs/source/api/circuit.rst index 910c5ef6..59c76ddd 100644 --- a/docs/source/api/circuit.rst +++ b/docs/source/api/circuit.rst @@ -1,5 +1,5 @@ tensorcircuit.circuit -================================================== +================================================================================ .. automodule:: tensorcircuit.circuit :members: :undoc-members: diff --git a/docs/source/api/cloud.rst b/docs/source/api/cloud.rst new file mode 100644 index 00000000..be2faf7d --- /dev/null +++ b/docs/source/api/cloud.rst @@ -0,0 +1,11 @@ +tensorcircuit.cloud +================================================================================ +.. toctree:: + cloud/abstraction.rst + cloud/apis.rst + cloud/config.rst + cloud/local.rst + cloud/quafu_provider.rst + cloud/tencent.rst + cloud/utils.rst + cloud/wrapper.rst \ No newline at end of file diff --git a/docs/source/api/cloud/abstraction.rst b/docs/source/api/cloud/abstraction.rst new file mode 100644 index 00000000..3f00247c --- /dev/null +++ b/docs/source/api/cloud/abstraction.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.abstraction +================================================================================ +.. automodule:: tensorcircuit.cloud.abstraction + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/apis.rst b/docs/source/api/cloud/apis.rst new file mode 100644 index 00000000..fe623eec --- /dev/null +++ b/docs/source/api/cloud/apis.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.apis +================================================================================ +.. automodule:: tensorcircuit.cloud.apis + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/config.rst b/docs/source/api/cloud/config.rst new file mode 100644 index 00000000..8f6282a0 --- /dev/null +++ b/docs/source/api/cloud/config.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.config +================================================================================ +.. automodule:: tensorcircuit.cloud.config + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/local.rst b/docs/source/api/cloud/local.rst new file mode 100644 index 00000000..649f66d6 --- /dev/null +++ b/docs/source/api/cloud/local.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.local +================================================================================ +.. automodule:: tensorcircuit.cloud.local + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/quafu_provider.rst b/docs/source/api/cloud/quafu_provider.rst new file mode 100644 index 00000000..06d15eee --- /dev/null +++ b/docs/source/api/cloud/quafu_provider.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.quafu_provider +================================================================================ +.. automodule:: tensorcircuit.cloud.quafu_provider + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/tencent.rst b/docs/source/api/cloud/tencent.rst new file mode 100644 index 00000000..431c3294 --- /dev/null +++ b/docs/source/api/cloud/tencent.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.tencent +================================================================================ +.. automodule:: tensorcircuit.cloud.tencent + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/utils.rst b/docs/source/api/cloud/utils.rst new file mode 100644 index 00000000..a7e33fe4 --- /dev/null +++ b/docs/source/api/cloud/utils.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.utils +================================================================================ +.. automodule:: tensorcircuit.cloud.utils + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cloud/wrapper.rst b/docs/source/api/cloud/wrapper.rst new file mode 100644 index 00000000..d65d3c07 --- /dev/null +++ b/docs/source/api/cloud/wrapper.rst @@ -0,0 +1,7 @@ +tensorcircuit.cloud.wrapper +================================================================================ +.. automodule:: tensorcircuit.cloud.wrapper + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/compiler.rst b/docs/source/api/compiler.rst index 43370b18..cb47419f 100644 --- a/docs/source/api/compiler.rst +++ b/docs/source/api/compiler.rst @@ -1,5 +1,6 @@ tensorcircuit.compiler -================================================== +================================================================================ .. toctree:: compiler/composed_compiler.rst - compiler/qiskit_compiler.rst \ No newline at end of file + compiler/qiskit_compiler.rst + compiler/simple_compiler.rst \ No newline at end of file diff --git a/docs/source/api/compiler/composed_compiler.rst b/docs/source/api/compiler/composed_compiler.rst index c856636d..07f7f23e 100644 --- a/docs/source/api/compiler/composed_compiler.rst +++ b/docs/source/api/compiler/composed_compiler.rst @@ -1,5 +1,5 @@ tensorcircuit.compiler.composed_compiler -================================================== +================================================================================ .. automodule:: tensorcircuit.compiler.composed_compiler :members: :undoc-members: diff --git a/docs/source/api/compiler/qiskit_compiler.rst b/docs/source/api/compiler/qiskit_compiler.rst index 369b4740..b46ae8dc 100644 --- a/docs/source/api/compiler/qiskit_compiler.rst +++ b/docs/source/api/compiler/qiskit_compiler.rst @@ -1,5 +1,5 @@ tensorcircuit.compiler.qiskit_compiler -================================================== +================================================================================ .. automodule:: tensorcircuit.compiler.qiskit_compiler :members: :undoc-members: diff --git a/docs/source/api/compiler/simple_compiler.rst b/docs/source/api/compiler/simple_compiler.rst new file mode 100644 index 00000000..941efba5 --- /dev/null +++ b/docs/source/api/compiler/simple_compiler.rst @@ -0,0 +1,7 @@ +tensorcircuit.compiler.simple_compiler +================================================================================ +.. automodule:: tensorcircuit.compiler.simple_compiler + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/cons.rst b/docs/source/api/cons.rst index 6e077058..d4f48ab6 100644 --- a/docs/source/api/cons.rst +++ b/docs/source/api/cons.rst @@ -1,5 +1,5 @@ tensorcircuit.cons -================================================== +================================================================================ .. automodule:: tensorcircuit.cons :members: :undoc-members: diff --git a/docs/source/api/densitymatrix.rst b/docs/source/api/densitymatrix.rst index 571647d2..274dc323 100644 --- a/docs/source/api/densitymatrix.rst +++ b/docs/source/api/densitymatrix.rst @@ -1,5 +1,5 @@ tensorcircuit.densitymatrix -================================================== +================================================================================ .. automodule:: tensorcircuit.densitymatrix :members: :undoc-members: diff --git a/docs/source/api/experimental.rst b/docs/source/api/experimental.rst index 16761d4c..dbdfa068 100644 --- a/docs/source/api/experimental.rst +++ b/docs/source/api/experimental.rst @@ -1,5 +1,5 @@ tensorcircuit.experimental -================================================== +================================================================================ .. automodule:: tensorcircuit.experimental :members: :undoc-members: diff --git a/docs/source/api/fgs.rst b/docs/source/api/fgs.rst new file mode 100644 index 00000000..f00001b4 --- /dev/null +++ b/docs/source/api/fgs.rst @@ -0,0 +1,7 @@ +tensorcircuit.fgs +================================================================================ +.. automodule:: tensorcircuit.fgs + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/gates.rst b/docs/source/api/gates.rst index 8f72fbcc..71428553 100644 --- a/docs/source/api/gates.rst +++ b/docs/source/api/gates.rst @@ -1,5 +1,5 @@ tensorcircuit.gates -================================================== +================================================================================ .. automodule:: tensorcircuit.gates :members: :undoc-members: diff --git a/docs/source/api/interfaces.rst b/docs/source/api/interfaces.rst index 6371d824..5b234d0f 100644 --- a/docs/source/api/interfaces.rst +++ b/docs/source/api/interfaces.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces -================================================== +================================================================================ .. toctree:: interfaces/numpy.rst interfaces/scipy.rst diff --git a/docs/source/api/interfaces/numpy.rst b/docs/source/api/interfaces/numpy.rst index 5df8b0bb..5271b873 100644 --- a/docs/source/api/interfaces/numpy.rst +++ b/docs/source/api/interfaces/numpy.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces.numpy -================================================== +================================================================================ .. automodule:: tensorcircuit.interfaces.numpy :members: :undoc-members: diff --git a/docs/source/api/interfaces/scipy.rst b/docs/source/api/interfaces/scipy.rst index c263bd93..284dcbe9 100644 --- a/docs/source/api/interfaces/scipy.rst +++ b/docs/source/api/interfaces/scipy.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces.scipy -================================================== +================================================================================ .. automodule:: tensorcircuit.interfaces.scipy :members: :undoc-members: diff --git a/docs/source/api/interfaces/tensorflow.rst b/docs/source/api/interfaces/tensorflow.rst index e02981b9..8ac1a344 100644 --- a/docs/source/api/interfaces/tensorflow.rst +++ b/docs/source/api/interfaces/tensorflow.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces.tensorflow -================================================== +================================================================================ .. automodule:: tensorcircuit.interfaces.tensorflow :members: :undoc-members: diff --git a/docs/source/api/interfaces/tensortrans.rst b/docs/source/api/interfaces/tensortrans.rst index b666e177..a92b166d 100644 --- a/docs/source/api/interfaces/tensortrans.rst +++ b/docs/source/api/interfaces/tensortrans.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces.tensortrans -================================================== +================================================================================ .. automodule:: tensorcircuit.interfaces.tensortrans :members: :undoc-members: diff --git a/docs/source/api/interfaces/torch.rst b/docs/source/api/interfaces/torch.rst index 28090f54..5f7e3dea 100644 --- a/docs/source/api/interfaces/torch.rst +++ b/docs/source/api/interfaces/torch.rst @@ -1,5 +1,5 @@ tensorcircuit.interfaces.torch -================================================== +================================================================================ .. automodule:: tensorcircuit.interfaces.torch :members: :undoc-members: diff --git a/docs/source/api/keras.rst b/docs/source/api/keras.rst index 5ed313b2..9f2e4860 100644 --- a/docs/source/api/keras.rst +++ b/docs/source/api/keras.rst @@ -1,5 +1,5 @@ tensorcircuit.keras -================================================== +================================================================================ .. automodule:: tensorcircuit.keras :members: :undoc-members: diff --git a/docs/source/api/mps_base.rst b/docs/source/api/mps_base.rst index caf11b36..039da259 100644 --- a/docs/source/api/mps_base.rst +++ b/docs/source/api/mps_base.rst @@ -1,5 +1,5 @@ tensorcircuit.mps_base -================================================== +================================================================================ .. automodule:: tensorcircuit.mps_base :members: :undoc-members: diff --git a/docs/source/api/mpscircuit.rst b/docs/source/api/mpscircuit.rst index a4de8119..58a68f56 100644 --- a/docs/source/api/mpscircuit.rst +++ b/docs/source/api/mpscircuit.rst @@ -1,5 +1,5 @@ tensorcircuit.mpscircuit -================================================== +================================================================================ .. automodule:: tensorcircuit.mpscircuit :members: :undoc-members: diff --git a/docs/source/api/noisemodel.rst b/docs/source/api/noisemodel.rst index ab152857..4930d8f0 100644 --- a/docs/source/api/noisemodel.rst +++ b/docs/source/api/noisemodel.rst @@ -1,5 +1,5 @@ tensorcircuit.noisemodel -================================================== +================================================================================ .. automodule:: tensorcircuit.noisemodel :members: :undoc-members: diff --git a/docs/source/api/quantum.rst b/docs/source/api/quantum.rst index c9d13b6b..f25c8a5d 100644 --- a/docs/source/api/quantum.rst +++ b/docs/source/api/quantum.rst @@ -1,5 +1,5 @@ tensorcircuit.quantum -================================================== +================================================================================ .. automodule:: tensorcircuit.quantum :members: :undoc-members: diff --git a/docs/source/api/results.rst b/docs/source/api/results.rst index 0bea95e7..2e60327c 100644 --- a/docs/source/api/results.rst +++ b/docs/source/api/results.rst @@ -1,5 +1,6 @@ tensorcircuit.results -================================================== +================================================================================ .. toctree:: results/counts.rst + results/qem.rst results/readout_mitigation.rst \ No newline at end of file diff --git a/docs/source/api/results/counts.rst b/docs/source/api/results/counts.rst index 7542d722..7f145206 100644 --- a/docs/source/api/results/counts.rst +++ b/docs/source/api/results/counts.rst @@ -1,5 +1,5 @@ tensorcircuit.results.counts -================================================== +================================================================================ .. automodule:: tensorcircuit.results.counts :members: :undoc-members: diff --git a/docs/source/api/results/qem.rst b/docs/source/api/results/qem.rst new file mode 100644 index 00000000..160098f7 --- /dev/null +++ b/docs/source/api/results/qem.rst @@ -0,0 +1,5 @@ +tensorcircuit.results.qem +================================================================================ +.. toctree:: + qem/benchmark_circuits.rst + qem/qem_methods.rst \ No newline at end of file diff --git a/docs/source/api/results/qem/benchmark_circuits.rst b/docs/source/api/results/qem/benchmark_circuits.rst new file mode 100644 index 00000000..3c339884 --- /dev/null +++ b/docs/source/api/results/qem/benchmark_circuits.rst @@ -0,0 +1,7 @@ +tensorcircuit.results.qem.benchmark_circuits +================================================================================ +.. automodule:: tensorcircuit.results.qem.benchmark_circuits + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/results/qem/qem_methods.rst b/docs/source/api/results/qem/qem_methods.rst new file mode 100644 index 00000000..a95bdf95 --- /dev/null +++ b/docs/source/api/results/qem/qem_methods.rst @@ -0,0 +1,7 @@ +tensorcircuit.results.qem.qem_methods +================================================================================ +.. automodule:: tensorcircuit.results.qem.qem_methods + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/results/readout_mitigation.rst b/docs/source/api/results/readout_mitigation.rst index 0d9baa3d..325fe21a 100644 --- a/docs/source/api/results/readout_mitigation.rst +++ b/docs/source/api/results/readout_mitigation.rst @@ -1,5 +1,5 @@ tensorcircuit.results.readout_mitigation -================================================== +================================================================================ .. automodule:: tensorcircuit.results.readout_mitigation :members: :undoc-members: diff --git a/docs/source/api/shadows.rst b/docs/source/api/shadows.rst new file mode 100644 index 00000000..7aea082e --- /dev/null +++ b/docs/source/api/shadows.rst @@ -0,0 +1,7 @@ +tensorcircuit.shadows +================================================================================ +.. automodule:: tensorcircuit.shadows + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/simplify.rst b/docs/source/api/simplify.rst index c1816c31..22833f9f 100644 --- a/docs/source/api/simplify.rst +++ b/docs/source/api/simplify.rst @@ -1,5 +1,5 @@ tensorcircuit.simplify -================================================== +================================================================================ .. automodule:: tensorcircuit.simplify :members: :undoc-members: diff --git a/docs/source/api/templates.rst b/docs/source/api/templates.rst index 330fa6db..202b049d 100644 --- a/docs/source/api/templates.rst +++ b/docs/source/api/templates.rst @@ -1,9 +1,10 @@ tensorcircuit.templates -================================================== +================================================================================ .. toctree:: + templates/ansatz.rst templates/blocks.rst templates/chems.rst + templates/conversions.rst templates/dataset.rst - templates/ensemble.rst templates/graphs.rst templates/measurements.rst \ No newline at end of file diff --git a/docs/source/api/templates/ansatz.rst b/docs/source/api/templates/ansatz.rst new file mode 100644 index 00000000..15f19650 --- /dev/null +++ b/docs/source/api/templates/ansatz.rst @@ -0,0 +1,7 @@ +tensorcircuit.templates.ansatz +================================================================================ +.. automodule:: tensorcircuit.templates.ansatz + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/templates/blocks.rst b/docs/source/api/templates/blocks.rst index 0c88f3d9..b7a0945a 100644 --- a/docs/source/api/templates/blocks.rst +++ b/docs/source/api/templates/blocks.rst @@ -1,5 +1,5 @@ tensorcircuit.templates.blocks -================================================== +================================================================================ .. automodule:: tensorcircuit.templates.blocks :members: :undoc-members: diff --git a/docs/source/api/templates/chems.rst b/docs/source/api/templates/chems.rst index 8a31f9d3..d06d9e39 100644 --- a/docs/source/api/templates/chems.rst +++ b/docs/source/api/templates/chems.rst @@ -1,5 +1,5 @@ tensorcircuit.templates.chems -================================================== +================================================================================ .. automodule:: tensorcircuit.templates.chems :members: :undoc-members: diff --git a/docs/source/api/templates/conversions.rst b/docs/source/api/templates/conversions.rst new file mode 100644 index 00000000..38cbe47f --- /dev/null +++ b/docs/source/api/templates/conversions.rst @@ -0,0 +1,7 @@ +tensorcircuit.templates.conversions +================================================================================ +.. automodule:: tensorcircuit.templates.conversions + :members: + :undoc-members: + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/source/api/templates/dataset.rst b/docs/source/api/templates/dataset.rst index 36b9e510..aa6cdfa7 100644 --- a/docs/source/api/templates/dataset.rst +++ b/docs/source/api/templates/dataset.rst @@ -1,5 +1,5 @@ tensorcircuit.templates.dataset -================================================== +================================================================================ .. automodule:: tensorcircuit.templates.dataset :members: :undoc-members: diff --git a/docs/source/api/templates/ensemble.rst b/docs/source/api/templates/ensemble.rst deleted file mode 100644 index c7dd6f85..00000000 --- a/docs/source/api/templates/ensemble.rst +++ /dev/null @@ -1,7 +0,0 @@ -tensorcircuit.templates.ensemble -================================================== -.. automodule:: tensorcircuit.templates.ensemble - :members: - :undoc-members: - :show-inheritance: - :inherited-members: \ No newline at end of file diff --git a/docs/source/api/templates/graphs.rst b/docs/source/api/templates/graphs.rst index 0a2141f0..b86ab51e 100644 --- a/docs/source/api/templates/graphs.rst +++ b/docs/source/api/templates/graphs.rst @@ -1,5 +1,5 @@ tensorcircuit.templates.graphs -================================================== +================================================================================ .. automodule:: tensorcircuit.templates.graphs :members: :undoc-members: diff --git a/docs/source/api/templates/measurements.rst b/docs/source/api/templates/measurements.rst index 2113f03b..7e05673c 100644 --- a/docs/source/api/templates/measurements.rst +++ b/docs/source/api/templates/measurements.rst @@ -1,5 +1,5 @@ tensorcircuit.templates.measurements -================================================== +================================================================================ .. automodule:: tensorcircuit.templates.measurements :members: :undoc-members: diff --git a/docs/source/api/torchnn.rst b/docs/source/api/torchnn.rst index 5a5b2775..9f9c6598 100644 --- a/docs/source/api/torchnn.rst +++ b/docs/source/api/torchnn.rst @@ -1,5 +1,5 @@ tensorcircuit.torchnn -================================================== +================================================================================ .. automodule:: tensorcircuit.torchnn :members: :undoc-members: diff --git a/docs/source/api/translation.rst b/docs/source/api/translation.rst index a33667f7..f320c909 100644 --- a/docs/source/api/translation.rst +++ b/docs/source/api/translation.rst @@ -1,5 +1,5 @@ tensorcircuit.translation -================================================== +================================================================================ .. automodule:: tensorcircuit.translation :members: :undoc-members: diff --git a/docs/source/api/utils.rst b/docs/source/api/utils.rst index 3fa45319..93ee9496 100644 --- a/docs/source/api/utils.rst +++ b/docs/source/api/utils.rst @@ -1,5 +1,5 @@ tensorcircuit.utils -================================================== +================================================================================ .. automodule:: tensorcircuit.utils :members: :undoc-members: diff --git a/docs/source/api/vis.rst b/docs/source/api/vis.rst index f27680f1..2cdc89e2 100644 --- a/docs/source/api/vis.rst +++ b/docs/source/api/vis.rst @@ -1,5 +1,5 @@ tensorcircuit.vis -================================================== +================================================================================ .. automodule:: tensorcircuit.vis :members: :undoc-members: diff --git a/docs/source/cnconf.py b/docs/source/cnconf.py index 8b01d026..ceecf794 100644 --- a/docs/source/cnconf.py +++ b/docs/source/cnconf.py @@ -48,7 +48,9 @@ "sphinx_copybutton", "nbsphinx", "toctree_filter", + "sphinx.ext.napoleon", "myst_parser", + "sphinx_design", ] autosectionlabel_prefix_document = True diff --git a/docs/source/conf.py b/docs/source/conf.py index 4f8e644e..9d8147d9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -50,8 +50,11 @@ "toctree_filter", "sphinx.ext.napoleon", "myst_parser", + "sphinx_design", ] +nbsphinx_allow_errors = True + autosectionlabel_prefix_document = True # Add any paths that contain templates here, relative to this directory. @@ -144,6 +147,7 @@ # Output file base name for HTML help builder. htmlhelp_basename = "tensorcircuitdoc" +html_title = "TensorCircuit Documentation" # -- Options for LaTeX output ------------------------------------------------ diff --git a/docs/source/contribs/development_Mac.md b/docs/source/contribs/development_Mac.md new file mode 100644 index 00000000..b2682f32 --- /dev/null +++ b/docs/source/contribs/development_Mac.md @@ -0,0 +1,113 @@ +# Tensorcircuit Installation Guide on MacOS + +Contributed by [_Mark (Zixuan) Song_](https://marksong.tech) + +Apple has updated Tensorflow (for MacOS) so that installation on M-series (until M2) and Intel-series Mac can follow the exact same procedure. + +## Starting From Scratch + +For completely new Macos or Macos without Xcode installed. + +If you have Xcode installed, skip to Install TC backends. + +### Install Xcode Command Line Tools + +Need graphical access to the machine. + +Run `xcode-select --install` to install if on optimal internet. + +Or Download it from [Apple](https://developer.apple.com/download/more/) Command Line Tools installation image then install it if the internet connection is weak. + +## Install TC Backends + +There are four backends to choose from, Numpy, Tensorflow, Jax, and Torch. + +### Install Jax, Pytorch (Optional) + +```bash +pip install [Package Name] +``` +### Install Tensorflow (Optional - Recommended) + +#### Install Miniconda (Optional - Recommended) + +If you wish to install Tensorflow optimized for MacOS (`tensorflow-macos`) or Tensorflow GPU optimized (`tensorflow-metal`) please install miniconda. + +If you wish to install Vanilla Tensorflow developed by Google (`tensorflow`) please skip this step. + +```bash +curl -o ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +source ~/miniconda/bin/activate +conda install -c apple tensorflow-deps +``` + +#### Installation + +```bash +pip install tensorflow +``` + +If you wish to use tensorflow-metal PluggableDevice, then continue install (not recommended): + +```bash +pip install tensorflow-metal +``` + +#### Verify Tensorflow Installation + +```python +import tensorflow as tf + +cifar = tf.keras.datasets.cifar100 +(x_train, y_train), (x_test, y_test) = cifar.load_data() +model = tf.keras.applications.ResNet50( + include_top=True, + weights=None, + input_shape=(32, 32, 3), + classes=100,) + +loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) +model.compile(optimizer="adam", loss=loss_fn, metrics=["accuracy"]) +model.fit(x_train, y_train, epochs=5, batch_size=64) +``` + +## Install Tensorcircuit + +```bash +pip install tensorcircuit +``` + +## Benchmarking + +This data is collected by running `benchmarks/scripts/vqe_tc.py` 10 times and average results. + + + + + + + + + + + + + + + + + + + + + + + + + + +
Vanilla TensorflowApple TensorflowApple Tensorflow with Metal Plugin
Construction Time11.49241641s11.31878941s11.6103961s
Iteration time0.002313011s0.002333004s0.046412581s
Total time11.72371747s11.55208979s16.25165417s
+ + +Until July 2023, this has been tested on Intel Macs running Ventura, M1 Macs running Ventura, M2 Macs running Ventura, and M2 Macs running Sonoma beta. \ No newline at end of file diff --git a/docs/source/contribs/development_MacARM.md b/docs/source/contribs/development_MacARM.md index ffddf582..73c63948 100644 --- a/docs/source/contribs/development_MacARM.md +++ b/docs/source/contribs/development_MacARM.md @@ -2,6 +2,9 @@ Contributed by Mark (Zixuan) Song +.. warning:: + This page is deprecated. Please visit `the update tutorial `_ for the latest information. + ## Starting From Scratch For completely new macos or macos without xcode and brew @@ -43,13 +46,7 @@ pip install [Package Name] ### Install Tensorflow (Optional) -#### Install Tensorflow (Recommended Approach) - -❗️ Tensorflow with MacOS optimization would not function correctly in version 2.11.0 and before. Do not use this version of tensorflow if you intented to train any machine learning model. - -FYI: Error can occur when machine learning training or gpu related code is involved. - -⚠️ Tensorflow without macos optimization does not support Metal API and utilizing GPU (both intel chips and M-series chips) until at least tensorflow 2.11. Tensorflow-macos would fail when running `tc.backend.to_dense()` +#### Install Tensorflow without MacOS optimization ``` conda config --add channels conda-forge @@ -75,13 +72,45 @@ model.compile(optimizer="adam", loss=loss_fn, metrics=["accuracy"]) model.fit(x_train, y_train, epochs=5, batch_size=64) ``` +#### Install Tensorflow with MacOS optimization (Recommended) + +For tensorflow version 2.13 or later: +``` +pip install tensorflow +pip install tensorflow-metal +``` + +For tensorflow version 2.12 or earlier: +``` +pip install tensorflow-macos +pip install tensorflow-metal +``` + +#### Verify Tensorflow Installation + +``` +import tensorflow as tf + +cifar = tf.keras.datasets.cifar100 +(x_train, y_train), (x_test, y_test) = cifar.load_data() +model = tf.keras.applications.ResNet50( + include_top=True, + weights=None, + input_shape=(32, 32, 3), + classes=100,) + +loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) +model.compile(optimizer="adam", loss=loss_fn, metrics=["accuracy"]) +model.fit(x_train, y_train, epochs=5, batch_size=64) +``` + ## Install Tensorcircuit ``` pip install tensorcircuit ``` -Testing Platform (Tested Feb 2023) +Testing Platform (Tested Jun 2023) - Platform 1: - MacOS Ventura 13.1 (Build version 22C65) @@ -89,3 +118,6 @@ Testing Platform (Tested Feb 2023) - Platform 2: - MacOS Ventura 13.2 (Build version 22D49) - M1 Ultra (Virtual) +- Platform 4: + - MacOS Sonoma 14.0 Beta 2 (Build version 23A5276g) + - M2 Max \ No newline at end of file diff --git a/docs/source/contribs/development_MacM1.rst b/docs/source/contribs/development_MacM1.rst index 3df9c949..8ce9f058 100644 --- a/docs/source/contribs/development_MacM1.rst +++ b/docs/source/contribs/development_MacM1.rst @@ -4,7 +4,7 @@ Contributed by (Yuqin Chen) .. warning:: - This page is deprecated. Please visit `the update tutorial `_ for latest information. + This page is deprecated. Please visit `the update tutorial `_ for the latest information. Why We Can't Run TensorCircuit on TensorlowBackend with Apple M1 diff --git a/docs/source/contribs/development_MacM2.md b/docs/source/contribs/development_MacM2.md new file mode 100644 index 00000000..b3daf5fb --- /dev/null +++ b/docs/source/contribs/development_MacM2.md @@ -0,0 +1,53 @@ +# Tensorcircuit Installation Guide on MacOS + +Contributed by [Hong-Ye Hu](https://github.com/hongyehu) + +.. warning:: + This page is deprecated. Please visit `the update tutorial `_ for the latest information. + +The key issue addressed in this document is **how to install both TensorFlow and Jax on a M2 chip MacOS without conflict**. + +## Starting From Scratch + +### Install Xcode Command Line Tools + +Need graphical access to the machine. + +Run `xcode-select --install` to install if on optimal internet. + +Or Download from [Apple](https://developer.apple.com/download/more/) Command Line Tools installation image then install if internet connection is weak. + +## Install Miniconda + +Due to the limitation of MacOS and packages, the lastest version of python does not always function as desired, thus miniconda installation is advised to solve the issues. And use anaconda virtual environment is always a good habit. + +``` +curl -o ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +source ~/miniconda/bin/activate +``` + +## Install Packages +First, create a virtual environment, and make sure the python version is 3.8.5 by +``` +conda create --name NewEnv python==3.8.5 +conda activate NewEnv +``` +Then, install the TensorFlow from `.whl` file (file can be downloaded from this [URL](https://drive.google.com/drive/folders/1oSipZLnoeQB0Awz8U68KYeCPsULy_dQ7)). This will install TensorFlow version 2.4.1 +``` +pip install ~/Downloads/tensorflow-2.4.1-py3-none-any.whl +``` +Next, one need to install **Jax** and **Optax** by +``` +conda install jax==0.3.0 +conda install optax==0.1.4 +``` +Now, hopefully, you should be able to use both Jax and TensorFlow in this environment. But sometimes, it may give you an error "ERROR: package Chardet not found.". +If that is the case, you can install it by `conda install chardet`. +Lastly, install tensorcircuit +``` +pip install tensorcircuit +``` +This is the solution that seems to work for M2-chip MacOS. Please let me know if there is a better solution! + + diff --git a/docs/source/contribs/development_Mac_cn.md b/docs/source/contribs/development_Mac_cn.md new file mode 100644 index 00000000..f23fd01f --- /dev/null +++ b/docs/source/contribs/development_Mac_cn.md @@ -0,0 +1,114 @@ +# MacOS Tensorcircuit 安装教程 + +[_Mark (Zixuan) Song_](https://marksong.tech) 撰写 + +由于苹果更新了Tensorflow,因此M系列(直到M2)和英特尔系列Mac上的安装可以遵循完全相同的过程。 + +## 从头开始 + +对于全新的Macos或未安装Xcode的Macos。 + +若您已安装Xcode,请跳转到安装TC后端。 + +### 安装Xcode命令行工具 + +需要对机器的图形访问 + +如果网络良好,请运行`xcode-select --install`进行安装。 + +或者,如果网络连接不理想,请从[苹果](https://developer.apple.com/download/more/)下载命令行工具安装映像,然后进行安装。 + +## 安装TC后端 + +有四个后端可供选择,Numpy,Tensorflow,Jax和Torch。 + +### 安装Jax、Pytorch(可选) + +```bash +pip install [Package Name] +``` + +### 安装Tensorflow(可选 - 推荐) + +#### 安装miniconda(可选 - 推荐) + +若您希望使用苹果为MacOS优化的Tensorflow(`tensorflow-macos`)或使用Tensorflow GPU优化(`tensorflow-metal`)请安装mimiconda。 + +若您希望使Google开发的原版Tensorflow(`tensorflow`)请跳过此步骤。 + +```bash +curl -o ~/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +source ~/miniconda/bin/activate +conda install -c apple tensorflow-deps +``` + +#### 安装步骤 + +```bash +pip install tensorflow +``` + +若您希望使用苹果为Tensorflow优化的Metal后端,请继续运行(不建议): + +```bash +pip install tensorflow-metal +``` + +#### 验证Tensorflow安装 + +```python +import tensorflow as tf + +cifar = tf.keras.datasets.cifar100 +(x_train, y_train), (x_test, y_test) = cifar.load_data() +model = tf.keras.applications.ResNet50( + include_top=True, + weights=None, + input_shape=(32, 32, 3), + classes=100,) + +loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) +model.compile(optimizer="adam", loss=loss_fn, metrics=["accuracy"]) +model.fit(x_train, y_train, epochs=5, batch_size=64) +``` + +## 安装Tensorcircuit + +```bash +pip install tensorcircuit +``` + +## 测试与比较 + +以下数据由运行`benchmarks/scripts/vqe_tc.py` 10次并取平均值得到。 + + + + + + + + + + + + + + + + + + + + + + + + + + +
原版Tensorflow苹果优化版Tensorflow苹果优化版Tensorflow并安装Tensorflow Metal插件
构建时间11.49241641s11.31878941s11.6103961s
迭代时间0.002313011s0.002333004s0.046412581s
从时间11.72371747s11.55208979s16.25165417s
+ + +直到2023年7月,这已在运行Ventura的英特尔i9 Mac、运行Ventura的M1 Mac、运行Ventura的M2 Mac、运行Sonoma测试版的M2 Mac上进行了测试。 \ No newline at end of file diff --git a/docs/source/contribution.rst b/docs/source/contribution.rst index 5e8d7385..d8dbd493 100644 --- a/docs/source/contribution.rst +++ b/docs/source/contribution.rst @@ -146,7 +146,59 @@ We use `sphinx `__ to manage the document The source files for docs are .rst file in docs/source. -For English docs, ``sphinx-build source build/html`` in docs dir is enough. The html version of the docs are in docs/build/html. +For English docs, ``sphinx-build source build/html`` and ``make latexpdf LATEXMKOPTS="-silent"`` in docs dir are enough. +The html and pdf version of the docs are in docs/build/html and docs/build/latex, respectively. + +**Formula Environment Attention** + +It should be noted that the formula environment ``$$CONTENT$$`` in markdown is equivalent to the ``equation`` environment in latex. +Therefore, in the jupyter notebook documents, do not nest the formula environment in ``$$CONTENT$$`` that is incompatible with +``equation`` in latex, such as ``eqnarray``, which will cause errors in the pdf file built by ``nbsphinx``. +However, compatible formula environments can be used. For example, this legal code in markdown + +.. code-block:: markdown + + $$ + \begin{split} + X&=Y\\ + &=Z + \end{split} + $$ + +will be convert to + +.. code-block:: latex + + \begin{equation} + \begin{split} + X&=Y\\ + &=Z + \end{split} + \end{equation} + +in latex automatically by ``nbsphinx``, which is a legal latex code. However, this legal code in markdown + +.. code-block:: markdown + + $$ + \begin{eqnarray} + X&=&Y\\ + &=&Z + \end{eqnarray} + $$ + +will be convert to + +.. code-block:: latex + + \begin{equation} + \begin{eqnarray} + X&=&Y\\ + &=&Z + \end{eqnarray} + \end{equation} + +in latex, which is an illegal latex code. **Auto Generation of API Docs:** diff --git a/docs/source/generate_rst.py b/docs/source/generate_rst.py index 60fcf0de..9b112c46 100644 --- a/docs/source/generate_rst.py +++ b/docs/source/generate_rst.py @@ -5,7 +5,7 @@ class RSTGenerator: - title_line = "=" * 50 + title_line = "=" * 80 toctree = ".. toctree::\n {}" automodule = ".. automodule:: {}\n :members:\n :undoc-members:\n :show-inheritance:\n :inherited-members:" @@ -21,11 +21,14 @@ def __init__( def cleanup(self): if os.path.exists("modules.rst"): os.remove("modules.rst") - shutil.rmtree(self.dfolder) + try: + shutil.rmtree(self.dfolder) + except FileNotFoundError: + pass os.makedirs(self.dfolder) def write(self, path, content): - if type(content) == type([]): + if isinstance(content, list): content = "\n".join(content) with open(path, "w") as f: @@ -33,70 +36,68 @@ def write(self, path, content): print(f"Finish writing {path}") - def single_file_module(self): - """Process the module in the self.pfolder/*.py""" - - for module_name in glob.glob(pj(self.pfolder, "*.py")): + def _file_generate(self, package_parents): + file_list = [] + for module_name in glob.glob(pj(self.pfolder, *package_parents, "*.py")): module_name = os.path.basename(module_name)[:-3] if module_name in self.ingnored_modules: continue - rst_file = pj(self.dfolder, f"{module_name}.rst") + rst_file = pj(self.dfolder, *package_parents, f"{module_name}.rst") + name = f"{self.name}" + for n in package_parents: + name += f".{n}" + name += f".{module_name}" content = [ - f"{self.name}.{module_name}", + name, self.title_line, - self.automodule.format(f"{self.name}.{module_name}"), + self.automodule.format(name), ] - self.write(rst_file, content) - self.tree[rst_file] = [] - - def subdir_files_module(self): - """Write the rst files for modules with subdir or files""" - for subdir in glob.glob(pj(self.pfolder, "*/")): + if not package_parents: + upper = self.dfolder + else: + upper = package_parents[-1] + file_list.append(upper + f"/{module_name}.rst") + for subdir in glob.glob(pj(self.pfolder, *package_parents, "*/")): if "_" in subdir: continue - subdir = os.path.basename(os.path.normpath(subdir)) - os.makedirs(pj(self.dfolder, subdir), exist_ok=True) - rst_file = pj(self.dfolder, f"{subdir}.rst") - self.tree[rst_file] = [] - - for module_name in glob.glob(pj(self.pfolder, subdir, f"*.py")): - module_name = os.path.basename(module_name)[:-3] - if module_name in self.ingnored_modules: - continue - - content = [ - f"{self.name}.{subdir}.{module_name}", - self.title_line, - self.automodule.format(f"{self.name}.{subdir}.{module_name}"), - ] - - self.write(pj(self.dfolder, subdir, f"{module_name}.rst"), content) - self.tree[rst_file].append(f"{subdir}/{module_name}.rst") - + os.makedirs(pj(self.dfolder, *package_parents, subdir), exist_ok=True) + rst_file = pj(self.dfolder, *package_parents, f"{subdir}.rst") + subdir_filelist = self._file_generate(package_parents + [subdir]) + + name = f"{self.name}" + for n in package_parents: + name += f".{n}" + name += f".{subdir}" content = [ - f"{self.name}.{subdir}", + name, self.title_line, - self.toctree.format("\n ".join(sorted(self.tree[rst_file]))), + self.toctree.format("\n ".join(sorted(subdir_filelist))), ] self.write(rst_file, content) - def modules_file(self): + if not package_parents: + upper = self.dfolder + else: + upper = package_parents[-1] + file_list.append(upper + f"/{subdir}.rst") + return file_list + + def modules_file(self, file_list): """Write the modules.rst""" content = [ self.name, self.title_line, - self.toctree.format("\n ".join(sorted(self.tree.keys()))), + self.toctree.format("\n ".join(sorted(file_list))), ] self.write("modules.rst", content) def start(self): self.cleanup() - self.single_file_module() - self.subdir_files_module() - self.modules_file() + file_list = self._file_generate([]) + self.modules_file(file_list) if __name__ == "__main__": diff --git a/docs/source/index.rst b/docs/source/index.rst index e45dd318..bd055a60 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,41 +1,196 @@ -Guide to TensorCircuit -================================== +TensorCircuit Documentation +=========================================================== .. image:: https://github.com/tencent-quantum-lab/tensorcircuit/blob/master/docs/source/statics/logov2.jpg?raw=true :target: https://github.com/tencent-quantum-lab/tensorcircuit -TensorCircuit is an open source quantum circuit and algorithm simulation framework. -* It is built for human beings. 👽 +**Welcome and congratulations! You have found TensorCircuit.** 👏 + +Introduction +--------------- + +TensorCircuit is an open-source high-performance quantum computing software framework in Python. + +* It is built for humans. 👽 * It is designed for speed, flexibility and elegance. 🚀 * It is empowered by advanced tensor network simulator engine. 🔋 +* It is ready for quantum hardware access with CPU/GPU/QPU (local/cloud) hybrid solutions. 🖥 + * It is implemented with industry-standard machine learning frameworks: TensorFlow, JAX, and PyTorch. 🤖 * It is compatible with machine learning engineering paradigms: automatic differentiation, just-in-time compilation, vectorized parallelism and GPU acceleration. 🛠 -Links ----------- +With the help of TensorCircuit, now get ready to efficiently and elegantly solve interesting and challenging quantum computing problems: from academic research prototype to industry application deployment. + + + + +Relevant Links +-------------------- + +TensorCircuit is created and maintained by `Shi-Xin Zhang `_ and this version is released by `Tencent Quantum Lab `_. -TensorCircuit is created and maintained by `Shi-Xin Zhang `_ and this version of the software is released by `Tencent Quantum Lab `_. The current core authors of TensorCircuit are `Shi-Xin Zhang `_ and `Yu-Qin Chen `_. -We also thank `contributions `_ from the lab and the open source community. +We also thank `contributions `_ from the open source community. + +If you have any further questions or collaboration ideas, please use the issue tracker or forum below, or send email to shixinzhang#tencent.com. + + +.. card-carousel:: 2 + + .. card:: Source code + :link: https://github.com/tencent-quantum-lab/tensorcircuit + :shadow: md + + GitHub + + + .. card:: Documentation + :link: https://tensorcircuit.readthedocs.io + :shadow: md + + Readthedocs + + + .. card:: Whitepaper + :link: https://quantum-journal.org/papers/q-2023-02-02-912/ + :shadow: md + + *Quantum* journal + + + .. card:: Issue Tracker + :link: https://github.com/tencent-quantum-lab/tensorcircuit/issues + :shadow: md + + GitHub Issues + + + .. card:: Forum + :link: https://github.com/tencent-quantum-lab/tensorcircuit/discussions + :shadow: md + + GitHub Discussions + + + .. card:: PyPI + :link: https://pypi.org/project/tensorcircuit + :shadow: md + + ``pip install`` + + + .. card:: DockerHub + :link: https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit + :shadow: md + + ``docker pull`` + + + .. card:: Application + :link: https://github.com/tencent-quantum-lab/tensorcircuit#research-and-applications + :shadow: md + + Research using TC + + + .. card:: Cloud + :link: https://quantum.tencent.com/cloud + + Tencent Quantum Cloud + + + + +.. + * Source code: https://github.com/tencent-quantum-lab/tensorcircuit + + * Documentation: https://tensorcircuit.readthedocs.io + + * Software Whitepaper (published in Quantum): https://quantum-journal.org/papers/q-2023-02-02-912/ + + * Issue Tracker: https://github.com/tencent-quantum-lab/tensorcircuit/issues + + * Forum: https://github.com/tencent-quantum-lab/tensorcircuit/discussions + + * PyPI page: https://pypi.org/project/tensorcircuit + + * DockerHub page: https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit + + * Research and projects based on TensorCircuit: https://github.com/tencent-quantum-lab/tensorcircuit#research-and-applications + + * Tencent Quantum Cloud Service: https://quantum.tencent.com/cloud/ + + + +Unified Quantum Programming +------------------------------ + +TensorCircuit is unifying infrastructures and interfaces for quantum computing. + +.. grid:: 1 2 4 4 + :margin: 0 + :padding: 0 + :gutter: 2 + + .. grid-item-card:: Unified Backends + :columns: 12 6 3 3 + :shadow: md + + Jax/TensorFlow/PyTorch/Numpy/Cupy + + .. grid-item-card:: Unified Devices + :columns: 12 6 3 3 + :shadow: md + + CPU/GPU/TPU + + .. grid-item-card:: Unified Providers + :columns: 12 6 3 3 + :shadow: md + + QPUs from different vendors + + .. grid-item-card:: Unified Resources + :columns: 12 6 3 3 + :shadow: md + + local/cloud/HPC + + +.. grid:: 1 2 4 4 + :margin: 0 + :padding: 0 + :gutter: 2 + + .. grid-item-card:: Unified Interfaces + :columns: 12 6 3 3 + :shadow: md + + numerical sim/hardware exp -* Source code: https://github.com/tencent-quantum-lab/tensorcircuit + .. grid-item-card:: Unified Engines + :columns: 12 6 3 3 + :shadow: md -* Software Whitepaper in Quantum: https://quantum-journal.org/papers/q-2023-02-02-912/ + ideal/noisy/approximate simulation -* Documentation: https://tensorcircuit.readthedocs.io + .. grid-item-card:: Unified Representations + :columns: 12 6 3 3 + :shadow: md -* Issue Tracker: https://github.com/tencent-quantum-lab/tensorcircuit/issues + from/to_IR/qiskit/openqasm/json -* Forum: https://github.com/tencent-quantum-lab/tensorcircuit/discussions + .. grid-item-card:: Unified Pipelines + :columns: 12 6 3 3 + :shadow: md -* PyPI page: https://pypi.org/project/tensorcircuit + stateless functional programming/stateful ML models -* DockerHub page: https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit diff --git a/docs/source/infras.rst b/docs/source/infras.rst index fb65098a..576de2a9 100644 --- a/docs/source/infras.rst +++ b/docs/source/infras.rst @@ -32,7 +32,7 @@ Overview of Modules **ML Interfaces Related Modules:** -- :py:mod:`tensorcircuit.interfaces`: Provide interfaces when quantum simulation backend is different from neural libraries. Currently include PyTorch and scipy optimizer interfaces. +- :py:mod:`tensorcircuit.interfaces`: Provide interfaces when quantum simulation backend is different from neural libraries. Currently include PyTorch, TensorFlow, NumPy and SciPy optimizer interfaces. - :py:mod:`tensorcircuit.keras`: Provide TensorFlow Keras layers, as well as wrappers of jitted function, save/load from tf side. @@ -62,7 +62,13 @@ Overview of Modules **Processing and error mitigation on sample results:** -- :py:mod:`tensorcircuit.results`: Provide tools to process count dict and to apply error mitigation +- :py:mod:`tensorcircuit.results`: Provide tools to process count dict and to apply error mitigation. + +**Cloud quantum hardware access module:** + +- :py:mod:`tensorcircuit.cloud`: Provide quantum cloud SDK that can access and program the real quantum hardware. + +- :py:mod:`tensorcircuit.compiler`: Provide compiler chains to compile and transform quantum circuits. **Shortcuts and Templates for Circuit Manipulation:** @@ -149,4 +155,29 @@ Also, note how ``^`` is overloaded as ``tn.connect`` to connect edges between di The convention to define the ``QuOperator`` is firstly giving ``out_edges`` (left index or row index of the matrix) and then giving ``in_edges`` (right index or column index of the matrix). The edges list contains edge objects from the TensorNetwork library. Such QuOperator/QuVector abstraction support various calculations only possible on matrix/vectors, such as matmul (``@``), adjoint (``.adjoint()``), scalar multiplication (``*``), tensor product (``|``), and partial trace (``.partial_trace(subsystems_to_trace_out)``). -To extract the matrix information of these objects, we can use ``.eval()`` or ``.eval_matrix()``, the former keeps the shape information of the tensor network while the latter gives the matrix representation with shape rank 2. \ No newline at end of file +To extract the matrix information of these objects, we can use ``.eval()`` or ``.eval_matrix()``, the former keeps the shape information of the tensor network while the latter gives the matrix representation with shape rank 2. + + +Quantum Cloud SDK: Layerwise API design +----------------------------------------------------- + +From lower level to higher level, a view of API layers invoking QPU calls + +- Vendor specific implementation of functional API in, e.g., :py:mod:`tensorcircuit.cloud.tencent` + +- Provider agnostic functional lower level API for task/device management in :py:mod:`tensorcircuit.cloud.apis` + +- Object oriented abstraction for Provider/Device/Task in :py:mod:`tensorcircuit.cloud.abstraction` + +- Unified batch submission interface as standarized in :py:meth:`tensorcircuit.cloud.wrapper.batch_submit_template` + +- Numerical and experimental unified all-in-one interface as :py:meth:`tensorcircuit.cloud.wrapper.batch_expectation_ps` + +- Application level code with QPU calls built directly on ``batch_expectation_ps`` or more fancy algorithms can be built on ``batch_submit_func`` so that these algorithms can be reused as long as one function ``batch_submit_func`` is defined for a given vendor (cheaper than defining a new provider from lower level). + + +.. Note:: + + For compiler, error mitigation and results post-processing parts, they can be carefully designed to decouple with the QPU calls, + so they are separately implemented in :py:mod:`tensorcircuit.compiler` and :py:mod:`tensorcircuit.results`, + and they can be independently useful even without tc's cloud access. diff --git a/docs/source/locale/zh/LC_MESSAGES/api.po b/docs/source/locale/zh/LC_MESSAGES/api.po index ce19c1ca..b7958e1e 100644 --- a/docs/source/locale/zh/LC_MESSAGES/api.po +++ b/docs/source/locale/zh/LC_MESSAGES/api.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: tensorcircuit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-02 14:19+0800\n" +"POT-Creation-Date: 2023-07-14 15:43+0800\n" "PO-Revision-Date: 2022-04-13 14:58+0800\n" "Last-Translator: Xinghan Yang\n" "Language: cn\n" @@ -16,7 +16,15 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.9.1\n" +"Generated-By: Babel 2.12.1\n" + +#: ../../source/api/about.rst:2 +msgid "tensorcircuit.about" +msgstr "" + +#: of tensorcircuit.about:1 tensorcircuit.about.about:1 +msgid "Prints the information for tensorcircuit installation and environment." +msgstr "" #: ../../source/api/abstractcircuit.rst:2 msgid "tensorcircuit.abstractcircuit" @@ -30,11 +38,17 @@ msgstr "" #: tensorcircuit.applications.utils.FakeModule:1 #: tensorcircuit.applications.vqes.VQNHE:1 #: tensorcircuit.backends.jax_backend.optax_optimizer:1 +#: tensorcircuit.backends.pytorch_backend.torch_jit_func:1 #: tensorcircuit.backends.pytorch_backend.torch_optimizer:1 #: tensorcircuit.backends.tensorflow_backend.keras_optimizer:1 +#: tensorcircuit.cloud.abstraction.Device:1 +#: tensorcircuit.cloud.abstraction.Provider:1 +#: tensorcircuit.cloud.abstraction.Task:1 +#: tensorcircuit.compiler.composed_compiler.Compiler:1 #: tensorcircuit.gates.GateF:1 tensorcircuit.noisemodel.NoiseConf:1 #: tensorcircuit.quantum.QuOperator:1 #: tensorcircuit.results.readout_mitigation.ReadoutMit:1 +#: tensorcircuit.templates.ensemble.bagging:1 #: tensorcircuit.templates.graphs.Grid2DCoord:1 msgid "Bases: :py:class:`object`" msgstr "" @@ -51,46 +65,55 @@ msgstr "" msgid "example" msgstr "" -#: keras.engine.base_layer.Layer.add_loss -#: keras.engine.base_layer.Layer.add_metric -#: keras.engine.base_layer.Layer.add_update -#: keras.engine.base_layer.Layer.add_weight keras.engine.base_layer.Layer.apply -#: keras.engine.base_layer.Layer.build -#: keras.engine.base_layer.Layer.compute_mask -#: keras.engine.base_layer.Layer.compute_output_shape -#: keras.engine.base_layer.Layer.compute_output_signature -#: keras.engine.base_layer.Layer.from_config -#: keras.engine.base_layer.Layer.get_input_at -#: keras.engine.base_layer.Layer.get_input_mask_at -#: keras.engine.base_layer.Layer.get_input_shape_at -#: keras.engine.base_layer.Layer.get_losses_for -#: keras.engine.base_layer.Layer.get_output_at -#: keras.engine.base_layer.Layer.get_output_mask_at -#: keras.engine.base_layer.Layer.get_output_shape_at -#: keras.engine.base_layer.Layer.get_updates_for -#: keras.engine.base_layer.Layer.set_weights keras.engine.training.Model.build -#: keras.engine.training.Model.compile keras.engine.training.Model.evaluate -#: keras.engine.training.Model.fit keras.engine.training.Model.from_config -#: keras.engine.training.Model.get_layer -#: keras.engine.training.Model.load_weights -#: keras.engine.training.Model.make_predict_function -#: keras.engine.training.Model.make_test_function -#: keras.engine.training.Model.make_train_function -#: keras.engine.training.Model.predict -#: keras.engine.training.Model.predict_on_batch -#: keras.engine.training.Model.predict_step keras.engine.training.Model.save -#: keras.engine.training.Model.save_spec -#: keras.engine.training.Model.save_weights keras.engine.training.Model.summary -#: keras.engine.training.Model.test_on_batch -#: keras.engine.training.Model.test_step keras.engine.training.Model.to_json -#: keras.engine.training.Model.to_yaml -#: keras.engine.training.Model.train_on_batch -#: keras.engine.training.Model.train_step -#: keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule.from_config +#: keras.src.engine.base_layer.Layer.add_loss +#: keras.src.engine.base_layer.Layer.add_metric +#: keras.src.engine.base_layer.Layer.add_update +#: keras.src.engine.base_layer.Layer.add_weight +#: keras.src.engine.base_layer.Layer.build +#: keras.src.engine.base_layer.Layer.build_from_config +#: keras.src.engine.base_layer.Layer.compute_mask +#: keras.src.engine.base_layer.Layer.compute_output_shape +#: keras.src.engine.base_layer.Layer.compute_output_signature +#: keras.src.engine.base_layer.Layer.from_config +#: keras.src.engine.base_layer.Layer.get_input_at +#: keras.src.engine.base_layer.Layer.get_input_mask_at +#: keras.src.engine.base_layer.Layer.get_input_shape_at +#: keras.src.engine.base_layer.Layer.get_output_at +#: keras.src.engine.base_layer.Layer.get_output_mask_at +#: keras.src.engine.base_layer.Layer.get_output_shape_at +#: keras.src.engine.base_layer.Layer.load_own_variables +#: keras.src.engine.base_layer.Layer.save_own_variables +#: keras.src.engine.base_layer.Layer.set_weights +#: keras.src.engine.training.Model.build +#: keras.src.engine.training.Model.compile +#: keras.src.engine.training.Model.compile_from_config +#: keras.src.engine.training.Model.compute_loss +#: keras.src.engine.training.Model.compute_metrics +#: keras.src.engine.training.Model.evaluate +#: keras.src.engine.training.Model.export keras.src.engine.training.Model.fit +#: keras.src.engine.training.Model.from_config +#: keras.src.engine.training.Model.get_layer +#: keras.src.engine.training.Model.load_weights +#: keras.src.engine.training.Model.make_predict_function +#: keras.src.engine.training.Model.make_test_function +#: keras.src.engine.training.Model.make_train_function +#: keras.src.engine.training.Model.predict +#: keras.src.engine.training.Model.predict_on_batch +#: keras.src.engine.training.Model.predict_step +#: keras.src.engine.training.Model.save +#: keras.src.engine.training.Model.save_weights +#: keras.src.engine.training.Model.summary +#: keras.src.engine.training.Model.test_on_batch +#: keras.src.engine.training.Model.test_step +#: keras.src.engine.training.Model.to_json +#: keras.src.engine.training.Model.to_yaml +#: keras.src.engine.training.Model.train_on_batch +#: keras.src.engine.training.Model.train_step +#: keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule.from_config #: of tensorcircuit.abstractcircuit.AbstractCircuit.append #: tensorcircuit.abstractcircuit.AbstractCircuit.append_from_qir -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list #: tensorcircuit.abstractcircuit.AbstractCircuit.barrier_instruction #: tensorcircuit.abstractcircuit.AbstractCircuit.cond_measurement #: tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps @@ -99,6 +122,7 @@ msgstr "" #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qir #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qiskit #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count +#: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition #: tensorcircuit.abstractcircuit.AbstractCircuit.initial_mapping #: tensorcircuit.abstractcircuit.AbstractCircuit.inverse #: tensorcircuit.abstractcircuit.AbstractCircuit.measure_instruction @@ -169,6 +193,7 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshape2 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshapem #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reverse +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan #: tensorcircuit.backends.abstract_backend.ExtendedBackend.scatter #: tensorcircuit.backends.abstract_backend.ExtendedBackend.set_random_state #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sizen @@ -183,6 +208,74 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_map #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_unflatten #: tensorcircuit.backends.backend_factory.get_backend +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acos +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.arange +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan2 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cast +#: tensorcircuit.backends.cupy_backend.CuPyBackend.concat +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix +#: tensorcircuit.backends.cupy_backend.CuPyBackend.copy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device_move +#: tensorcircuit.backends.cupy_backend.CuPyBackend.dtype +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eye +#: tensorcircuit.backends.cupy_backend.CuPyBackend.grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.i +#: tensorcircuit.backends.cupy_backend.CuPyBackend.imag +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor +#: tensorcircuit.backends.cupy_backend.CuPyBackend.jvp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.kron +#: tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.max +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mean +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mod +#: tensorcircuit.backends.cupy_backend.CuPyBackend.numpy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.onehot +#: tensorcircuit.backends.cupy_backend.CuPyBackend.real +#: tensorcircuit.backends.cupy_backend.CuPyBackend.relu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.reshape +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter +#: tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted +#: tensorcircuit.backends.cupy_backend.CuPyBackend.set_random_state +#: tensorcircuit.backends.cupy_backend.CuPyBackend.shape_tuple +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sign +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.size +#: tensorcircuit.backends.cupy_backend.CuPyBackend.softmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.solve +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stack +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.std +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tensordot +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tile +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense +#: tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vjp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vmap #: tensorcircuit.backends.jax_backend.JaxBackend.acos #: tensorcircuit.backends.jax_backend.JaxBackend.acosh #: tensorcircuit.backends.jax_backend.JaxBackend.arange @@ -227,6 +320,7 @@ msgstr "" #: tensorcircuit.backends.jax_backend.JaxBackend.real #: tensorcircuit.backends.jax_backend.JaxBackend.relu #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift +#: tensorcircuit.backends.jax_backend.JaxBackend.scan #: tensorcircuit.backends.jax_backend.JaxBackend.scatter #: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted #: tensorcircuit.backends.jax_backend.JaxBackend.set_random_state @@ -425,6 +519,7 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.real #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.right_shift +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scatter #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.set_random_state @@ -471,6 +566,7 @@ msgstr "" #: tensorcircuit.channels.evol_superop #: tensorcircuit.channels.generaldepolarizingchannel #: tensorcircuit.channels.is_hermitian_matrix +#: tensorcircuit.channels.isotropicdepolarizingchannel #: tensorcircuit.channels.kraus_identity_check #: tensorcircuit.channels.kraus_to_choi tensorcircuit.channels.kraus_to_super #: tensorcircuit.channels.kraus_to_super_gate @@ -489,6 +585,20 @@ msgstr "" #: tensorcircuit.circuit.Circuit.replace_mps_inputs #: tensorcircuit.circuit.Circuit.unitary_kraus #: tensorcircuit.circuit.Circuit.wavefunction tensorcircuit.circuit.expectation +#: tensorcircuit.cloud.abstraction.Device.topology_graph +#: tensorcircuit.cloud.abstraction.Task.details +#: tensorcircuit.cloud.abstraction.Task.results +#: tensorcircuit.cloud.apis.get_device tensorcircuit.cloud.apis.get_provider +#: tensorcircuit.cloud.apis.get_task tensorcircuit.cloud.apis.get_task_details +#: tensorcircuit.cloud.apis.get_token tensorcircuit.cloud.apis.list_devices +#: tensorcircuit.cloud.apis.list_properties tensorcircuit.cloud.apis.list_tasks +#: tensorcircuit.cloud.apis.resubmit_task tensorcircuit.cloud.apis.set_device +#: tensorcircuit.cloud.apis.set_provider tensorcircuit.cloud.apis.set_token +#: tensorcircuit.cloud.apis.submit_task tensorcircuit.cloud.tencent.submit_task +#: tensorcircuit.cloud.utils.set_proxy +#: tensorcircuit.cloud.wrapper.batch_expectation_ps +#: tensorcircuit.compiler.composed_compiler.DefaultCompiler.__init__ +#: tensorcircuit.compiler.qiskit_compiler.qiskit_compile #: tensorcircuit.cons.get_contractor tensorcircuit.cons.get_dtype #: tensorcircuit.cons.plain_contractor tensorcircuit.cons.runtime_backend #: tensorcircuit.cons.runtime_dtype tensorcircuit.cons.set_contractor @@ -501,6 +611,7 @@ msgstr "" #: tensorcircuit.densitymatrix.DMCircuit.expectation #: tensorcircuit.densitymatrix.DMCircuit.to_circuit #: tensorcircuit.densitymatrix.DMCircuit2.apply_general_kraus_delayed..apply +#: tensorcircuit.experimental.evol_global tensorcircuit.experimental.evol_local #: tensorcircuit.experimental.hamiltonian_evol #: tensorcircuit.experimental.parameter_shift_grad #: tensorcircuit.experimental.parameter_shift_grad_v2 @@ -522,6 +633,7 @@ msgstr "" #: tensorcircuit.interfaces.tensortrans.numpy_args_to_backend #: tensorcircuit.interfaces.tensortrans.which_backend #: tensorcircuit.interfaces.torch.torch_interface +#: tensorcircuit.interfaces.torch.torch_interface_kws #: tensorcircuit.keras.QuantumLayer.__init__ #: tensorcircuit.keras.QuantumLayer.build tensorcircuit.keras.load_func #: tensorcircuit.keras.output_asis_loss tensorcircuit.keras.save_func @@ -543,6 +655,8 @@ msgstr "" #: tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors #: tensorcircuit.mpscircuit.split_tensor #: tensorcircuit.noisemodel.NoiseConf.add_noise +#: tensorcircuit.noisemodel.NoiseConf.add_noise_by_condition +#: tensorcircuit.noisemodel.NoiseConf.channel_count #: tensorcircuit.noisemodel.apply_qir_with_noise #: tensorcircuit.noisemodel.circuit_with_noise #: tensorcircuit.noisemodel.expectation_noisfy @@ -579,7 +693,7 @@ msgstr "" #: tensorcircuit.quantum.gibbs_state #: tensorcircuit.quantum.heisenberg_hamiltonian tensorcircuit.quantum.identity #: tensorcircuit.quantum.measurement_counts -#: tensorcircuit.quantum.mutual_information +#: tensorcircuit.quantum.mutual_information tensorcircuit.quantum.ps2xyz #: tensorcircuit.quantum.quantum_constructor tensorcircuit.quantum.quimb2qop #: tensorcircuit.quantum.reduced_density_matrix #: tensorcircuit.quantum.renyi_entropy tensorcircuit.quantum.renyi_free_energy @@ -587,8 +701,15 @@ msgstr "" #: tensorcircuit.quantum.sample_bin2int tensorcircuit.quantum.sample_int2bin #: tensorcircuit.quantum.spin_by_basis tensorcircuit.quantum.taylorlnm #: tensorcircuit.quantum.tn2qop tensorcircuit.quantum.trace_distance -#: tensorcircuit.quantum.truncated_free_energy +#: tensorcircuit.quantum.truncated_free_energy tensorcircuit.quantum.xyz2ps #: tensorcircuit.results.counts.expectation +#: tensorcircuit.results.counts.plot_histogram +#: tensorcircuit.results.qem.qem_methods.add_dd +#: tensorcircuit.results.qem.qem_methods.apply_dd +#: tensorcircuit.results.qem.qem_methods.apply_rc +#: tensorcircuit.results.qem.qem_methods.apply_zne +#: tensorcircuit.results.qem.qem_methods.prune_ddcircuit +#: tensorcircuit.results.qem.qem_methods.used_qubits #: tensorcircuit.results.readout_mitigation.ReadoutMit.__init__ #: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction #: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation @@ -606,7 +727,6 @@ msgstr "" #: tensorcircuit.templates.blocks.example_block #: tensorcircuit.templates.blocks.qft #: tensorcircuit.templates.blocks.state_centric -#: tensorcircuit.templates.chems.get_ps #: tensorcircuit.templates.graphs.Grid2DCoord.__init__ #: tensorcircuit.templates.graphs.Grid2DCoord.all_cols #: tensorcircuit.templates.graphs.Grid2DCoord.all_rows @@ -619,6 +739,7 @@ msgstr "" #: tensorcircuit.templates.measurements.operator_expectation #: tensorcircuit.templates.measurements.sparse_expectation #: tensorcircuit.templates.measurements.spin_glass_measurements +#: tensorcircuit.torchnn.HardwareNet.__init__ #: tensorcircuit.torchnn.QuantumNet.__init__ tensorcircuit.translation.eqasm2tc #: tensorcircuit.translation.perm_matrix tensorcircuit.translation.qir2cirq #: tensorcircuit.translation.qir2json tensorcircuit.translation.qir2qiskit @@ -630,13 +751,23 @@ msgstr "" #: tensorcircuit.vis.render_pdf #: tensorflow.python.module.module.Module.with_name_scope #: tensornetwork.backends.abstract_backend.AbstractBackend.deserialize_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagonal +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigh #: tensornetwork.backends.abstract_backend.AbstractBackend.eigs #: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh #: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos +#: tensornetwork.backends.abstract_backend.AbstractBackend.eps #: tensornetwork.backends.abstract_backend.AbstractBackend.gmres +#: tensornetwork.backends.abstract_backend.AbstractBackend.index_update +#: tensornetwork.backends.abstract_backend.AbstractBackend.inv +#: tensornetwork.backends.abstract_backend.AbstractBackend.item #: tensornetwork.backends.abstract_backend.AbstractBackend.pivot #: tensornetwork.backends.abstract_backend.AbstractBackend.power #: tensornetwork.backends.abstract_backend.AbstractBackend.serialize_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.shape_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.slice +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace #: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal #: tensornetwork.backends.jax.jax_backend.JaxBackend.eigh #: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs @@ -701,7 +832,6 @@ msgstr "" #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tuple #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sign #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.slice -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace #: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator #: tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality @@ -725,18 +855,24 @@ msgstr "" #: torch.nn.modules.module.Module.get_buffer #: torch.nn.modules.module.Module.get_parameter #: torch.nn.modules.module.Module.get_submodule +#: torch.nn.modules.module.Module.ipu #: torch.nn.modules.module.Module.load_state_dict #: torch.nn.modules.module.Module.named_buffers #: torch.nn.modules.module.Module.named_modules #: torch.nn.modules.module.Module.named_parameters #: torch.nn.modules.module.Module.parameters #: torch.nn.modules.module.Module.register_buffer +#: torch.nn.modules.module.Module.register_forward_hook +#: torch.nn.modules.module.Module.register_forward_pre_hook +#: torch.nn.modules.module.Module.register_full_backward_hook +#: torch.nn.modules.module.Module.register_full_backward_pre_hook #: torch.nn.modules.module.Module.register_parameter #: torch.nn.modules.module.Module.requires_grad_ #: torch.nn.modules.module.Module.set_extra_state -#: torch.nn.modules.module.Module.to torch.nn.modules.module.Module.to_empty -#: torch.nn.modules.module.Module.train torch.nn.modules.module.Module.type -#: torch.nn.modules.module.Module.xpu torch.nn.modules.module.Module.zero_grad +#: torch.nn.modules.module.Module.state_dict torch.nn.modules.module.Module.to +#: torch.nn.modules.module.Module.to_empty torch.nn.modules.module.Module.train +#: torch.nn.modules.module.Module.type torch.nn.modules.module.Module.xpu +#: torch.nn.modules.module.Module.zero_grad msgid "Parameters" msgstr "" @@ -750,40 +886,44 @@ msgid "" "means plain concatenation." msgstr "" -#: keras.engine.base_layer.Layer.add_weight keras.engine.base_layer.Layer.apply -#: keras.engine.base_layer.Layer.compute_mask -#: keras.engine.base_layer.Layer.compute_output_shape -#: keras.engine.base_layer.Layer.compute_output_signature -#: keras.engine.base_layer.Layer.count_params -#: keras.engine.base_layer.Layer.from_config -#: keras.engine.base_layer.Layer.get_config -#: keras.engine.base_layer.Layer.get_input_at -#: keras.engine.base_layer.Layer.get_input_mask_at -#: keras.engine.base_layer.Layer.get_input_shape_at -#: keras.engine.base_layer.Layer.get_losses_for -#: keras.engine.base_layer.Layer.get_output_at -#: keras.engine.base_layer.Layer.get_output_mask_at -#: keras.engine.base_layer.Layer.get_output_shape_at -#: keras.engine.base_layer.Layer.get_updates_for -#: keras.engine.base_layer.Layer.get_weights -#: keras.engine.training.Model.evaluate keras.engine.training.Model.fit -#: keras.engine.training.Model.from_config -#: keras.engine.training.Model.get_config keras.engine.training.Model.get_layer -#: keras.engine.training.Model.get_weights -#: keras.engine.training.Model.load_weights -#: keras.engine.training.Model.make_predict_function -#: keras.engine.training.Model.make_test_function -#: keras.engine.training.Model.make_train_function -#: keras.engine.training.Model.predict -#: keras.engine.training.Model.predict_on_batch -#: keras.engine.training.Model.predict_step -#: keras.engine.training.Model.save_spec -#: keras.engine.training.Model.test_on_batch -#: keras.engine.training.Model.test_step keras.engine.training.Model.to_json -#: keras.engine.training.Model.to_yaml -#: keras.engine.training.Model.train_on_batch -#: keras.engine.training.Model.train_step -#: keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule.from_config +#: keras.src.engine.base_layer.Layer.add_weight +#: keras.src.engine.base_layer.Layer.compute_mask +#: keras.src.engine.base_layer.Layer.compute_output_shape +#: keras.src.engine.base_layer.Layer.compute_output_signature +#: keras.src.engine.base_layer.Layer.count_params +#: keras.src.engine.base_layer.Layer.from_config +#: keras.src.engine.base_layer.Layer.get_build_config +#: keras.src.engine.base_layer.Layer.get_config +#: keras.src.engine.base_layer.Layer.get_input_at +#: keras.src.engine.base_layer.Layer.get_input_mask_at +#: keras.src.engine.base_layer.Layer.get_input_shape_at +#: keras.src.engine.base_layer.Layer.get_output_at +#: keras.src.engine.base_layer.Layer.get_output_mask_at +#: keras.src.engine.base_layer.Layer.get_output_shape_at +#: keras.src.engine.base_layer.Layer.get_weights +#: keras.src.engine.training.Model.compute_loss +#: keras.src.engine.training.Model.compute_metrics +#: keras.src.engine.training.Model.evaluate keras.src.engine.training.Model.fit +#: keras.src.engine.training.Model.from_config +#: keras.src.engine.training.Model.get_compile_config +#: keras.src.engine.training.Model.get_config +#: keras.src.engine.training.Model.get_layer +#: keras.src.engine.training.Model.get_metrics_result +#: keras.src.engine.training.Model.get_weight_paths +#: keras.src.engine.training.Model.get_weights +#: keras.src.engine.training.Model.make_predict_function +#: keras.src.engine.training.Model.make_test_function +#: keras.src.engine.training.Model.make_train_function +#: keras.src.engine.training.Model.predict +#: keras.src.engine.training.Model.predict_on_batch +#: keras.src.engine.training.Model.predict_step +#: keras.src.engine.training.Model.test_on_batch +#: keras.src.engine.training.Model.test_step +#: keras.src.engine.training.Model.to_json +#: keras.src.engine.training.Model.to_yaml +#: keras.src.engine.training.Model.train_on_batch +#: keras.src.engine.training.Model.train_step +#: keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule.from_config #: of tensorcircuit.abstractcircuit.AbstractCircuit.append #: tensorcircuit.abstractcircuit.AbstractCircuit.cond_measurement #: tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps @@ -792,6 +932,7 @@ msgstr "" #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qir #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qiskit #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count +#: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_summary #: tensorcircuit.abstractcircuit.AbstractCircuit.get_positional_logical_mapping #: tensorcircuit.abstractcircuit.AbstractCircuit.initial_mapping @@ -984,6 +1125,7 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshape2 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshapem #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reverse +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan #: tensorcircuit.backends.abstract_backend.ExtendedBackend.scatter #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sizen #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul @@ -997,6 +1139,78 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_map #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_unflatten #: tensorcircuit.backends.backend_factory.get_backend +#: tensorcircuit.backends.cupy_backend.CuPyBackend.abs +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acos +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.arange +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan2 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cast +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond +#: tensorcircuit.backends.cupy_backend.CuPyBackend.conj +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix +#: tensorcircuit.backends.cupy_backend.CuPyBackend.copy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cos +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device_move +#: tensorcircuit.backends.cupy_backend.CuPyBackend.dtype +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.expm +#: tensorcircuit.backends.cupy_backend.CuPyBackend.grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.i +#: tensorcircuit.backends.cupy_backend.CuPyBackend.imag +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor +#: tensorcircuit.backends.cupy_backend.CuPyBackend.jit +#: tensorcircuit.backends.cupy_backend.CuPyBackend.jvp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.kron +#: tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.max +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mean +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mod +#: tensorcircuit.backends.cupy_backend.CuPyBackend.multiply +#: tensorcircuit.backends.cupy_backend.CuPyBackend.numpy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.onehot +#: tensorcircuit.backends.cupy_backend.CuPyBackend.real +#: tensorcircuit.backends.cupy_backend.CuPyBackend.relu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.reshape +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter +#: tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted +#: tensorcircuit.backends.cupy_backend.CuPyBackend.shape_tuple +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.size +#: tensorcircuit.backends.cupy_backend.CuPyBackend.softmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.solve +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stack +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.std +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sum +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tile +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense +#: tensorcircuit.backends.cupy_backend.CuPyBackend.transpose +#: tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vjp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vmap #: tensorcircuit.backends.jax_backend.JaxBackend.abs #: tensorcircuit.backends.jax_backend.JaxBackend.acos #: tensorcircuit.backends.jax_backend.JaxBackend.acosh @@ -1043,6 +1257,7 @@ msgstr "" #: tensorcircuit.backends.jax_backend.JaxBackend.real #: tensorcircuit.backends.jax_backend.JaxBackend.relu #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift +#: tensorcircuit.backends.jax_backend.JaxBackend.scan #: tensorcircuit.backends.jax_backend.JaxBackend.scatter #: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted #: tensorcircuit.backends.jax_backend.JaxBackend.sigmoid @@ -1250,6 +1465,7 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.real #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.right_shift +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scatter #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sigmoid @@ -1297,6 +1513,7 @@ msgstr "" #: tensorcircuit.channels.evol_superop #: tensorcircuit.channels.generaldepolarizingchannel #: tensorcircuit.channels.is_hermitian_matrix +#: tensorcircuit.channels.isotropicdepolarizingchannel #: tensorcircuit.channels.kraus_to_choi tensorcircuit.channels.kraus_to_super #: tensorcircuit.channels.kraus_to_super_gate #: tensorcircuit.channels.krausgate_to_krausmatrix @@ -1312,6 +1529,26 @@ msgstr "" #: tensorcircuit.circuit.Circuit.measure_reference #: tensorcircuit.circuit.Circuit.unitary_kraus #: tensorcircuit.circuit.Circuit.wavefunction tensorcircuit.circuit.expectation +#: tensorcircuit.cloud.abstraction.Device.list_properties +#: tensorcircuit.cloud.abstraction.Device.native_gates +#: tensorcircuit.cloud.abstraction.Device.topology +#: tensorcircuit.cloud.abstraction.Device.topology_graph +#: tensorcircuit.cloud.abstraction.Task.details +#: tensorcircuit.cloud.abstraction.Task.get_device +#: tensorcircuit.cloud.abstraction.Task.resubmit +#: tensorcircuit.cloud.abstraction.Task.results +#: tensorcircuit.cloud.abstraction.Task.state +#: tensorcircuit.cloud.apis.get_device tensorcircuit.cloud.apis.get_provider +#: tensorcircuit.cloud.apis.get_task tensorcircuit.cloud.apis.get_task_details +#: tensorcircuit.cloud.apis.get_token tensorcircuit.cloud.apis.list_devices +#: tensorcircuit.cloud.apis.list_properties +#: tensorcircuit.cloud.apis.list_providers tensorcircuit.cloud.apis.list_tasks +#: tensorcircuit.cloud.apis.resubmit_task tensorcircuit.cloud.apis.set_device +#: tensorcircuit.cloud.apis.set_provider tensorcircuit.cloud.apis.set_token +#: tensorcircuit.cloud.apis.submit_task tensorcircuit.cloud.tencent.submit_task +#: tensorcircuit.cloud.utils.set_proxy +#: tensorcircuit.cloud.wrapper.batch_expectation_ps +#: tensorcircuit.compiler.qiskit_compiler.qiskit_compile #: tensorcircuit.cons.get_contractor tensorcircuit.cons.get_dtype #: tensorcircuit.cons.plain_contractor tensorcircuit.cons.set_contractor #: tensorcircuit.cons.set_dtype tensorcircuit.cons.set_function_backend @@ -1323,6 +1560,7 @@ msgstr "" #: tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator #: tensorcircuit.densitymatrix.DMCircuit.to_circuit #: tensorcircuit.densitymatrix.DMCircuit.wavefunction +#: tensorcircuit.experimental.evol_global tensorcircuit.experimental.evol_local #: tensorcircuit.experimental.hamiltonian_evol #: tensorcircuit.experimental.parameter_shift_grad #: tensorcircuit.experimental.parameter_shift_grad_v2 @@ -1346,6 +1584,24 @@ msgstr "" #: tensorcircuit.interfaces.tensortrans.numpy_args_to_backend #: tensorcircuit.interfaces.tensortrans.which_backend #: tensorcircuit.interfaces.torch.torch_interface +#: tensorcircuit.interfaces.torch.torch_interface_kws +#: tensorcircuit.keras.HardwareLayer.compute_dtype +#: tensorcircuit.keras.HardwareLayer.input +#: tensorcircuit.keras.HardwareLayer.input_mask +#: tensorcircuit.keras.HardwareLayer.input_shape +#: tensorcircuit.keras.HardwareLayer.input_spec +#: tensorcircuit.keras.HardwareLayer.losses +#: tensorcircuit.keras.HardwareLayer.metrics +#: tensorcircuit.keras.HardwareLayer.non_trainable_variables +#: tensorcircuit.keras.HardwareLayer.non_trainable_weights +#: tensorcircuit.keras.HardwareLayer.output +#: tensorcircuit.keras.HardwareLayer.output_mask +#: tensorcircuit.keras.HardwareLayer.output_shape +#: tensorcircuit.keras.HardwareLayer.submodules +#: tensorcircuit.keras.HardwareLayer.trainable_variables +#: tensorcircuit.keras.HardwareLayer.trainable_weights +#: tensorcircuit.keras.HardwareLayer.variables +#: tensorcircuit.keras.HardwareLayer.weights #: tensorcircuit.keras.QuantumLayer.compute_dtype #: tensorcircuit.keras.QuantumLayer.input #: tensorcircuit.keras.QuantumLayer.input_mask @@ -1382,6 +1638,7 @@ msgstr "" #: tensorcircuit.mpscircuit.MPSCircuit.wavefunction #: tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors #: tensorcircuit.mpscircuit.split_tensor +#: tensorcircuit.noisemodel.NoiseConf.channel_count #: tensorcircuit.noisemodel.apply_qir_with_noise #: tensorcircuit.noisemodel.circuit_with_noise #: tensorcircuit.noisemodel.expectation_noisfy @@ -1416,7 +1673,7 @@ msgstr "" #: tensorcircuit.quantum.gibbs_state #: tensorcircuit.quantum.heisenberg_hamiltonian tensorcircuit.quantum.identity #: tensorcircuit.quantum.measurement_counts -#: tensorcircuit.quantum.mutual_information +#: tensorcircuit.quantum.mutual_information tensorcircuit.quantum.ps2xyz #: tensorcircuit.quantum.quantum_constructor tensorcircuit.quantum.quimb2qop #: tensorcircuit.quantum.reduced_density_matrix #: tensorcircuit.quantum.renyi_entropy tensorcircuit.quantum.renyi_free_energy @@ -1425,8 +1682,15 @@ msgstr "" #: tensorcircuit.quantum.spin_by_basis tensorcircuit.quantum.taylorlnm #: tensorcircuit.quantum.tn2qop tensorcircuit.quantum.trace_distance #: tensorcircuit.quantum.trace_product -#: tensorcircuit.quantum.truncated_free_energy +#: tensorcircuit.quantum.truncated_free_energy tensorcircuit.quantum.xyz2ps #: tensorcircuit.results.counts.expectation +#: tensorcircuit.results.counts.plot_histogram +#: tensorcircuit.results.qem.qem_methods.add_dd +#: tensorcircuit.results.qem.qem_methods.apply_dd +#: tensorcircuit.results.qem.qem_methods.apply_rc +#: tensorcircuit.results.qem.qem_methods.apply_zne +#: tensorcircuit.results.qem.qem_methods.prune_ddcircuit +#: tensorcircuit.results.qem.qem_methods.used_qubits #: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation #: tensorcircuit.results.readout_mitigation.ReadoutMit.expectation #: tensorcircuit.results.readout_mitigation.ReadoutMit.get_matrix @@ -1442,7 +1706,6 @@ msgstr "" #: tensorcircuit.templates.blocks.example_block #: tensorcircuit.templates.blocks.qft #: tensorcircuit.templates.blocks.state_centric -#: tensorcircuit.templates.chems.get_ps #: tensorcircuit.templates.graphs.Grid2DCoord.all_cols #: tensorcircuit.templates.graphs.Grid2DCoord.all_rows #: tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph @@ -1463,16 +1726,32 @@ msgstr "" #: tensorcircuit.utils.return_partial tensorcircuit.vis.gate_name_trans #: tensorcircuit.vis.qir2tex tensorcircuit.vis.render_pdf #: tensorflow.python.module.module.Module.with_name_scope +#: tensornetwork.backends.abstract_backend.AbstractBackend.addition +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_left_multiplication +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_right_multiplication #: tensornetwork.backends.abstract_backend.AbstractBackend.deserialize_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagflat +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagonal +#: tensornetwork.backends.abstract_backend.AbstractBackend.divide +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigh #: tensornetwork.backends.abstract_backend.AbstractBackend.eigs #: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh #: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos +#: tensornetwork.backends.abstract_backend.AbstractBackend.eps #: tensornetwork.backends.abstract_backend.AbstractBackend.exp #: tensornetwork.backends.abstract_backend.AbstractBackend.gmres +#: tensornetwork.backends.abstract_backend.AbstractBackend.inv +#: tensornetwork.backends.abstract_backend.AbstractBackend.item #: tensornetwork.backends.abstract_backend.AbstractBackend.log +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul #: tensornetwork.backends.abstract_backend.AbstractBackend.pivot #: tensornetwork.backends.abstract_backend.AbstractBackend.power +#: tensornetwork.backends.abstract_backend.AbstractBackend.random_uniform #: tensornetwork.backends.abstract_backend.AbstractBackend.serialize_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.shape_tensor +#: tensornetwork.backends.abstract_backend.AbstractBackend.subtraction +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace #: tensornetwork.backends.jax.jax_backend.JaxBackend.addition #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_left_multiplication #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_right_multiplication @@ -1571,7 +1850,6 @@ msgstr "" #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tuple #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.subtraction #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.transpose #: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator @@ -1595,12 +1873,14 @@ msgstr "" #: torch.nn.modules.module.Module.get_extra_state #: torch.nn.modules.module.Module.get_parameter #: torch.nn.modules.module.Module.get_submodule -#: torch.nn.modules.module.Module.half +#: torch.nn.modules.module.Module.half torch.nn.modules.module.Module.ipu #: torch.nn.modules.module.Module.load_state_dict #: torch.nn.modules.module.Module.register_backward_hook #: torch.nn.modules.module.Module.register_forward_hook #: torch.nn.modules.module.Module.register_forward_pre_hook #: torch.nn.modules.module.Module.register_full_backward_hook +#: torch.nn.modules.module.Module.register_full_backward_pre_hook +#: torch.nn.modules.module.Module.register_load_state_dict_post_hook #: torch.nn.modules.module.Module.requires_grad_ #: torch.nn.modules.module.Module.state_dict torch.nn.modules.module.Module.to #: torch.nn.modules.module.Module.to_empty torch.nn.modules.module.Module.train @@ -1621,6 +1901,7 @@ msgstr "" #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qir #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qiskit #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count +#: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_summary #: tensorcircuit.abstractcircuit.AbstractCircuit.get_positional_logical_mapping #: tensorcircuit.abstractcircuit.AbstractCircuit.initial_mapping @@ -1653,6 +1934,7 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshape2 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshapem #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reverse +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan #: tensorcircuit.backends.abstract_backend.ExtendedBackend.scatter #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sizen #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul @@ -1666,6 +1948,70 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_map #: tensorcircuit.backends.abstract_backend.ExtendedBackend.tree_unflatten #: tensorcircuit.backends.backend_factory.get_backend +#: tensorcircuit.backends.cupy_backend.CuPyBackend.abs +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acos +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.arange +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asin +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan2 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cast +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix +#: tensorcircuit.backends.cupy_backend.CuPyBackend.copy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cosh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device_move +#: tensorcircuit.backends.cupy_backend.CuPyBackend.dtype +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.i +#: tensorcircuit.backends.cupy_backend.CuPyBackend.imag +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor +#: tensorcircuit.backends.cupy_backend.CuPyBackend.jit +#: tensorcircuit.backends.cupy_backend.CuPyBackend.jvp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.kron +#: tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.max +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mean +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mod +#: tensorcircuit.backends.cupy_backend.CuPyBackend.numpy +#: tensorcircuit.backends.cupy_backend.CuPyBackend.onehot +#: tensorcircuit.backends.cupy_backend.CuPyBackend.real +#: tensorcircuit.backends.cupy_backend.CuPyBackend.relu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter +#: tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sinh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.size +#: tensorcircuit.backends.cupy_backend.CuPyBackend.softmax +#: tensorcircuit.backends.cupy_backend.CuPyBackend.solve +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stack +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu +#: tensorcircuit.backends.cupy_backend.CuPyBackend.std +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sum +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tan +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tanh +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tile +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense +#: tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vjp +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vmap #: tensorcircuit.backends.jax_backend.JaxBackend.abs #: tensorcircuit.backends.jax_backend.JaxBackend.acos #: tensorcircuit.backends.jax_backend.JaxBackend.acosh @@ -1710,6 +2056,7 @@ msgstr "" #: tensorcircuit.backends.jax_backend.JaxBackend.real #: tensorcircuit.backends.jax_backend.JaxBackend.relu #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift +#: tensorcircuit.backends.jax_backend.JaxBackend.scan #: tensorcircuit.backends.jax_backend.JaxBackend.scatter #: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted #: tensorcircuit.backends.jax_backend.JaxBackend.sigmoid @@ -1907,6 +2254,7 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.real #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.right_shift +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scatter #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sigmoid @@ -1953,6 +2301,7 @@ msgstr "" #: tensorcircuit.channels.evol_superop #: tensorcircuit.channels.generaldepolarizingchannel #: tensorcircuit.channels.is_hermitian_matrix +#: tensorcircuit.channels.isotropicdepolarizingchannel #: tensorcircuit.channels.kraus_to_choi tensorcircuit.channels.kraus_to_super #: tensorcircuit.channels.kraus_to_super_gate #: tensorcircuit.channels.krausgate_to_krausmatrix @@ -1968,6 +2317,25 @@ msgstr "" #: tensorcircuit.circuit.Circuit.measure_reference #: tensorcircuit.circuit.Circuit.unitary_kraus #: tensorcircuit.circuit.Circuit.wavefunction tensorcircuit.circuit.expectation +#: tensorcircuit.cloud.abstraction.Device.list_properties +#: tensorcircuit.cloud.abstraction.Device.native_gates +#: tensorcircuit.cloud.abstraction.Device.topology +#: tensorcircuit.cloud.abstraction.Device.topology_graph +#: tensorcircuit.cloud.abstraction.Task.details +#: tensorcircuit.cloud.abstraction.Task.get_device +#: tensorcircuit.cloud.abstraction.Task.resubmit +#: tensorcircuit.cloud.abstraction.Task.results +#: tensorcircuit.cloud.abstraction.Task.state +#: tensorcircuit.cloud.apis.get_device tensorcircuit.cloud.apis.get_provider +#: tensorcircuit.cloud.apis.get_task tensorcircuit.cloud.apis.get_task_details +#: tensorcircuit.cloud.apis.get_token tensorcircuit.cloud.apis.list_devices +#: tensorcircuit.cloud.apis.list_properties +#: tensorcircuit.cloud.apis.list_providers tensorcircuit.cloud.apis.list_tasks +#: tensorcircuit.cloud.apis.resubmit_task tensorcircuit.cloud.apis.set_device +#: tensorcircuit.cloud.apis.set_provider tensorcircuit.cloud.apis.set_token +#: tensorcircuit.cloud.apis.submit_task tensorcircuit.cloud.tencent.submit_task +#: tensorcircuit.cloud.wrapper.batch_expectation_ps +#: tensorcircuit.compiler.qiskit_compiler.qiskit_compile #: tensorcircuit.cons.get_contractor tensorcircuit.cons.get_dtype #: tensorcircuit.cons.plain_contractor tensorcircuit.cons.runtime_backend #: tensorcircuit.cons.runtime_contractor tensorcircuit.cons.runtime_dtype @@ -1981,6 +2349,7 @@ msgstr "" #: tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator #: tensorcircuit.densitymatrix.DMCircuit.to_circuit #: tensorcircuit.densitymatrix.DMCircuit.wavefunction +#: tensorcircuit.experimental.evol_global tensorcircuit.experimental.evol_local #: tensorcircuit.experimental.hamiltonian_evol #: tensorcircuit.experimental.parameter_shift_grad #: tensorcircuit.experimental.parameter_shift_grad_v2 @@ -2003,8 +2372,9 @@ msgstr "" #: tensorcircuit.interfaces.tensortrans.general_args_to_numpy #: tensorcircuit.interfaces.tensortrans.numpy_args_to_backend #: tensorcircuit.interfaces.tensortrans.which_backend -#: tensorcircuit.interfaces.torch.torch_interface tensorcircuit.keras.load_func -#: tensorcircuit.keras.output_asis_loss +#: tensorcircuit.interfaces.torch.torch_interface +#: tensorcircuit.interfaces.torch.torch_interface_kws +#: tensorcircuit.keras.load_func tensorcircuit.keras.output_asis_loss #: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate #: tensorcircuit.mps_base.FiniteMPS.measure_local_operator #: tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator @@ -2023,6 +2393,7 @@ msgstr "" #: tensorcircuit.mpscircuit.MPSCircuit.wavefunction #: tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors #: tensorcircuit.mpscircuit.split_tensor +#: tensorcircuit.noisemodel.NoiseConf.channel_count #: tensorcircuit.noisemodel.apply_qir_with_noise #: tensorcircuit.noisemodel.circuit_with_noise #: tensorcircuit.noisemodel.expectation_noisfy @@ -2057,7 +2428,7 @@ msgstr "" #: tensorcircuit.quantum.gibbs_state #: tensorcircuit.quantum.heisenberg_hamiltonian tensorcircuit.quantum.identity #: tensorcircuit.quantum.measurement_counts -#: tensorcircuit.quantum.mutual_information +#: tensorcircuit.quantum.mutual_information tensorcircuit.quantum.ps2xyz #: tensorcircuit.quantum.quantum_constructor tensorcircuit.quantum.quimb2qop #: tensorcircuit.quantum.reduced_density_matrix #: tensorcircuit.quantum.renyi_entropy tensorcircuit.quantum.renyi_free_energy @@ -2066,8 +2437,15 @@ msgstr "" #: tensorcircuit.quantum.spin_by_basis tensorcircuit.quantum.taylorlnm #: tensorcircuit.quantum.tn2qop tensorcircuit.quantum.trace_distance #: tensorcircuit.quantum.trace_product -#: tensorcircuit.quantum.truncated_free_energy +#: tensorcircuit.quantum.truncated_free_energy tensorcircuit.quantum.xyz2ps #: tensorcircuit.results.counts.expectation +#: tensorcircuit.results.counts.plot_histogram +#: tensorcircuit.results.qem.qem_methods.add_dd +#: tensorcircuit.results.qem.qem_methods.apply_dd +#: tensorcircuit.results.qem.qem_methods.apply_rc +#: tensorcircuit.results.qem.qem_methods.apply_zne +#: tensorcircuit.results.qem.qem_methods.prune_ddcircuit +#: tensorcircuit.results.qem.qem_methods.used_qubits #: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation #: tensorcircuit.results.readout_mitigation.ReadoutMit.expectation #: tensorcircuit.results.readout_mitigation.ReadoutMit.get_matrix @@ -2083,7 +2461,6 @@ msgstr "" #: tensorcircuit.templates.blocks.example_block #: tensorcircuit.templates.blocks.qft #: tensorcircuit.templates.blocks.state_centric -#: tensorcircuit.templates.chems.get_ps #: tensorcircuit.templates.graphs.Grid2DCoord.all_cols #: tensorcircuit.templates.graphs.Grid2DCoord.all_rows #: tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph @@ -2103,9 +2480,20 @@ msgstr "" #: tensorcircuit.utils.benchmark tensorcircuit.utils.is_m1mac #: tensorcircuit.utils.return_partial tensorcircuit.vis.gate_name_trans #: tensorcircuit.vis.qir2tex tensorcircuit.vis.render_pdf +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_left_multiplication +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_right_multiplication +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagflat +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagonal +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigh #: tensornetwork.backends.abstract_backend.AbstractBackend.eigs #: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh +#: tensornetwork.backends.abstract_backend.AbstractBackend.eps #: tensornetwork.backends.abstract_backend.AbstractBackend.gmres +#: tensornetwork.backends.abstract_backend.AbstractBackend.inv +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul +#: tensornetwork.backends.abstract_backend.AbstractBackend.random_uniform +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_left_multiplication #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_right_multiplication #: tensornetwork.backends.jax.jax_backend.JaxBackend.diagflat @@ -2151,7 +2539,6 @@ msgstr "" #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.inv #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.random_uniform #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace #: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator #: tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality @@ -2168,12 +2555,14 @@ msgstr "" #: torch.nn.modules.module.Module.get_extra_state #: torch.nn.modules.module.Module.get_parameter #: torch.nn.modules.module.Module.get_submodule -#: torch.nn.modules.module.Module.half +#: torch.nn.modules.module.Module.half torch.nn.modules.module.Module.ipu #: torch.nn.modules.module.Module.load_state_dict #: torch.nn.modules.module.Module.register_backward_hook #: torch.nn.modules.module.Module.register_forward_hook #: torch.nn.modules.module.Module.register_forward_pre_hook #: torch.nn.modules.module.Module.register_full_backward_hook +#: torch.nn.modules.module.Module.register_full_backward_pre_hook +#: torch.nn.modules.module.Module.register_load_state_dict_post_hook #: torch.nn.modules.module.Module.requires_grad_ #: torch.nn.modules.module.Module.state_dict torch.nn.modules.module.Module.to #: torch.nn.modules.module.Module.to_empty torch.nn.modules.module.Module.train @@ -2194,7 +2583,10 @@ msgstr "" #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qir #: tensorcircuit.abstractcircuit.AbstractCircuit.from_qiskit #: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count +#: tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition #: tensorcircuit.abstractcircuit.AbstractCircuit.to_qir +#: tensorcircuit.backends.cupy_backend.CuPyBackend.grad +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad #: tensorcircuit.backends.jax_backend.JaxBackend.grad #: tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad #: tensorcircuit.backends.numpy_backend.NumpyBackend.grad @@ -2215,20 +2607,23 @@ msgstr "" #: tensorcircuit.channels.amplitudedampingchannel #: tensorcircuit.channels.depolarizingchannel #: tensorcircuit.channels.generaldepolarizingchannel +#: tensorcircuit.channels.isotropicdepolarizingchannel #: tensorcircuit.channels.phasedampingchannel #: tensorcircuit.channels.resetchannel #: tensorcircuit.channels.thermalrelaxationchannel #: tensorcircuit.circuit.Circuit.expectation #: tensorcircuit.circuit.Circuit.measure_reference #: tensorcircuit.circuit.Circuit.replace_mps_inputs +#: tensorcircuit.cloud.wrapper.batch_expectation_ps #: tensorcircuit.cons.set_tensornetwork_backend tensorcircuit.gates.bmatrix #: tensorcircuit.gates.matrix_for_gate tensorcircuit.gates.num_to_tensor #: tensorcircuit.interfaces.numpy.numpy_interface #: tensorcircuit.interfaces.scipy.scipy_optimize_interface #: tensorcircuit.interfaces.tensorflow.tensorflow_interface #: tensorcircuit.interfaces.tensortrans.args_to_tensor -#: tensorcircuit.interfaces.torch.torch_interface tensorcircuit.keras.load_func -#: tensorcircuit.keras.save_func +#: tensorcircuit.interfaces.torch.torch_interface +#: tensorcircuit.interfaces.torch.torch_interface_kws +#: tensorcircuit.keras.load_func tensorcircuit.keras.save_func #: tensorcircuit.quantum.QuAdjointVector.from_tensor #: tensorcircuit.quantum.QuOperator.from_tensor #: tensorcircuit.quantum.QuOperator.tensor_product @@ -2242,6 +2637,7 @@ msgstr "" #: tensorcircuit.quantum.quantum_constructor #: tensorcircuit.quantum.renyi_free_energy tensorcircuit.quantum.spin_by_basis #: tensorcircuit.quantum.trace_product tensorcircuit.simplify.infer_new_shape +#: tensorcircuit.torchnn.HardwareNet.__init__ #: tensorcircuit.torchnn.QuantumNet.__init__ tensorcircuit.translation.qir2cirq #: tensorcircuit.translation.qir2qiskit tensorcircuit.translation.qiskit2tc #: tensorcircuit.utils.append tensorcircuit.utils.return_partial @@ -2266,6 +2662,8 @@ msgid "add a barrier instruction flag, no effect on numerical simulation" msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.barrier_instruction:3 +#: tensorcircuit.abstractcircuit.AbstractCircuit.measure_instruction:3 +#: tensorcircuit.abstractcircuit.AbstractCircuit.reset_instruction:3 msgid "the corresponding qubits" msgstr "" @@ -2316,6 +2714,7 @@ msgid "" "Visualise the circuit. This method recevies the keywords as same as " "qiskit.circuit.QuantumCircuit.draw. More details can be found here: " "https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.draw.html." +" Interesting kws options include: ``idle_wires``(bool)" msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:1 @@ -2340,10 +2739,17 @@ msgid "sites to apply Z gate, defaults to None" msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:32 +msgid "" +"or one can apply a ps structures instead of ``x``, ``y``, ``z``, e.g. [0," +" 1, 3, 0, 2, 2] for X_1Z_2Y_4Y_5 defaults to None, ``ps`` can overwrite " +"``x``, ``y`` and ``z``" +msgstr "" + +#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:36 msgid "whether to cache and reuse the wavefunction, defaults to True" msgstr "" -#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:34 +#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:38 #: tensorcircuit.basecircuit.BaseCircuit.sample_expectation_ps:46 #: tensorcircuit.circuit.Circuit.expectation:32 #: tensorcircuit.densitymatrix.DMCircuit.expectation:8 @@ -2352,7 +2758,7 @@ msgstr "" msgid "Noise Configuration, defaults to None" msgstr "" -#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:36 +#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:40 #: tensorcircuit.basecircuit.BaseCircuit.sample_expectation_ps:48 #: tensorcircuit.circuit.Circuit.expectation:34 #: tensorcircuit.noisemodel.expectation_noisfy:7 @@ -2361,7 +2767,7 @@ msgid "" " to 1000" msgstr "" -#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:38 +#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:42 #: tensorcircuit.basecircuit.BaseCircuit.sample_expectation_ps:50 #: tensorcircuit.circuit.Circuit.expectation:36 #: tensorcircuit.densitymatrix.DMCircuit.expectation:10 @@ -2372,7 +2778,7 @@ msgid "" "None, used for noisfy circuit sampling" msgstr "" -#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:41 +#: of tensorcircuit.abstractcircuit.AbstractCircuit.expectation_ps:45 msgid "Expectation value" msgstr "" @@ -2385,11 +2791,23 @@ msgstr "" #: tensorcircuit.abstractcircuit.AbstractCircuit.from_json_file:7 #: tensorcircuit.abstractcircuit.AbstractCircuit.initial_mapping:9 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.from_dlpack:5 +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan:4 +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan:6 +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan:8 +#: tensorcircuit.backends.abstract_backend.ExtendedBackend.scan:10 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.to_dlpack:3 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.to_dlpack:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.arange:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mean:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.std:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.std:12 #: tensorcircuit.backends.jax_backend.JaxBackend.arange:9 #: tensorcircuit.backends.jax_backend.JaxBackend.from_dlpack:5 #: tensorcircuit.backends.jax_backend.JaxBackend.mean:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.scan:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.scan:6 +#: tensorcircuit.backends.jax_backend.JaxBackend.scan:8 +#: tensorcircuit.backends.jax_backend.JaxBackend.scan:10 #: tensorcircuit.backends.jax_backend.JaxBackend.std:3 #: tensorcircuit.backends.jax_backend.JaxBackend.std:12 #: tensorcircuit.backends.jax_backend.JaxBackend.to_dlpack:3 @@ -2408,6 +2826,10 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.arange:9 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.from_dlpack:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mean:9 +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan:4 +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan:6 +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan:8 +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan:10 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.std:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.std:12 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.to_dlpack:3 @@ -2415,14 +2837,41 @@ msgstr "" #: tensorcircuit.basecircuit.BaseCircuit.expectation_before:6 #: tensorcircuit.basecircuit.BaseCircuit.expectation_before:7 #: tensorcircuit.channels.is_hermitian_matrix:9 +#: tensorcircuit.cloud.abstraction.Device.native_gates:3 +#: tensorcircuit.cloud.abstraction.Task.details:8 +#: tensorcircuit.cloud.abstraction.Task.get_device:3 +#: tensorcircuit.cloud.abstraction.Task.state:3 +#: tensorcircuit.cloud.apis.get_device:10 +#: tensorcircuit.cloud.apis.get_provider:8 tensorcircuit.cloud.apis.get_task:3 +#: tensorcircuit.cloud.apis.get_task:9 +#: tensorcircuit.cloud.apis.get_task_details:3 +#: tensorcircuit.cloud.apis.get_task_details:10 +#: tensorcircuit.cloud.apis.get_token:8 tensorcircuit.cloud.apis.list_devices:7 +#: tensorcircuit.cloud.apis.list_providers:3 +#: tensorcircuit.cloud.apis.resubmit_task:3 +#: tensorcircuit.cloud.apis.resubmit_task:7 +#: tensorcircuit.cloud.apis.set_device:10 +#: tensorcircuit.cloud.apis.set_provider:8 +#: tensorcircuit.cloud.apis.set_token:13 #: tensorcircuit.cons.runtime_contractor:3 #: tensorcircuit.cons.set_function_contractor:3 +#: tensorcircuit.experimental.evol_global:4 +#: tensorcircuit.experimental.evol_global:9 +#: tensorcircuit.experimental.evol_global:11 +#: tensorcircuit.experimental.evol_local:4 +#: tensorcircuit.experimental.evol_local:6 +#: tensorcircuit.experimental.evol_local:13 #: tensorcircuit.experimental.hamiltonian_evol:4 #: tensorcircuit.experimental.hamiltonian_evol:6 #: tensorcircuit.experimental.hamiltonian_evol:8 tensorcircuit.gates.u_gate:16 -#: tensorcircuit.quantum.count_vector2dict:9 -#: tensorcircuit.quantum.sample2count:3 tensorcircuit.quantum.sample2count:5 -#: tensorcircuit.quantum.sample2count:9 +#: tensorcircuit.interfaces.torch.torch_interface_kws:22 +#: tensorcircuit.interfaces.torch.torch_interface_kws:28 +#: tensorcircuit.quantum.count_vector2dict:9 tensorcircuit.quantum.ps2xyz:5 +#: tensorcircuit.quantum.ps2xyz:7 tensorcircuit.quantum.sample2count:3 +#: tensorcircuit.quantum.sample2count:5 tensorcircuit.quantum.sample2count:9 +#: tensorcircuit.quantum.xyz2ps:3 tensorcircuit.quantum.xyz2ps:7 +#: tensorcircuit.results.counts.plot_histogram:6 +#: tensorcircuit.results.counts.plot_histogram:8 #: tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph:6 #: tensorcircuit.translation.eqasm2tc:3 tensorcircuit.translation.eqasm2tc:9 #: tensorcircuit.translation.qir2json:3 tensorcircuit.translation.qir2json:8 @@ -2445,8 +2894,24 @@ msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.from_json_file:5 #: tensorcircuit.abstractcircuit.AbstractCircuit.initial_mapping:7 +#: tensorcircuit.cloud.apis.get_provider:3 tensorcircuit.cloud.apis.get_task:5 +#: tensorcircuit.cloud.apis.get_task:7 +#: tensorcircuit.cloud.apis.get_task_details:5 +#: tensorcircuit.cloud.apis.get_token:4 tensorcircuit.cloud.apis.get_token:6 +#: tensorcircuit.cloud.apis.list_devices:3 +#: tensorcircuit.cloud.apis.list_devices:5 +#: tensorcircuit.cloud.apis.list_properties:3 +#: tensorcircuit.cloud.apis.list_properties:5 +#: tensorcircuit.cloud.apis.list_properties:7 +#: tensorcircuit.cloud.apis.list_tasks:3 tensorcircuit.cloud.apis.list_tasks:5 +#: tensorcircuit.cloud.apis.list_tasks:7 +#: tensorcircuit.cloud.apis.resubmit_task:5 +#: tensorcircuit.cloud.apis.set_provider:3 tensorcircuit.cloud.apis.set_token:5 +#: tensorcircuit.cloud.apis.set_token:7 tensorcircuit.cloud.apis.submit_task:7 +#: tensorcircuit.cloud.apis.submit_task:9 +#: tensorcircuit.cloud.apis.submit_task:11 #: tensorcircuit.experimental.hamiltonian_evol:10 -#: tensorcircuit.translation.eqasm2tc:5 +#: tensorcircuit.quantum.xyz2ps:5 tensorcircuit.translation.eqasm2tc:5 msgid "_description_, defaults to None" msgstr "" @@ -2507,13 +2972,27 @@ msgid "count the gate number of the circuit" msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_count:14 -msgid "gate name list to be counted, defaults to None (counting all gates)" +msgid "" +"gate name or gate name list to be counted, defaults to None (counting all" +" gates)" msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_count:16 msgid "the total number of all gates or gates in the ``gate_list``" msgstr "" +#: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition:1 +msgid "count the number of gates that satisfy certain condition" +msgstr "" + +#: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition:14 +msgid "the condition for counting the gate" +msgstr "" + +#: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_count_by_condition:16 +msgid "the total number of all gates which satisfy the ``condition``" +msgstr "" + #: of tensorcircuit.abstractcircuit.AbstractCircuit.gate_summary:1 msgid "return the summary dictionary on gate type - gate count pair" msgstr "" @@ -2573,11 +3052,6 @@ msgstr "" msgid "add a measurement instruction flag, no effect on numerical simulation" msgstr "" -#: of tensorcircuit.abstractcircuit.AbstractCircuit.measure_instruction:3 -#: tensorcircuit.abstractcircuit.AbstractCircuit.reset_instruction:3 -msgid "the corresponding qubit" -msgstr "" - #: of tensorcircuit.abstractcircuit.AbstractCircuit.prepend:1 msgid "prepend circuit ``c`` before" msgstr "" @@ -2668,6 +3142,10 @@ msgid "Translate ``tc.Circuit`` to a qiskit QuantumCircuit object." msgstr "" #: of tensorcircuit.abstractcircuit.AbstractCircuit.to_qiskit:5 +msgid "whether also export the inputs" +msgstr "" + +#: of tensorcircuit.abstractcircuit.AbstractCircuit.to_qiskit:7 msgid "A qiskit object of this circuit." msgstr "" @@ -3329,7 +3807,7 @@ msgstr "" #: of tensorcircuit.applications.van.MADE:1 #: tensorcircuit.applications.van.NMF:1 #: tensorcircuit.applications.van.PixelCNN:1 -msgid "Bases: :py:class:`keras.engine.training.Model`" +msgid "Bases: :py:class:`~keras.src.engine.training.Model`" msgstr "" #: of tensorcircuit.applications.van.MADE.activity_regularizer:1 @@ -3339,15 +3817,16 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.activity_regularizer:1 #: tensorcircuit.applications.van.ResidualBlock.activity_regularizer:1 #: tensorcircuit.applications.vqes.Linear.activity_regularizer:1 +#: tensorcircuit.keras.HardwareLayer.activity_regularizer:1 #: tensorcircuit.keras.QuantumLayer.activity_regularizer:1 msgid "Optional regularizer function for the output of this layer." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:1 of +#: keras.src.engine.base_layer.Layer.add_loss:1 of msgid "Add loss tensor(s), potentially dependent on layer inputs." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:3 of +#: keras.src.engine.base_layer.Layer.add_loss:3 of msgid "" "Some losses (for instance, activity regularization losses) may be " "dependent on the inputs passed when calling a layer. Hence, when reusing " @@ -3356,40 +3835,46 @@ msgid "" "automatically keeps track of dependencies." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:9 of +#: keras.src.engine.base_layer.Layer.add_loss:9 of msgid "" "This method can be used inside a subclassed layer or model's `call` " "function, in which case `losses` should be a Tensor or list of Tensors." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:12 -#: keras.engine.base_layer.Layer.add_loss:26 -#: keras.engine.base_layer.Layer.add_loss:42 -#: keras.engine.training.Model.compile:3 keras.engine.training.Model.save:28 of +#: keras.src.engine.base_layer.Layer.add_loss:12 +#: keras.src.engine.base_layer.Layer.add_loss:32 +#: keras.src.engine.base_layer.Layer.add_loss:48 +#: keras.src.engine.training.Model.compile:3 +#: keras.src.engine.training.Model.export:15 +#: keras.src.engine.training.Model.get_weight_paths:18 +#: keras.src.engine.training.Model.save:38 of #: tensorcircuit.applications.van.MaskedConv2D.metrics:3 #: tensorcircuit.applications.van.MaskedLinear.metrics:3 #: tensorcircuit.applications.van.ResidualBlock.metrics:3 #: tensorcircuit.applications.vqes.Linear.metrics:3 +#: tensorcircuit.keras.HardwareLayer.metrics:3 #: tensorcircuit.keras.QuantumLayer.metrics:3 msgid "Example:" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:14 of +#: keras.src.engine.base_layer.Layer.add_loss:14 of msgid "```python class MyLayer(tf.keras.layers.Layer):" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:17 -#: keras.engine.base_layer.Layer.add_metric:14 of +#: keras.src.engine.base_layer.Layer.add_loss:17 +#: keras.src.engine.base_layer.Layer.add_metric:14 +#: keras.src.engine.training.Model.get_weight_paths:30 of msgid "def call(self, inputs):" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:17 of +#: keras.src.engine.base_layer.Layer.add_loss:17 of msgid "self.add_loss(tf.abs(tf.reduce_mean(inputs))) return inputs" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:19 -#: keras.engine.base_layer.Layer.add_metric:16 -#: keras.engine.training.Model.compile:10 of +#: keras.src.engine.base_layer.Layer.add_loss:19 +#: keras.src.engine.base_layer.Layer.add_metric:16 +#: keras.src.engine.training.Model.compile:10 +#: keras.src.engine.training.Model.compute_metrics:21 of #: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:21 #: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:35 #: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:21 @@ -3399,16 +3884,24 @@ msgstr "" msgid "```" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:21 of +#: keras.src.engine.base_layer.Layer.add_loss:21 of msgid "" -"This method can also be called directly on a Functional Model during " -"construction. In this case, any loss Tensors passed to this Model must be" -" symbolic and be able to be traced back to the model's `Input`s. These " -"losses become part of the model's topology and are tracked in " +"The same code works in distributed training: the input to `add_loss()` is" +" treated like a regularization loss and averaged across replicas by the " +"training loop (both built-in `Model.fit()` and compliant custom training " +"loops)." +msgstr "" + +#: keras.src.engine.base_layer.Layer.add_loss:26 of +msgid "" +"The `add_loss` method can also be called directly on a Functional Model " +"during construction. In this case, any loss Tensors passed to this Model " +"must be symbolic and be able to be traced back to the model's `Input`s. " +"These losses become part of the model's topology and are tracked in " "`get_config`." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:28 of +#: keras.src.engine.base_layer.Layer.add_loss:34 of msgid "" "```python inputs = tf.keras.Input(shape=(10,)) x = " "tf.keras.layers.Dense(10)(inputs) outputs = tf.keras.layers.Dense(1)(x) " @@ -3416,7 +3909,7 @@ msgid "" "model.add_loss(tf.abs(tf.reduce_mean(x))) ```" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:37 of +#: keras.src.engine.base_layer.Layer.add_loss:43 of msgid "" "If this is not the case for your loss (if, for example, your loss " "references a `Variable` of one of the model's layers), you can wrap your " @@ -3424,7 +3917,7 @@ msgid "" "the model's topology since they can't be serialized." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:44 of +#: keras.src.engine.base_layer.Layer.add_loss:50 of msgid "" "```python inputs = tf.keras.Input(shape=(10,)) d = " "tf.keras.layers.Dense(10) x = d(inputs) outputs = " @@ -3433,57 +3926,47 @@ msgid "" "```" msgstr "" -#: keras.engine.base_layer.Layer.add_loss:54 of +#: keras.src.engine.base_layer.Layer.add_loss:60 of msgid "" "Loss tensor, or list/tuple of tensors. Rather than tensors, losses may " "also be zero-argument callables which create a loss tensor." msgstr "" -#: keras.engine.base_layer.Layer.add_loss:56 of -msgid "" -"Additional keyword arguments for backward compatibility. Accepted values:" -" inputs - Deprecated, will be automatically inferred." -msgstr "" - -#: keras.engine.base_layer.Layer.add_loss:56 of -msgid "Additional keyword arguments for backward compatibility. Accepted values:" -msgstr "" - -#: keras.engine.base_layer.Layer.add_loss:58 of -msgid "inputs - Deprecated, will be automatically inferred." +#: keras.src.engine.base_layer.Layer.add_loss:63 of +msgid "Used for backwards compatibility only." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:1 of +#: keras.src.engine.base_layer.Layer.add_metric:1 of msgid "Adds metric tensor to the layer." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:3 of +#: keras.src.engine.base_layer.Layer.add_metric:3 of msgid "" "This method can be used inside the `call()` method of a subclassed layer " "or model." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:6 of +#: keras.src.engine.base_layer.Layer.add_metric:6 of msgid "```python class MyMetricLayer(tf.keras.layers.Layer):" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:10 of +#: keras.src.engine.base_layer.Layer.add_metric:10 of msgid "def __init__(self):" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:9 of +#: keras.src.engine.base_layer.Layer.add_metric:9 of msgid "" "super(MyMetricLayer, self).__init__(name='my_metric_layer') self.mean = " "tf.keras.metrics.Mean(name='metric_1')" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:13 of +#: keras.src.engine.base_layer.Layer.add_metric:13 of msgid "" "self.add_metric(self.mean(inputs)) self.add_metric(tf.reduce_sum(inputs)," " name='metric_2') return inputs" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:18 of +#: keras.src.engine.base_layer.Layer.add_metric:18 of msgid "" "This method can also be called directly on a Functional Model during " "construction. In this case, any tensor passed to this Model must be " @@ -3492,7 +3975,7 @@ msgid "" " the model via `save()`." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:24 of +#: keras.src.engine.base_layer.Layer.add_metric:24 of msgid "" "```python inputs = tf.keras.Input(shape=(10,)) x = " "tf.keras.layers.Dense(10)(inputs) outputs = tf.keras.layers.Dense(1)(x) " @@ -3500,7 +3983,7 @@ msgid "" "model.add_metric(math_ops.reduce_sum(x), name='metric_1') ```" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:32 of +#: keras.src.engine.base_layer.Layer.add_metric:32 of msgid "" "Note: Calling `add_metric()` with the result of a metric object on a " "Functional Model, as shown in the example below, is not supported. This " @@ -3508,7 +3991,7 @@ msgid "" "inputs." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:36 of +#: keras.src.engine.base_layer.Layer.add_metric:37 of msgid "" "```python inputs = tf.keras.Input(shape=(10,)) x = " "tf.keras.layers.Dense(10)(inputs) outputs = tf.keras.layers.Dense(1)(x) " @@ -3516,15 +3999,15 @@ msgid "" "model.add_metric(tf.keras.metrics.Mean()(x), name='metric_1') ```" msgstr "" -#: keras.engine.base_layer.Layer.add_metric:44 of +#: keras.src.engine.base_layer.Layer.add_metric:45 of msgid "Metric tensor." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:45 of +#: keras.src.engine.base_layer.Layer.add_metric:46 of msgid "String metric name." msgstr "" -#: keras.engine.base_layer.Layer.add_metric:46 of +#: keras.src.engine.base_layer.Layer.add_metric:47 of msgid "" "Additional keyword arguments for backward compatibility. Accepted values:" " `aggregation` - When the `value` tensor provided is not the result of " @@ -3532,11 +4015,11 @@ msgid "" " a `keras.Metric.Mean`." msgstr "" -#: keras.engine.base_layer.Layer.add_update:1 of +#: keras.src.engine.base_layer.Layer.add_update:1 of msgid "Add update op(s), potentially dependent on layer inputs." msgstr "" -#: keras.engine.base_layer.Layer.add_update:3 of +#: keras.src.engine.base_layer.Layer.add_update:3 of msgid "" "Weight updates (for instance, the updates of the moving mean and variance" " in a BatchNormalization layer) may be dependent on the inputs passed " @@ -3546,14 +4029,14 @@ msgid "" "dependencies." msgstr "" -#: keras.engine.base_layer.Layer.add_update:10 of +#: keras.src.engine.base_layer.Layer.add_update:10 of msgid "" "This call is ignored when eager execution is enabled (in that case, " "variable updates are run on the fly and thus do not need to be tracked " "for later execution)." msgstr "" -#: keras.engine.base_layer.Layer.add_update:14 of +#: keras.src.engine.base_layer.Layer.add_update:14 of msgid "" "Update op, or list/tuple of update ops, or zero-arg callable that returns" " an update op. A zero-arg callable should be passed in order to disable " @@ -3561,39 +4044,35 @@ msgid "" "executing in Eager mode." msgstr "" -#: keras.engine.base_layer.Layer.add_update:18 of -msgid "Deprecated, will be automatically inferred." -msgstr "" - -#: keras.engine.base_layer.Layer.add_variable:1 of +#: keras.src.engine.base_layer.Layer.add_variable:1 of msgid "Deprecated, do NOT use! Alias for `add_weight`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:1 of +#: keras.src.engine.base_layer.Layer.add_weight:1 of msgid "Adds a new variable to the layer." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:3 of +#: keras.src.engine.base_layer.Layer.add_weight:3 of msgid "Variable name." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:4 of +#: keras.src.engine.base_layer.Layer.add_weight:4 of msgid "Variable shape. Defaults to scalar if unspecified." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:5 of +#: keras.src.engine.base_layer.Layer.add_weight:5 of msgid "The type of the variable. Defaults to `self.dtype`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:6 of +#: keras.src.engine.base_layer.Layer.add_weight:6 of msgid "Initializer instance (callable)." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:7 of +#: keras.src.engine.base_layer.Layer.add_weight:7 of msgid "Regularizer instance (callable)." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:8 of +#: keras.src.engine.base_layer.Layer.add_weight:8 of msgid "" "Boolean, whether the variable should be part of the layer's " "\"trainable_variables\" (e.g. variables, biases) or " @@ -3601,15 +4080,28 @@ msgid "" " `trainable` cannot be `True` if `synchronization` is set to `ON_READ`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:13 of +#: keras.src.engine.base_layer.Layer.add_weight:13 of msgid "Constraint instance (callable)." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:14 of -msgid "Whether to use `ResourceVariable`." +#: keras.src.engine.base_layer.Layer.add_weight:14 of +msgid "" +"Whether to use a `ResourceVariable` or not. See [this guide]( " +"https://www.tensorflow.org/guide/migrate/tf1_vs_tf2#resourcevariables_instead_of_referencevariables)" +" for more information." +msgstr "" + +#: keras.src.engine.base_layer.Layer.add_weight:14 of +msgid "" +"Whether to use a `ResourceVariable` or not. See [this guide]( " +"https://www.tensorflow.org/guide/migrate/tf1_vs_tf2#resourcevariables_instead_of_referencevariables)" +msgstr "" + +#: keras.src.engine.base_layer.Layer.add_weight:17 of +msgid "for more information." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:15 of +#: keras.src.engine.base_layer.Layer.add_weight:18 of msgid "" "Indicates when a distributed a variable will be aggregated. Accepted " "values are constants defined in the class `tf.VariableSynchronization`. " @@ -3618,37 +4110,39 @@ msgid "" "is set to `ON_READ`, `trainable` must not be set to `True`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:21 of +#: keras.src.engine.base_layer.Layer.add_weight:24 of msgid "" "Indicates how a distributed variable will be aggregated. Accepted values " "are constants defined in the class `tf.VariableAggregation`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:24 of +#: keras.src.engine.base_layer.Layer.add_weight:27 of msgid "" "Additional keyword arguments. Accepted values are `getter`, " "`collections`, `experimental_autocast` and `caching_device`." msgstr "" -#: keras.engine.base_layer.Layer.add_weight:27 of +#: keras.src.engine.base_layer.Layer.add_weight:30 of msgid "The variable created." msgstr "" -#: keras.engine.base_layer.Layer.add_weight -#: keras.engine.base_layer.Layer.compute_output_signature -#: keras.engine.base_layer.Layer.count_params -#: keras.engine.base_layer.Layer.get_input_at -#: keras.engine.base_layer.Layer.get_input_shape_at -#: keras.engine.base_layer.Layer.get_output_at -#: keras.engine.base_layer.Layer.get_output_shape_at -#: keras.engine.base_layer.Layer.set_weights keras.engine.training.Model.build -#: keras.engine.training.Model.evaluate keras.engine.training.Model.fit -#: keras.engine.training.Model.load_weights keras.engine.training.Model.predict -#: keras.engine.training.Model.predict_on_batch -#: keras.engine.training.Model.save_weights keras.engine.training.Model.summary -#: keras.engine.training.Model.test_on_batch -#: keras.engine.training.Model.to_yaml -#: keras.engine.training.Model.train_on_batch of +#: keras.src.engine.base_layer.Layer.add_weight +#: keras.src.engine.base_layer.Layer.compute_output_signature +#: keras.src.engine.base_layer.Layer.count_params +#: keras.src.engine.base_layer.Layer.get_input_at +#: keras.src.engine.base_layer.Layer.get_input_shape_at +#: keras.src.engine.base_layer.Layer.get_output_at +#: keras.src.engine.base_layer.Layer.get_output_shape_at +#: keras.src.engine.base_layer.Layer.set_weights +#: keras.src.engine.training.Model.build +#: keras.src.engine.training.Model.evaluate keras.src.engine.training.Model.fit +#: keras.src.engine.training.Model.predict +#: keras.src.engine.training.Model.predict_on_batch +#: keras.src.engine.training.Model.save_weights +#: keras.src.engine.training.Model.summary +#: keras.src.engine.training.Model.test_on_batch +#: keras.src.engine.training.Model.to_yaml +#: keras.src.engine.training.Model.train_on_batch of #: tensorcircuit.applications.van.MADE.input #: tensorcircuit.applications.van.MADE.input_mask #: tensorcircuit.applications.van.MADE.input_shape @@ -3698,7 +4192,13 @@ msgstr "" #: tensorcircuit.basecircuit.BaseCircuit.expectation_before #: tensorcircuit.circuit.Circuit.expectation tensorcircuit.circuit.expectation #: tensorcircuit.cons.get_contractor tensorcircuit.cons.set_contractor -#: tensorcircuit.gates.bmatrix tensorcircuit.keras.QuantumLayer.input +#: tensorcircuit.gates.bmatrix tensorcircuit.keras.HardwareLayer.input +#: tensorcircuit.keras.HardwareLayer.input_mask +#: tensorcircuit.keras.HardwareLayer.input_shape +#: tensorcircuit.keras.HardwareLayer.output +#: tensorcircuit.keras.HardwareLayer.output_mask +#: tensorcircuit.keras.HardwareLayer.output_shape +#: tensorcircuit.keras.QuantumLayer.input #: tensorcircuit.keras.QuantumLayer.input_mask #: tensorcircuit.keras.QuantumLayer.input_shape #: tensorcircuit.keras.QuantumLayer.output @@ -3725,52 +4225,23 @@ msgstr "" msgid "Raises" msgstr "" -#: keras.engine.base_layer.Layer.add_weight:29 of +#: keras.src.engine.base_layer.Layer.add_weight:32 of msgid "" "When giving unsupported dtype and no initializer or when trainable " -"has been set to True with synchronization set as `ON_READ`." -msgstr "" - -#: keras.engine.base_layer.Layer.apply:1 -#: keras.engine.base_layer.Layer.get_losses_for:1 -#: keras.engine.base_layer.Layer.get_updates_for:1 of -#: tensorcircuit.applications.van.MADE.state_updates:1 -#: tensorcircuit.applications.van.NMF.state_updates:1 -#: tensorcircuit.applications.van.PixelCNN.state_updates:1 -msgid "Deprecated, do NOT use!" -msgstr "" - -#: keras.engine.base_layer.Layer.apply:3 of -msgid "This is an alias of `self.__call__`." -msgstr "" - -#: keras.engine.base_layer.Layer.apply:5 of -msgid "Input tensor(s)." -msgstr "" - -#: keras.engine.base_layer.Layer.apply:6 of -msgid "additional positional arguments to be passed to `self.call`." -msgstr "" - -#: keras.engine.base_layer.Layer.apply:7 of -msgid "additional keyword arguments to be passed to `self.call`." -msgstr "" - -#: keras.engine.base_layer.Layer.apply:9 of -msgid "Output tensor(s)." +"has been set to True with synchronization set as `ON_READ`." msgstr "" -#: keras.engine.training.Model.build:1 of +#: keras.src.engine.training.Model.build:1 of msgid "Builds the model based on input shapes received." msgstr "" -#: keras.engine.training.Model.build:3 of +#: keras.src.engine.training.Model.build:3 of msgid "" "This is to be used for subclassed models, which do not know at " "instantiation time what their inputs look like." msgstr "" -#: keras.engine.training.Model.build:6 of +#: keras.src.engine.training.Model.build:6 of msgid "" "This method only exists for users who want to call `model.build()` in a " "standalone way (as a substitute for calling the model on real data to " @@ -3778,28 +4249,44 @@ msgid "" "never throw unexpected errors in an unrelated workflow)." msgstr "" -#: keras.engine.training.Model.build:11 of +#: keras.src.engine.training.Model.build:11 of msgid "" "Single tuple, `TensorShape` instance, or list/dict of shapes, where " "shapes are tuples, integers, or `TensorShape` instances." msgstr "" -#: keras.engine.training.Model.build:14 of +#: keras.src.engine.training.Model.build:15 of msgid "" "1. In case of invalid user-provided data (not of type tuple, list," " `TensorShape`, or dict). 2. If the model requires call arguments " "that are agnostic to the input shapes (positional or keyword arg " -"in call signature). 3. If not all layers were properly built. 4. " -"If float type inputs are not supported within the layers." +"in call signature). 3. If not all layers were properly built." +" 4. If float type inputs are not supported within the layers." msgstr "" -#: keras.engine.training.Model.build:14 of +#: keras.src.engine.training.Model.build:15 of msgid "" "In case of invalid user-provided data (not of type tuple, list, " "`TensorShape`, or dict). 2. If the model requires call arguments that" " are agnostic to the input shapes (positional or keyword arg in " -"call signature). 3. If not all layers were properly built. 4. If " -"float type inputs are not supported within the layers." +"call signature). 3. If not all layers were properly built." +" 4. If float type inputs are not supported within the layers." +msgstr "" + +#: keras.src.engine.base_layer.Layer.build_from_config:1 of +msgid "Builds the layer's states with the supplied config dict." +msgstr "" + +#: keras.src.engine.base_layer.Layer.build_from_config:3 of +msgid "" +"By default, this method calls the `build(config[\"input_shape\"])` " +"method, which creates weights based on the layer's input shape in the " +"supplied config. If your config contains other information needed to load" +" the layer's state, you should override this method." +msgstr "" + +#: keras.src.engine.base_layer.Layer.build_from_config:8 of +msgid "Dict containing the input shape associated with this layer." msgstr "" #: of tensorcircuit.applications.van.MADE.call:1 @@ -3845,24 +4332,10 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.call:15 msgid "" "A mask or list of masks. A mask can be either a boolean tensor or None " -"(no mask). For more details, check the guide " +"(no mask). For more details, check the guide " "[here](https://www.tensorflow.org/guide/keras/masking_and_padding)." msgstr "" -#: of tensorcircuit.applications.van.MADE.call:15 -#: tensorcircuit.applications.van.NMF.call:15 -#: tensorcircuit.applications.van.PixelCNN.call:15 -msgid "" -"A mask or list of masks. A mask can be either a boolean tensor or None " -"(no mask). For more details, check the guide" -msgstr "" - -#: of tensorcircuit.applications.van.MADE.call:17 -#: tensorcircuit.applications.van.NMF.call:17 -#: tensorcircuit.applications.van.PixelCNN.call:17 -msgid "[here](https://www.tensorflow.org/guide/keras/masking_and_padding)." -msgstr "" - #: of tensorcircuit.applications.van.MADE.call:19 #: tensorcircuit.applications.van.NMF.call:19 #: tensorcircuit.applications.van.PixelCNN.call:19 @@ -3871,35 +4344,35 @@ msgid "" "more than one outputs." msgstr "" -#: keras.engine.training.Model.compile:1 of +#: keras.src.engine.training.Model.compile:1 of msgid "Configures the model for training." msgstr "" -#: keras.engine.training.Model.compile:5 of +#: keras.src.engine.training.Model.compile:5 of msgid "" "```python " "model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3)," msgstr "" -#: keras.engine.training.Model.compile:7 of +#: keras.src.engine.training.Model.compile:7 of msgid "" "loss=tf.keras.losses.BinaryCrossentropy(), " "metrics=[tf.keras.metrics.BinaryAccuracy()," msgstr "" -#: keras.engine.training.Model.compile:9 of +#: keras.src.engine.training.Model.compile:9 of msgid "tf.keras.metrics.FalseNegatives()])" msgstr "" -#: keras.engine.training.Model.compile:12 of +#: keras.src.engine.training.Model.compile:12 of msgid "" "String (name of optimizer) or optimizer instance. See " "`tf.keras.optimizers`." msgstr "" -#: keras.engine.training.Model.compile:14 of +#: keras.src.engine.training.Model.compile:14 of msgid "" -"Loss function. Maybe be a string (name of loss function), or a " +"Loss function. May be a string (name of loss function), or a " "`tf.keras.losses.Loss` instance. See `tf.keras.losses`. A loss function " "is any callable with the signature `loss = fn(y_true, y_pred)`, where " "`y_true` are the ground truth values, and `y_pred` are the model's " @@ -3916,7 +4389,7 @@ msgid "" "individual losses, unless `loss_weights` is specified." msgstr "" -#: keras.engine.training.Model.compile:34 of +#: keras.src.engine.training.Model.compile:34 of msgid "" "List of metrics to be evaluated by the model during training and testing." " Each of this can be a string (name of a built-in function), function or " @@ -3924,80 +4397,117 @@ msgid "" "you will use `metrics=['accuracy']`. A function is any callable with the " "signature `result = fn(y_true, y_pred)`. To specify different metrics for" " different outputs of a multi-output model, you could also pass a " -"dictionary, such as `metrics={'output_a': 'accuracy', 'output_b': " -"['accuracy', 'mse']}`. You can also pass a list to specify a metric or a " -"list of metrics for each output, such as `metrics=[['accuracy'], " -"['accuracy', 'mse']]` or `metrics=['accuracy', ['accuracy', 'mse']]`. " -"When you pass the strings 'accuracy' or 'acc', we convert this to one of " -"`tf.keras.metrics.BinaryAccuracy`, " +"dictionary, such as `metrics={'output_a':'accuracy', " +"'output_b':['accuracy', 'mse']}`. You can also pass a list to specify a " +"metric or a list of metrics for each output, such as " +"`metrics=[['accuracy'], ['accuracy', 'mse']]` or `metrics=['accuracy', " +"['accuracy', 'mse']]`. When you pass the strings 'accuracy' or 'acc', we " +"convert this to one of `tf.keras.metrics.BinaryAccuracy`, " "`tf.keras.metrics.CategoricalAccuracy`, " -"`tf.keras.metrics.SparseCategoricalAccuracy` based on the loss function " -"used and the model output shape. We do a similar conversion for the " -"strings 'crossentropy' and 'ce' as well." +"`tf.keras.metrics.SparseCategoricalAccuracy` based on the shapes of the " +"targets and of the model output. We do a similar conversion for the " +"strings 'crossentropy' and 'ce' as well. The metrics passed here are " +"evaluated without sample weighting; if you would like sample weighting to" +" apply, you can specify your metrics via the `weighted_metrics` argument " +"instead." msgstr "" -#: keras.engine.training.Model.compile:51 of +#: keras.src.engine.training.Model.compile:56 of msgid "" "Optional list or dictionary specifying scalar coefficients (Python " "floats) to weight the loss contributions of different model outputs. The " "loss value that will be minimized by the model will then be the *weighted" " sum* of all individual losses, weighted by the `loss_weights` " -"coefficients. If a list, it is expected to have a 1:1 mapping to the " -"model's outputs. If a dict, it is expected to map output names " -"(strings) to scalar coefficients." +"coefficients. If a list, it is expected to have a 1:1 mapping to the " +"model's outputs. If a dict, it is expected to map output names (strings) " +"to scalar coefficients." msgstr "" -#: keras.engine.training.Model.compile:51 of +#: keras.src.engine.training.Model.compile:64 of msgid "" -"Optional list or dictionary specifying scalar coefficients (Python " -"floats) to weight the loss contributions of different model outputs. The " -"loss value that will be minimized by the model will then be the *weighted" -" sum* of all individual losses, weighted by the `loss_weights` " -"coefficients." +"List of metrics to be evaluated and weighted by `sample_weight` or " +"`class_weight` during training and testing." msgstr "" -#: keras.engine.training.Model.compile:57 of -msgid "If a list, it is expected to have a 1:1 mapping to the model's" +#: keras.src.engine.training.Model.compile:66 of +msgid "" +"Bool. If `True`, this `Model`'s logic will not be wrapped in a " +"`tf.function`. Recommended to leave this as `None` unless your `Model` " +"cannot be run inside a `tf.function`. `run_eagerly=True` is not supported" +" when using `tf.distribute.experimental.ParameterServerStrategy`. " +"Defaults to `False`." msgstr "" -#: keras.engine.training.Model.compile:57 of +#: keras.src.engine.training.Model.compile:66 of msgid "" -"outputs. If a dict, it is expected to map output names (strings) to " -"scalar coefficients." +"Bool. If `True`, this `Model`'s logic will not be wrapped in a " +"`tf.function`. Recommended to leave this as `None` unless your `Model` " +"cannot be run inside a `tf.function`. `run_eagerly=True` is not supported" +" when using `tf.distribute.experimental.ParameterServerStrategy`. " +"Defaults to" +msgstr "" + +#: keras.src.engine.training.Model.compile:71 of +msgid "`False`." msgstr "" -#: keras.engine.training.Model.compile:59 of +#: keras.src.engine.training.Model.compile:72 of msgid "" -"List of metrics to be evaluated and weighted by `sample_weight` or " -"`class_weight` during training and testing." +"Int. The number of batches to run during each `tf.function` call. Running" +" multiple batches inside a single `tf.function` call can greatly improve " +"performance on TPUs or small models with a large Python overhead. At " +"most, one full epoch will be run each execution. If a number larger than " +"the size of the epoch is passed, the execution will be truncated to the " +"size of the epoch. Note that if `steps_per_execution` is set to `N`, " +"`Callback.on_batch_begin` and `Callback.on_batch_end` methods will only " +"be called every `N` batches (i.e. before/after each `tf.function` " +"execution). Defaults to `1`." msgstr "" -#: keras.engine.training.Model.compile:61 of +#: keras.src.engine.training.Model.compile:82 of msgid "" -"Bool. Defaults to `False`. If `True`, this `Model`'s logic will not be " -"wrapped in a `tf.function`. Recommended to leave this as `None` unless " -"your `Model` cannot be run inside a `tf.function`. `run_eagerly=True` is " -"not supported when using " -"`tf.distribute.experimental.ParameterServerStrategy`." +"If `True`, compile the model training step with XLA. " +"[XLA](https://www.tensorflow.org/xla) is an optimizing compiler for " +"machine learning. `jit_compile` is not enabled for by default. Note that " +"`jit_compile=True` may not necessarily work for all models. For more " +"information on supported operations please refer to the [XLA " +"documentation](https://www.tensorflow.org/xla). Also refer to [known XLA " +"issues](https://www.tensorflow.org/xla/known_issues) for more details." msgstr "" -#: keras.engine.training.Model.compile:66 of +#: keras.src.engine.training.Model.compile:93 of msgid "" -"Int. Defaults to 1. The number of batches to run during each " -"`tf.function` call. Running multiple batches inside a single " -"`tf.function` call can greatly improve performance on TPUs or small " -"models with a large Python overhead. At most, one full epoch will be run " -"each execution. If a number larger than the size of the epoch is passed, " -"the execution will be truncated to the size of the epoch. Note that if " -"`steps_per_execution` is set to `N`, `Callback.on_batch_begin` and " -"`Callback.on_batch_end` methods will only be called every `N` batches " -"(i.e. before/after each `tf.function` execution)." +"Integer or 'auto'. Used for `tf.distribute.ParameterServerStrategy` " +"training only. This arg sets the number of shards to split the dataset " +"into, to enable an exact visitation guarantee for evaluation, meaning the" +" model will be applied to each dataset element exactly once, even if " +"workers fail. The dataset must be sharded to ensure separate workers do " +"not process the same data. The number of shards should be at least the " +"number of workers for good performance. A value of 'auto' turns on exact " +"evaluation and uses a heuristic for the number of shards based on the " +"number of workers. 0, meaning no visitation guarantee is provided. NOTE: " +"Custom implementations of `Model.test_step` will be ignored when doing " +"exact evaluation. Defaults to `0`." msgstr "" -#: keras.engine.training.Model.compile:77 of +#: keras.src.engine.training.Model.compile:106 of msgid "Arguments supported for backwards compatibility only." msgstr "" +#: keras.src.engine.training.Model.compile_from_config:1 of +msgid "Compiles the model with the information given in config." +msgstr "" + +#: keras.src.engine.training.Model.compile_from_config:3 of +msgid "" +"This method uses the information in the config (optimizer, loss, metrics," +" etc.) to compile the model." +msgstr "" + +#: keras.src.engine.training.Model.compile_from_config:6 of +msgid "Dict containing information for compiling the model." +msgstr "" + #: of tensorcircuit.applications.van.MADE.compute_dtype:1 #: tensorcircuit.applications.van.MaskedConv2D.compute_dtype:1 #: tensorcircuit.applications.van.MaskedLinear.compute_dtype:1 @@ -4005,6 +4515,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.compute_dtype:1 #: tensorcircuit.applications.van.ResidualBlock.compute_dtype:1 #: tensorcircuit.applications.vqes.Linear.compute_dtype:1 +#: tensorcircuit.keras.HardwareLayer.compute_dtype:1 #: tensorcircuit.keras.QuantumLayer.compute_dtype:1 msgid "The dtype of the layer's computations." msgstr "" @@ -4016,6 +4527,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.compute_dtype:3 #: tensorcircuit.applications.van.ResidualBlock.compute_dtype:3 #: tensorcircuit.applications.vqes.Linear.compute_dtype:3 +#: tensorcircuit.keras.HardwareLayer.compute_dtype:3 #: tensorcircuit.keras.QuantumLayer.compute_dtype:3 msgid "" "This is equivalent to `Layer.dtype_policy.compute_dtype`. Unless mixed " @@ -4030,6 +4542,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.compute_dtype:7 #: tensorcircuit.applications.van.ResidualBlock.compute_dtype:7 #: tensorcircuit.applications.vqes.Linear.compute_dtype:7 +#: tensorcircuit.keras.HardwareLayer.compute_dtype:7 #: tensorcircuit.keras.QuantumLayer.compute_dtype:7 msgid "" "Layers automatically cast their inputs to the compute dtype, which causes" @@ -4045,6 +4558,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.compute_dtype:12 #: tensorcircuit.applications.van.ResidualBlock.compute_dtype:12 #: tensorcircuit.applications.vqes.Linear.compute_dtype:12 +#: tensorcircuit.keras.HardwareLayer.compute_dtype:12 #: tensorcircuit.keras.QuantumLayer.compute_dtype:12 msgid "" "Layers often perform certain internal computations in higher precision " @@ -4059,60 +4573,207 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.compute_dtype:16 #: tensorcircuit.applications.van.ResidualBlock.compute_dtype:16 #: tensorcircuit.applications.vqes.Linear.compute_dtype:16 +#: tensorcircuit.keras.HardwareLayer.compute_dtype:16 #: tensorcircuit.keras.QuantumLayer.compute_dtype:16 msgid "The layer's compute dtype." msgstr "" -#: keras.engine.base_layer.Layer.compute_mask:1 of +#: keras.src.engine.training.Model.compute_loss:1 of +msgid "Compute the total loss, validate it, and return it." +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:3 of +msgid "" +"Subclasses can optionally override this method to provide custom loss " +"computation logic." +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:6 of +msgid "Example: ```python class MyModel(tf.keras.Model):" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:12 of +msgid "def __init__(self, *args, **kwargs):" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:11 of +msgid "" +"super(MyModel, self).__init__(*args, **kwargs) self.loss_tracker = " +"tf.keras.metrics.Mean(name='loss')" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:18 of +msgid "def compute_loss(self, x, y, y_pred, sample_weight):" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:15 of +msgid "" +"loss = tf.reduce_mean(tf.math.squared_difference(y_pred, y)) loss += " +"tf.add_n(self.losses) self.loss_tracker.update_state(loss) return loss" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:21 of +msgid "def reset_metrics(self):" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:21 of +msgid "self.loss_tracker.reset_states()" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:23 of +msgid "@property def metrics(self):" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:25 of +msgid "return [self.loss_tracker]" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:27 of +msgid "" +"tensors = tf.random.uniform((10, 10)), tf.random.uniform((10,)) dataset =" +" tf.data.Dataset.from_tensor_slices(tensors).repeat().batch(1)" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:30 of +msgid "" +"inputs = tf.keras.layers.Input(shape=(10,), name='my_input') outputs = " +"tf.keras.layers.Dense(10)(inputs) model = MyModel(inputs, outputs) " +"model.add_loss(tf.reduce_sum(outputs))" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:35 of +msgid "" +"optimizer = tf.keras.optimizers.SGD() model.compile(optimizer, " +"loss='mse', steps_per_execution=10) model.fit(dataset, epochs=2, " +"steps_per_epoch=10) print('My custom loss: ', " +"model.loss_tracker.result().numpy()) ```" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:41 +#: keras.src.engine.training.Model.compute_metrics:23 of +msgid "Input data." +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:42 +#: keras.src.engine.training.Model.compute_metrics:24 of +msgid "Target data." +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:43 of +msgid "Predictions returned by the model (output of `model(x)`)" +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:44 +#: keras.src.engine.training.Model.compute_metrics:26 of +msgid "Sample weights for weighting the loss function." +msgstr "" + +#: keras.src.engine.training.Model.compute_loss:46 of +msgid "" +"The total loss as a `tf.Tensor`, or `None` if no loss results (which is " +"the case when called by `Model.test_step`)." +msgstr "" + +#: keras.src.engine.base_layer.Layer.compute_mask:1 of msgid "Computes an output mask tensor." msgstr "" -#: keras.engine.base_layer.Layer.compute_mask:3 -#: keras.engine.base_layer.Layer.compute_mask:4 of +#: keras.src.engine.base_layer.Layer.compute_mask:3 +#: keras.src.engine.base_layer.Layer.compute_mask:4 of msgid "Tensor or list of tensors." msgstr "" -#: keras.engine.base_layer.Layer.compute_mask:6 of +#: keras.src.engine.base_layer.Layer.compute_mask:6 of msgid "" "None or a tensor (or list of tensors, one per output tensor of the " "layer)." msgstr "" -#: keras.engine.base_layer.Layer.compute_mask:8 of +#: keras.src.engine.base_layer.Layer.compute_mask:8 of msgid "None or a tensor (or list of tensors," msgstr "" -#: keras.engine.base_layer.Layer.compute_mask:9 of +#: keras.src.engine.base_layer.Layer.compute_mask:9 of msgid "one per output tensor of the layer)." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_shape:1 of +#: keras.src.engine.training.Model.compute_metrics:1 of +msgid "Update metric states and collect all metrics to be returned." +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:3 of +msgid "" +"Subclasses can optionally override this method to provide custom metric " +"updating and collection logic." +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:6 of +msgid "Example: ```python class MyModel(tf.keras.Sequential):" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:10 of +msgid "def compute_metrics(self, x, y, y_pred, sample_weight):" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:12 of +msgid "" +"# This super call updates `self.compiled_metrics` and returns # results " +"for all metrics listed in `self.metrics`. metric_results = super(MyModel," +" self).compute_metrics(" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:15 of +msgid "x, y, y_pred, sample_weight)" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:17 of +msgid "" +"# Note that `self.custom_metric` is not listed in `self.metrics`. " +"self.custom_metric.update_state(x, y, y_pred, sample_weight) " +"metric_results['custom_metric_name'] = self.custom_metric.result() return" +" metric_results" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:25 of +msgid "Predictions returned by the model (output of `model.call(x)`)" +msgstr "" + +#: keras.src.engine.training.Model.compute_metrics:28 of +msgid "" +"A `dict` containing values that will be passed to " +"`tf.keras.callbacks.CallbackList.on_train_batch_end()`. Typically, the " +"values of the metrics listed in `self.metrics` are returned. Example: " +"`{'loss': 0.2, 'accuracy': 0.7}`." +msgstr "" + +#: keras.src.engine.base_layer.Layer.compute_output_shape:1 of msgid "Computes the output shape of the layer." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_shape:3 of +#: keras.src.engine.base_layer.Layer.compute_output_shape:3 of msgid "" -"If the layer has not been built, this method will call `build` on the " -"layer. This assumes that the layer will later be used with inputs that " -"match the input shape provided here." +"This method will cause the layer's state to be built, if that has not " +"happened before. This requires that the layer will later be used with " +"inputs that match the input shape provided here." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_shape:7 of +#: keras.src.engine.base_layer.Layer.compute_output_shape:7 of msgid "" -"Shape tuple (tuple of integers) or list of shape tuples (one per output " -"tensor of the layer). Shape tuples can include None for free dimensions, " -"instead of an integer." +"Shape tuple (tuple of integers) or `tf.TensorShape`, or structure of " +"shape tuples / `tf.TensorShape` instances (one per output tensor of the " +"layer). Shape tuples can include None for free dimensions, instead of an " +"integer." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_shape:12 of -msgid "An input shape tuple." +#: keras.src.engine.base_layer.Layer.compute_output_shape:13 of +msgid "A `tf.TensorShape` instance or structure of `tf.TensorShape` instances." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:1 of +#: keras.src.engine.base_layer.Layer.compute_output_signature:1 of msgid "Compute the output tensor signature of the layer based on the inputs." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:3 of +#: keras.src.engine.base_layer.Layer.compute_output_signature:3 of msgid "" "Unlike a TensorShape object, a TensorSpec object contains both shape and " "dtype information for a tensor. This method allows layers to provide " @@ -4122,44 +4783,59 @@ msgid "" "matches the input dtype." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:10 of +#: keras.src.engine.base_layer.Layer.compute_output_signature:10 of msgid "" "Single TensorSpec or nested structure of TensorSpec objects, describing a" " candidate input for the layer." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:13 of +#: keras.src.engine.base_layer.Layer.compute_output_signature:13 of msgid "" -"Single TensorSpec or nested structure of TensorSpec objects, describing" -" how the layer would transform the provided input." +"Single TensorSpec or nested structure of TensorSpec objects, describing" +" how the layer would transform the provided input." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:16 of -msgid "Single TensorSpec or nested structure of TensorSpec objects, describing" +#: keras.src.engine.base_layer.Layer.compute_output_signature:16 of +msgid "Single TensorSpec or nested structure of TensorSpec objects," msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:16 of -msgid "how the layer would transform the provided input." +#: keras.src.engine.base_layer.Layer.compute_output_signature:16 of +msgid "describing how the layer would transform the provided input." msgstr "" -#: keras.engine.base_layer.Layer.compute_output_signature:18 of +#: keras.src.engine.base_layer.Layer.compute_output_signature:18 of msgid "If input_signature contains a non-TensorSpec object." msgstr "" -#: keras.engine.base_layer.Layer.count_params:1 of +#: keras.src.engine.base_layer.Layer.count_params:1 of msgid "Count the total number of scalars composing the weights." msgstr "" -#: keras.engine.base_layer.Layer.count_params:3 of +#: keras.src.engine.base_layer.Layer.count_params:3 of msgid "An integer count." msgstr "" -#: keras.engine.base_layer.Layer.count_params:5 of +#: keras.src.engine.base_layer.Layer.count_params:5 of msgid "" "if the layer isn't yet built (in which case its weights aren't yet " "defined)." msgstr "" +#: of tensorcircuit.applications.van.MADE.distribute_reduction_method:1 +#: tensorcircuit.applications.van.NMF.distribute_reduction_method:1 +#: tensorcircuit.applications.van.PixelCNN.distribute_reduction_method:1 +msgid "The method employed to reduce per-replica values during training." +msgstr "" + +#: of tensorcircuit.applications.van.MADE.distribute_reduction_method:3 +#: tensorcircuit.applications.van.NMF.distribute_reduction_method:3 +#: tensorcircuit.applications.van.PixelCNN.distribute_reduction_method:3 +msgid "" +"Unless specified, the value \"auto\" will be assumed, indicating that the" +" reduction strategy should be chosen based on the current running " +"environment. See `reduce_per_replica` function for more details." +msgstr "" + #: of tensorcircuit.applications.van.MADE.distribute_strategy:1 #: tensorcircuit.applications.van.NMF.distribute_strategy:1 #: tensorcircuit.applications.van.PixelCNN.distribute_strategy:1 @@ -4173,6 +4849,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.dtype:1 #: tensorcircuit.applications.van.ResidualBlock.dtype:1 #: tensorcircuit.applications.vqes.Linear.dtype:1 +#: tensorcircuit.keras.HardwareLayer.dtype:1 #: tensorcircuit.keras.QuantumLayer.dtype:1 msgid "The dtype of the layer weights." msgstr "" @@ -4184,6 +4861,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.dtype:3 #: tensorcircuit.applications.van.ResidualBlock.dtype:3 #: tensorcircuit.applications.vqes.Linear.dtype:3 +#: tensorcircuit.keras.HardwareLayer.dtype:3 #: tensorcircuit.keras.QuantumLayer.dtype:3 msgid "" "This is equivalent to `Layer.dtype_policy.variable_dtype`. Unless mixed " @@ -4198,6 +4876,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.dtype_policy:1 #: tensorcircuit.applications.van.ResidualBlock.dtype_policy:1 #: tensorcircuit.applications.vqes.Linear.dtype_policy:1 +#: tensorcircuit.keras.HardwareLayer.dtype_policy:1 #: tensorcircuit.keras.QuantumLayer.dtype_policy:1 msgid "The dtype policy associated with this layer." msgstr "" @@ -4209,6 +4888,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.dtype_policy:3 #: tensorcircuit.applications.van.ResidualBlock.dtype_policy:3 #: tensorcircuit.applications.vqes.Linear.dtype_policy:3 +#: tensorcircuit.keras.HardwareLayer.dtype_policy:3 #: tensorcircuit.keras.QuantumLayer.dtype_policy:3 msgid "This is an instance of a `tf.keras.mixed_precision.Policy`." msgstr "" @@ -4220,19 +4900,20 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.dynamic:1 #: tensorcircuit.applications.van.ResidualBlock.dynamic:1 #: tensorcircuit.applications.vqes.Linear.dynamic:1 +#: tensorcircuit.keras.HardwareLayer.dynamic:1 #: tensorcircuit.keras.QuantumLayer.dynamic:1 msgid "Whether the layer is dynamic (eager-only); set in the constructor." msgstr "" -#: keras.engine.training.Model.evaluate:1 of +#: keras.src.engine.training.Model.evaluate:1 of msgid "Returns the loss value & metrics values for the model in test mode." msgstr "" -#: keras.engine.training.Model.evaluate:3 of +#: keras.src.engine.training.Model.evaluate:3 of msgid "Computation is done in batches (see the `batch_size` arg.)" msgstr "" -#: keras.engine.training.Model.evaluate:5 of +#: keras.src.engine.training.Model.evaluate:5 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the model has multiple inputs). - A TensorFlow tensor, " @@ -4240,63 +4921,67 @@ msgid "" "mapping input names to the corresponding array/tensors, if the model " "has named inputs. - A `tf.data` dataset. Should return a tuple of " "either `(inputs, targets)` or `(inputs, targets, sample_weights)`. - A " -"generator or `keras.utils.Sequence` returning `(inputs, targets)` or " +"generator or `keras.utils.Sequence` returning `(inputs, targets)` or " "`(inputs, targets, sample_weights)`. A more detailed description of " "unpacking behavior for iterator types (Dataset, generator, Sequence) is " "given in the `Unpacking behavior for iterator-like inputs` section of " "`Model.fit`." msgstr "" -#: keras.engine.training.Model.evaluate:5 keras.engine.training.Model.fit:3 -#: keras.engine.training.Model.train_on_batch:3 of +#: keras.src.engine.training.Model.evaluate:5 +#: keras.src.engine.training.Model.fit:3 +#: keras.src.engine.training.Model.train_on_batch:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays" msgstr "" -#: keras.engine.training.Model.evaluate:7 keras.engine.training.Model.fit:5 -#: keras.engine.training.Model.predict:13 -#: keras.engine.training.Model.train_on_batch:5 -#: keras.engine.training.Model.train_on_batch:7 of +#: keras.src.engine.training.Model.evaluate:7 +#: keras.src.engine.training.Model.fit:5 +#: keras.src.engine.training.Model.predict:28 +#: keras.src.engine.training.Model.train_on_batch:5 +#: keras.src.engine.training.Model.train_on_batch:7 of msgid "(in case the model has multiple inputs)." msgstr "" -#: keras.engine.training.Model.evaluate:8 keras.engine.training.Model.fit:6 -#: keras.engine.training.Model.predict:14 of +#: keras.src.engine.training.Model.evaluate:8 +#: keras.src.engine.training.Model.fit:6 +#: keras.src.engine.training.Model.predict:29 of msgid "" "A TensorFlow tensor, or a list of tensors (in case the model has multiple" " inputs)." msgstr "" -#: keras.engine.training.Model.evaluate:10 keras.engine.training.Model.fit:8 of +#: keras.src.engine.training.Model.evaluate:10 +#: keras.src.engine.training.Model.fit:8 of msgid "" "A dict mapping input names to the corresponding array/tensors, if the " "model has named inputs." msgstr "" -#: keras.engine.training.Model.evaluate:12 keras.engine.training.Model.fit:10 -#: of +#: keras.src.engine.training.Model.evaluate:12 +#: keras.src.engine.training.Model.fit:10 of msgid "" "A `tf.data` dataset. Should return a tuple of either `(inputs, targets)` " "or `(inputs, targets, sample_weights)`." msgstr "" -#: keras.engine.training.Model.evaluate:15 keras.engine.training.Model.fit:13 -#: of +#: keras.src.engine.training.Model.evaluate:15 +#: keras.src.engine.training.Model.fit:13 of msgid "" "A generator or `keras.utils.Sequence` returning `(inputs, targets)` or " "`(inputs, targets, sample_weights)`." msgstr "" -#: keras.engine.training.Model.evaluate:17 -#: keras.engine.training.Model.predict:18 of +#: keras.src.engine.training.Model.evaluate:17 +#: keras.src.engine.training.Model.predict:33 of msgid "" "A more detailed description of unpacking behavior for iterator types " "(Dataset, generator, Sequence) is given in the `Unpacking behavior for " "iterator-like inputs` section of `Model.fit`." msgstr "" -#: keras.engine.training.Model.evaluate:20 of +#: keras.src.engine.training.Model.evaluate:20 of msgid "" "Target data. Like the input data `x`, it could be either Numpy array(s) " "or TensorFlow tensor(s). It should be consistent with `x` (you cannot " @@ -4305,7 +4990,7 @@ msgid "" "specified (since targets will be obtained from the iterator/dataset)." msgstr "" -#: keras.engine.training.Model.evaluate:26 of +#: keras.src.engine.training.Model.evaluate:26 of msgid "" "Integer or `None`. Number of samples per batch of computation. If " "unspecified, `batch_size` will default to 32. Do not specify the " @@ -4313,34 +4998,41 @@ msgid "" "`keras.utils.Sequence` instances (since they generate batches)." msgstr "" -#: keras.engine.training.Model.evaluate:31 of -msgid "0 or 1. Verbosity mode. 0 = silent, 1 = progress bar." +#: keras.src.engine.training.Model.evaluate:31 +#: keras.src.engine.training.Model.predict:42 of +msgid "" +"`\"auto\"`, 0, 1, or 2. Verbosity mode. 0 = silent, 1 = progress bar, 2 =" +" single line. `\"auto\"` becomes 1 for most cases, and to 2 when used " +"with `ParameterServerStrategy`. Note that the progress bar is not " +"particularly useful when logged to a file, so `verbose=2` is recommended " +"when not running interactively (e.g. in a production environment). " +"Defaults to 'auto'." msgstr "" -#: keras.engine.training.Model.evaluate:32 of +#: keras.src.engine.training.Model.evaluate:38 of msgid "" "Optional Numpy array of weights for the test samples, used for weighting " "the loss function. You can either pass a flat (1D) Numpy array with the " "same length as the input samples (1:1 mapping between weights and " "samples), or in the case of temporal data, you can pass a 2D array " "with shape `(samples, sequence_length)`, to apply a different weight " -"to every timestep of every sample. This argument is not supported " -"when `x` is a dataset, instead pass sample weights as the third " +"to every timestep of every sample. This argument is not supported " +"when `x` is a dataset, instead pass sample weights as the third " "element of `x`." msgstr "" -#: keras.engine.training.Model.evaluate:32 of +#: keras.src.engine.training.Model.evaluate:38 of msgid "" "Optional Numpy array of weights for the test samples, used for weighting " "the loss function. You can either pass a flat (1D) Numpy array with the " "same length as the input samples" msgstr "" -#: keras.engine.training.Model.evaluate:38 of +#: keras.src.engine.training.Model.evaluate:45 of msgid "(1:1 mapping between weights and samples), or in the case of" msgstr "" -#: keras.engine.training.Model.evaluate:36 of +#: keras.src.engine.training.Model.evaluate:42 of msgid "" "temporal data, you can pass a 2D array with shape `(samples, " "sequence_length)`, to apply a different weight to every timestep of every" @@ -4348,7 +5040,7 @@ msgid "" "pass sample weights as the third element of `x`." msgstr "" -#: keras.engine.training.Model.evaluate:40 of +#: keras.src.engine.training.Model.evaluate:47 of msgid "" "Integer or `None`. Total number of steps (batches of samples) before " "declaring the evaluation round finished. Ignored with the default value " @@ -4357,30 +5049,33 @@ msgid "" "with array inputs." msgstr "" -#: keras.engine.training.Model.evaluate:45 of +#: keras.src.engine.training.Model.evaluate:52 of msgid "" "List of `keras.callbacks.Callback` instances. List of callbacks to apply " -"during evaluation. See [callbacks](/api_docs/python/tf/keras/callbacks)." +"during evaluation. See " +"[callbacks](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks)." msgstr "" -#: keras.engine.training.Model.evaluate:48 keras.engine.training.Model.fit:160 -#: keras.engine.training.Model.predict:36 of +#: keras.src.engine.training.Model.evaluate:55 +#: keras.src.engine.training.Model.predict:58 of msgid "" "Integer. Used for generator or `keras.utils.Sequence` input only. Maximum" " size for the generator queue. If unspecified, `max_queue_size` will " "default to 10." msgstr "" -#: keras.engine.training.Model.evaluate:51 keras.engine.training.Model.fit:163 -#: keras.engine.training.Model.predict:39 of +#: keras.src.engine.training.Model.evaluate:58 +#: keras.src.engine.training.Model.fit:178 +#: keras.src.engine.training.Model.predict:62 of msgid "" "Integer. Used for generator or `keras.utils.Sequence` input only. Maximum" " number of processes to spin up when using process-based threading. If " "unspecified, `workers` will default to 1." msgstr "" -#: keras.engine.training.Model.evaluate:54 keras.engine.training.Model.fit:167 -#: keras.engine.training.Model.predict:43 of +#: keras.src.engine.training.Model.evaluate:62 +#: keras.src.engine.training.Model.fit:182 +#: keras.src.engine.training.Model.predict:66 of msgid "" "Boolean. Used for generator or `keras.utils.Sequence` input only. If " "`True`, use process-based threading. If unspecified, " @@ -4390,32 +5085,26 @@ msgid "" "children processes." msgstr "" -#: keras.engine.training.Model.evaluate:60 -#: keras.engine.training.Model.test_on_batch:21 -#: keras.engine.training.Model.train_on_batch:25 of +#: keras.src.engine.training.Model.evaluate:69 +#: keras.src.engine.training.Model.test_on_batch:21 +#: keras.src.engine.training.Model.train_on_batch:27 of msgid "" "If `True`, loss and metric results are returned as a dict, with each key " "being the name of the metric. If `False`, they are returned as a list." msgstr "" -#: keras.engine.training.Model.evaluate:63 of +#: keras.src.engine.training.Model.evaluate:72 of msgid "Unused at this time." msgstr "" -#: keras.engine.training.Model.evaluate:65 of +#: keras.src.engine.training.Model.evaluate:74 of msgid "" "See the discussion of `Unpacking behavior for iterator-like inputs` for " "`Model.fit`." msgstr "" -#: keras.engine.training.Model.evaluate:68 of -msgid "" -"`Model.evaluate` is not yet supported with " -"`tf.distribute.experimental.ParameterServerStrategy`." -msgstr "" - -#: keras.engine.training.Model.evaluate:71 -#: keras.engine.training.Model.test_on_batch:25 of +#: keras.src.engine.training.Model.evaluate:77 +#: keras.src.engine.training.Model.test_on_batch:25 of msgid "" "Scalar test loss (if the model has a single output and no metrics) or " "list of scalars (if the model has multiple outputs and/or metrics). The " @@ -4423,42 +5112,89 @@ msgid "" "scalar outputs." msgstr "" -#: keras.engine.training.Model.evaluate:76 of +#: keras.src.engine.training.Model.evaluate:82 of msgid "If `model.evaluate` is wrapped in a `tf.function`." msgstr "" -#: keras.engine.training.Model.evaluate_generator:1 of +#: keras.src.engine.training.Model.evaluate_generator:1 of msgid "Evaluates the model on a data generator." msgstr "" -#: keras.engine.training.Model.evaluate_generator:4 -#: keras.engine.training.Model.fit_generator:4 -#: keras.engine.training.Model.predict_generator:4 of +#: keras.src.engine.training.Model.evaluate_generator:4 +#: keras.src.engine.training.Model.fit_generator:4 +#: keras.src.engine.training.Model.predict_generator:4 of msgid "DEPRECATED:" msgstr "" -#: keras.engine.training.Model.evaluate_generator:4 of +#: keras.src.engine.training.Model.evaluate_generator:4 of msgid "" "`Model.evaluate` now supports generators, so there is no longer any need " "to use this endpoint." msgstr "" -#: keras.engine.base_layer.Layer.finalize_state:1 of +#: keras.src.engine.training.Model.export:1 of +msgid "Create a SavedModel artifact for inference (e.g. via TF-Serving)." +msgstr "" + +#: keras.src.engine.training.Model.export:3 of +msgid "" +"This method lets you export a model to a lightweight SavedModel artifact " +"that contains the model's forward pass only (its `call()` method) and can" +" be served via e.g. TF-Serving. The forward pass is registered under the " +"name `serve()` (see example below)." +msgstr "" + +#: keras.src.engine.training.Model.export:8 of +msgid "" +"The original code of the model (including any custom layers you may have " +"used) is *no longer* necessary to reload the artifact -- it is entirely " +"standalone." +msgstr "" + +#: keras.src.engine.training.Model.export:12 of +msgid "`str` or `pathlib.Path` object. Path where to save the artifact." +msgstr "" + +#: keras.src.engine.training.Model.export:17 of +msgid "```python # Create the artifact model.export(\"path/to/location\")" +msgstr "" + +#: keras.src.engine.training.Model.export:21 of +msgid "" +"# Later, in a different process / environment... reloaded_artifact = " +"tf.saved_model.load(\"path/to/location\") predictions = " +"reloaded_artifact.serve(input_data) ```" +msgstr "" + +#: keras.src.engine.training.Model.export:26 of +msgid "" +"If you would like to customize your serving endpoints, you can use the " +"lower-level `keras.export.ExportArchive` class. The `export()` method " +"relies on `ExportArchive` internally." +msgstr "" + +#: keras.src.engine.base_layer.Layer.finalize_state:1 of msgid "Finalizes the layers state after updating layer weights." msgstr "" -#: keras.engine.base_layer.Layer.finalize_state:3 of +#: keras.src.engine.base_layer.Layer.finalize_state:3 of msgid "" "This function can be subclassed in a layer and will be called after " "updating a layer weights. It can be overridden to finalize any additional" " layer state after a weight update." msgstr "" -#: keras.engine.training.Model.fit:1 of -msgid "Trains the model for a fixed number of epochs (iterations on a dataset)." +#: keras.src.engine.base_layer.Layer.finalize_state:7 of +msgid "" +"This function will be called after weights of a layer have been restored " +"from a loaded model." +msgstr "" + +#: keras.src.engine.training.Model.fit:1 of +msgid "Trains the model for a fixed number of epochs (dataset iterations)." msgstr "" -#: keras.engine.training.Model.fit:3 of +#: keras.src.engine.training.Model.fit:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the model has multiple inputs). - A TensorFlow tensor, " @@ -4466,7 +5202,7 @@ msgid "" "mapping input names to the corresponding array/tensors, if the model " "has named inputs. - A `tf.data` dataset. Should return a tuple of " "either `(inputs, targets)` or `(inputs, targets, sample_weights)`. - A " -"generator or `keras.utils.Sequence` returning `(inputs, targets)` or " +"generator or `keras.utils.Sequence` returning `(inputs, targets)` or " "`(inputs, targets, sample_weights)`. - A " "`tf.keras.utils.experimental.DatasetCreator`, which wraps a callable " "that takes a single argument of type `tf.distribute.InputContext`, and " @@ -4474,12 +5210,15 @@ msgid "" " prefer to specify the per-replica batching and sharding logic for the " "`Dataset`. See `tf.keras.utils.experimental.DatasetCreator` doc for " "more information. A more detailed description of unpacking behavior for" -" iterator types (Dataset, generator, Sequence) is given below. If using " +" iterator types (Dataset, generator, Sequence) is given below. If these " +"include `sample_weights` as a third component, note that sample weighting" +" applies to the `weighted_metrics` argument but not the `metrics` " +"argument in `compile()`. If using " "`tf.distribute.experimental.ParameterServerStrategy`, only " "`DatasetCreator` type is supported for `x`." msgstr "" -#: keras.engine.training.Model.fit:15 of +#: keras.src.engine.training.Model.fit:15 of msgid "" "A `tf.keras.utils.experimental.DatasetCreator`, which wraps a callable " "that takes a single argument of type `tf.distribute.InputContext`, and " @@ -4489,15 +5228,18 @@ msgid "" "information." msgstr "" -#: keras.engine.training.Model.fit:22 of +#: keras.src.engine.training.Model.fit:22 of msgid "" "A more detailed description of unpacking behavior for iterator types " -"(Dataset, generator, Sequence) is given below. If using " +"(Dataset, generator, Sequence) is given below. If these include " +"`sample_weights` as a third component, note that sample weighting applies" +" to the `weighted_metrics` argument but not the `metrics` argument in " +"`compile()`. If using " "`tf.distribute.experimental.ParameterServerStrategy`, only " "`DatasetCreator` type is supported for `x`." msgstr "" -#: keras.engine.training.Model.fit:26 of +#: keras.src.engine.training.Model.fit:29 of msgid "" "Target data. Like the input data `x`, it could be either Numpy array(s) " "or TensorFlow tensor(s). It should be consistent with `x` (you cannot " @@ -4506,7 +5248,7 @@ msgid "" "specified (since targets will be obtained from `x`)." msgstr "" -#: keras.engine.training.Model.fit:32 of +#: keras.src.engine.training.Model.fit:35 of msgid "" "Integer or `None`. Number of samples per gradient update. If unspecified," " `batch_size` will default to 32. Do not specify the `batch_size` if your" @@ -4514,7 +5256,7 @@ msgid "" "instances (since they generate batches)." msgstr "" -#: keras.engine.training.Model.fit:38 of +#: keras.src.engine.training.Model.fit:41 of msgid "" "Integer. Number of epochs to train the model. An epoch is an iteration " "over the entire `x` and `y` data provided (unless the `steps_per_epoch` " @@ -4524,16 +5266,17 @@ msgid "" "merely until the epoch of index `epochs` is reached." msgstr "" -#: keras.engine.training.Model.fit:48 of +#: keras.src.engine.training.Model.fit:51 of msgid "" "'auto', 0, 1, or 2. Verbosity mode. 0 = silent, 1 = progress bar, 2 = one" -" line per epoch. 'auto' defaults to 1 for most cases, but 2 when used " -"with `ParameterServerStrategy`. Note that the progress bar is not " -"particularly useful when logged to a file, so verbose=2 is recommended " -"when not running interactively (eg, in a production environment)." +" line per epoch. 'auto' becomes 1 for most cases, but 2 when used with " +"`ParameterServerStrategy`. Note that the progress bar is not particularly" +" useful when logged to a file, so verbose=2 is recommended when not " +"running interactively (eg, in a production environment). Defaults to " +"'auto'." msgstr "" -#: keras.engine.training.Model.fit:55 of +#: keras.src.engine.training.Model.fit:58 of msgid "" "List of `keras.callbacks.Callback` instances. List of callbacks to apply " "during training. See `tf.keras.callbacks`. Note " @@ -4547,43 +5290,21 @@ msgid "" "`steps_per_epoch` value." msgstr "" -#: keras.engine.training.Model.fit:66 of -msgid "" -"Float between 0 and 1. Fraction of the training data to be used as " -"validation data. The model will set apart this fraction of the training " -"data, will not train on it, and will evaluate the loss and any model " -"metrics on this data at the end of each epoch. The validation data is " -"selected from the last samples in the `x` and `y` data provided, before " -"shuffling. This argument is not supported when `x` is a dataset, " -"generator or `keras.utils.Sequence` instance. `validation_split` is not " -"yet supported with `tf.distribute.experimental.ParameterServerStrategy`." -msgstr "" - -#: keras.engine.training.Model.fit:74 of -msgid "Float between 0 and 1." -msgstr "" - -#: keras.engine.training.Model.fit:68 of -msgid "" -"Fraction of the training data to be used as validation data. The model " -"will set apart this fraction of the training data, will not train on it, " -"and will evaluate the loss and any model metrics on this data at the end " -"of each epoch. The validation data is selected from the last samples in " -"the `x` and `y` data provided, before shuffling. This argument is not " -"supported when `x` is a dataset, generator or" -msgstr "" - -#: keras.engine.training.Model.fit:77 of -msgid "`keras.utils.Sequence` instance." -msgstr "" - -#: keras.engine.training.Model.fit:77 of +#: keras.src.engine.training.Model.fit:70 of msgid "" -"`validation_split` is not yet supported with " +"Float between 0 and 1. Fraction of the training data to be used as " +"validation data. The model will set apart this fraction of the training " +"data, will not train on it, and will evaluate the loss and any model " +"metrics on this data at the end of each epoch. The validation data is " +"selected from the last samples in the `x` and `y` data provided, before " +"shuffling. This argument is not supported when `x` is a dataset, " +"generator or `keras.utils.Sequence` instance. If both `validation_data` " +"and `validation_split` are provided, `validation_data` will override " +"`validation_split`. `validation_split` is not yet supported with " "`tf.distribute.experimental.ParameterServerStrategy`." msgstr "" -#: keras.engine.training.Model.fit:79 of +#: keras.src.engine.training.Model.fit:84 of msgid "" "Data on which to evaluate the loss and any model metrics at the end of " "each epoch. The model will not be trained on this data. Thus, note the " @@ -4591,14 +5312,14 @@ msgid "" "or `validation_data` is not affected by regularization layers like noise " "and dropout. `validation_data` will override `validation_split`. " "`validation_data` could be: - A tuple `(x_val, y_val)` of Numpy arrays " -"or tensors. - A tuple `(x_val, y_val, val_sample_weights)` of NumPy " -"arrays. - A `tf.data.Dataset`. - A Python generator or " +"or tensors. - A tuple `(x_val, y_val, val_sample_weights)` of NumPy" +" arrays. - A `tf.data.Dataset`. - A Python generator or " "`keras.utils.Sequence` returning `(inputs, targets)` or `(inputs, " "targets, sample_weights)`. `validation_data` is not yet supported with " "`tf.distribute.experimental.ParameterServerStrategy`." msgstr "" -#: keras.engine.training.Model.fit:79 of +#: keras.src.engine.training.Model.fit:84 of msgid "" "Data on which to evaluate the loss and any model metrics at the end of " "each epoch. The model will not be trained on this data. Thus, note the " @@ -4608,33 +5329,33 @@ msgid "" "`validation_data` could be:" msgstr "" -#: keras.engine.training.Model.fit:87 of +#: keras.src.engine.training.Model.fit:92 of msgid "A tuple `(x_val, y_val)` of Numpy arrays or tensors." msgstr "" -#: keras.engine.training.Model.fit:88 of +#: keras.src.engine.training.Model.fit:93 of msgid "A tuple `(x_val, y_val, val_sample_weights)` of NumPy arrays." msgstr "" -#: keras.engine.training.Model.fit:89 of +#: keras.src.engine.training.Model.fit:95 of msgid "A `tf.data.Dataset`." msgstr "" -#: keras.engine.training.Model.fit:90 of +#: keras.src.engine.training.Model.fit:96 of msgid "A Python generator or `keras.utils.Sequence` returning" msgstr "" -#: keras.engine.training.Model.fit:91 of +#: keras.src.engine.training.Model.fit:97 of msgid "`(inputs, targets)` or `(inputs, targets, sample_weights)`." msgstr "" -#: keras.engine.training.Model.fit:92 of +#: keras.src.engine.training.Model.fit:98 of msgid "" "`validation_data` is not yet supported with " "`tf.distribute.experimental.ParameterServerStrategy`." msgstr "" -#: keras.engine.training.Model.fit:94 of +#: keras.src.engine.training.Model.fit:100 of msgid "" "Boolean (whether to shuffle the training data before each epoch) or str " "(for 'batch'). This argument is ignored when `x` is a generator or an " @@ -4643,57 +5364,39 @@ msgid "" "effect when `steps_per_epoch` is not `None`." msgstr "" -#: keras.engine.training.Model.fit:100 of +#: keras.src.engine.training.Model.fit:106 of msgid "" "Optional dictionary mapping class indices (integers) to a weight (float) " "value, used for weighting the loss function (during training only). This " "can be useful to tell the model to \"pay more attention\" to samples from" -" an under-represented class." -msgstr "" - -#: keras.engine.training.Model.fit:106 of -msgid "" -"Optional Numpy array of weights for the training samples, used for " -"weighting the loss function (during training only). You can either pass " -"a flat (1D) Numpy array with the same length as the input samples (1:1 " -"mapping between weights and samples), or in the case of temporal data, " -"you can pass a 2D array with shape `(samples, sequence_length)`, to " -"apply a different weight to every timestep of every sample. This " -"argument is not supported when `x` is a dataset, generator, or " -"`keras.utils.Sequence` instance, instead provide the sample_weights as " -"the third element of `x`." -msgstr "" - -#: keras.engine.training.Model.fit:115 of -msgid "Optional Numpy array of weights for" +" an under-represented class. When `class_weight` is specified and targets" +" have a rank of 2 or greater, either `y` must be one-hot encoded, or an " +"explicit final dimension of `1` must be included for sparse class labels." msgstr "" -#: keras.engine.training.Model.fit:108 of +#: keras.src.engine.training.Model.fit:115 of msgid "" -"the training samples, used for weighting the loss function (during " -"training only). You can either pass a flat (1D) Numpy array with the same" -" length as the input samples (1:1 mapping between weights and samples), " -"or in the case of temporal data, you can pass a 2D array with shape " -"`(samples, sequence_length)`, to apply a different weight to every " -"timestep of every sample. This argument is not supported when `x` is a " -"dataset, generator, or" -msgstr "" - -#: keras.engine.training.Model.fit:117 of -msgid "`keras.utils.Sequence` instance, instead provide the sample_weights" -msgstr "" - -#: keras.engine.training.Model.fit:118 of -msgid "as the third element of `x`." +"Optional Numpy array of weights for the training samples, used for " +"weighting the loss function (during training only). You can either pass a" +" flat (1D) Numpy array with the same length as the input samples (1:1 " +"mapping between weights and samples), or in the case of temporal data, " +"you can pass a 2D array with shape `(samples, sequence_length)`, to apply" +" a different weight to every timestep of every sample. This argument is " +"not supported when `x` is a dataset, generator, or `keras.utils.Sequence`" +" instance, instead provide the sample_weights as the third element of " +"`x`. Note that sample weighting does not apply to metrics specified via " +"the `metrics` argument in `compile()`. To apply sample weighting to your " +"metrics, you can specify them via the `weighted_metrics` in `compile()` " +"instead." msgstr "" -#: keras.engine.training.Model.fit:119 of +#: keras.src.engine.training.Model.fit:131 of msgid "" "Integer. Epoch at which to start training (useful for resuming a previous" " training run)." msgstr "" -#: keras.engine.training.Model.fit:122 of +#: keras.src.engine.training.Model.fit:134 of msgid "" "Integer or `None`. Total number of steps (batches of samples) before " "declaring one epoch finished and starting the next epoch. When training " @@ -4701,15 +5404,15 @@ msgid "" " equal to the number of samples in your dataset divided by the batch " "size, or 1 if that cannot be determined. If x is a `tf.data` dataset, and" " 'steps_per_epoch' is None, the epoch will run until the input dataset is" -" exhausted. When passing an infinitely repeating dataset, you must " +" exhausted. When passing an infinitely repeating dataset, you must " "specify the `steps_per_epoch` argument. If `steps_per_epoch=-1` the " -"training will run indefinitely with an infinitely repeating dataset. This" -" argument is not supported with array inputs. When using " +"training will run indefinitely with an infinitely repeating dataset. " +"This argument is not supported with array inputs. When using " "`tf.distribute.experimental.ParameterServerStrategy`: * " "`steps_per_epoch=None` is not supported." msgstr "" -#: keras.engine.training.Model.fit:122 of +#: keras.src.engine.training.Model.fit:134 of msgid "" "Integer or `None`. Total number of steps (batches of samples) before " "declaring one epoch finished and starting the next epoch. When training " @@ -4717,18 +5420,18 @@ msgid "" " equal to the number of samples in your dataset divided by the batch " "size, or 1 if that cannot be determined. If x is a `tf.data` dataset, and" " 'steps_per_epoch' is None, the epoch will run until the input dataset is" -" exhausted. When passing an infinitely repeating dataset, you must " +" exhausted. When passing an infinitely repeating dataset, you must " "specify the `steps_per_epoch` argument. If `steps_per_epoch=-1` the " -"training will run indefinitely with an infinitely repeating dataset. This" -" argument is not supported with array inputs. When using " +"training will run indefinitely with an infinitely repeating dataset. " +"This argument is not supported with array inputs. When using " "`tf.distribute.experimental.ParameterServerStrategy`:" msgstr "" -#: keras.engine.training.Model.fit:136 of +#: keras.src.engine.training.Model.fit:149 of msgid "`steps_per_epoch=None` is not supported." msgstr "" -#: keras.engine.training.Model.fit:137 of +#: keras.src.engine.training.Model.fit:150 of msgid "" "Only relevant if `validation_data` is provided and is a `tf.data` " "dataset. Total number of steps (batches of samples) to draw before " @@ -4742,7 +5445,7 @@ msgid "" "time." msgstr "" -#: keras.engine.training.Model.fit:147 of +#: keras.src.engine.training.Model.fit:161 of msgid "" "Integer or `None`. Number of samples per validation batch. If " "unspecified, will default to `batch_size`. Do not specify the " @@ -4751,10 +5454,10 @@ msgid "" "batches)." msgstr "" -#: keras.engine.training.Model.fit:153 of +#: keras.src.engine.training.Model.fit:167 of msgid "" "Only relevant if validation data is provided. Integer or " -"`collections.abc.Container` instance (e.g. list, tuple, etc.). If an " +"`collections.abc.Container` instance (e.g. list, tuple, etc.). If an " "integer, specifies how many training epochs to run before a new " "validation run is performed, e.g. `validation_freq=2` runs validation " "every 2 epochs. If a Container, specifies the epochs on which to run " @@ -4762,19 +5465,26 @@ msgid "" "of the 1st, 2nd, and 10th epochs." msgstr "" -#: keras.engine.training.Model.fit:196 of +#: keras.src.engine.training.Model.fit:175 of +msgid "" +"Integer. Used for generator or `keras.utils.Sequence` input only. Maximum" +" size for the generator queue. If unspecified, `max_queue_size` will " +"default to 10." +msgstr "" + +#: keras.src.engine.training.Model.fit:214 of msgid "Unpacking behavior for iterator-like inputs:" msgstr "" -#: keras.engine.training.Model.fit:175 of +#: keras.src.engine.training.Model.fit:191 of msgid "A common pattern is to pass a tf.data.Dataset, generator, or" msgstr "" -#: keras.engine.training.Model.fit:176 of +#: keras.src.engine.training.Model.fit:192 of msgid "" "tf.keras.utils.Sequence to the `x` argument of fit, which will in fact " "yield not only features (x) but optionally targets (y) and sample " -"weights. Keras requires that the output of such iterator-likes be " +"weights. Keras requires that the output of such iterator-likes be " "unambiguous. The iterator should return a tuple of length 1, 2, or 3, " "where the optional second and third elements will be used for y and " "sample_weight respectively. Any other type provided will be wrapped in a " @@ -4784,31 +5494,31 @@ msgid "" "features, targets, and weights from the keys of a single dict." msgstr "" -#: keras.engine.training.Model.fit:186 of -msgid "A notable unsupported data type is the namedtuple. The reason is that" +#: keras.src.engine.training.Model.fit:203 of +msgid "A notable unsupported data type is the namedtuple. The reason is" msgstr "" -#: keras.engine.training.Model.fit:187 of +#: keras.src.engine.training.Model.fit:204 of msgid "" -"it behaves like both an ordered datatype (tuple) and a mapping datatype " -"(dict). So given a namedtuple of the form:" +"that it behaves like both an ordered datatype (tuple) and a mapping " +"datatype (dict). So given a namedtuple of the form:" msgstr "" -#: keras.engine.training.Model.fit:189 of +#: keras.src.engine.training.Model.fit:206 of msgid "`namedtuple(\"example_tuple\", [\"y\", \"x\"])`" msgstr "" -#: keras.engine.training.Model.fit:190 of +#: keras.src.engine.training.Model.fit:207 of msgid "" "it is ambiguous whether to reverse the order of the elements when " "interpreting the value. Even worse is a tuple of the form:" msgstr "" -#: keras.engine.training.Model.fit:192 of +#: keras.src.engine.training.Model.fit:209 of msgid "`namedtuple(\"other_tuple\", [\"x\", \"y\", \"z\"])`" msgstr "" -#: keras.engine.training.Model.fit:193 of +#: keras.src.engine.training.Model.fit:210 of msgid "" "where it is unclear if the tuple was intended to be unpacked into x, y, " "and sample_weight or passed through as a single element to `x`. As a " @@ -4816,44 +5526,44 @@ msgid "" "encounters a namedtuple. (Along with instructions to remedy the issue.)" msgstr "" -#: keras.engine.training.Model.fit:198 of +#: keras.src.engine.training.Model.fit:216 of msgid "" "A `History` object. Its `History.history` attribute is a record of " "training loss values and metrics values at successive epochs, as well as " "validation loss values and validation metrics values (if applicable)." msgstr "" -#: keras.engine.training.Model.fit:203 of +#: keras.src.engine.training.Model.fit:221 of msgid "1. If the model was never compiled or," msgstr "" -#: keras.engine.training.Model.fit:203 of +#: keras.src.engine.training.Model.fit:221 of msgid "If the model was never compiled or," msgstr "" -#: keras.engine.training.Model.fit:205 of +#: keras.src.engine.training.Model.fit:223 of msgid "" "In case of mismatch between the provided input data and what the " "model expects or when the input data is empty." msgstr "" -#: keras.engine.training.Model.fit_generator:1 of +#: keras.src.engine.training.Model.fit_generator:1 of msgid "Fits the model on data yielded batch-by-batch by a Python generator." msgstr "" -#: keras.engine.training.Model.fit_generator:4 of +#: keras.src.engine.training.Model.fit_generator:4 of msgid "" "`Model.fit` now supports generators, so there is no longer any need to " "use this endpoint." msgstr "" -#: keras.engine.base_layer.Layer.from_config:1 -#: keras.engine.training.Model.from_config:1 of +#: keras.src.engine.base_layer.Layer.from_config:1 +#: keras.src.engine.training.Model.from_config:1 of msgid "Creates a layer from its config." msgstr "" -#: keras.engine.base_layer.Layer.from_config:3 -#: keras.engine.training.Model.from_config:3 of +#: keras.src.engine.base_layer.Layer.from_config:3 +#: keras.src.engine.training.Model.from_config:3 of msgid "" "This method is the reverse of `get_config`, capable of instantiating the " "same layer from the config dictionary. It does not handle layer " @@ -4861,69 +5571,106 @@ msgid "" "`set_weights`)." msgstr "" -#: keras.engine.base_layer.Layer.from_config:8 -#: keras.engine.training.Model.from_config:8 of +#: keras.src.engine.base_layer.Layer.from_config:8 +#: keras.src.engine.training.Model.from_config:8 of msgid "A Python dictionary, typically the output of get_config." msgstr "" -#: keras.engine.base_layer.Layer.from_config:11 -#: keras.engine.training.Model.from_config:11 -#: keras.engine.training.Model.get_layer:9 of +#: keras.src.engine.base_layer.Layer.from_config:11 +#: keras.src.engine.training.Model.from_config:11 +#: keras.src.engine.training.Model.get_layer:9 of msgid "A layer instance." msgstr "" -#: keras.engine.base_layer.Layer.get_config:1 -#: keras.engine.training.Model.get_config:1 of -msgid "Returns the config of the layer." +#: keras.src.engine.base_layer.Layer.get_build_config:1 of +msgid "Returns a dictionary with the layer's input shape." msgstr "" -#: keras.engine.base_layer.Layer.get_config:3 -#: keras.engine.training.Model.get_config:3 of +#: keras.src.engine.base_layer.Layer.get_build_config:3 of msgid "" -"A layer config is a Python dictionary (serializable) containing the " -"configuration of a layer. The same layer can be reinstantiated later " -"(without its trained weights) from this configuration." +"This method returns a config dict that can be used by " +"`build_from_config(config)` to create all states (e.g. Variables and " +"Lookup tables) needed by the layer." msgstr "" -#: keras.engine.base_layer.Layer.get_config:8 -#: keras.engine.training.Model.get_config:8 of +#: keras.src.engine.base_layer.Layer.get_build_config:7 of msgid "" -"The config of a layer does not include connectivity information, nor the " -"layer class name. These are handled by `Network` (one layer of " -"abstraction above)." +"By default, the config only contains the input shape that the layer was " +"built with. If you're writing a custom layer that creates state in an " +"unusual way, you should override this method to make sure this state is " +"already created when Keras attempts to load its value upon model loading." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_build_config:13 of +msgid "A dict containing the input shape associated with the layer." +msgstr "" + +#: keras.src.engine.training.Model.get_compile_config:1 of +msgid "Returns a serialized config with information for compiling the model." msgstr "" -#: keras.engine.base_layer.Layer.get_config:12 -#: keras.engine.training.Model.get_config:12 of +#: keras.src.engine.training.Model.get_compile_config:3 of +msgid "" +"This method returns a config dictionary containing all the information " +"(optimizer, loss, metrics, etc.) with which the model was compiled." +msgstr "" + +#: keras.src.engine.training.Model.get_compile_config:6 of +msgid "A dict containing information for compiling the model." +msgstr "" + +#: keras.src.engine.training.Model.get_config:1 of +msgid "Returns the config of the `Model`." +msgstr "" + +#: keras.src.engine.training.Model.get_config:3 of +msgid "" +"Config is a Python dictionary (serializable) containing the configuration" +" of an object, which in this case is a `Model`. This allows the `Model` " +"to be be reinstantiated later (without its trained weights) from this " +"configuration." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_config:12 +#: keras.src.engine.training.Model.get_config:8 of msgid "" "Note that `get_config()` does not guarantee to return a fresh copy of " "dict every time it is called. The callers should make a copy of the " "returned dict if they want to modify it." msgstr "" -#: keras.engine.base_layer.Layer.get_config:16 -#: keras.engine.training.Model.get_config:16 of -msgid "Python dictionary." +#: keras.src.engine.training.Model.get_config:12 of +msgid "" +"Developers of subclassed `Model` are advised to override this method, and" +" continue to update the dict from `super(MyModel, self).get_config()` to " +"provide the proper configuration of this `Model`. The default config will" +" return config dict for init parameters if they are basic types. Raises " +"`NotImplementedError` when in cases where a custom `get_config()` " +"implementation is required for the subclassed model." msgstr "" -#: keras.engine.base_layer.Layer.get_input_at:1 of +#: keras.src.engine.training.Model.get_config:19 of +msgid "Python dictionary containing the configuration of this `Model`." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_input_at:1 of msgid "Retrieves the input tensor(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_input_at:3 of +#: keras.src.engine.base_layer.Layer.get_input_at:3 of msgid "" "Integer, index of the node from which to retrieve the attribute. E.g. " "`node_index=0` will correspond to the first input node of the layer." msgstr "" -#: keras.engine.base_layer.Layer.get_input_at:8 of +#: keras.src.engine.base_layer.Layer.get_input_at:8 of msgid "A tensor (or list of tensors if the layer has multiple inputs)." msgstr "" -#: keras.engine.base_layer.Layer.get_input_at:10 -#: keras.engine.base_layer.Layer.get_input_shape_at:11 -#: keras.engine.base_layer.Layer.get_output_at:10 -#: keras.engine.base_layer.Layer.get_output_shape_at:11 of +#: keras.src.engine.base_layer.Layer.get_input_at:10 +#: keras.src.engine.base_layer.Layer.get_input_shape_at:11 +#: keras.src.engine.base_layer.Layer.get_output_at:10 +#: keras.src.engine.base_layer.Layer.get_output_shape_at:11 of #: tensorcircuit.applications.van.MADE.input:8 #: tensorcircuit.applications.van.MaskedConv2D.input:8 #: tensorcircuit.applications.van.MaskedLinear.input:8 @@ -4931,129 +5678,192 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input:8 #: tensorcircuit.applications.van.ResidualBlock.input:8 #: tensorcircuit.applications.vqes.Linear.input:8 +#: tensorcircuit.keras.HardwareLayer.input:8 #: tensorcircuit.keras.QuantumLayer.input:8 msgid "If called in Eager mode." msgstr "" -#: keras.engine.base_layer.Layer.get_input_mask_at:1 of +#: keras.src.engine.base_layer.Layer.get_input_mask_at:1 of msgid "Retrieves the input mask tensor(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_input_mask_at:3 -#: keras.engine.base_layer.Layer.get_input_shape_at:3 -#: keras.engine.base_layer.Layer.get_output_mask_at:3 -#: keras.engine.base_layer.Layer.get_output_shape_at:3 of +#: keras.src.engine.base_layer.Layer.get_input_mask_at:3 +#: keras.src.engine.base_layer.Layer.get_input_shape_at:3 +#: keras.src.engine.base_layer.Layer.get_output_mask_at:3 +#: keras.src.engine.base_layer.Layer.get_output_shape_at:3 of msgid "" "Integer, index of the node from which to retrieve the attribute. E.g. " "`node_index=0` will correspond to the first time the layer was called." msgstr "" -#: keras.engine.base_layer.Layer.get_input_mask_at:8 of +#: keras.src.engine.base_layer.Layer.get_input_mask_at:8 of msgid "A mask tensor (or list of tensors if the layer has multiple inputs)." msgstr "" -#: keras.engine.base_layer.Layer.get_input_shape_at:1 of +#: keras.src.engine.base_layer.Layer.get_input_shape_at:1 of msgid "Retrieves the input shape(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_input_shape_at:8 of +#: keras.src.engine.base_layer.Layer.get_input_shape_at:8 of msgid "A shape tuple (or list of shape tuples if the layer has multiple inputs)." msgstr "" -#: keras.engine.training.Model.get_layer:1 of +#: keras.src.engine.training.Model.get_layer:1 of msgid "Retrieves a layer based on either its name (unique) or index." msgstr "" -#: keras.engine.training.Model.get_layer:3 of +#: keras.src.engine.training.Model.get_layer:3 of msgid "" "If `name` and `index` are both provided, `index` will take precedence. " "Indices are based on order of horizontal graph traversal (bottom-up)." msgstr "" -#: keras.engine.training.Model.get_layer:6 of +#: keras.src.engine.training.Model.get_layer:6 of msgid "String, name of layer." msgstr "" -#: keras.engine.training.Model.get_layer:7 of +#: keras.src.engine.training.Model.get_layer:7 of msgid "Integer, index of layer." msgstr "" -#: keras.engine.base_layer.Layer.get_losses_for:3 of -msgid "Retrieves losses relevant to a specific set of inputs." +#: keras.src.engine.training.Model.get_metrics_result:1 of +msgid "Returns the model's metrics values as a dict." msgstr "" -#: keras.engine.base_layer.Layer.get_losses_for:5 -#: keras.engine.base_layer.Layer.get_updates_for:5 of -msgid "Input tensor or list/tuple of input tensors." +#: keras.src.engine.training.Model.get_metrics_result:3 of +msgid "" +"If any of the metric result is a dict (containing multiple metrics), each" +" of them gets added to the top level returned dict of this method." msgstr "" -#: keras.engine.base_layer.Layer.get_losses_for:7 of -msgid "List of loss tensors of the layer that depend on `inputs`." +#: keras.src.engine.training.Model.get_metrics_result:6 of +msgid "" +"A `dict` containing values of the metrics listed in `self.metrics`. " +"Example: `{'loss': 0.2, 'accuracy': 0.7}`." msgstr "" -#: keras.engine.base_layer.Layer.get_output_at:1 of +#: keras.src.engine.base_layer.Layer.get_output_at:1 of msgid "Retrieves the output tensor(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_output_at:3 of +#: keras.src.engine.base_layer.Layer.get_output_at:3 of msgid "" "Integer, index of the node from which to retrieve the attribute. E.g. " "`node_index=0` will correspond to the first output node of the layer." msgstr "" -#: keras.engine.base_layer.Layer.get_output_at:8 of +#: keras.src.engine.base_layer.Layer.get_output_at:8 of msgid "A tensor (or list of tensors if the layer has multiple outputs)." msgstr "" -#: keras.engine.base_layer.Layer.get_output_mask_at:1 of +#: keras.src.engine.base_layer.Layer.get_output_mask_at:1 of msgid "Retrieves the output mask tensor(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_output_mask_at:8 of +#: keras.src.engine.base_layer.Layer.get_output_mask_at:8 of msgid "A mask tensor (or list of tensors if the layer has multiple outputs)." msgstr "" -#: keras.engine.base_layer.Layer.get_output_shape_at:1 of +#: keras.src.engine.base_layer.Layer.get_output_shape_at:1 of msgid "Retrieves the output shape(s) of a layer at a given node." msgstr "" -#: keras.engine.base_layer.Layer.get_output_shape_at:8 of +#: keras.src.engine.base_layer.Layer.get_output_shape_at:8 of msgid "A shape tuple (or list of shape tuples if the layer has multiple outputs)." msgstr "" -#: keras.engine.base_layer.Layer.get_updates_for:3 of -msgid "Retrieves updates relevant to a specific set of inputs." +#: keras.src.engine.training.Model.get_weight_paths:1 of +msgid "Retrieve all the variables and their paths for the model." msgstr "" -#: keras.engine.base_layer.Layer.get_updates_for:7 of -msgid "List of update ops of the layer that depend on `inputs`." +#: keras.src.engine.training.Model.get_weight_paths:3 of +msgid "" +"The variable path (string) is a stable key to identify a `tf.Variable` " +"instance owned by the model. It can be used to specify variable-specific " +"configurations (e.g. DTensor, quantization) from a global view." +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:7 of +msgid "" +"This method returns a dict with weight object paths as keys and the " +"corresponding `tf.Variable` instances as values." +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:10 of +msgid "" +"Note that if the model is a subclassed model and the weights haven't been" +" initialized, an empty dict will be returned." +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:13 of +msgid "" +"A dict where keys are variable paths and values are `tf.Variable` " +"instances." +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:16 of +msgid "A dict where keys are variable paths and values are `tf.Variable`" +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:16 of +msgid "instances." +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:20 of +msgid "```python class SubclassModel(tf.keras.Model):" msgstr "" -#: keras.engine.training.Model.get_weights:1 of +#: keras.src.engine.training.Model.get_weight_paths:26 of +msgid "def __init__(self, name=None):" +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:24 of +msgid "" +"super().__init__(name=name) self.d1 = tf.keras.layers.Dense(10) self.d2 =" +" tf.keras.layers.Dense(20)" +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:29 of +msgid "x = self.d1(inputs) return self.d2(x)" +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:32 of +msgid "" +"model = SubclassModel() model(tf.zeros((10, 10))) weight_paths = " +"model.get_weight_paths() # weight_paths: # { # 'd1.kernel': " +"model.d1.kernel, # 'd1.bias': model.d1.bias, # 'd2.kernel': " +"model.d2.kernel, # 'd2.bias': model.d2.bias, # }" +msgstr "" + +#: keras.src.engine.training.Model.get_weight_paths:43 of +msgid "" +"# Functional model inputs = tf.keras.Input((10,), batch_size=10) x = " +"tf.keras.layers.Dense(20, name='d1')(inputs) output = " +"tf.keras.layers.Dense(30, name='d2')(x) model = tf.keras.Model(inputs, " +"output) d1 = model.layers[1] d2 = model.layers[2] weight_paths = " +"model.get_weight_paths() # weight_paths: # { # 'd1.kernel': d1.kernel," +" # 'd1.bias': d1.bias, # 'd2.kernel': d2.kernel, # 'd2.bias': " +"d2.bias, # } ```" +msgstr "" + +#: keras.src.engine.training.Model.get_weights:1 of msgid "Retrieves the weights of the model." msgstr "" -#: keras.engine.training.Model.get_weights:3 of +#: keras.src.engine.training.Model.get_weights:3 of msgid "A flat list of Numpy arrays." msgstr "" #: of tensorcircuit.applications.van.MADE.inbound_nodes:1 -#: tensorcircuit.applications.van.MADE.outbound_nodes:1 #: tensorcircuit.applications.van.MaskedConv2D.inbound_nodes:1 -#: tensorcircuit.applications.van.MaskedConv2D.outbound_nodes:1 #: tensorcircuit.applications.van.MaskedLinear.inbound_nodes:1 -#: tensorcircuit.applications.van.MaskedLinear.outbound_nodes:1 #: tensorcircuit.applications.van.NMF.inbound_nodes:1 -#: tensorcircuit.applications.van.NMF.outbound_nodes:1 #: tensorcircuit.applications.van.PixelCNN.inbound_nodes:1 -#: tensorcircuit.applications.van.PixelCNN.outbound_nodes:1 #: tensorcircuit.applications.van.ResidualBlock.inbound_nodes:1 -#: tensorcircuit.applications.van.ResidualBlock.outbound_nodes:1 #: tensorcircuit.applications.vqes.Linear.inbound_nodes:1 -#: tensorcircuit.applications.vqes.Linear.outbound_nodes:1 +#: tensorcircuit.keras.HardwareLayer.inbound_nodes:1 #: tensorcircuit.keras.QuantumLayer.inbound_nodes:1 -#: tensorcircuit.keras.QuantumLayer.outbound_nodes:1 -msgid "Deprecated, do NOT use! Only for compatibility with external Keras." +msgid "Return Functional API nodes upstream of this layer." msgstr "" #: of tensorcircuit.applications.van.MADE.input:1 @@ -5063,6 +5873,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input:1 #: tensorcircuit.applications.van.ResidualBlock.input:1 #: tensorcircuit.applications.vqes.Linear.input:1 +#: tensorcircuit.keras.HardwareLayer.input:1 #: tensorcircuit.keras.QuantumLayer.input:1 msgid "Retrieves the input tensor(s) of a layer." msgstr "" @@ -5074,6 +5885,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input:3 #: tensorcircuit.applications.van.ResidualBlock.input:3 #: tensorcircuit.applications.vqes.Linear.input:3 +#: tensorcircuit.keras.HardwareLayer.input:3 #: tensorcircuit.keras.QuantumLayer.input:3 msgid "" "Only applicable if the layer has exactly one input, i.e. if it is " @@ -5087,6 +5899,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input:6 #: tensorcircuit.applications.van.ResidualBlock.input:6 #: tensorcircuit.applications.vqes.Linear.input:6 +#: tensorcircuit.keras.HardwareLayer.input:6 #: tensorcircuit.keras.QuantumLayer.input:6 msgid "Input tensor or list of input tensors." msgstr "" @@ -5098,6 +5911,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input:9 #: tensorcircuit.applications.van.ResidualBlock.input:9 #: tensorcircuit.applications.vqes.Linear.input:9 +#: tensorcircuit.keras.HardwareLayer.input:9 #: tensorcircuit.keras.QuantumLayer.input:9 msgid "If no inbound nodes are found." msgstr "" @@ -5109,6 +5923,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_mask:1 #: tensorcircuit.applications.van.ResidualBlock.input_mask:1 #: tensorcircuit.applications.vqes.Linear.input_mask:1 +#: tensorcircuit.keras.HardwareLayer.input_mask:1 #: tensorcircuit.keras.QuantumLayer.input_mask:1 msgid "Retrieves the input mask tensor(s) of a layer." msgstr "" @@ -5127,6 +5942,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.output_mask:3 #: tensorcircuit.applications.vqes.Linear.input_mask:3 #: tensorcircuit.applications.vqes.Linear.output_mask:3 +#: tensorcircuit.keras.HardwareLayer.input_mask:3 +#: tensorcircuit.keras.HardwareLayer.output_mask:3 #: tensorcircuit.keras.QuantumLayer.input_mask:3 #: tensorcircuit.keras.QuantumLayer.output_mask:3 msgid "" @@ -5141,6 +5958,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_mask:6 #: tensorcircuit.applications.van.ResidualBlock.input_mask:6 #: tensorcircuit.applications.vqes.Linear.input_mask:6 +#: tensorcircuit.keras.HardwareLayer.input_mask:6 #: tensorcircuit.keras.QuantumLayer.input_mask:6 msgid "Input mask tensor (potentially None) or list of input mask tensors." msgstr "" @@ -5159,6 +5977,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.output_mask:9 #: tensorcircuit.applications.vqes.Linear.input_mask:9 #: tensorcircuit.applications.vqes.Linear.output_mask:9 +#: tensorcircuit.keras.HardwareLayer.input_mask:9 +#: tensorcircuit.keras.HardwareLayer.output_mask:9 #: tensorcircuit.keras.QuantumLayer.input_mask:9 #: tensorcircuit.keras.QuantumLayer.output_mask:9 msgid "if the layer is connected to" @@ -5171,6 +5991,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_shape:1 #: tensorcircuit.applications.van.ResidualBlock.input_shape:1 #: tensorcircuit.applications.vqes.Linear.input_shape:1 +#: tensorcircuit.keras.HardwareLayer.input_shape:1 #: tensorcircuit.keras.QuantumLayer.input_shape:1 msgid "Retrieves the input shape(s) of a layer." msgstr "" @@ -5182,6 +6003,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_shape:3 #: tensorcircuit.applications.van.ResidualBlock.input_shape:3 #: tensorcircuit.applications.vqes.Linear.input_shape:3 +#: tensorcircuit.keras.HardwareLayer.input_shape:3 #: tensorcircuit.keras.QuantumLayer.input_shape:3 msgid "" "Only applicable if the layer has exactly one input, i.e. if it is " @@ -5195,6 +6017,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_shape:7 #: tensorcircuit.applications.van.ResidualBlock.input_shape:7 #: tensorcircuit.applications.vqes.Linear.input_shape:7 +#: tensorcircuit.keras.HardwareLayer.input_shape:7 #: tensorcircuit.keras.QuantumLayer.input_shape:7 msgid "" "Input shape, as an integer shape tuple (or list of shape tuples, one " @@ -5208,6 +6031,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_shape:10 #: tensorcircuit.applications.van.ResidualBlock.input_shape:10 #: tensorcircuit.applications.vqes.Linear.input_shape:10 +#: tensorcircuit.keras.HardwareLayer.input_shape:10 #: tensorcircuit.keras.QuantumLayer.input_shape:10 msgid "if the layer has no defined input_shape." msgstr "" @@ -5233,6 +6057,9 @@ msgstr "" #: tensorcircuit.applications.vqes.Linear.input_shape:11 #: tensorcircuit.applications.vqes.Linear.output:9 #: tensorcircuit.applications.vqes.Linear.output_shape:10 +#: tensorcircuit.keras.HardwareLayer.input_shape:11 +#: tensorcircuit.keras.HardwareLayer.output:9 +#: tensorcircuit.keras.HardwareLayer.output_shape:10 #: tensorcircuit.keras.QuantumLayer.input_shape:11 #: tensorcircuit.keras.QuantumLayer.output:9 #: tensorcircuit.keras.QuantumLayer.output_shape:10 @@ -5246,6 +6073,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:1 #: tensorcircuit.applications.van.ResidualBlock.input_spec:1 #: tensorcircuit.applications.vqes.Linear.input_spec:1 +#: tensorcircuit.keras.HardwareLayer.input_spec:1 #: tensorcircuit.keras.QuantumLayer.input_spec:1 msgid "`InputSpec` instance(s) describing the input format for this layer." msgstr "" @@ -5257,6 +6085,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:3 #: tensorcircuit.applications.van.ResidualBlock.input_spec:3 #: tensorcircuit.applications.vqes.Linear.input_spec:3 +#: tensorcircuit.keras.HardwareLayer.input_spec:3 #: tensorcircuit.keras.QuantumLayer.input_spec:3 msgid "" "When you create a layer subclass, you can set `self.input_spec` to enable" @@ -5272,6 +6101,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:8 #: tensorcircuit.applications.van.ResidualBlock.input_spec:8 #: tensorcircuit.applications.vqes.Linear.input_spec:8 +#: tensorcircuit.keras.HardwareLayer.input_spec:8 #: tensorcircuit.keras.QuantumLayer.input_spec:8 msgid "```python self.input_spec = tf.keras.layers.InputSpec(ndim=4) ```" msgstr "" @@ -5283,6 +6113,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:12 #: tensorcircuit.applications.van.ResidualBlock.input_spec:12 #: tensorcircuit.applications.vqes.Linear.input_spec:12 +#: tensorcircuit.keras.HardwareLayer.input_spec:12 #: tensorcircuit.keras.QuantumLayer.input_spec:12 msgid "" "Now, if you try to call the layer on an input that isn't rank 4 (for " @@ -5297,6 +6128,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:16 #: tensorcircuit.applications.van.ResidualBlock.input_spec:16 #: tensorcircuit.applications.vqes.Linear.input_spec:16 +#: tensorcircuit.keras.HardwareLayer.input_spec:16 #: tensorcircuit.keras.QuantumLayer.input_spec:16 msgid "" "``` ValueError: Input 0 of layer conv2d is incompatible with the layer: " @@ -5310,6 +6142,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:21 #: tensorcircuit.applications.van.ResidualBlock.input_spec:21 #: tensorcircuit.applications.vqes.Linear.input_spec:21 +#: tensorcircuit.keras.HardwareLayer.input_spec:21 #: tensorcircuit.keras.QuantumLayer.input_spec:21 msgid "" "Input checks that can be specified via `input_spec` include: - Structure " @@ -5324,6 +6157,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:27 #: tensorcircuit.applications.van.ResidualBlock.input_spec:27 #: tensorcircuit.applications.vqes.Linear.input_spec:27 +#: tensorcircuit.keras.HardwareLayer.input_spec:27 #: tensorcircuit.keras.QuantumLayer.input_spec:27 msgid "For more information, see `tf.keras.layers.InputSpec`." msgstr "" @@ -5335,96 +6169,130 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.input_spec:29 #: tensorcircuit.applications.van.ResidualBlock.input_spec:29 #: tensorcircuit.applications.vqes.Linear.input_spec:29 +#: tensorcircuit.keras.HardwareLayer.input_spec:29 #: tensorcircuit.keras.QuantumLayer.input_spec:29 msgid "A `tf.keras.layers.InputSpec` instance, or nested structure thereof." msgstr "" -#: keras.engine.training.Model.load_weights:1 of -msgid "Loads all layer weights, either from a TensorFlow or an HDF5 weight file." +#: of tensorcircuit.applications.van.MADE.jit_compile:1 +#: tensorcircuit.applications.van.NMF.jit_compile:1 +#: tensorcircuit.applications.van.PixelCNN.jit_compile:1 +msgid "Specify whether to compile the model with XLA." msgstr "" -#: keras.engine.training.Model.load_weights:3 of +#: of tensorcircuit.applications.van.MADE.jit_compile:3 +#: tensorcircuit.applications.van.NMF.jit_compile:3 +#: tensorcircuit.applications.van.PixelCNN.jit_compile:3 msgid "" -"If `by_name` is False weights are loaded based on the network's topology." -" This means the architecture should be the same as when the weights were " -"saved. Note that layers that don't have weights are not taken into " -"account in the topological ordering, so adding or removing layers is fine" -" as long as they don't have weights." +"[XLA](https://www.tensorflow.org/xla) is an optimizing compiler for " +"machine learning. `jit_compile` is not enabled by default. Note that " +"`jit_compile=True` may not necessarily work for all models." msgstr "" -#: keras.engine.training.Model.load_weights:9 of +#: of tensorcircuit.applications.van.MADE.jit_compile:7 +#: tensorcircuit.applications.van.NMF.jit_compile:7 +#: tensorcircuit.applications.van.PixelCNN.jit_compile:7 msgid "" -"If `by_name` is True, weights are loaded into layers only if they share " -"the same name. This is useful for fine-tuning or transfer-learning models" -" where some of the layers have changed." +"For more information on supported operations please refer to the [XLA " +"documentation](https://www.tensorflow.org/xla). Also refer to [known XLA " +"issues](https://www.tensorflow.org/xla/known_issues) for more details." msgstr "" -#: keras.engine.training.Model.load_weights:13 of +#: keras.src.engine.base_layer.Layer.load_own_variables:1 of +msgid "Loads the state of the layer." +msgstr "" + +#: keras.src.engine.base_layer.Layer.load_own_variables:3 of msgid "" -"Only topological loading (`by_name=False`) is supported when loading " -"weights from the TensorFlow format. Note that topological loading differs" -" slightly between TensorFlow and HDF5 formats for user-defined classes " -"inheriting from `tf.keras.Model`: HDF5 loads based on a flattened list of" -" weights, while the TensorFlow format loads based on the object-local " -"names of attributes to which layers are assigned in the `Model`'s " -"constructor." +"You can override this method to take full control of how the state of the" +" layer is loaded upon calling `keras.models.load_model()`." +msgstr "" + +#: keras.src.engine.base_layer.Layer.load_own_variables:6 of +msgid "Dict from which the state of the model will be loaded." msgstr "" -#: keras.engine.training.Model.load_weights:20 of +#: keras.src.engine.training.Model.load_weights:1 of +msgid "Loads all layer weights from a saved files." +msgstr "" + +#: keras.src.engine.training.Model.load_weights:3 of msgid "" -"String, path to the weights file to load. For weight files in TensorFlow " -"format, this is the file prefix (the same as was passed to " -"`save_weights`). This can also be a path to a SavedModel saved from " -"`model.save`." +"The saved file could be a SavedModel file, a `.keras` file (v3 saving " +"format), or a file created via `model.save_weights()`." msgstr "" -#: keras.engine.training.Model.load_weights:24 of +#: keras.src.engine.training.Model.load_weights:6 of msgid "" -"Boolean, whether to load weights by name or by topological order. Only " -"topological loading is supported for weight files in TensorFlow format." +"By default, weights are loaded based on the network's topology. This " +"means the architecture should be the same as when the weights were saved." +" Note that layers that don't have weights are not taken into account in " +"the topological ordering, so adding or removing layers is fine as long as" +" they don't have weights." +msgstr "" + +#: keras.src.engine.training.Model.load_weights:12 of +msgid "**Partial weight loading**" msgstr "" -#: keras.engine.training.Model.load_weights:27 of +#: keras.src.engine.training.Model.load_weights:14 of msgid "" -"Boolean, whether to skip loading of layers where there is a mismatch in " -"the number of weights, or a mismatch in the shape of the weight (only " -"valid when `by_name=True`)." +"If you have modified your model, for instance by adding a new layer (with" +" weights) or by changing the shape of the weights of a layer, you can " +"choose to ignore errors and continue loading by setting " +"`skip_mismatch=True`. In this case any layer with mismatching weights " +"will be skipped. A warning will be displayed for each skipped layer." msgstr "" -#: keras.engine.training.Model.load_weights:30 of +#: keras.src.engine.training.Model.load_weights:21 of +msgid "**Weight loading by name**" +msgstr "" + +#: keras.src.engine.training.Model.load_weights:23 of msgid "" -"Optional `tf.train.CheckpointOptions` object that specifies options for " -"loading weights." +"If your weights are saved as a `.h5` file created via " +"`model.save_weights()`, you can use the argument `by_name=True`." +msgstr "" + +#: keras.src.engine.training.Model.load_weights:26 of +msgid "" +"In this case, weights are loaded into layers only if they share the same " +"name. This is useful for fine-tuning or transfer-learning models where " +"some of the layers have changed." msgstr "" -#: keras.engine.training.Model.load_weights:33 of +#: keras.src.engine.training.Model.load_weights:30 of msgid "" -"When loading a weight file in TensorFlow format, returns the same status " -"object as `tf.train.Checkpoint.restore`. When graph building, restore ops" -" are run automatically as soon as the network is built (on first call for" -" user-defined classes inheriting from `Model`, immediately if it is " -"already built). When loading weights in HDF5 format, returns `None`." +"Note that only topological loading (`by_name=False`) is supported when " +"loading weights from the `.keras` v3 format or from the TensorFlow " +"SavedModel format." msgstr "" -#: keras.engine.training.Model.load_weights:33 of +#: keras.src.engine.training.Model.load_weights:34 of msgid "" -"When loading a weight file in TensorFlow format, returns the same status " -"object as `tf.train.Checkpoint.restore`. When graph building, restore ops" -" are run automatically as soon as the network is built (on first call for" -" user-defined classes inheriting from `Model`, immediately if it is " -"already built)." +"String, path to the weights file to load. For weight files in TensorFlow " +"format, this is the file prefix (the same as was passed to " +"`save_weights()`). This can also be a path to a SavedModel or a `.keras` " +"file (v3 saving format) saved via `model.save()`." msgstr "" -#: keras.engine.training.Model.load_weights:39 of -msgid "When loading weights in HDF5 format, returns `None`." +#: keras.src.engine.training.Model.load_weights:39 of +msgid "" +"Boolean, whether to skip loading of layers where there is a mismatch in " +"the number of weights, or a mismatch in the shape of the weights." msgstr "" -#: keras.engine.training.Model.load_weights:41 of -msgid "If `h5py` is not available and the weight file is in HDF5 format." +#: keras.src.engine.training.Model.load_weights:42 of +msgid "" +"Boolean, whether to load weights by name or by topological order. Only " +"topological loading is supported for weight files in the `.keras` v3 " +"format or in the TensorFlow SavedModel format." msgstr "" -#: keras.engine.training.Model.load_weights:42 of -msgid "If `skip_mismatch` is set to `True` when `by_name` is `False`." +#: keras.src.engine.training.Model.load_weights:45 of +msgid "" +"Optional `tf.train.CheckpointOptions` object that specifies options for " +"loading weights (only valid for a SavedModel file)." msgstr "" #: of tensorcircuit.applications.van.MADE.losses:1 @@ -5434,6 +6302,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.losses:1 #: tensorcircuit.applications.van.ResidualBlock.losses:1 #: tensorcircuit.applications.vqes.Linear.losses:1 +#: tensorcircuit.keras.HardwareLayer.losses:1 #: tensorcircuit.keras.QuantumLayer.losses:1 msgid "List of losses added using the `add_loss()` API." msgstr "" @@ -5445,6 +6314,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.losses:3 #: tensorcircuit.applications.van.ResidualBlock.losses:3 #: tensorcircuit.applications.vqes.Linear.losses:3 +#: tensorcircuit.keras.HardwareLayer.losses:3 #: tensorcircuit.keras.QuantumLayer.losses:3 msgid "" "Variable regularization tensors are created when this property is " @@ -5453,53 +6323,55 @@ msgid "" "variables." msgstr "" -#: keras.engine.training.Model.reset_metrics:3 of -#: tensorcircuit.applications.van.MADE.losses:7 +#: keras.src.engine.training.Model.reset_metrics:3 of +#: tensorcircuit.applications.van.MADE.losses:8 #: tensorcircuit.applications.van.MADE.metrics:6 #: tensorcircuit.applications.van.MADE.metrics_names:6 -#: tensorcircuit.applications.van.MaskedConv2D.losses:7 -#: tensorcircuit.applications.van.MaskedLinear.losses:7 -#: tensorcircuit.applications.van.NMF.losses:7 +#: tensorcircuit.applications.van.MaskedConv2D.losses:8 +#: tensorcircuit.applications.van.MaskedLinear.losses:8 +#: tensorcircuit.applications.van.NMF.losses:8 #: tensorcircuit.applications.van.NMF.metrics:6 #: tensorcircuit.applications.van.NMF.metrics_names:6 -#: tensorcircuit.applications.van.PixelCNN.losses:7 +#: tensorcircuit.applications.van.PixelCNN.losses:8 #: tensorcircuit.applications.van.PixelCNN.metrics:6 #: tensorcircuit.applications.van.PixelCNN.metrics_names:6 -#: tensorcircuit.applications.van.ResidualBlock.losses:7 -#: tensorcircuit.applications.vqes.Linear.losses:7 -#: tensorcircuit.keras.QuantumLayer.losses:7 +#: tensorcircuit.applications.van.ResidualBlock.losses:8 +#: tensorcircuit.applications.vqes.Linear.losses:8 +#: tensorcircuit.keras.HardwareLayer.losses:8 +#: tensorcircuit.keras.QuantumLayer.losses:8 msgid "Examples:" msgstr "" -#: of tensorcircuit.applications.van.MADE.losses:39 -#: tensorcircuit.applications.van.MaskedConv2D.losses:39 -#: tensorcircuit.applications.van.MaskedLinear.losses:39 -#: tensorcircuit.applications.van.NMF.losses:39 -#: tensorcircuit.applications.van.PixelCNN.losses:39 -#: tensorcircuit.applications.van.ResidualBlock.losses:39 -#: tensorcircuit.applications.vqes.Linear.losses:39 -#: tensorcircuit.keras.QuantumLayer.losses:39 +#: of tensorcircuit.applications.van.MADE.losses:40 +#: tensorcircuit.applications.van.MaskedConv2D.losses:40 +#: tensorcircuit.applications.van.MaskedLinear.losses:40 +#: tensorcircuit.applications.van.NMF.losses:40 +#: tensorcircuit.applications.van.PixelCNN.losses:40 +#: tensorcircuit.applications.van.ResidualBlock.losses:40 +#: tensorcircuit.applications.vqes.Linear.losses:40 +#: tensorcircuit.keras.HardwareLayer.losses:40 +#: tensorcircuit.keras.QuantumLayer.losses:40 msgid "A list of tensors." msgstr "" -#: keras.engine.training.Model.make_predict_function:1 of +#: keras.src.engine.training.Model.make_predict_function:1 of msgid "Creates a function that executes one step of inference." msgstr "" -#: keras.engine.training.Model.make_predict_function:3 of +#: keras.src.engine.training.Model.make_predict_function:3 of msgid "" "This method can be overridden to support custom inference logic. This " "method is called by `Model.predict` and `Model.predict_on_batch`." msgstr "" -#: keras.engine.training.Model.make_predict_function:6 of +#: keras.src.engine.training.Model.make_predict_function:6 of msgid "" "Typically, this method directly controls `tf.function` and " "`tf.distribute.Strategy` settings, and delegates the actual evaluation " "logic to `Model.predict_step`." msgstr "" -#: keras.engine.training.Model.make_predict_function:10 of +#: keras.src.engine.training.Model.make_predict_function:10 of msgid "" "This function is cached the first time `Model.predict` or " "`Model.predict_on_batch` is called. The cache is cleared whenever " @@ -5507,36 +6379,36 @@ msgid "" "function with `force=True`." msgstr "" -#: keras.engine.training.Model.make_predict_function:15 of +#: keras.src.engine.training.Model.make_predict_function:15 of msgid "" "Whether to regenerate the predict function and skip the cached function " "if available." msgstr "" -#: keras.engine.training.Model.make_predict_function:18 of +#: keras.src.engine.training.Model.make_predict_function:18 of msgid "" "Function. The function created by this method should accept a " "`tf.data.Iterator`, and return the outputs of the `Model`." msgstr "" -#: keras.engine.training.Model.make_test_function:1 of +#: keras.src.engine.training.Model.make_test_function:1 of msgid "Creates a function that executes one step of evaluation." msgstr "" -#: keras.engine.training.Model.make_test_function:3 of +#: keras.src.engine.training.Model.make_test_function:3 of msgid "" "This method can be overridden to support custom evaluation logic. This " "method is called by `Model.evaluate` and `Model.test_on_batch`." msgstr "" -#: keras.engine.training.Model.make_test_function:6 of +#: keras.src.engine.training.Model.make_test_function:6 of msgid "" "Typically, this method directly controls `tf.function` and " "`tf.distribute.Strategy` settings, and delegates the actual evaluation " "logic to `Model.test_step`." msgstr "" -#: keras.engine.training.Model.make_test_function:10 of +#: keras.src.engine.training.Model.make_test_function:10 of msgid "" "This function is cached the first time `Model.evaluate` or " "`Model.test_on_batch` is called. The cache is cleared whenever " @@ -5544,37 +6416,37 @@ msgid "" "function with `force=True`." msgstr "" -#: keras.engine.training.Model.make_test_function:15 of +#: keras.src.engine.training.Model.make_test_function:15 of msgid "" "Whether to regenerate the test function and skip the cached function if " "available." msgstr "" -#: keras.engine.training.Model.make_test_function:18 of +#: keras.src.engine.training.Model.make_test_function:18 of msgid "" "Function. The function created by this method should accept a " "`tf.data.Iterator`, and return a `dict` containing values that will be " "passed to `tf.keras.Callbacks.on_test_batch_end`." msgstr "" -#: keras.engine.training.Model.make_train_function:1 of +#: keras.src.engine.training.Model.make_train_function:1 of msgid "Creates a function that executes one step of training." msgstr "" -#: keras.engine.training.Model.make_train_function:3 of +#: keras.src.engine.training.Model.make_train_function:3 of msgid "" "This method can be overridden to support custom training logic. This " "method is called by `Model.fit` and `Model.train_on_batch`." msgstr "" -#: keras.engine.training.Model.make_train_function:6 of +#: keras.src.engine.training.Model.make_train_function:6 of msgid "" "Typically, this method directly controls `tf.function` and " "`tf.distribute.Strategy` settings, and delegates the actual training " "logic to `Model.train_step`." msgstr "" -#: keras.engine.training.Model.make_train_function:10 of +#: keras.src.engine.training.Model.make_train_function:10 of msgid "" "This function is cached the first time `Model.fit` or " "`Model.train_on_batch` is called. The cache is cleared whenever " @@ -5582,13 +6454,13 @@ msgid "" "function with `force=True`." msgstr "" -#: keras.engine.training.Model.make_train_function:15 of +#: keras.src.engine.training.Model.make_train_function:15 of msgid "" "Whether to regenerate the train function and skip the cached function if " "available." msgstr "" -#: keras.engine.training.Model.make_train_function:18 of +#: keras.src.engine.training.Model.make_train_function:18 of msgid "" "Function. The function created by this method should accept a " "`tf.data.Iterator`, and return a `dict` containing values that will be " @@ -5599,7 +6471,7 @@ msgstr "" #: of tensorcircuit.applications.van.MADE.metrics:1 #: tensorcircuit.applications.van.NMF.metrics:1 #: tensorcircuit.applications.van.PixelCNN.metrics:1 -msgid "Returns the model's metrics added using `compile()`, `add_metric()` APIs." +msgid "Return metrics added using `compile()` or `add_metric()`." msgstr "" #: of tensorcircuit.applications.van.MADE.metrics:3 @@ -5631,6 +6503,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.name:1 #: tensorcircuit.applications.van.ResidualBlock.name:1 #: tensorcircuit.applications.vqes.Linear.name:1 +#: tensorcircuit.keras.HardwareLayer.name:1 #: tensorcircuit.keras.QuantumLayer.name:1 msgid "Name of the layer (string), set in the constructor." msgstr "" @@ -5642,6 +6515,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.name_scope:1 #: tensorcircuit.applications.van.ResidualBlock.name_scope:1 #: tensorcircuit.applications.vqes.Linear.name_scope:1 +#: tensorcircuit.keras.HardwareLayer.name_scope:1 #: tensorcircuit.keras.QuantumLayer.name_scope:1 msgid "Returns a `tf.name_scope` instance for this class." msgstr "" @@ -5653,6 +6527,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.non_trainable_variables:1 #: tensorcircuit.applications.van.ResidualBlock.non_trainable_variables:1 #: tensorcircuit.applications.vqes.Linear.non_trainable_variables:1 +#: tensorcircuit.keras.HardwareLayer.non_trainable_variables:1 #: tensorcircuit.keras.QuantumLayer.non_trainable_variables:1 msgid "" "Sequence of non-trainable variables owned by this module and its " @@ -5673,6 +6548,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.trainable_variables:3 #: tensorcircuit.applications.vqes.Linear.non_trainable_variables:3 #: tensorcircuit.applications.vqes.Linear.trainable_variables:3 +#: tensorcircuit.keras.HardwareLayer.non_trainable_variables:3 +#: tensorcircuit.keras.HardwareLayer.trainable_variables:3 #: tensorcircuit.keras.QuantumLayer.non_trainable_variables:3 #: tensorcircuit.keras.QuantumLayer.trainable_variables:3 msgid "" @@ -5696,6 +6573,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.trainable_variables:7 #: tensorcircuit.applications.vqes.Linear.non_trainable_variables:7 #: tensorcircuit.applications.vqes.Linear.trainable_variables:7 +#: tensorcircuit.keras.HardwareLayer.non_trainable_variables:7 +#: tensorcircuit.keras.HardwareLayer.trainable_variables:7 #: tensorcircuit.keras.QuantumLayer.non_trainable_variables:7 #: tensorcircuit.keras.QuantumLayer.trainable_variables:7 msgid "" @@ -5710,6 +6589,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.non_trainable_weights:1 #: tensorcircuit.applications.van.ResidualBlock.non_trainable_weights:1 #: tensorcircuit.applications.vqes.Linear.non_trainable_weights:1 +#: tensorcircuit.keras.HardwareLayer.non_trainable_weights:1 #: tensorcircuit.keras.QuantumLayer.non_trainable_weights:1 msgid "List of all non-trainable weights tracked by this layer." msgstr "" @@ -5721,6 +6601,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.non_trainable_weights:3 #: tensorcircuit.applications.van.ResidualBlock.non_trainable_weights:3 #: tensorcircuit.applications.vqes.Linear.non_trainable_weights:3 +#: tensorcircuit.keras.HardwareLayer.non_trainable_weights:3 #: tensorcircuit.keras.QuantumLayer.non_trainable_weights:3 msgid "" "Non-trainable weights are *not* updated during training. They are " @@ -5734,10 +6615,23 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.non_trainable_weights:6 #: tensorcircuit.applications.van.ResidualBlock.non_trainable_weights:6 #: tensorcircuit.applications.vqes.Linear.non_trainable_weights:6 +#: tensorcircuit.keras.HardwareLayer.non_trainable_weights:6 #: tensorcircuit.keras.QuantumLayer.non_trainable_weights:6 msgid "A list of non-trainable variables." msgstr "" +#: of tensorcircuit.applications.van.MADE.outbound_nodes:1 +#: tensorcircuit.applications.van.MaskedConv2D.outbound_nodes:1 +#: tensorcircuit.applications.van.MaskedLinear.outbound_nodes:1 +#: tensorcircuit.applications.van.NMF.outbound_nodes:1 +#: tensorcircuit.applications.van.PixelCNN.outbound_nodes:1 +#: tensorcircuit.applications.van.ResidualBlock.outbound_nodes:1 +#: tensorcircuit.applications.vqes.Linear.outbound_nodes:1 +#: tensorcircuit.keras.HardwareLayer.outbound_nodes:1 +#: tensorcircuit.keras.QuantumLayer.outbound_nodes:1 +msgid "Return Functional API nodes downstream of this layer." +msgstr "" + #: of tensorcircuit.applications.van.MADE.output:1 #: tensorcircuit.applications.van.MaskedConv2D.output:1 #: tensorcircuit.applications.van.MaskedLinear.output:1 @@ -5745,6 +6639,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output:1 #: tensorcircuit.applications.van.ResidualBlock.output:1 #: tensorcircuit.applications.vqes.Linear.output:1 +#: tensorcircuit.keras.HardwareLayer.output:1 #: tensorcircuit.keras.QuantumLayer.output:1 msgid "Retrieves the output tensor(s) of a layer." msgstr "" @@ -5756,6 +6651,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output:3 #: tensorcircuit.applications.van.ResidualBlock.output:3 #: tensorcircuit.applications.vqes.Linear.output:3 +#: tensorcircuit.keras.HardwareLayer.output:3 #: tensorcircuit.keras.QuantumLayer.output:3 msgid "" "Only applicable if the layer has exactly one output, i.e. if it is " @@ -5769,6 +6665,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output:6 #: tensorcircuit.applications.van.ResidualBlock.output:6 #: tensorcircuit.applications.vqes.Linear.output:6 +#: tensorcircuit.keras.HardwareLayer.output:6 #: tensorcircuit.keras.QuantumLayer.output:6 msgid "Output tensor or list of output tensors." msgstr "" @@ -5780,6 +6677,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output:8 #: tensorcircuit.applications.van.ResidualBlock.output:8 #: tensorcircuit.applications.vqes.Linear.output:8 +#: tensorcircuit.keras.HardwareLayer.output:8 #: tensorcircuit.keras.QuantumLayer.output:8 msgid "if the layer is connected to more than one incoming layers." msgstr "" @@ -5791,6 +6689,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_mask:1 #: tensorcircuit.applications.van.ResidualBlock.output_mask:1 #: tensorcircuit.applications.vqes.Linear.output_mask:1 +#: tensorcircuit.keras.HardwareLayer.output_mask:1 #: tensorcircuit.keras.QuantumLayer.output_mask:1 msgid "Retrieves the output mask tensor(s) of a layer." msgstr "" @@ -5802,6 +6701,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_mask:6 #: tensorcircuit.applications.van.ResidualBlock.output_mask:6 #: tensorcircuit.applications.vqes.Linear.output_mask:6 +#: tensorcircuit.keras.HardwareLayer.output_mask:6 #: tensorcircuit.keras.QuantumLayer.output_mask:6 msgid "Output mask tensor (potentially None) or list of output mask tensors." msgstr "" @@ -5813,6 +6713,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_shape:1 #: tensorcircuit.applications.van.ResidualBlock.output_shape:1 #: tensorcircuit.applications.vqes.Linear.output_shape:1 +#: tensorcircuit.keras.HardwareLayer.output_shape:1 #: tensorcircuit.keras.QuantumLayer.output_shape:1 msgid "Retrieves the output shape(s) of a layer." msgstr "" @@ -5824,6 +6725,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_shape:3 #: tensorcircuit.applications.van.ResidualBlock.output_shape:3 #: tensorcircuit.applications.vqes.Linear.output_shape:3 +#: tensorcircuit.keras.HardwareLayer.output_shape:3 #: tensorcircuit.keras.QuantumLayer.output_shape:3 msgid "" "Only applicable if the layer has one output, or if all outputs have the " @@ -5837,6 +6739,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_shape:6 #: tensorcircuit.applications.van.ResidualBlock.output_shape:6 #: tensorcircuit.applications.vqes.Linear.output_shape:6 +#: tensorcircuit.keras.HardwareLayer.output_shape:6 #: tensorcircuit.keras.QuantumLayer.output_shape:6 msgid "" "Output shape, as an integer shape tuple (or list of shape tuples, one " @@ -5850,26 +6753,50 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.output_shape:9 #: tensorcircuit.applications.van.ResidualBlock.output_shape:9 #: tensorcircuit.applications.vqes.Linear.output_shape:9 +#: tensorcircuit.keras.HardwareLayer.output_shape:9 #: tensorcircuit.keras.QuantumLayer.output_shape:9 msgid "if the layer has no defined output shape." msgstr "" -#: keras.engine.training.Model.predict:1 of +#: keras.src.engine.training.Model.predict:1 of msgid "Generates output predictions for the input samples." msgstr "" -#: keras.engine.training.Model.predict:3 of +#: keras.src.engine.training.Model.predict:3 of +msgid "" +"Computation is done in batches. This method is designed for batch " +"processing of large numbers of inputs. It is not intended for use inside " +"of loops that iterate over your data and process small numbers of inputs " +"at a time." +msgstr "" + +#: keras.src.engine.training.Model.predict:8 of +msgid "" +"For small numbers of inputs that fit in one batch, directly use " +"`__call__()` for faster execution, e.g., `model(x)`, or `model(x, " +"training=False)` if you have layers such as " +"`tf.keras.layers.BatchNormalization` that behave differently during " +"inference. You may pair the individual model call with a `tf.function` " +"for additional performance inside your inner loop. If you need access to " +"numpy array values instead of tensors after your model call, you can use " +"`tensor.numpy()` to get the numpy array value of an eager tensor." +msgstr "" + +#: keras.src.engine.training.Model.predict:18 of +msgid "" +"Also, note the fact that test loss is not affected by regularization " +"layers like noise and dropout." +msgstr "" + +#: keras.src.engine.training.Model.predict:21 of msgid "" -"Computation is done in batches. This method is designed for performance " -"in large scale inputs. For small amount of inputs that fit in one batch, " -"directly using `__call__()` is recommended for faster execution, e.g., " -"`model(x)`, or `model(x, training=False)` if you have layers such as " -"`tf.keras.layers.BatchNormalization` that behaves differently during " -"inference. Also, note the fact that test loss is not affected by " -"regularization layers like noise and dropout." +"Note: See [this FAQ entry]( https://keras.io/getting_started/faq/#whats-" +"the-difference-between-model-methods-predict-and-call) for more details " +"about the difference between `Model` methods `predict()` and " +"`__call__()`." msgstr "" -#: keras.engine.training.Model.predict:11 of +#: keras.src.engine.training.Model.predict:26 of msgid "" "Input samples. It could be: - A Numpy array (or array-like), or a list of" " arrays (in case the model has multiple inputs). - A TensorFlow tensor," @@ -5880,21 +6807,21 @@ msgid "" "iterator-like inputs` section of `Model.fit`." msgstr "" -#: keras.engine.training.Model.predict:11 of +#: keras.src.engine.training.Model.predict:26 of msgid "" "Input samples. It could be: - A Numpy array (or array-like), or a list of" " arrays" msgstr "" -#: keras.engine.training.Model.predict:16 of +#: keras.src.engine.training.Model.predict:31 of msgid "A `tf.data` dataset." msgstr "" -#: keras.engine.training.Model.predict:17 of +#: keras.src.engine.training.Model.predict:32 of msgid "A generator or `keras.utils.Sequence` instance." msgstr "" -#: keras.engine.training.Model.predict:21 of +#: keras.src.engine.training.Model.predict:36 of msgid "" "Integer or `None`. Number of samples per batch. If unspecified, " "`batch_size` will default to 32. Do not specify the `batch_size` if your " @@ -5902,11 +6829,7 @@ msgid "" "instances (since they generate batches)." msgstr "" -#: keras.engine.training.Model.predict:27 of -msgid "Verbosity mode, 0 or 1." -msgstr "" - -#: keras.engine.training.Model.predict:28 of +#: keras.src.engine.training.Model.predict:49 of msgid "" "Total number of steps (batches of samples) before declaring the " "prediction round finished. Ignored with the default value of `None`. If x" @@ -5914,13 +6837,14 @@ msgid "" "the input dataset is exhausted." msgstr "" -#: keras.engine.training.Model.predict:33 of +#: keras.src.engine.training.Model.predict:54 of msgid "" "List of `keras.callbacks.Callback` instances. List of callbacks to apply " -"during prediction. See [callbacks](/api_docs/python/tf/keras/callbacks)." +"during prediction. See [callbacks]( " +"https://www.tensorflow.org/api_docs/python/tf/keras/callbacks)." msgstr "" -#: keras.engine.training.Model.predict:50 of +#: keras.src.engine.training.Model.predict:74 of msgid "" "See the discussion of `Unpacking behavior for iterator-like inputs` for " "`Model.fit`. Note that Model.predict uses the same interpretation rules " @@ -5928,105 +6852,105 @@ msgid "" "all three methods." msgstr "" -#: keras.engine.training.Model.predict:55 -#: keras.engine.training.Model.predict_on_batch:9 of +#: keras.src.engine.training.Model.predict:79 +#: keras.src.engine.training.Model.predict_on_batch:9 of msgid "Numpy array(s) of predictions." msgstr "" -#: keras.engine.training.Model.predict:57 of +#: keras.src.engine.training.Model.predict:81 of msgid "If `model.predict` is wrapped in a `tf.function`." msgstr "" -#: keras.engine.training.Model.predict:58 of +#: keras.src.engine.training.Model.predict:82 of msgid "" "In case of mismatch between the provided input data and the model's " "expectations, or in case a stateful model receives a number of " "samples that is not a multiple of the batch size." msgstr "" -#: keras.engine.training.Model.predict_generator:1 of +#: keras.src.engine.training.Model.predict_generator:1 of msgid "Generates predictions for the input samples from a data generator." msgstr "" -#: keras.engine.training.Model.predict_generator:4 of +#: keras.src.engine.training.Model.predict_generator:4 of msgid "" "`Model.predict` now supports generators, so there is no longer any need " "to use this endpoint." msgstr "" -#: keras.engine.training.Model.predict_on_batch:1 of +#: keras.src.engine.training.Model.predict_on_batch:1 of msgid "Returns predictions for a single batch of samples." msgstr "" -#: keras.engine.training.Model.predict_on_batch:3 of +#: keras.src.engine.training.Model.predict_on_batch:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the model has multiple inputs). - A TensorFlow " "tensor, or a list of tensors (in case the model has multiple inputs)." msgstr "" -#: keras.engine.training.Model.predict_on_batch:3 -#: keras.engine.training.Model.test_on_batch:3 of +#: keras.src.engine.training.Model.predict_on_batch:3 +#: keras.src.engine.training.Model.test_on_batch:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the" msgstr "" -#: keras.engine.training.Model.predict_on_batch:5 -#: keras.engine.training.Model.test_on_batch:5 of +#: keras.src.engine.training.Model.predict_on_batch:5 +#: keras.src.engine.training.Model.test_on_batch:5 of msgid "model has multiple inputs)." msgstr "" -#: keras.engine.training.Model.predict_on_batch:7 -#: keras.engine.training.Model.test_on_batch:6 of +#: keras.src.engine.training.Model.predict_on_batch:7 +#: keras.src.engine.training.Model.test_on_batch:6 of msgid "A TensorFlow tensor, or a list of tensors (in case the model has" msgstr "" -#: keras.engine.training.Model.predict_on_batch:7 -#: keras.engine.training.Model.test_on_batch:7 of +#: keras.src.engine.training.Model.predict_on_batch:7 +#: keras.src.engine.training.Model.test_on_batch:7 of msgid "multiple inputs)." msgstr "" -#: keras.engine.training.Model.predict_on_batch:11 of -msgid "If `model.predict_on_batch` is wrapped in a `tf.function`." +#: keras.src.engine.training.Model.predict_on_batch:11 of +msgid "If `model.predict_on_batch` is wrapped in a `tf.function`." msgstr "" -#: keras.engine.training.Model.predict_step:1 of +#: keras.src.engine.training.Model.predict_step:1 of msgid "The logic for one inference step." msgstr "" -#: keras.engine.training.Model.predict_step:3 of +#: keras.src.engine.training.Model.predict_step:3 of msgid "" "This method can be overridden to support custom inference logic. This " "method is called by `Model.make_predict_function`." msgstr "" -#: keras.engine.training.Model.predict_step:6 of +#: keras.src.engine.training.Model.predict_step:6 of msgid "" "This method should contain the mathematical logic for one step of " -"inference. This typically includes the forward pass." +"inference. This typically includes the forward pass." msgstr "" -#: keras.engine.training.Model.predict_step:9 of +#: keras.src.engine.training.Model.predict_step:9 of msgid "" "Configuration details for *how* this logic is run (e.g. `tf.function` and" " `tf.distribute.Strategy` settings), should be left to " "`Model.make_predict_function`, which can also be overridden." msgstr "" -#: keras.engine.training.Model.predict_step:13 -#: keras.engine.training.Model.test_step:15 -#: keras.engine.training.Model.train_step:16 of +#: keras.src.engine.training.Model.predict_step:13 +#: keras.src.engine.training.Model.test_step:15 +#: keras.src.engine.training.Model.train_step:17 of msgid "A nested structure of `Tensor`s." msgstr "" -#: keras.engine.training.Model.predict_step:15 of +#: keras.src.engine.training.Model.predict_step:15 of msgid "" "The result of one inference step, typically the output of calling the " "`Model` on data." msgstr "" -#: keras.engine.training.Model.reset_metrics:1 of +#: keras.src.engine.training.Model.reset_metrics:1 of msgid "Resets the state of all the metrics in the model." msgstr "" @@ -6059,116 +6983,170 @@ msgstr "" msgid "Boolean, whether the model should run eagerly." msgstr "" -#: keras.engine.training.Model.save:1 of -msgid "Saves the model to Tensorflow SavedModel or a single HDF5 file." +#: keras.src.engine.training.Model.save:1 of +msgid "Saves a model as a TensorFlow SavedModel or HDF5 file." msgstr "" -#: keras.engine.training.Model.save:3 of -msgid "" -"Please see `tf.keras.models.save_model` or the [Serialization and Saving " -"guide](https://keras.io/guides/serialization_and_saving/) for details." +#: keras.src.engine.training.Model.save:4 of +msgid "See the [Serialization and Saving guide](" msgstr "" -#: keras.engine.training.Model.save:7 of -msgid "String, PathLike, path to SavedModel or H5 file to save the model." +#: keras.src.engine.training.Model.save:4 of +msgid "https://keras.io/guides/serialization_and_saving/) for details." msgstr "" -#: keras.engine.training.Model.save:9 -#: keras.engine.training.Model.save_weights:47 of -msgid "" -"Whether to silently overwrite any existing file at the target location, " -"or provide the user with a manual prompt." +#: keras.src.engine.training.Model.save:6 of +msgid "Keras model instance to be saved." +msgstr "" + +#: keras.src.engine.training.Model.save:7 of +msgid "`str` or `pathlib.Path` object. Path where to save the model." msgstr "" -#: keras.engine.training.Model.save:11 of -msgid "If True, save optimizer's state together." +#: keras.src.engine.training.Model.save:9 of +msgid "" +"Whether we should overwrite any existing model at the target location, or" +" instead ask the user via an interactive prompt." msgstr "" -#: keras.engine.training.Model.save:12 of +#: keras.src.engine.training.Model.save:12 of msgid "" -"Either `'tf'` or `'h5'`, indicating whether to save the model to " -"Tensorflow SavedModel or HDF5. Defaults to 'tf' in TF 2.X, and 'h5' in TF" -" 1.X." +"Either `\"keras\"`, `\"tf\"`, `\"h5\"`, indicating whether to save the " +"model in the native Keras format (`.keras`), in the TensorFlow SavedModel" +" format (referred to as \"SavedModel\" below), or in the legacy HDF5 " +"format (`.h5`). Defaults to `\"tf\"` in TF 2.X, and `\"h5\"` in TF 1.X." +msgstr "" + +#: keras.src.engine.training.Model.save:36 of +msgid "SavedModel format arguments:" +msgstr "" + +#: keras.src.engine.training.Model.save:22 of +msgid "include_optimizer: Only applied to SavedModel and legacy HDF5" +msgstr "" + +#: keras.src.engine.training.Model.save:22 of +msgid "formats. If False, do not save the optimizer state. Defaults to `True`." +msgstr "" + +#: keras.src.engine.training.Model.save:25 of +msgid "signatures: Only applies to SavedModel format. Signatures to save" msgstr "" -#: keras.engine.training.Model.save:15 of +#: keras.src.engine.training.Model.save:25 of msgid "" -"Signatures to save with the SavedModel. Applicable to the 'tf' format " -"only. Please see the `signatures` argument in `tf.saved_model.save` for " -"details." +"with the SavedModel. See the `signatures` argument in " +"`tf.saved_model.save` for details." +msgstr "" + +#: keras.src.engine.training.Model.save:28 of +msgid "options: Only applies to SavedModel format." msgstr "" -#: keras.engine.training.Model.save:18 of +#: keras.src.engine.training.Model.save:28 of msgid "" -"(only applies to SavedModel format) `tf.saved_model.SaveOptions` object " -"that specifies options for saving to SavedModel." +"`tf.saved_model.SaveOptions` object that specifies SavedModel saving " +"options." +msgstr "" + +#: keras.src.engine.training.Model.save:36 of +msgid "save_traces: Only applies to SavedModel format. When enabled, the" msgstr "" -#: keras.engine.training.Model.save:21 of +#: keras.src.engine.training.Model.save:31 of msgid "" -"(only applies to SavedModel format) When enabled, the SavedModel will " -"store the function traces for each layer. This can be disabled, so that " -"only the configs of each layer are stored. Defaults to `True`. Disabling " -"this will decrease serialization time and reduce file size, but it " -"requires that all custom layers/models implement a `get_config()` method." +"SavedModel will store the function traces for each layer. This can be " +"disabled, so that only the configs of each layer are stored. Defaults to " +"`True`. Disabling this will decrease serialization time and reduce file " +"size, but it requires that all custom layers/models implement a " +"`get_config()` method." +msgstr "" + +#: keras.src.engine.training.Model.save:40 of +msgid "```python model = tf.keras.Sequential([" msgstr "" -#: keras.engine.training.Model.save:30 of -msgid "```python from keras.models import load_model" +#: keras.src.engine.training.Model.save:42 of +msgid "tf.keras.layers.Dense(5, input_shape=(3,)), tf.keras.layers.Softmax()])" msgstr "" -#: keras.engine.training.Model.save:33 of +#: keras.src.engine.training.Model.save:44 of msgid "" -"model.save('my_model.h5') # creates a HDF5 file 'my_model.h5' del model" -" # deletes the existing model" +"model.save(\"model.keras\") loaded_model = " +"tf.keras.models.load_model(\"model.keras\") x = tf.random.uniform((10, " +"3)) assert np.allclose(model.predict(x), loaded_model.predict(x)) ```" +msgstr "" + +#: keras.src.engine.training.Model.save:50 of +msgid "Note that `model.save()` is an alias for `tf.keras.models.save_model()`." +msgstr "" + +#: keras.src.engine.base_layer.Layer.save_own_variables:1 of +msgid "Saves the state of the layer." msgstr "" -#: keras.engine.training.Model.save:36 of +#: keras.src.engine.base_layer.Layer.save_own_variables:3 of msgid "" -"# returns a compiled model # identical to the previous one model = " -"load_model('my_model.h5') ```" +"You can override this method to take full control of how the state of the" +" layer is saved upon calling `model.save()`." +msgstr "" + +#: keras.src.engine.base_layer.Layer.save_own_variables:6 of +msgid "Dict where the state of the model will be saved." msgstr "" -#: keras.engine.training.Model.save_spec:1 of -msgid "Returns the `tf.TensorSpec` of call inputs as a tuple `(args, kwargs)`." +#: keras.src.engine.training.Model.save_spec:1 of +msgid "Returns the `tf.TensorSpec` of call args as a tuple `(args, kwargs)`." msgstr "" -#: keras.engine.training.Model.save_spec:3 of +#: keras.src.engine.training.Model.save_spec:3 of msgid "" "This value is automatically defined after calling the model for the first" " time. Afterwards, you can use it when exporting the model for serving:" msgstr "" -#: keras.engine.training.Model.save_spec:6 of +#: keras.src.engine.training.Model.save_spec:7 of msgid "```python model = tf.keras.Model(...)" msgstr "" -#: keras.engine.training.Model.save_spec:9 of +#: keras.src.engine.training.Model.save_spec:10 of msgid "@tf.function def serve(*args, **kwargs):" msgstr "" -#: keras.engine.training.Model.save_spec:11 of +#: keras.src.engine.training.Model.save_spec:12 of msgid "" "outputs = model(*args, **kwargs) # Apply postprocessing steps, or add " "additional outputs. ... return outputs" msgstr "" -#: keras.engine.training.Model.save_spec:16 of +#: keras.src.engine.training.Model.save_spec:17 of msgid "" -"# arg_specs is `[tf.TensorSpec(...), ...]`. kwarg_specs, in this example," -" is # an empty dict since functional models do not use keyword arguments." -" arg_specs, kwarg_specs = model.save_spec()" +"# arg_specs is `[tf.TensorSpec(...), ...]`. kwarg_specs, in this # " +"example, is an empty dict since functional models do not use keyword # " +"arguments. arg_specs, kwarg_specs = model.save_spec()" msgstr "" -#: keras.engine.training.Model.save_spec:20 of +#: keras.src.engine.training.Model.save_spec:23 of msgid "model.save(path, signatures={" msgstr "" -#: keras.engine.training.Model.save_spec:21 of -msgid "'serving_default': serve.get_concrete_function(*arg_specs, **kwarg_specs)" +#: keras.src.engine.training.Model.save_spec:23 of +msgid "'serving_default': serve.get_concrete_function(*arg_specs," +msgstr "" + +#: keras.src.engine.training.Model.save_spec:24 of +msgid "**kwarg_specs)" +msgstr "" + +#: keras.src.engine.training.Model.save_spec:26 of +msgid "})" +msgstr "" + +#: keras.src.engine.training.Model.save_spec of +msgid "param dynamic_batch" msgstr "" -#: keras.engine.training.Model.save_spec:25 of +#: keras.src.engine.training.Model.save_spec:28 of msgid "" "Whether to set the batch sizes of all the returned `tf.TensorSpec` to " "`None`. (Note that when defining functional or Sequential models with " @@ -6176,7 +7154,11 @@ msgid "" "preserved). Defaults to `True`." msgstr "" -#: keras.engine.training.Model.save_spec:30 of +#: keras.src.engine.training.Model.save_spec of +msgid "returns" +msgstr "" + +#: keras.src.engine.training.Model.save_spec:33 of msgid "" "If the model inputs are defined, returns a tuple `(args, kwargs)`. All " "elements in `args` and `kwargs` are `tf.TensorSpec`. If the model inputs " @@ -6184,49 +7166,49 @@ msgid "" "when calling the model, `model.fit`, `model.evaluate` or `model.predict`." msgstr "" -#: keras.engine.training.Model.save_weights:1 of +#: keras.src.engine.training.Model.save_weights:1 of msgid "Saves all layer weights." msgstr "" -#: keras.engine.training.Model.save_weights:3 of +#: keras.src.engine.training.Model.save_weights:3 of msgid "" "Either saves in HDF5 or in TensorFlow format based on the `save_format` " "argument." msgstr "" -#: keras.engine.training.Model.save_weights:14 of +#: keras.src.engine.training.Model.save_weights:14 of msgid "When saving in HDF5 format, the weight file has:" msgstr "" -#: keras.engine.training.Model.save_weights:7 of +#: keras.src.engine.training.Model.save_weights:7 of msgid "`layer_names` (attribute), a list of strings" msgstr "" -#: keras.engine.training.Model.save_weights:8 of +#: keras.src.engine.training.Model.save_weights:8 of msgid "(ordered names of model layers)." msgstr "" -#: keras.engine.training.Model.save_weights:14 of +#: keras.src.engine.training.Model.save_weights:14 of msgid "For every layer, a `group` named `layer.name`" msgstr "" -#: keras.engine.training.Model.save_weights:11 of +#: keras.src.engine.training.Model.save_weights:11 of msgid "For every such layer group, a group attribute `weight_names`," msgstr "" -#: keras.engine.training.Model.save_weights:11 of +#: keras.src.engine.training.Model.save_weights:11 of msgid "a list of strings (ordered names of weights tensor of the layer)." msgstr "" -#: keras.engine.training.Model.save_weights:14 of +#: keras.src.engine.training.Model.save_weights:14 of msgid "For every weight in the layer, a dataset" msgstr "" -#: keras.engine.training.Model.save_weights:14 of +#: keras.src.engine.training.Model.save_weights:14 of msgid "storing the weight value, named after the weight tensor." msgstr "" -#: keras.engine.training.Model.save_weights:16 of +#: keras.src.engine.training.Model.save_weights:16 of msgid "" "When saving in TensorFlow format, all objects referenced by the network " "are saved in the same format as `tf.train.Checkpoint`, including any " @@ -6239,7 +7221,7 @@ msgid "" "`tf.train.Checkpoint` and `tf.keras.Model` for details." msgstr "" -#: keras.engine.training.Model.save_weights:26 of +#: keras.src.engine.training.Model.save_weights:26 of msgid "" "While the formats are the same, do not mix `save_weights` and " "`tf.train.Checkpoint`. Checkpoints saved by `Model.save_weights` should " @@ -6249,7 +7231,7 @@ msgid "" "`save_weights` for training checkpoints." msgstr "" -#: keras.engine.training.Model.save_weights:33 of +#: keras.src.engine.training.Model.save_weights:33 of msgid "" "The TensorFlow format matches objects and variables by starting at a root" " object, `self` for `save_weights`, and greedily matching attribute " @@ -6258,11 +7240,11 @@ msgid "" "This means saving a `tf.keras.Model` using `save_weights` and loading " "into a `tf.train.Checkpoint` with a `Model` attached (or vice versa) will" " not match the `Model`'s variables. See the [guide to training " -"checkpoints](https://www.tensorflow.org/guide/checkpoint) for details on " -"the TensorFlow format." +"checkpoints]( https://www.tensorflow.org/guide/checkpoint) for details on" +" the TensorFlow format." msgstr "" -#: keras.engine.training.Model.save_weights:43 of +#: keras.src.engine.training.Model.save_weights:44 of msgid "" "String or PathLike, path to the file to save the weights to. When saving " "in TensorFlow format, this is the prefix used for checkpoint files " @@ -6270,28 +7252,34 @@ msgid "" " to be saved in HDF5 format." msgstr "" -#: keras.engine.training.Model.save_weights:49 of +#: keras.src.engine.training.Model.save_weights:48 of +msgid "" +"Whether to silently overwrite any existing file at the target location, " +"or provide the user with a manual prompt." +msgstr "" + +#: keras.src.engine.training.Model.save_weights:50 of msgid "" "Either 'tf' or 'h5'. A `filepath` ending in '.h5' or '.keras' will " -"default to HDF5 if `save_format` is `None`. Otherwise `None` defaults to " -"'tf'." +"default to HDF5 if `save_format` is `None`. Otherwise, `None` becomes " +"'tf'. Defaults to `None`." msgstr "" -#: keras.engine.training.Model.save_weights:52 of +#: keras.src.engine.training.Model.save_weights:53 of msgid "" "Optional `tf.train.CheckpointOptions` object that specifies options for " "saving weights." msgstr "" -#: keras.engine.training.Model.save_weights:55 of -msgid "If `h5py` is not available when attempting to save in HDF5 format." +#: keras.src.engine.training.Model.save_weights:56 of +msgid "If `h5py` is not available when attempting to save in HDF5 format." msgstr "" -#: keras.engine.base_layer.Layer.set_weights:1 of +#: keras.src.engine.base_layer.Layer.set_weights:1 of msgid "Sets the weights of the layer, from NumPy arrays." msgstr "" -#: keras.engine.base_layer.Layer.set_weights:3 of +#: keras.src.engine.base_layer.Layer.set_weights:3 of msgid "" "The weights of a layer represent the state of the layer. This function " "sets the weight values from numpy arrays. The weight values should be " @@ -6300,27 +7288,33 @@ msgid "" " layer." msgstr "" -#: keras.engine.base_layer.Layer.get_weights:8 -#: keras.engine.base_layer.Layer.set_weights:9 of +#: keras.src.engine.base_layer.Layer.get_weights:8 +#: keras.src.engine.base_layer.Layer.set_weights:9 of msgid "" "For example, a `Dense` layer returns a list of two values: the kernel " "matrix and the bias vector. These can be used to set the weights of " "another `Dense` layer:" msgstr "" -#: keras.engine.base_layer.Layer.set_weights:33 of +#: keras.src.engine.base_layer.Layer.set_weights:33 of msgid "" "a list of NumPy arrays. The number of arrays and their shape must match " "number of the dimensions of the weights of the layer (i.e. it should " "match the output of `get_weights`)." msgstr "" -#: keras.engine.base_layer.Layer.set_weights:39 of +#: keras.src.engine.base_layer.Layer.set_weights:39 of msgid "" "If the provided weights list does not match the layer's " "specifications." msgstr "" +#: of tensorcircuit.applications.van.MADE.state_updates:1 +#: tensorcircuit.applications.van.NMF.state_updates:1 +#: tensorcircuit.applications.van.PixelCNN.state_updates:1 +msgid "Deprecated, do NOT use!" +msgstr "" + #: of tensorcircuit.applications.van.MADE.state_updates:3 #: tensorcircuit.applications.van.NMF.state_updates:3 #: tensorcircuit.applications.van.PixelCNN.state_updates:3 @@ -6348,6 +7342,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.submodules:1 #: tensorcircuit.applications.van.ResidualBlock.submodules:1 #: tensorcircuit.applications.vqes.Linear.submodules:1 +#: tensorcircuit.keras.HardwareLayer.submodules:1 #: tensorcircuit.keras.QuantumLayer.submodules:1 msgid "Sequence of all sub-modules." msgstr "" @@ -6359,6 +7354,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.submodules:3 #: tensorcircuit.applications.van.ResidualBlock.submodules:3 #: tensorcircuit.applications.vqes.Linear.submodules:3 +#: tensorcircuit.keras.HardwareLayer.submodules:3 #: tensorcircuit.keras.QuantumLayer.submodules:3 msgid "" "Submodules are modules which are properties of this module, or found as " @@ -6372,38 +7368,55 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.submodules:18 #: tensorcircuit.applications.van.ResidualBlock.submodules:18 #: tensorcircuit.applications.vqes.Linear.submodules:18 +#: tensorcircuit.keras.HardwareLayer.submodules:18 #: tensorcircuit.keras.QuantumLayer.submodules:18 msgid "A sequence of all submodules." msgstr "" -#: keras.engine.training.Model.summary:1 of +#: keras.src.engine.training.Model.summary:1 of msgid "Prints a string summary of the network." msgstr "" -#: keras.engine.training.Model.summary:3 of +#: keras.src.engine.training.Model.summary:3 of msgid "" "Total length of printed lines (e.g. set this to adapt the display to " "different terminal window sizes)." msgstr "" -#: keras.engine.training.Model.summary:6 of +#: keras.src.engine.training.Model.summary:6 of msgid "" "Relative or absolute positions of log elements in each line. If not " -"provided, defaults to `[.33, .55, .67, 1.]`." +"provided, becomes `[0.3, 0.6, 0.70, 1.]`. Defaults to `None`." msgstr "" -#: keras.engine.training.Model.summary:9 of +#: keras.src.engine.training.Model.summary:9 of msgid "" -"Print function to use. Defaults to `print`. It will be called on each " -"line of the summary. You can set it to a custom function in order to " -"capture the string summary." +"Print function to use. By default, prints to `stdout`. If `stdout` " +"doesn't work in your environment, change to `print`. It will be called on" +" each line of the summary. You can set it to a custom function in order " +"to capture the string summary." +msgstr "" + +#: keras.src.engine.training.Model.summary:14 of +msgid "Whether to expand the nested models. Defaults to `False`." +msgstr "" + +#: keras.src.engine.training.Model.summary:16 of +msgid "Whether to show if a layer is trainable. Defaults to `False`." msgstr "" -#: keras.engine.training.Model.summary:13 of -msgid "Whether to expand the nested models. If not provided, defaults to `False`." +#: keras.src.engine.training.Model.summary:18 of +msgid "" +"a list or tuple of 2 strings, which is the starting layer name and ending" +" layer name (both inclusive) indicating the range of layers to be printed" +" in summary. It also accepts regex patterns instead of exact name. In " +"such case, start predicate will be the first element it matches to " +"`layer_range[0]` and the end predicate will be the last element it " +"matches to `layer_range[1]`. By default `None` which considers all layers" +" of model." msgstr "" -#: keras.engine.training.Model.summary:16 of +#: keras.src.engine.training.Model.summary:27 of msgid "if `summary()` is called before the model is built." msgstr "" @@ -6414,41 +7427,43 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.supports_masking:1 #: tensorcircuit.applications.van.ResidualBlock.supports_masking:1 #: tensorcircuit.applications.vqes.Linear.supports_masking:1 +#: tensorcircuit.keras.HardwareLayer.supports_masking:1 #: tensorcircuit.keras.QuantumLayer.supports_masking:1 msgid "Whether this layer supports computing a mask using `compute_mask`." msgstr "" -#: keras.engine.training.Model.test_on_batch:1 of +#: keras.src.engine.training.Model.test_on_batch:1 of msgid "Test the model on a single batch of samples." msgstr "" -#: keras.engine.training.Model.test_on_batch:3 of +#: keras.src.engine.training.Model.test_on_batch:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the model has multiple inputs). - A TensorFlow " "tensor, or a list of tensors (in case the model has multiple inputs)." -" - A dict mapping input names to the corresponding array/tensors, if " +" - A dict mapping input names to the corresponding array/tensors, if " "the model has named inputs." msgstr "" -#: keras.engine.training.Model.test_on_batch:8 of -msgid "A dict mapping input names to the corresponding array/tensors, if" +#: keras.src.engine.training.Model.test_on_batch:8 +#: keras.src.engine.training.Model.train_on_batch:8 of +msgid "A dict mapping input names to the corresponding array/tensors," msgstr "" -#: keras.engine.training.Model.test_on_batch:9 of -msgid "the model has named inputs." +#: keras.src.engine.training.Model.test_on_batch:9 +#: keras.src.engine.training.Model.train_on_batch:9 of +msgid "if the model has named inputs." msgstr "" -#: keras.engine.training.Model.test_on_batch:10 -#: keras.engine.training.Model.train_on_batch:10 of +#: keras.src.engine.training.Model.test_on_batch:10 of msgid "" "Target data. Like the input data `x`, it could be either Numpy array(s) " "or TensorFlow tensor(s). It should be consistent with `x` (you cannot " "have Numpy inputs and tensor targets, or inversely)." msgstr "" -#: keras.engine.training.Model.test_on_batch:13 -#: keras.engine.training.Model.train_on_batch:13 of +#: keras.src.engine.training.Model.test_on_batch:13 +#: keras.src.engine.training.Model.train_on_batch:12 of msgid "" "Optional array of the same length as x, containing weights to apply to " "the model's loss for each sample. In the case of temporal data, you can " @@ -6456,105 +7471,105 @@ msgid "" "different weight to every timestep of every sample." msgstr "" -#: keras.engine.training.Model.test_on_batch:18 -#: keras.engine.training.Model.train_on_batch:22 of +#: keras.src.engine.training.Model.test_on_batch:18 +#: keras.src.engine.training.Model.train_on_batch:24 of msgid "" "If `True`, the metrics returned will be only for this batch. If `False`, " "the metrics will be statefully accumulated across batches." msgstr "" -#: keras.engine.training.Model.test_on_batch:30 of -msgid "If `model.test_on_batch` is wrapped in a `tf.function`." +#: keras.src.engine.training.Model.test_on_batch:30 of +msgid "If `model.test_on_batch` is wrapped in a `tf.function`." msgstr "" -#: keras.engine.training.Model.test_step:1 of +#: keras.src.engine.training.Model.test_step:1 of msgid "The logic for one evaluation step." msgstr "" -#: keras.engine.training.Model.test_step:3 of +#: keras.src.engine.training.Model.test_step:3 of msgid "" "This method can be overridden to support custom evaluation logic. This " "method is called by `Model.make_test_function`." msgstr "" -#: keras.engine.training.Model.test_step:6 of +#: keras.src.engine.training.Model.test_step:6 of msgid "" "This function should contain the mathematical logic for one step of " "evaluation. This typically includes the forward pass, loss calculation, " "and metrics updates." msgstr "" -#: keras.engine.training.Model.test_step:11 of +#: keras.src.engine.training.Model.test_step:11 of msgid "" "Configuration details for *how* this logic is run (e.g. `tf.function` and" " `tf.distribute.Strategy` settings), should be left to " "`Model.make_test_function`, which can also be overridden." msgstr "" -#: keras.engine.training.Model.test_step:17 of +#: keras.src.engine.training.Model.test_step:17 of msgid "" "A `dict` containing values that will be passed to " "`tf.keras.callbacks.CallbackList.on_train_batch_end`. Typically, the " "values of the `Model`'s metrics are returned." msgstr "" -#: keras.engine.training.Model.to_json:1 of +#: keras.src.engine.training.Model.to_json:1 of msgid "Returns a JSON string containing the network configuration." msgstr "" -#: keras.engine.training.Model.to_json:3 of +#: keras.src.engine.training.Model.to_json:3 of msgid "" "To load a network from a JSON save file, use " "`keras.models.model_from_json(json_string, custom_objects={})`." msgstr "" -#: keras.engine.training.Model.to_json:6 of -msgid "Additional keyword arguments to be passed to `json.dumps()`." +#: keras.src.engine.training.Model.to_json:6 of +msgid "Additional keyword arguments to be passed to *`json.dumps()`." msgstr "" -#: keras.engine.training.Model.to_json:9 of +#: keras.src.engine.training.Model.to_json:9 of msgid "A JSON string." msgstr "" -#: keras.engine.training.Model.to_yaml:1 of +#: keras.src.engine.training.Model.to_yaml:1 of msgid "Returns a yaml string containing the network configuration." msgstr "" -#: keras.engine.training.Model.to_yaml:3 of +#: keras.src.engine.training.Model.to_yaml:3 of msgid "" "Note: Since TF 2.6, this method is no longer supported and will raise a " "RuntimeError." msgstr "" -#: keras.engine.training.Model.to_yaml:6 of +#: keras.src.engine.training.Model.to_yaml:6 of msgid "" "To load a network from a yaml save file, use " "`keras.models.model_from_yaml(yaml_string, custom_objects={})`." msgstr "" -#: keras.engine.training.Model.to_yaml:9 of +#: keras.src.engine.training.Model.to_yaml:9 of msgid "" "`custom_objects` should be a dictionary mapping the names of custom " "losses / layers / etc to the corresponding functions / classes." msgstr "" -#: keras.engine.training.Model.to_yaml:13 of +#: keras.src.engine.training.Model.to_yaml:13 of msgid "Additional keyword arguments to be passed to `yaml.dump()`." msgstr "" -#: keras.engine.training.Model.to_yaml:16 of +#: keras.src.engine.training.Model.to_yaml:16 of msgid "A YAML string." msgstr "" -#: keras.engine.training.Model.to_yaml:18 of +#: keras.src.engine.training.Model.to_yaml:18 of msgid "announces that the method poses a security risk" msgstr "" -#: keras.engine.training.Model.train_on_batch:1 of +#: keras.src.engine.training.Model.train_on_batch:1 of msgid "Runs a single gradient update on a single batch of data." msgstr "" -#: keras.engine.training.Model.train_on_batch:3 of +#: keras.src.engine.training.Model.train_on_batch:3 of msgid "" "Input data. It could be: - A Numpy array (or array-like), or a list of " "arrays (in case the model has multiple inputs). - A TensorFlow " @@ -6563,27 +7578,28 @@ msgid "" "the model has named inputs." msgstr "" -#: keras.engine.training.Model.train_on_batch:6 of +#: keras.src.engine.training.Model.train_on_batch:6 of msgid "A TensorFlow tensor, or a list of tensors" msgstr "" -#: keras.engine.training.Model.train_on_batch:8 of -msgid "A dict mapping input names to the corresponding array/tensors," -msgstr "" - -#: keras.engine.training.Model.train_on_batch:9 of -msgid "if the model has named inputs." +#: keras.src.engine.training.Model.train_on_batch:10 of +msgid "" +"Target data. Like the input data `x`, it could be either Numpy array(s) " +"or TensorFlow tensor(s)." msgstr "" -#: keras.engine.training.Model.train_on_batch:18 of +#: keras.src.engine.training.Model.train_on_batch:17 of msgid "" "Optional dictionary mapping class indices (integers) to a weight (float) " "to apply to the model's loss for the samples from this class during " "training. This can be useful to tell the model to \"pay more attention\" " -"to samples from an under-represented class." +"to samples from an under-represented class. When `class_weight` is " +"specified and targets have a rank of 2 or greater, either `y` must be " +"one-hot encoded, or an explicit final dimension of `1` must be included " +"for sparse class labels." msgstr "" -#: keras.engine.training.Model.train_on_batch:29 of +#: keras.src.engine.training.Model.train_on_batch:31 of msgid "" "Scalar training loss (if the model has a single output and no metrics) or" " list of scalars (if the model has multiple outputs and/or metrics). The " @@ -6591,38 +7607,38 @@ msgid "" "scalar outputs." msgstr "" -#: keras.engine.training.Model.train_on_batch:35 of +#: keras.src.engine.training.Model.train_on_batch:37 of msgid "If `model.train_on_batch` is wrapped in a `tf.function`." msgstr "" -#: keras.engine.training.Model.train_step:1 of +#: keras.src.engine.training.Model.train_step:1 of msgid "The logic for one training step." msgstr "" -#: keras.engine.training.Model.train_step:3 of +#: keras.src.engine.training.Model.train_step:3 of msgid "" "This method can be overridden to support custom training logic. For " "concrete examples of how to override this method see [Customizing what " -"happends in " -"fit](https://www.tensorflow.org/guide/keras/customizing_what_happens_in_fit)." -" This method is called by `Model.make_train_function`." +"happens in fit]( " +"https://www.tensorflow.org/guide/keras/customizing_what_happens_in_fit). " +"This method is called by `Model.make_train_function`." msgstr "" -#: keras.engine.training.Model.train_step:8 of +#: keras.src.engine.training.Model.train_step:9 of msgid "" "This method should contain the mathematical logic for one step of " -"training. This typically includes the forward pass, loss calculation, " +"training. This typically includes the forward pass, loss calculation, " "backpropagation, and metric updates." msgstr "" -#: keras.engine.training.Model.train_step:12 of +#: keras.src.engine.training.Model.train_step:13 of msgid "" "Configuration details for *how* this logic is run (e.g. `tf.function` and" " `tf.distribute.Strategy` settings), should be left to " "`Model.make_train_function`, which can also be overridden." msgstr "" -#: keras.engine.training.Model.train_step:18 of +#: keras.src.engine.training.Model.train_step:19 of msgid "" "A `dict` containing values that will be passed to " "`tf.keras.callbacks.CallbackList.on_train_batch_end`. Typically, the " @@ -6637,6 +7653,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.trainable_variables:1 #: tensorcircuit.applications.van.ResidualBlock.trainable_variables:1 #: tensorcircuit.applications.vqes.Linear.trainable_variables:1 +#: tensorcircuit.keras.HardwareLayer.trainable_variables:1 #: tensorcircuit.keras.QuantumLayer.trainable_variables:1 msgid "Sequence of trainable variables owned by this module and its submodules." msgstr "" @@ -6648,6 +7665,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.trainable_weights:1 #: tensorcircuit.applications.van.ResidualBlock.trainable_weights:1 #: tensorcircuit.applications.vqes.Linear.trainable_weights:1 +#: tensorcircuit.keras.HardwareLayer.trainable_weights:1 #: tensorcircuit.keras.QuantumLayer.trainable_weights:1 msgid "List of all trainable weights tracked by this layer." msgstr "" @@ -6659,6 +7677,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.trainable_weights:3 #: tensorcircuit.applications.van.ResidualBlock.trainable_weights:3 #: tensorcircuit.applications.vqes.Linear.trainable_weights:3 +#: tensorcircuit.keras.HardwareLayer.trainable_weights:3 #: tensorcircuit.keras.QuantumLayer.trainable_weights:3 msgid "Trainable weights are updated via gradient descent during training." msgstr "" @@ -6670,6 +7689,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.trainable_weights:5 #: tensorcircuit.applications.van.ResidualBlock.trainable_weights:5 #: tensorcircuit.applications.vqes.Linear.trainable_weights:5 +#: tensorcircuit.keras.HardwareLayer.trainable_weights:5 #: tensorcircuit.keras.QuantumLayer.trainable_weights:5 msgid "A list of trainable variables." msgstr "" @@ -6681,6 +7701,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.variable_dtype:1 #: tensorcircuit.applications.van.ResidualBlock.variable_dtype:1 #: tensorcircuit.applications.vqes.Linear.variable_dtype:1 +#: tensorcircuit.keras.HardwareLayer.variable_dtype:1 #: tensorcircuit.keras.QuantumLayer.variable_dtype:1 msgid "Alias of `Layer.dtype`, the dtype of the weights." msgstr "" @@ -6699,6 +7720,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.weights:1 #: tensorcircuit.applications.vqes.Linear.variables:1 #: tensorcircuit.applications.vqes.Linear.weights:1 +#: tensorcircuit.keras.HardwareLayer.variables:1 +#: tensorcircuit.keras.HardwareLayer.weights:1 #: tensorcircuit.keras.QuantumLayer.variables:1 #: tensorcircuit.keras.QuantumLayer.weights:1 msgid "Returns the list of all layer variables/weights." @@ -6711,6 +7734,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.variables:3 #: tensorcircuit.applications.van.ResidualBlock.variables:3 #: tensorcircuit.applications.vqes.Linear.variables:3 +#: tensorcircuit.keras.HardwareLayer.variables:3 #: tensorcircuit.keras.QuantumLayer.variables:3 msgid "Alias of `self.weights`." msgstr "" @@ -6725,6 +7749,7 @@ msgstr "" #: tensorcircuit.applications.van.PixelCNN.weights:3 #: tensorcircuit.applications.van.ResidualBlock.variables:5 #: tensorcircuit.applications.vqes.Linear.variables:5 +#: tensorcircuit.keras.HardwareLayer.variables:5 #: tensorcircuit.keras.QuantumLayer.variables:5 msgid "" "Note: This will not track the weights of nested `tf.Modules` that are not" @@ -6745,6 +7770,8 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.weights:3 #: tensorcircuit.applications.vqes.Linear.variables:8 #: tensorcircuit.applications.vqes.Linear.weights:3 +#: tensorcircuit.keras.HardwareLayer.variables:8 +#: tensorcircuit.keras.HardwareLayer.weights:3 #: tensorcircuit.keras.QuantumLayer.variables:8 #: tensorcircuit.keras.QuantumLayer.weights:3 msgid "A list of variables." @@ -6772,33 +7799,36 @@ msgstr "" #: tensorcircuit.applications.van.MaskedLinear:1 #: tensorcircuit.applications.van.ResidualBlock:1 #: tensorcircuit.applications.vqes.Linear:1 tensorcircuit.keras.QuantumLayer:1 -msgid "Bases: :py:class:`keras.engine.base_layer.Layer`" +msgid "Bases: :py:class:`~keras.src.engine.base_layer.Layer`" msgstr "" -#: keras.engine.base_layer.Layer.build:1 of +#: keras.src.engine.base_layer.Layer.build:1 of #: tensorcircuit.applications.van.MaskedConv2D.build:1 #: tensorcircuit.keras.QuantumLayer.build:1 -msgid "Creates the variables of the layer (optional, for subclass implementers)." +msgid "Creates the variables of the layer (for subclass implementers)." msgstr "" -#: keras.engine.base_layer.Layer.build:3 of +#: keras.src.engine.base_layer.Layer.build:3 of #: tensorcircuit.applications.van.MaskedConv2D.build:3 #: tensorcircuit.keras.QuantumLayer.build:3 msgid "" "This is a method that implementers of subclasses of `Layer` or `Model` " "can override if they need a state-creation step in-between layer " -"instantiation and layer call." +"instantiation and layer call. It is invoked automatically before the " +"first execution of `call()`." msgstr "" -#: keras.engine.base_layer.Layer.build:7 of -#: tensorcircuit.applications.van.MaskedConv2D.build:7 -#: tensorcircuit.keras.QuantumLayer.build:7 -msgid "This is typically used to create the weights of `Layer` subclasses." +#: keras.src.engine.base_layer.Layer.build:8 of +#: tensorcircuit.applications.van.MaskedConv2D.build:8 +#: tensorcircuit.keras.QuantumLayer.build:8 +msgid "" +"This is typically used to create the weights of `Layer` subclasses (at " +"the discretion of the subclass implementer)." msgstr "" -#: keras.engine.base_layer.Layer.build:9 of -#: tensorcircuit.applications.van.MaskedConv2D.build:9 -#: tensorcircuit.keras.QuantumLayer.build:9 +#: keras.src.engine.base_layer.Layer.build:11 of +#: tensorcircuit.applications.van.MaskedConv2D.build:11 +#: tensorcircuit.keras.QuantumLayer.build:11 msgid "" "Instance of `TensorShape`, or list of instances of `TensorShape` if the " "layer expects a list of inputs (one instance per input)." @@ -6816,81 +7846,79 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.call:3 #: tensorcircuit.applications.vqes.Linear.call:3 msgid "" -"Note here that `call()` method in `tf.keras` is little bit different from" -" `keras` API. In `keras` API, you can pass support masking for layers as " -"additional arguments. Whereas `tf.keras` has `compute_mask()` method to " -"support masking." +"The `call()` method may not create state (except in its first invocation," +" wrapping the creation of variables or other resources in " +"`tf.init_scope()`). It is recommended to create state, including " +"`tf.Variable` instances and nested `Layer` instances," +msgstr "" + +#: of tensorcircuit.applications.van.MaskedConv2D.call:7 +#: tensorcircuit.applications.van.MaskedLinear.call:7 +#: tensorcircuit.applications.van.ResidualBlock.call:7 +#: tensorcircuit.applications.vqes.Linear.call:7 +msgid "in `__init__()`, or in the `build()` method that is" msgstr "" #: of tensorcircuit.applications.van.MaskedConv2D.call:8 #: tensorcircuit.applications.van.MaskedLinear.call:8 #: tensorcircuit.applications.van.ResidualBlock.call:8 #: tensorcircuit.applications.vqes.Linear.call:8 +msgid "called automatically before `call()` executes for the first time." +msgstr "" + +#: of tensorcircuit.applications.van.MaskedConv2D.call:10 +#: tensorcircuit.applications.van.MaskedLinear.call:10 +#: tensorcircuit.applications.van.ResidualBlock.call:10 +#: tensorcircuit.applications.vqes.Linear.call:10 msgid "" "Input tensor, or dict/list/tuple of input tensors. The first positional " "`inputs` argument is subject to special rules: - `inputs` must be " "explicitly passed. A layer cannot have zero arguments, and `inputs` " "cannot be provided via the default value of a keyword argument. - NumPy" -" array or Python scalar values in `inputs` get cast as tensors. - Keras " -"mask metadata is only collected from `inputs`. - Layers are built " +" array or Python scalar values in `inputs` get cast as tensors. - Keras" +" mask metadata is only collected from `inputs`. - Layers are built " "(`build(input_shape)` method) using shape info from `inputs` only. - " "`input_spec` compatibility is only checked against `inputs`. - Mixed " "precision input casting is only applied to `inputs`. If a layer has " "tensor arguments in `*args` or `**kwargs`, their casting behavior in " "mixed precision should be handled manually. - The SavedModel input " -"specification is generated using `inputs` only. - Integration with " +"specification is generated using `inputs` only. - Integration with " "various ecosystem packages like TFMOT, TFLite, TF.js, etc is only " "supported for `inputs` and not for tensors in positional and keyword " "arguments." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:8 -#: tensorcircuit.applications.van.MaskedLinear.call:8 -#: tensorcircuit.applications.van.ResidualBlock.call:8 -#: tensorcircuit.applications.vqes.Linear.call:8 +#: of tensorcircuit.applications.van.MaskedConv2D.call:10 +#: tensorcircuit.applications.van.MaskedLinear.call:10 +#: tensorcircuit.applications.van.ResidualBlock.call:10 +#: tensorcircuit.applications.vqes.Linear.call:10 msgid "" "Input tensor, or dict/list/tuple of input tensors. The first positional " "`inputs` argument is subject to special rules: - `inputs` must be " "explicitly passed. A layer cannot have zero" msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:11 -#: tensorcircuit.applications.van.MaskedLinear.call:11 -#: tensorcircuit.applications.van.ResidualBlock.call:11 -#: tensorcircuit.applications.vqes.Linear.call:11 -msgid "" -"arguments, and `inputs` cannot be provided via the default value of a " -"keyword argument." -msgstr "" - #: of tensorcircuit.applications.van.MaskedConv2D.call:13 #: tensorcircuit.applications.van.MaskedLinear.call:13 #: tensorcircuit.applications.van.ResidualBlock.call:13 #: tensorcircuit.applications.vqes.Linear.call:13 -msgid "NumPy array or Python scalar values in `inputs` get cast as tensors." -msgstr "" - -#: of tensorcircuit.applications.van.MaskedConv2D.call:14 -#: tensorcircuit.applications.van.MaskedLinear.call:14 -#: tensorcircuit.applications.van.ResidualBlock.call:14 -#: tensorcircuit.applications.vqes.Linear.call:14 -msgid "Keras mask metadata is only collected from `inputs`." +msgid "" +"arguments, and `inputs` cannot be provided via the default value of a " +"keyword argument." msgstr "" #: of tensorcircuit.applications.van.MaskedConv2D.call:15 #: tensorcircuit.applications.van.MaskedLinear.call:15 #: tensorcircuit.applications.van.ResidualBlock.call:15 #: tensorcircuit.applications.vqes.Linear.call:15 -msgid "" -"Layers are built (`build(input_shape)` method) using shape info from " -"`inputs` only." +msgid "NumPy array or Python scalar values in `inputs` get cast as tensors." msgstr "" #: of tensorcircuit.applications.van.MaskedConv2D.call:17 #: tensorcircuit.applications.van.MaskedLinear.call:17 #: tensorcircuit.applications.van.ResidualBlock.call:17 #: tensorcircuit.applications.vqes.Linear.call:17 -msgid "`input_spec` compatibility is only checked against `inputs`." +msgid "Keras mask metadata is only collected from `inputs`." msgstr "" #: of tensorcircuit.applications.van.MaskedConv2D.call:18 @@ -6898,57 +7926,73 @@ msgstr "" #: tensorcircuit.applications.van.ResidualBlock.call:18 #: tensorcircuit.applications.vqes.Linear.call:18 msgid "" -"Mixed precision input casting is only applied to `inputs`. If a layer has" -" tensor arguments in `*args` or `**kwargs`, their casting behavior in " -"mixed precision should be handled manually." +"Layers are built (`build(input_shape)` method) using shape info from " +"`inputs` only." +msgstr "" + +#: of tensorcircuit.applications.van.MaskedConv2D.call:20 +#: tensorcircuit.applications.van.MaskedLinear.call:20 +#: tensorcircuit.applications.van.ResidualBlock.call:20 +#: tensorcircuit.applications.vqes.Linear.call:20 +msgid "`input_spec` compatibility is only checked against `inputs`." msgstr "" #: of tensorcircuit.applications.van.MaskedConv2D.call:21 #: tensorcircuit.applications.van.MaskedLinear.call:21 #: tensorcircuit.applications.van.ResidualBlock.call:21 #: tensorcircuit.applications.vqes.Linear.call:21 +msgid "" +"Mixed precision input casting is only applied to `inputs`. If a layer has" +" tensor arguments in `*args` or `**kwargs`, their casting behavior in " +"mixed precision should be handled manually." +msgstr "" + +#: of tensorcircuit.applications.van.MaskedConv2D.call:24 +#: tensorcircuit.applications.van.MaskedLinear.call:24 +#: tensorcircuit.applications.van.ResidualBlock.call:24 +#: tensorcircuit.applications.vqes.Linear.call:24 msgid "The SavedModel input specification is generated using `inputs` only." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:22 -#: tensorcircuit.applications.van.MaskedLinear.call:22 -#: tensorcircuit.applications.van.ResidualBlock.call:22 -#: tensorcircuit.applications.vqes.Linear.call:22 +#: of tensorcircuit.applications.van.MaskedConv2D.call:26 +#: tensorcircuit.applications.van.MaskedLinear.call:26 +#: tensorcircuit.applications.van.ResidualBlock.call:26 +#: tensorcircuit.applications.vqes.Linear.call:26 msgid "" "Integration with various ecosystem packages like TFMOT, TFLite, TF.js, " "etc is only supported for `inputs` and not for tensors in positional and " "keyword arguments." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:25 -#: tensorcircuit.applications.van.MaskedLinear.call:25 -#: tensorcircuit.applications.van.ResidualBlock.call:25 -#: tensorcircuit.applications.vqes.Linear.call:25 +#: of tensorcircuit.applications.van.MaskedConv2D.call:29 +#: tensorcircuit.applications.van.MaskedLinear.call:29 +#: tensorcircuit.applications.van.ResidualBlock.call:29 +#: tensorcircuit.applications.vqes.Linear.call:29 msgid "" "Additional positional arguments. May contain tensors, although this is " "not recommended, for the reasons above." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:27 -#: tensorcircuit.applications.van.MaskedLinear.call:27 -#: tensorcircuit.applications.van.ResidualBlock.call:27 -#: tensorcircuit.applications.vqes.Linear.call:27 +#: of tensorcircuit.applications.van.MaskedConv2D.call:31 +#: tensorcircuit.applications.van.MaskedLinear.call:31 +#: tensorcircuit.applications.van.ResidualBlock.call:31 +#: tensorcircuit.applications.vqes.Linear.call:31 msgid "" "Additional keyword arguments. May contain tensors, although this is not " "recommended, for the reasons above. The following optional keyword " "arguments are reserved: - `training`: Boolean scalar tensor of Python " "boolean indicating whether the `call` is meant for training or " "inference. - `mask`: Boolean input mask. If the layer's `call()` method " -"takes a `mask` argument, its default value will be set to the mask " -"generated for `inputs` by the previous layer (if `input` did come from " -"a layer that generated a corresponding mask, i.e. if it came from a " -"Keras layer with masking support)." +"takes a `mask` argument, its default value will be set to the mask " +"generated for `inputs` by the previous layer (if `input` did come from " +"a layer that generated a corresponding mask, i.e. if it came from a " +"Keras layer with masking support)." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:27 -#: tensorcircuit.applications.van.MaskedLinear.call:27 -#: tensorcircuit.applications.van.ResidualBlock.call:27 -#: tensorcircuit.applications.vqes.Linear.call:27 +#: of tensorcircuit.applications.van.MaskedConv2D.call:31 +#: tensorcircuit.applications.van.MaskedLinear.call:31 +#: tensorcircuit.applications.van.ResidualBlock.call:31 +#: tensorcircuit.applications.vqes.Linear.call:31 msgid "" "Additional keyword arguments. May contain tensors, although this is not " "recommended, for the reasons above. The following optional keyword " @@ -6956,17 +8000,17 @@ msgid "" "boolean indicating" msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:31 -#: tensorcircuit.applications.van.MaskedLinear.call:31 -#: tensorcircuit.applications.van.ResidualBlock.call:31 -#: tensorcircuit.applications.vqes.Linear.call:31 +#: of tensorcircuit.applications.van.MaskedConv2D.call:35 +#: tensorcircuit.applications.van.MaskedLinear.call:35 +#: tensorcircuit.applications.van.ResidualBlock.call:35 +#: tensorcircuit.applications.vqes.Linear.call:35 msgid "whether the `call` is meant for training or inference." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:32 -#: tensorcircuit.applications.van.MaskedLinear.call:32 -#: tensorcircuit.applications.van.ResidualBlock.call:32 -#: tensorcircuit.applications.vqes.Linear.call:32 +#: of tensorcircuit.applications.van.MaskedConv2D.call:36 +#: tensorcircuit.applications.van.MaskedLinear.call:36 +#: tensorcircuit.applications.van.ResidualBlock.call:36 +#: tensorcircuit.applications.vqes.Linear.call:36 msgid "" "`mask`: Boolean input mask. If the layer's `call()` method takes a `mask`" " argument, its default value will be set to the mask generated for " @@ -6975,18 +8019,40 @@ msgid "" "masking support)." msgstr "" -#: of tensorcircuit.applications.van.MaskedConv2D.call:38 -#: tensorcircuit.applications.van.MaskedLinear.call:38 -#: tensorcircuit.applications.van.ResidualBlock.call:38 -#: tensorcircuit.applications.vqes.Linear.call:38 +#: of tensorcircuit.applications.van.MaskedConv2D.call:42 +#: tensorcircuit.applications.van.MaskedLinear.call:42 +#: tensorcircuit.applications.van.ResidualBlock.call:42 +#: tensorcircuit.applications.vqes.Linear.call:42 msgid "A tensor or list/tuple of tensors." msgstr "" -#: keras.engine.base_layer.Layer.get_weights:1 of +#: keras.src.engine.base_layer.Layer.get_config:1 of +msgid "Returns the config of the layer." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_config:3 of +msgid "" +"A layer config is a Python dictionary (serializable) containing the " +"configuration of a layer. The same layer can be reinstantiated later " +"(without its trained weights) from this configuration." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_config:8 of +msgid "" +"The config of a layer does not include connectivity information, nor the " +"layer class name. These are handled by `Network` (one layer of " +"abstraction above)." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_config:16 of +msgid "Python dictionary." +msgstr "" + +#: keras.src.engine.base_layer.Layer.get_weights:1 of msgid "Returns the current weights of the layer, as NumPy arrays." msgstr "" -#: keras.engine.base_layer.Layer.get_weights:3 of +#: keras.src.engine.base_layer.Layer.get_weights:3 of msgid "" "The weights of a layer represent the state of the layer. This function " "returns both trainable and non-trainable weight values associated with " @@ -6994,7 +8060,7 @@ msgid "" "state into similarly parameterized layers." msgstr "" -#: keras.engine.base_layer.Layer.get_weights:32 of +#: keras.src.engine.base_layer.Layer.get_weights:32 of msgid "Weights values as a list of NumPy arrays." msgstr "" @@ -7002,6 +8068,7 @@ msgstr "" #: tensorcircuit.applications.van.MaskedLinear.metrics:1 #: tensorcircuit.applications.van.ResidualBlock.metrics:1 #: tensorcircuit.applications.vqes.Linear.metrics:1 +#: tensorcircuit.keras.HardwareLayer.metrics:1 #: tensorcircuit.keras.QuantumLayer.metrics:1 msgid "List of metrics added using the `add_metric()` API." msgstr "" @@ -7010,6 +8077,7 @@ msgstr "" #: tensorcircuit.applications.van.MaskedLinear.metrics:13 #: tensorcircuit.applications.van.ResidualBlock.metrics:13 #: tensorcircuit.applications.vqes.Linear.metrics:13 +#: tensorcircuit.keras.HardwareLayer.metrics:13 #: tensorcircuit.keras.QuantumLayer.metrics:13 msgid "A list of `Metric` objects." msgstr "" @@ -7025,20 +8093,20 @@ msgstr "" #: of tensorcircuit.applications.vqes.JointSchedule:1 msgid "" "Bases: " -":py:class:`keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule`" +":py:class:`~keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule`" msgstr "" -#: keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule.from_config:1 +#: keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule.from_config:1 #: of msgid "Instantiates a `LearningRateSchedule` from its config." msgstr "" -#: keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule.from_config:3 +#: keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule.from_config:3 #: of msgid "Output of `get_config()`." msgstr "" -#: keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule.from_config:5 +#: keras.src.optimizers.schedules.learning_rate_schedule.LearningRateSchedule.from_config:5 #: of msgid "A `LearningRateSchedule` instance." msgstr "" @@ -7071,6 +8139,43 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:3 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:15 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:13 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmax:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmax:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.concat:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cond:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix:10 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum:8 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.max:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.max:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:11 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:15 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:13 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.switch:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tile:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tile:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:29 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:36 #: tensorcircuit.backends.jax_backend.JaxBackend.argmax:3 #: tensorcircuit.backends.jax_backend.JaxBackend.argmax:7 #: tensorcircuit.backends.jax_backend.JaxBackend.argmin:3 @@ -7216,8 +8321,13 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vectorized_value_and_grad:29 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vectorized_value_and_grad:36 #: tensorcircuit.basecircuit.BaseCircuit.sample_expectation_ps:53 -#: tensorcircuit.quantum.count_d2s:10 tensorcircuit.quantum.count_d2s:14 -#: tensorcircuit.quantum.count_s2d:4 tensorcircuit.quantum.count_s2d:8 +#: tensorcircuit.cloud.abstraction.Device.list_properties:3 +#: tensorcircuit.cloud.abstraction.Device.topology:3 +#: tensorcircuit.cloud.abstraction.Device.topology_graph:5 +#: tensorcircuit.cloud.tencent.submit_task:6 +#: tensorcircuit.cloud.tencent.submit_task:8 tensorcircuit.quantum.count_d2s:10 +#: tensorcircuit.quantum.count_d2s:14 tensorcircuit.quantum.count_s2d:4 +#: tensorcircuit.quantum.count_s2d:8 #: tensorcircuit.simplify.pseudo_contract_between:3 #: tensorcircuit.simplify.pseudo_contract_between:5 #: tensorcircuit.simplify.pseudo_contract_between:7 @@ -7259,27 +8369,23 @@ msgstr "" msgid "The `tc.backend` object that with all registered universal functions." msgstr "" -#: ../../source/api/backends/jax_backend.rst:2 -msgid "tensorcircuit.backends.jax_backend" -msgstr "" - -#: of tensorcircuit.backends.jax_backend:1 -msgid "Backend magic inherited from tensornetwork: jax backend" +#: ../../source/api/backends/cupy_backend.rst:2 +msgid "tensorcircuit.backends.cupy_backend" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend:1 -msgid "" -"Bases: :py:class:`tensornetwork.backends.jax.jax_backend.JaxBackend`, " -":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" +#: of tensorcircuit.backends.cupy_backend:1 +msgid "CuPy backend. Not in the tensornetwork package and highly experimental." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend:1 msgid "" -"See the original backend API at `jax backend " -"`_" +"Bases: " +":py:class:`~tensornetwork.backends.abstract_backend.AbstractBackend`, " +":py:class:`~tensorcircuit.backends.abstract_backend.ExtendedBackend`" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.abs:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.abs:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.abs:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.abs:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.abs:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.abs:1 @@ -7288,14 +8394,17 @@ msgid "" " tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.abs:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.abs:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.abs:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.abs:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.abs:4 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.abs:4 msgid "Its elementwise absolute value." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.acos:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.acos:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asin:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.acos:1 #: tensorcircuit.backends.jax_backend.JaxBackend.asin:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.acos:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.asin:1 @@ -7307,6 +8416,22 @@ msgid "Return the acos of a tensor ``a``." msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.sqrtmh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acos:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.acosh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asin:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.asinh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atan2:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.atanh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.copy:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cosh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.kron:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.kron:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.numpy:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sinh:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tan:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tanh:3 #: tensorcircuit.backends.jax_backend.JaxBackend.acos:3 #: tensorcircuit.backends.jax_backend.JaxBackend.acosh:3 #: tensorcircuit.backends.jax_backend.JaxBackend.asin:3 @@ -7374,28 +8499,32 @@ msgstr "" msgid "tensor in matrix form" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.acos:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.acos:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.acos:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.acos:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.acos:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.acos:5 msgid "acos of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.acosh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.acosh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.acosh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.acosh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.acosh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.acosh:1 msgid "Return the acosh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.acosh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.acosh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.acosh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.acosh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.acosh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.acosh:5 msgid "acosh of ``a``" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.addition:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.addition:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.addition:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.addition:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.addition:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.addition:1 @@ -7404,7 +8533,13 @@ msgid "" "implementation. :param tensor1: A tensor. :param tensor2: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cos:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.conj:4 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cos:4 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.expm:4 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.multiply:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sin:4 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.softmax:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.cos:4 #: tensorcircuit.backends.jax_backend.JaxBackend.expm:4 #: tensorcircuit.backends.jax_backend.JaxBackend.sin:4 #: tensorcircuit.backends.jax_backend.JaxBackend.softmax:9 @@ -7422,8 +8557,11 @@ msgstr "" #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sin:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.softmax:9 #: tensorcircuit.experimental.hamiltonian_evol:12 +#: tensornetwork.backends.abstract_backend.AbstractBackend.addition:6 +#: tensornetwork.backends.abstract_backend.AbstractBackend.divide:6 #: tensornetwork.backends.abstract_backend.AbstractBackend.exp:4 #: tensornetwork.backends.abstract_backend.AbstractBackend.log:4 +#: tensornetwork.backends.abstract_backend.AbstractBackend.subtraction:6 #: tensornetwork.backends.jax.jax_backend.JaxBackend.addition:6 #: tensornetwork.backends.jax.jax_backend.JaxBackend.conj:4 #: tensornetwork.backends.jax.jax_backend.JaxBackend.divide:6 @@ -7459,6 +8597,7 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.adjoint:3 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshape2:3 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.reshapem:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.relu:9 #: tensorcircuit.backends.jax_backend.JaxBackend.relu:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.relu:9 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.relu:9 @@ -7470,42 +8609,49 @@ msgstr "" msgid "adjoint tensor of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.arange:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.arange:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.arange:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.arange:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.arange:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.arange:1 msgid "Values are generated within the half-open interval [start, stop)" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.arange:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.arange:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.arange:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.arange:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.arange:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.arange:3 msgid "start index" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.arange:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.arange:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.arange:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.arange:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.arange:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.arange:5 msgid "end index, defaults to None" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.arange:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.arange:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.arange:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.arange:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.arange:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.arange:7 msgid "steps, defaults to 1" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.argmax:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.argmax:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.argmax:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.argmax:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.argmax:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.argmax:1 msgid "Return the index of maximum of an array an axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.argmax:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.argmax:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.argmin:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.argmax:5 #: tensorcircuit.backends.jax_backend.JaxBackend.argmin:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.argmax:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.argmin:5 @@ -7516,70 +8662,80 @@ msgstr "" msgid "[description], defaults to 0, different behavior from numpy defaults!" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.argmin:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.argmin:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.argmin:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.argmin:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.argmin:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.argmin:1 msgid "Return the index of minimum of an array an axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.asin:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.asin:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.asin:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.asin:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.asin:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.asin:5 msgid "asin of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.asinh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.asinh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.asinh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.asinh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.asinh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.asinh:1 msgid "Return the asinh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.asinh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.asinh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.asinh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.asinh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.asinh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.asinh:5 msgid "asinh of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atan:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atan:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.atan:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atan:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atan:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atan:1 msgid "Return the atan of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atan:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atan:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.atan:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atan:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atan:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atan:5 msgid "atan of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atan2:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atan2:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.atan2:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atan2:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atan2:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atan2:1 msgid "Return the atan of a tensor ``y``/``x``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atan2:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atan2:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.atan2:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atan2:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atan2:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atan2:5 msgid "atan2 of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atanh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atanh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.atanh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atanh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atanh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atanh:1 msgid "Return the atanh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.atanh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.atanh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.atanh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.atanh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.atanh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.atanh:5 @@ -7587,6 +8743,7 @@ msgid "atanh of ``a``" msgstr "" #: of +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_left_multiplication:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_left_multiplication:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.broadcast_left_multiplication:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.broadcast_left_multiplication:1 @@ -7600,6 +8757,8 @@ msgid "" msgstr "" #: of +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_left_multiplication:8 +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_right_multiplication:8 #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_left_multiplication:8 #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_right_multiplication:8 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.broadcast_left_multiplication:8 @@ -7612,6 +8771,7 @@ msgid "The result of multiplying `tensor1` onto `tensor2`." msgstr "" #: of +#: tensornetwork.backends.abstract_backend.AbstractBackend.broadcast_right_multiplication:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.broadcast_right_multiplication:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.broadcast_right_multiplication:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.broadcast_right_multiplication:1 @@ -7624,7 +8784,8 @@ msgid "" "tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cast:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cast:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.cast:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cast:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cast:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cast:1 @@ -7632,6 +8793,10 @@ msgid "Cast the tensor dtype of a ``a``." msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.sizen:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.cast:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.imag:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.real:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.size:3 #: tensorcircuit.backends.jax_backend.JaxBackend.cast:3 #: tensorcircuit.backends.jax_backend.JaxBackend.imag:3 #: tensorcircuit.backends.jax_backend.JaxBackend.real:3 @@ -7651,21 +8816,24 @@ msgstr "" msgid "tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cast:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cast:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.cast:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cast:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cast:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cast:5 msgid "\"float32\", \"float64\", \"complex64\", \"complex128\"" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cast:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cast:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.cast:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cast:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cast:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cast:7 msgid "``a`` of new dtype" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.concat:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.concat:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.concat:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.concat:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.concat:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.concat:1 @@ -7676,6 +8844,10 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randu:5 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:9 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.concat:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:31 #: tensorcircuit.backends.jax_backend.JaxBackend.concat:5 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randn:5 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randu:5 @@ -7695,7 +8867,8 @@ msgstr "" msgid "[description], defaults to 0" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cond:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cond:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.cond:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cond:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cond:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cond:1 @@ -7704,14 +8877,16 @@ msgid "" "functionality of ``jax.lax.cond``." msgstr "" -#: of tensorcircuit.backends.pytorch_backend._conj_torch:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.conj:1 +#: tensorcircuit.backends.pytorch_backend._conj_torch:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.conj:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.conj:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.conj:1 msgid "Return the complex conjugate of `tensor` :param tensor: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.convert_to_tensor:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.convert_to_tensor:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.convert_to_tensor:1 #: tensorcircuit.backends.numpy_backend._convert_to_tensor_numpy:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.convert_to_tensor:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.convert_to_tensor:1 @@ -7720,6 +8895,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.coo_sparse_matrix:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix:1 #: tensorcircuit.backends.jax_backend.JaxBackend.coo_sparse_matrix:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.coo_sparse_matrix:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.coo_sparse_matrix:1 @@ -7730,6 +8906,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.coo_sparse_matrix:4 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix:4 #: tensorcircuit.backends.jax_backend.JaxBackend.coo_sparse_matrix:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.coo_sparse_matrix:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.coo_sparse_matrix:4 @@ -7738,6 +8915,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.coo_sparse_matrix:6 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix:6 #: tensorcircuit.backends.jax_backend.JaxBackend.coo_sparse_matrix:6 #: tensorcircuit.backends.numpy_backend.NumpyBackend.coo_sparse_matrix:6 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.coo_sparse_matrix:6 @@ -7746,6 +8924,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.coo_sparse_matrix:8 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.coo_sparse_matrix:8 #: tensorcircuit.backends.jax_backend.JaxBackend.coo_sparse_matrix:8 #: tensorcircuit.backends.numpy_backend.NumpyBackend.coo_sparse_matrix:8 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.coo_sparse_matrix:8 @@ -7767,49 +8946,56 @@ msgstr "" msgid "SparseTensor in backend format" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.copy:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.copy:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.copy:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.copy:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.copy:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.copy:1 msgid "Return the copy of ``a``, matrix exponential." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.copy:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.copy:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.copy:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.copy:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.copy:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.copy:5 msgid "matrix exponential of matrix ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cos:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cos:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.cos:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cos:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cos:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cos:1 msgid "Return cos of `tensor`. :param tensor: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cosh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cosh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.cosh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cosh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cosh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cosh:1 msgid "Return the cosh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cosh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cosh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.cosh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cosh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cosh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cosh:5 msgid "cosh of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cumsum:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.cumsum:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cumsum:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cumsum:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cumsum:1 msgid "Return the cumulative sum of the elements along a given axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.cumsum:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.cumsum:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.cumsum:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.cumsum:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.cumsum:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.cumsum:5 @@ -7836,14 +9022,17 @@ msgstr "" msgid "The tensor object represented by the string." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.device:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.device:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.device:1 msgid "get the universal device str for the tensor, in the format of tf" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.device_move:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.device:3 #: tensorcircuit.backends.jax_backend.JaxBackend.device_move:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device_move:3 @@ -7855,35 +9044,40 @@ msgstr "" msgid "the tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.device:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.device:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.device:5 msgid "device str where the tensor lives on" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device_move:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device_move:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.device_move:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device_move:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.device_move:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.device_move:1 msgid "move tensor ``a`` to device ``dev``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device_move:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device_move:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.device_move:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device_move:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.device_move:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.device_move:5 msgid "device str or device obj in corresponding backend" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.device_move:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.device_move:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.device_move:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.device_move:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.device_move:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.device_move:7 msgid "the tensor on new device" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagflat:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagflat:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagflat:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagflat:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagflat:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagflat:1 @@ -7893,21 +9087,24 @@ msgid "" "which to place its elements." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagflat:6 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagflat:6 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagflat:6 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagflat:6 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagflat:6 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagflat:6 msgid "A new tensor with all zeros save the specified diagonal." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:1 msgid "Return specified diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:3 @@ -7921,7 +9118,8 @@ msgid "" "diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:11 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:11 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:11 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:11 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:11 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:11 @@ -7930,7 +9128,14 @@ msgid "" "matrices from vectors, use diagflat." msgstr "" -#: of tensorcircuit.backends.tensorflow_backend._tensordot_tf:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.reshape:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.shape_tuple:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.tensordot:3 +#: tensorcircuit.backends.tensorflow_backend._tensordot_tf:3 +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:14 +#: tensornetwork.backends.abstract_backend.AbstractBackend.shape_tensor:3 +#: tensornetwork.backends.abstract_backend.AbstractBackend.slice:3 +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace:10 #: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:14 #: tensornetwork.backends.jax.jax_backend.JaxBackend.reshape:3 #: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tensor:3 @@ -7961,7 +9166,9 @@ msgstr "" msgid "A tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:15 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:15 +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace:11 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:15 #: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:11 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:15 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:11 @@ -7970,16 +9177,21 @@ msgstr "" msgid "Offset of the diagonal from the main diagonal." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:16 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:19 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:12 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:15 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:16 +#: tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:19 +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace:12 +#: tensornetwork.backends.abstract_backend.AbstractBackend.trace:15 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:16 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:19 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:12 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:15 msgid "" "Axis to be used as the first/second axis of the 2D sub-arrays from which " -"the diagonals should be taken. Defaults to second last/last axis." +"the diagonals should be taken. Defaults to second-last/last axis." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:23 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:23 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:23 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:23 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:25 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:33 @@ -7988,21 +9200,24 @@ msgid "" "batched diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:25 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:25 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:25 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:25 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:27 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:35 msgid "A dim = min(1, tensor.ndim - 2) tensor storing" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:26 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.diagonal:26 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:26 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:26 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.diagonal:28 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.diagonal:36 msgid "the batched diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.divide:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.divide:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.divide:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.divide:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.divide:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.divide:1 @@ -8011,145 +9226,77 @@ msgid "" "implementation. :param tensor1: A tensor. :param tensor2: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.dtype:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.dtype:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.dtype:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.dtype:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.dtype:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.dtype:1 msgid "Obtain dtype string for tensor ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.dtype:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.dtype:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.dtype:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.dtype:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.dtype:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.dtype:3 msgid "The tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.dtype:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.dtype:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.dtype:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.dtype:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.dtype:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.dtype:5 msgid "dtype str, such as \"complex64\"" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigh:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigh:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigh:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eigh:1 msgid "Compute eigenvectors and eigenvalues of a hermitian matrix." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigh:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigh:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigh:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eigh:3 msgid "A symetric matrix." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigh:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigh:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigh:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigh:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eigh:5 msgid "The eigenvalues in ascending order. Tensor: The eigenvectors." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:1 msgid "" -"Implicitly restarted Arnoldi method for finding the lowest eigenvector-" -"eigenvalue pairs of a linear operator `A`. `A` is a function implementing" -" the matrix-vector product." +"Arnoldi method for finding the lowest eigenvector-eigenvalue pairs of a " +"linear operator `A`. `A` is a callable implementing the matrix-vector " +"product. If no `initial_state` is provided then `shape` and `dtype` have " +"to be passed so that a suitable initial state can be randomly generated." +" :param A: A (sparse) implementation of a linear operator :param arsg: A " +"list of arguments to `A`. `A` will be called as" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:6 -msgid "" -"WARNING: This routine uses jax.jit to reduce runtimes. jitting is " -"triggered at the first invocation of `eigs`, and on any subsequent calls " -"if the python `id` of `A` changes, even if the formal definition of `A` " -"stays the same. Example: the following will jit once at the beginning, " -"and then never again:" +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:8 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:8 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:8 +msgid "`res = A(initial_state, *args)`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:12 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:12 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:10 -msgid "```python import jax import numpy as np def A(H,x):" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:16 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:31 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:16 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:31 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:14 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:29 -msgid "return jax.np.dot(H,x)" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:19 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:19 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:17 -msgid "for n in range(100):" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:18 -msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigs(A, [H],x) #jitting is " -"triggerd only at `n=0`" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:23 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:23 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:21 -msgid "" -"The following code triggers jitting at every iteration, which results in " -"considerably reduced performance" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:26 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:26 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:24 -msgid "```python import jax import numpy as np for n in range(100):" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:30 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:30 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:28 -msgid "def A(H,x):" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:32 -msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigs(A, [H],x) #jitting is " -"triggerd at every step `n`" -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:37 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:37 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:35 -msgid "" -"A (sparse) implementation of a linear operator. Call signature of `A` is " -"`res = A(vector, *args)`, where `vector` can be an arbitrary `Tensor`, " -"and `res.shape` has to be `vector.shape`." -msgstr "" - -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:6 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:40 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:40 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:38 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:9 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:6 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:6 -msgid "" -"A list of arguments to `A`. `A` will be called as `res = " -"A(initial_state, *args)`." -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:42 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:42 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:9 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:9 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:11 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:9 msgid "" "An initial vector for the algorithm. If `None`, a random initial `Tensor`" -" is created using the `backend.randn` method" +" is created using the `numpy.random.randn` method." msgstr "" #: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:12 @@ -8165,12 +9312,16 @@ msgstr "" msgid "The shape of the input-dimension of `A`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:45 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:45 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:43 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:13 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:13 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:11 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:15 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:13 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:11 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:11 msgid "" -"The dtype of the input `A`. If no `initial_state` is provided, a random " -"initial state with shape `shape` and dtype `dtype` is created." +"The dtype of the input `A`. If both no `initial_state` is provided, a " +"random initial state with shape `shape` and dtype `dtype` is created." msgstr "" #: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:15 @@ -8186,111 +9337,121 @@ msgstr "" msgid "The number of iterations (number of krylov vectors)." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:48 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:48 -msgid "The number of eigenvector-eigenvalue pairs to be computed." -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:49 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:49 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:16 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:16 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:14 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:18 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:16 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:14 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:14 msgid "" -"The desired precision of the eigenvalues. For the jax backend this has " -"currently no effect, and precision of eigenvalues is not guaranteed. This" -" feature may be added at a later point. To increase precision the caller " -"can either increase `maxiter` or `num_krylov_vecs`." +"The nummber of eigenvector-eigenvalue pairs to be computed. If `numeig > " +"1`, `reorthogonalize` has to be `True`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:53 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:53 -msgid "" -"Flag for targetting different types of eigenvalues. Currently supported " -"are `which = 'LR'` (larges real part) and `which = 'LM'` (larges " -"magnitude)." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:18 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:18 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:20 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:18 +msgid "The desired precision of the eigenvalus. Uses" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:56 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:56 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:19 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:19 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:19 msgid "" -"Maximum number of restarts. For `maxiter=0` the routine becomes " -"equivalent to a simple Arnoldi method." +"['LM' | 'SM' | 'LR' | 'SR' | 'LI' | 'SI'] Which `k` eigenvectors and " +"eigenvalues to find: 'LM' : largest magnitude 'SM' : smallest " +"magnitude 'LR' : largest real part 'SR' : smallest real part " +"'LI' : largest imaginary part 'SI' : smallest imaginary part Note " +"that not all of those might be supported by specialized backends." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:59 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:59 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:19 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:19 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:19 msgid "" -"(eigvals, eigvecs) eigvals: A list of `numeig` eigenvalues eigvecs: A " -"list of `numeig` eigenvectors" +"['LM' | 'SM' | 'LR' | 'SR' | 'LI' | 'SI'] Which `k` eigenvectors and " +"eigenvalues to find:" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:33 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:62 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:62 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:66 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:33 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:33 -msgid "(eigvals, eigvecs)" +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:21 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:21 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:21 +msgid "" +"'LM' : largest magnitude 'SM' : smallest magnitude 'LR' : largest real " +"part 'SR' : smallest real part 'LI' : largest imaginary part 'SI' : " +"smallest imaginary part" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:62 -#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:62 -msgid "" -"eigvals: A list of `numeig` eigenvalues eigvecs: A list of `numeig` " -"eigenvectors" +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:27 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:27 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:27 +msgid "Note that not all of those might be supported by specialized backends." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:1 -msgid "" -"Implicitly restarted Lanczos method for finding the lowest eigenvector-" -"eigenvalue pairs of a symmetric (hermitian) linear operator `A`. `A` is a" -" function implementing the matrix-vector product." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:28 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:28 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:28 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:28 +msgid "The maximum number of iterations." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:6 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:30 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:30 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:30 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:30 msgid "" -"WARNING: This routine uses jax.jit to reduce runtimes. jitting is " -"triggered at the first invocation of `eigsh`, and on any subsequent calls" -" if the python `id` of `A` changes, even if the formal definition of `A` " -"stays the same. Example: the following will jit once at the beginning, " -"and then never again:" +"An array of `numeig` lowest eigenvalues `list`: A list of `numeig` lowest" +" eigenvectors" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:18 -msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigsh(A, [H],x) #jitting is " -"triggerd only at `n=0`" +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:32 +#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:32 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:32 +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:12 +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:10 +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.position:10 +#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:9 +msgid "`Tensor`" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:32 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:1 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:1 msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigsh(A, [H],x) #jitting is " -"triggerd at every step `n`" +"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " +"symmetric (hermitian) linear operator `A`. `A` is a callable implementing" +" the matrix-vector product. If no `initial_state` is provided then " +"`shape` and `dtype` have to be passed so that a suitable initial state " +"can be randomly generated. :param A: A (sparse) implementation of a " +"linear operator :param arsg: A list of arguments to `A`. `A` will be " +"called as" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:1 msgid "" -"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " -"hermitian linear operator `A`. `A` is a function implementing the matrix-" -"vector product. WARNING: This routine uses jax.jit to reduce runtimes. " -"jitting is triggered at the first invocation of `eigsh_lanczos`, and on " -"any subsequent calls if the python `id` of `A` changes, even if the " -"formal definition of `A` stays the same. Example: the following will jit " -"once at the beginning, and then never again:" +"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of " +"`A`. :param A: A (sparse) implementation of a linear operator." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:16 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:4 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:4 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:4 msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigsh_lanczos(A, [H],x) " -"#jitting is triggerd only at `n=0`" +"Call signature of `A` is `res = A(vector, *args)`, where `vector` can be " +"an arbitrary `Tensor`, and `res.shape` has to be `vector.shape`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:30 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:6 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:40 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:40 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:38 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:9 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:6 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:6 msgid "" -"H = jax.np.array(np.random.rand(10,10)) x = " -"jax.np.array(np.random.rand(10,10)) res = eigsh_lanczos(A, [H],x) " -"#jitting is triggerd at every step `n`" +"A list of arguments to `A`. `A` will be called as `res = " +"A(initial_state, *args)`." msgstr "" #: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:8 @@ -8301,18 +9462,12 @@ msgid "" "`Tensor` is created using the `backend.randn` method" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:46 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:16 msgid "" -"The number of eigenvector-eigenvalue pairs to be computed. If `numeig > " -"1`, `reorthogonalize` has to be `True`." -msgstr "" - -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:48 -msgid "" -"The desired precision of the eigenvalues. For the jax backend this has " -"currently no effect, and precision of eigenvalues is not guaranteed. This" -" feature may be added at a later point. To increase precision the caller " -"can increase `num_krylov_vecs`." +"The desired precision of the eigenvalus. Uses " +"`backend.norm(eigvalsnew[0:numeig] - eigvalsold[0:numeig]) < tol` as " +"stopping criterion between two diagonalization steps of the tridiagonal " +"operator." msgstr "" #: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:20 @@ -8326,11 +9481,12 @@ msgid "" "found." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:57 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:25 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:25 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:25 msgid "" "The tridiagonal Operator is diagonalized every `ndiag` iterations to " -"check convergence. This has currently no effect for the jax backend, but " -"may be added at a later point." +"check convergence." msgstr "" #: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:27 @@ -8342,54 +9498,73 @@ msgid "" "orthogonalization (more costly than `reorthogonalize=False`)" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:63 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:30 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:30 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:30 msgid "" -"(eigvals, eigvecs) eigvals: A jax-array containing `numeig` lowest " -"eigenvalues eigvecs: A list of `numeig` lowest eigenvectors" +"(eigvals, eigvecs) eigvals: A list of `numeig` lowest eigenvalues " +"eigvecs: A list of `numeig` lowest eigenvectors" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:66 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:33 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:62 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:62 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:66 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:33 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:33 +msgid "(eigvals, eigvecs)" +msgstr "" + +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:33 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:33 +#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:33 msgid "" -"eigvals: A jax-array containing `numeig` lowest eigenvalues eigvecs: A " -"list of `numeig` lowest eigenvectors" +"eigvals: A list of `numeig` lowest eigenvalues eigvecs: A list of " +"`numeig` lowest eigenvectors" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eigvalsh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.eigvalsh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eigvalsh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.eigvalsh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.eigvalsh:1 msgid "Get the eigenvalues of matrix ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eigvalsh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eigvalsh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.eigvalsh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eigvalsh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.eigvalsh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.eigvalsh:5 msgid "eigenvalues of ``a``" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.einsum:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.einsum:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.einsum:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.einsum:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.einsum:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.einsum:1 msgid "Calculate sum of products of tensors according to expression." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eps:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eps:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eps:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eps:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eps:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eps:1 msgid "Return machine epsilon for given `dtype`" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eps:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eps:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eps:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eps:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eps:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eps:3 msgid "A dtype." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eps:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.eps:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eps:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eps:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eps:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.eps:5 @@ -8403,21 +9578,24 @@ msgstr "" msgid "Return elementwise exp of `tensor`. :param tensor: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.expm:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.expm:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.expm:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.expm:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.expm:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.expm:1 msgid "Return expm log of `matrix`, matrix exponential. :param matrix: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eye:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eye:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.eye:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eye:4 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.eye:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.eye:4 msgid "Return an identity matrix of dimension `dim`" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eye:2 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eye:2 +#: tensorcircuit.backends.jax_backend.JaxBackend.eye:2 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eye:2 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.eye:2 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.eye:2 @@ -8427,7 +9605,9 @@ msgid "" "Block-sparse behavior is currently not supported" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eye:6 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eye:6 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.eye:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.eye:6 #: tensorcircuit.backends.jax_backend.JaxBackend.eye:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eye:6 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eye:9 @@ -8438,7 +9618,8 @@ msgstr "" msgid "The dimension of the returned matrix." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.eye:8 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.eye:8 +#: tensorcircuit.backends.jax_backend.JaxBackend.eye:8 #: tensorcircuit.backends.numpy_backend.NumpyBackend.eye:8 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.eye:8 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.eye:8 @@ -8633,14 +9814,17 @@ msgid "" "convergence was achieved, the number of restarts otherwise." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.grad:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.grad:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.grad:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.grad:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.grad:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.grad:1 msgid "Return the function which is the grad function of input ``f``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.grad:13 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.grad:13 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad:13 +#: tensorcircuit.backends.jax_backend.JaxBackend.grad:13 #: tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:13 #: tensorcircuit.backends.numpy_backend.NumpyBackend.grad:13 #: tensorcircuit.backends.numpy_backend.NumpyBackend.value_and_grad:13 @@ -8651,7 +9835,9 @@ msgstr "" msgid "the function to be differentiated" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.grad:15 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.grad:15 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad:15 +#: tensorcircuit.backends.jax_backend.JaxBackend.grad:15 #: tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:15 #: tensorcircuit.backends.numpy_backend.NumpyBackend.grad:15 #: tensorcircuit.backends.numpy_backend.NumpyBackend.value_and_grad:15 @@ -8664,42 +9850,48 @@ msgid "" "be 0" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.grad:17 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.grad:17 +#: tensorcircuit.backends.jax_backend.JaxBackend.grad:17 #: tensorcircuit.backends.numpy_backend.NumpyBackend.grad:17 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.grad:17 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.grad:17 msgid "the grad function of ``f`` with the same set of arguments as ``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.i:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.i:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.i:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.i:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.i:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.i:1 msgid "Return 1.j in as a tensor compatible with the backend." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.i:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.i:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.i:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.i:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.i:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.i:3 msgid "\"complex64\" or \"complex128\"" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.i:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.i:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.i:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.i:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.i:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.i:5 msgid "1.j tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.imag:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.imag:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.imag:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.imag:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.imag:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.imag:1 msgid "Return the elementwise imaginary value of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.imag:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.imag:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.imag:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.imag:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.imag:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.imag:5 @@ -8709,6 +9901,8 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randc:1 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randc:1 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:1 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randc:1 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randc:1 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randn:1 @@ -8721,6 +9915,7 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randc:5 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randc:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:5 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randc:5 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randc:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randc:5 @@ -8730,6 +9925,7 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randc:7 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randc:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:7 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randc:7 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randc:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randc:7 @@ -8739,6 +9935,7 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randc:9 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randc:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randc:9 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randc:9 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randc:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randc:9 @@ -8763,6 +9960,8 @@ msgstr "" #: tensorcircuit.backends.abstract_backend.ExtendedBackend.implicit_randu:7 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:11 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:9 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:11 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:9 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randn:3 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randn:7 #: tensorcircuit.backends.jax_backend.JaxBackend.implicit_randu:3 @@ -8783,28 +9982,32 @@ msgstr "" msgid "[description], defaults to \"32\"" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.index_update:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.index_update:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.index_update:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.index_update:1 msgid "Update `tensor` at elements defined by `mask` with value `assignee`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.index_update:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.index_update:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.index_update:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.index_update:3 msgid "A `Tensor` object." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:4 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.index_update:4 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:4 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.index_update:4 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.index_update:4 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.index_update:4 msgid "A boolean mask." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.index_update:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.index_update:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.index_update:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.index_update:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.index_update:5 @@ -8813,21 +10016,24 @@ msgid "" "`mask` is `True`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.inv:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.inv:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.inv:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.inv:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.inv:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.inv:1 msgid "Compute the matrix inverse of `matrix`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.inv:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.inv:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.inv:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.inv:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.inv:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.inv:3 msgid "A matrix." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.inv:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.inv:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.inv:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.inv:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.inv:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.inv:5 @@ -8835,6 +10041,7 @@ msgid "The inverse of `matrix`" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.is_sparse:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse:1 #: tensorcircuit.backends.jax_backend.JaxBackend.is_sparse:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_sparse:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_sparse:1 @@ -8842,6 +10049,7 @@ msgid "Determine whether the type of input ``a`` is ``sparse``." msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.is_sparse:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse:3 #: tensorcircuit.backends.jax_backend.JaxBackend.is_sparse:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_sparse:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_sparse:3 @@ -8849,48 +10057,55 @@ msgid "input matrix ``a``" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.is_sparse:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.is_sparse:5 #: tensorcircuit.backends.jax_backend.JaxBackend.is_sparse:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_sparse:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_sparse:5 msgid "a bool indicating whether the matrix ``a`` is sparse" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_tensor:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.is_tensor:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_tensor:1 msgid "Return a boolean on whether ``a`` is a tensor in backend package." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_tensor:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.is_tensor:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_tensor:3 msgid "a tensor to be determined" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.is_tensor:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.is_tensor:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.is_tensor:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.is_tensor:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.is_tensor:5 msgid "whether ``a`` is a tensor" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.item:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.item:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.item:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.item:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.item:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.item:1 msgid "Return the item of a 1-element tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.item:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.item:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.item:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.item:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.item:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.item:3 msgid "A 1-element tensor" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.item:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.item:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.item:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.item:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.item:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.item:5 @@ -8926,7 +10141,8 @@ msgstr "" msgid "outer tuple for input args, inner tuple for outputs" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jit:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jit:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.jit:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jit:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jit:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jit:1 @@ -8936,14 +10152,16 @@ msgid "" "Arguments to `fun`. :param kwargs: Keyword arguments to `fun`." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jit:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jit:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.jit:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jit:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jit:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jit:7 msgid "jitted/graph-compiled version of `fun`, or just `fun`." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jvp:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jvp:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.jvp:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jvp:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jvp:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jvp:1 @@ -8952,14 +10170,17 @@ msgid "" " Strictly speaking, this function is value_and_jvp." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jvp:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jvp:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.jvp:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jvp:4 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jvp:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jvp:4 msgid "The function to compute jvp" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jvp:6 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jvp:6 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vjp:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.jvp:6 #: tensorcircuit.backends.jax_backend.JaxBackend.vjp:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jvp:6 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vjp:7 @@ -8970,14 +10191,16 @@ msgstr "" msgid "input for ``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jvp:8 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jvp:8 +#: tensorcircuit.backends.jax_backend.JaxBackend.jvp:8 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jvp:8 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jvp:8 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jvp:8 msgid "tangents" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.jvp:10 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.jvp:10 +#: tensorcircuit.backends.jax_backend.JaxBackend.jvp:10 #: tensorcircuit.backends.numpy_backend.NumpyBackend.jvp:10 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.jvp:10 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.jvp:10 @@ -8986,28 +10209,34 @@ msgid "" "output of ``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.kron:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.kron:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.kron:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.kron:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.kron:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.kron:1 msgid "Return the kronecker product of two matrices ``a`` and ``b``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.kron:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.kron:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.kron:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.kron:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.kron:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.kron:7 msgid "kronecker product of ``a`` and ``b``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.left_shift:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.left_shift:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.left_shift:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.left_shift:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.left_shift:1 msgid "Shift the bits of an integer x to the left y bits." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.left_shift:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.mod:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.left_shift:3 #: tensorcircuit.backends.jax_backend.JaxBackend.mod:3 #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.left_shift:3 @@ -9022,7 +10251,9 @@ msgstr "" msgid "input values" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.left_shift:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.left_shift:5 #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.left_shift:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.right_shift:5 @@ -9033,7 +10264,9 @@ msgstr "" msgid "Number of bits shift to ``x``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.left_shift:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.left_shift:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.left_shift:7 #: tensorcircuit.backends.jax_backend.JaxBackend.right_shift:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.left_shift:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.right_shift:7 @@ -9052,6 +10285,7 @@ msgid "Return elementwise natural logarithm of `tensor`. :param tensor: A tensor msgstr "" #: of tensorcircuit.backends.tensorflow_backend._matmul_tf:1 +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.matmul:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.matmul:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.matmul:1 @@ -9062,6 +10296,7 @@ msgid "" msgstr "" #: of tensorcircuit.backends.tensorflow_backend._matmul_tf:5 +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul:5 #: tensornetwork.backends.jax.jax_backend.JaxBackend.matmul:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.matmul:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.matmul:5 @@ -9069,6 +10304,7 @@ msgid "matrices." msgstr "" #: of tensorcircuit.backends.tensorflow_backend._matmul_tf:6 +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul:6 #: tensornetwork.backends.jax.jax_backend.JaxBackend.matmul:6 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.matmul:6 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.matmul:6 @@ -9078,6 +10314,7 @@ msgid "" msgstr "" #: of tensorcircuit.backends.tensorflow_backend._matmul_tf:8 +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul:8 #: tensornetwork.backends.jax.jax_backend.JaxBackend.matmul:8 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.matmul:8 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.matmul:8 @@ -9087,20 +10324,24 @@ msgid "" msgstr "" #: of tensorcircuit.backends.tensorflow_backend._matmul_tf:12 +#: tensornetwork.backends.abstract_backend.AbstractBackend.matmul:12 #: tensornetwork.backends.jax.jax_backend.JaxBackend.matmul:12 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.matmul:12 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.matmul:12 msgid "The result of performing the matmul." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.max:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.max:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.max:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.max:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.max:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.max:1 msgid "Return the maximum of an array or maximum along an axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.max:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.max:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.min:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.max:5 #: tensorcircuit.backends.jax_backend.JaxBackend.min:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.max:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.min:5 @@ -9112,42 +10353,49 @@ msgstr "" msgid "[description], defaults to None" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mean:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mean:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.mean:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mean:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mean:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mean:1 msgid "Compute the arithmetic mean for ``a`` along the specified ``axis``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mean:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mean:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.mean:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mean:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mean:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mean:3 msgid "tensor to take average" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mean:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mean:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.mean:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mean:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mean:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mean:5 msgid "the axis to take mean, defaults to None indicating sum over flatten array" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mean:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mean:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.mean:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mean:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mean:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mean:7 +#: tensorcircuit.interfaces.torch.torch_interface_kws:26 msgid "_description_, defaults to False" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.min:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.min:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.min:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.min:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.min:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.min:1 msgid "Return the minimum of an array or minimum along an axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mod:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mod:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.mod:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mod:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mod:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mod:1 @@ -9156,28 +10404,32 @@ msgid "" "consistent)" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mod:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mod:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.mod:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mod:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mod:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mod:5 msgid "mod ``y``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.mod:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.mod:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.mod:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.mod:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.mod:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.mod:7 msgid "results" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.multiply:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.multiply:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.multiply:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.multiply:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.multiply:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.multiply:1 msgid "Return the default multiplication of `tensor`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.multiply:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.multiply:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.multiply:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.multiply:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.multiply:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.multiply:3 @@ -9186,14 +10438,16 @@ msgid "" ":param tensor2: A tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.norm:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.norm:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.norm:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.norm:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.norm:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.norm:1 msgid "Calculate the L2-norm of the elements of `tensor`" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.numpy:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.numpy:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.numpy:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.numpy:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.numpy:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.numpy:1 @@ -9202,7 +10456,8 @@ msgid "" "function." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.numpy:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.numpy:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.numpy:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.numpy:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.numpy:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.numpy:5 @@ -9213,7 +10468,8 @@ msgstr "" msgid "See doc for :py:meth:`onehot`" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.onehot:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.onehot:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.onehot:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.onehot:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.onehot:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.onehot:1 @@ -9223,28 +10479,32 @@ msgid "" "one:" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.onehot:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.onehot:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.onehot:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.onehot:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.onehot:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.onehot:5 msgid "input tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.onehot:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.onehot:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.onehot:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.onehot:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.onehot:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.onehot:7 msgid "number of features in onehot dimension" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.onehot:9 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.onehot:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.onehot:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.onehot:9 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.onehot:9 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.onehot:9 msgid "onehot tensor with the last extra dimension" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.ones:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.ones:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.ones:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.ones:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.ones:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.ones:1 @@ -9256,7 +10516,8 @@ msgid "" "shape: int :param dtype: The dtype of the returned matrix." msgstr "" -#: of tensorcircuit.backends.tensorflow_backend._outer_product_tf:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.outer_product:1 +#: tensorcircuit.backends.tensorflow_backend._outer_product_tf:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.outer_product:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.outer_product:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.outer_product:1 @@ -9287,30 +10548,71 @@ msgstr "" msgid "The pivoted tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 +msgid "Returns the exponentiation of tensor a raised to b." +msgstr "" + +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:4 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:4 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:4 +msgid "If b is a tensor, then the exponentiation is element-wise" +msgstr "" + +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:3 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:3 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:3 msgid "" -"Returns the power of tensor a to the value of b. In the case b is a " -"tensor, then the power is by element" +"between the two tensors, with a as the base and b as the power. Note that" +" a and b must be broadcastable to the same shape if b is a tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:3 -msgid "with a as the base and b as the exponent." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 +msgid "If b is a scalar, then the exponentiation is each value in a" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:5 -msgid "In the case b is a scalar, then the power of each value in a" +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 +msgid "raised to the power of b." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:5 -msgid "is raised to the exponent of b." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:9 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:9 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:9 +msgid "The tensor containing the bases." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:7 -msgid "The tensor that contains the base." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:10 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:10 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:10 +msgid "The tensor containing the powers; or a single scalar as the power." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:8 -msgid "The tensor that contains the exponent or a single scalar." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:12 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:12 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:12 +msgid "" +"The tensor that is each element of a raised to the power of b. Note " +"that the shape of the returned tensor is that produced by the broadcast" +" of a and b." +msgstr "" + +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:15 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:15 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:15 +msgid "The tensor that is each element of a raised to the" +msgstr "" + +#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:15 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:15 +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:15 +msgid "" +"power of b. Note that the shape of the returned tensor is that produced " +"by the broadcast of a and b." msgstr "" #: of @@ -9350,13 +10652,13 @@ msgstr "" msgid "The drawn sample as an int tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend._qr_jax:1 -msgid "" -"Computes the QR decomposition of a tensor. See " -"tensornetwork.backends.tensorflow.decompositions for details." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.qr:1 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.qr:1 +msgid "Computes the QR decomposition of a tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.randn:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.randn:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.randn:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.randn:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.randn:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.randn:1 @@ -9366,7 +10668,8 @@ msgid "" "`ShapeType` object (for block-sparse backends)." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.randn:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.randn:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.randn:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.randn:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.randn:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.randn:5 @@ -9386,14 +10689,16 @@ msgid "" "utility to write backend agnostic code instead of doing magic things." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.random_uniform:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.random_uniform:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.random_uniform:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.random_uniform:1 msgid "Return a random uniform matrix of dimension `dim`." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.random_uniform:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.random_uniform:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.random_uniform:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.random_uniform:3 @@ -9407,28 +10712,32 @@ msgid "" "random number generator" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:14 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.random_uniform:14 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.random_uniform:14 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.random_uniform:14 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.random_uniform:14 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.random_uniform:14 msgid "random uniform initialized tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.real:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.real:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.real:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.real:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.real:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.real:1 msgid "Return the elementwise real value of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.real:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.real:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.real:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.real:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.real:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.real:5 msgid "real value of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.relu:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.relu:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.relu:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.relu:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.relu:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu:1 @@ -9437,28 +10746,32 @@ msgid "" "function:" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.relu:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.relu:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.relu:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.relu:4 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.relu:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu:4 msgid "\\mathrm{relu}(x)=\\max(x,0)" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.relu:11 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.relu:11 +#: tensorcircuit.backends.jax_backend.JaxBackend.relu:11 #: tensorcircuit.backends.numpy_backend.NumpyBackend.relu:11 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.relu:11 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.relu:11 msgid "Tensor after relu" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.reshape:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.reshape:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.reshape:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.reshape:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.reshape:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.reshape:1 msgid "Reshape tensor to the given shape." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.reshape:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.reshape:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.reshape:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.reshape:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.reshape:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.reshape:5 @@ -9493,20 +10806,27 @@ msgstr "" msgid "1D tensor in reverse order" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.right_shift:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.right_shift:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.right_shift:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.right_shift:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.right_shift:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.right_shift:1 msgid "Shift the bits of an integer x to the right y bits." msgstr "" -#: of tensorcircuit.backends.jax_backend._rq_jax:1 -msgid "" -"Computes the RQ (reversed QR) decomposition of a tensor. See " -"tensornetwork.backends.tensorflow.decompositions for details." +#: of tensornetwork.backends.abstract_backend.AbstractBackend.rq:1 +#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.rq:1 +msgid "Computes the RQ (reversed QR) decomposition of a tensor." +msgstr "" + +#: of tensorcircuit.backends.abstract_backend.ExtendedBackend.scan:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.scan:1 +#: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scan:1 +msgid "This API follows ``tf.scan`` covention, i.e. no ys supported as jax" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.scatter:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.scatter:1 #: tensorcircuit.backends.jax_backend.JaxBackend.scatter:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.scatter:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.scatter:1 @@ -9515,28 +10835,32 @@ msgid "" "shape with rank 2 for now." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.searchsorted:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.searchsorted:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted:1 msgid "Find indices where elements should be inserted to maintain order." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.searchsorted:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.searchsorted:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted:3 msgid "input array sorted in ascending order" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.searchsorted:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.searchsorted:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted:5 msgid "value to inserted" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.searchsorted:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.searchsorted:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted:7 @@ -9546,7 +10870,8 @@ msgid "" "return either 0 or N (where N is the length of a), defaults to \"left\"" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:12 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.searchsorted:12 +#: tensorcircuit.backends.jax_backend.JaxBackend.searchsorted:12 #: tensorcircuit.backends.numpy_backend.NumpyBackend.searchsorted:12 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.searchsorted:12 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.searchsorted:12 @@ -9561,7 +10886,7 @@ msgstr "" msgid "Return a string that serializes the given tensor." msgstr "" -#: of +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sign:4 #: tensornetwork.backends.abstract_backend.AbstractBackend.serialize_tensor:3 #: tensornetwork.backends.jax.jax_backend.JaxBackend.sign:7 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.serialize_tensor:3 @@ -9579,6 +10904,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.set_random_state:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.set_random_state:1 #: tensorcircuit.backends.jax_backend.JaxBackend.set_random_state:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.set_random_state:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.set_random_state:1 @@ -9587,6 +10913,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.set_random_state:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.set_random_state:3 #: tensorcircuit.backends.jax_backend.JaxBackend.set_random_state:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.set_random_state:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.set_random_state:3 @@ -9595,6 +10922,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.set_random_state:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.set_random_state:5 #: tensorcircuit.backends.jax_backend.JaxBackend.set_random_state:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.set_random_state:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.set_random_state:5 @@ -9603,56 +10931,64 @@ msgid "" " the state on the backend" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_concat:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.shape_concat:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_concat:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_concat:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_concat:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_concat:1 msgid "Concatenate a sequence of tensors together about the given axis." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_prod:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.shape_prod:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_prod:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_prod:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_prod:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_prod:1 msgid "Take the product of all of the elements in values" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tensor:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.shape_tensor:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tensor:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_tensor:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_tensor:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tensor:1 msgid "Get the shape of a tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tensor:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.shape_tensor:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tensor:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_tensor:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_tensor:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tensor:5 msgid "The shape of the input tensor returned as another tensor." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tuple:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.shape_tuple:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tuple:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_tuple:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_tuple:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tuple:1 msgid "Get the shape of a tensor as a tuple of integers." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tuple:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.shape_tuple:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.shape_tuple:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.shape_tuple:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.shape_tuple:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.shape_tuple:5 msgid "The shape of the input tensor returned as a tuple of ints." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.sigmoid:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sigmoid:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.sigmoid:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sigmoid:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.sigmoid:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sigmoid:1 msgid "Compute sigmoid of input ``a``" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.sign:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sign:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.sign:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.sign:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sign:1 msgid "" @@ -9660,41 +10996,40 @@ msgid "" "tensor[i] > 0, == 0, and < 0 respectively." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.sign:4 -msgid "" -"For complex input the behaviour of this function may depend on the " -"backend. The Jax backend version returns y[i] = x[i]/sqrt(x[i]^2)." -msgstr "" - -#: of tensorcircuit.backends.jax_backend.JaxBackend.sin:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sin:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.sin:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sin:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.sin:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sin:1 msgid "Return sin of `tensor`. :param tensor: A tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.sinh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sinh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.sinh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sinh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.sinh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sinh:1 msgid "Return the sinh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.sinh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sinh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.sinh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sinh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.sinh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sinh:5 msgid "sinh of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.size:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.size:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.size:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.size:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.size:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.size:1 msgid "Return the total number of elements in ``a`` in tensor form." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.size:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.size:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.size:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.size:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.size:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.size:5 @@ -9709,28 +11044,32 @@ msgstr "" msgid "the total number of elements in tensor ``a``" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.slice:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.slice:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.slice:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.slice:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.slice:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.slice:1 msgid "Obtains a slice of a tensor based on start_indices and slice_sizes." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.slice:4 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.slice:4 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.slice:4 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.slice:4 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.slice:4 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.slice:4 msgid "Tuple of integers denoting start indices of slice." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.slice:5 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.slice:5 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.slice:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.slice:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.slice:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.slice:5 msgid "Tuple of integers denoting size of slice along each axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.softmax:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.softmax:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.softmax:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.softmax:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.softmax:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.softmax:1 @@ -9739,14 +11078,16 @@ msgid "" "range [0,1] such that the elements along axis sum to 1." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.softmax:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.softmax:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.softmax:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.softmax:4 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.softmax:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.softmax:4 msgid "\\mathrm{softmax}(x) = \\frac{\\exp(x_i)}{\\sum_j \\exp(x_j)}" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.softmax:11 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.softmax:11 +#: tensorcircuit.backends.jax_backend.JaxBackend.softmax:11 #: tensorcircuit.backends.numpy_backend.NumpyBackend.softmax:11 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.softmax:11 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.softmax:11 @@ -9755,7 +11096,9 @@ msgid "" "all axis sum." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.softmax:13 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.softmax:13 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stack:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.softmax:13 #: tensorcircuit.backends.jax_backend.JaxBackend.stack:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.softmax:13 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stack:7 @@ -9766,28 +11109,32 @@ msgstr "" msgid "concatenated tensor" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.solve:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.solve:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.solve:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.solve:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.solve:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.solve:1 msgid "Solve the linear system Ax=b and return the solution x." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.solve:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.solve:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.solve:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.solve:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.solve:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.solve:3 msgid "The multiplied matrix." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.solve:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.solve:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.solve:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.solve:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.solve:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.solve:5 msgid "The resulted matrix." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.solve:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.solve:7 +#: tensorcircuit.backends.jax_backend.JaxBackend.solve:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.solve:7 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.solve:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.solve:7 @@ -9796,6 +11143,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul:1 #: tensorcircuit.backends.jax_backend.JaxBackend.sparse_dense_matmul:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sparse_dense_matmul:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sparse_dense_matmul:1 @@ -9805,6 +11153,8 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul:3 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.to_dense:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense:3 #: tensorcircuit.backends.jax_backend.JaxBackend.sparse_dense_matmul:3 #: tensorcircuit.backends.jax_backend.JaxBackend.to_dense:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sparse_dense_matmul:3 @@ -9816,6 +11166,7 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul:5 #: tensorcircuit.backends.jax_backend.JaxBackend.sparse_dense_matmul:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sparse_dense_matmul:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sparse_dense_matmul:5 @@ -9824,13 +11175,15 @@ msgstr "" #: of #: tensorcircuit.backends.abstract_backend.ExtendedBackend.sparse_dense_matmul:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.sparse_dense_matmul:7 #: tensorcircuit.backends.jax_backend.JaxBackend.sparse_dense_matmul:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.sparse_dense_matmul:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.sparse_dense_matmul:7 msgid "dense matrix" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.sqrt:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.sqrt:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.sqrt:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.sqrt:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.sqrt:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sqrt:1 @@ -9845,21 +11198,24 @@ msgstr "" msgid "sqrtm of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.stack:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.stack:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.stack:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stack:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.stack:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stack:1 msgid "Concatenates a sequence of tensors ``a`` along a new dimension ``axis``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.stack:3 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.stack:3 +#: tensorcircuit.backends.jax_backend.JaxBackend.stack:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stack:3 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.stack:3 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stack:3 msgid "List of tensors in the same shape" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.stack:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.stack:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.stack:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stack:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.stack:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stack:5 @@ -9868,6 +11224,8 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:5 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:3 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:3 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randn:5 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randu:3 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randn:5 @@ -9878,6 +11236,7 @@ msgid "stateful register for each package" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:7 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:7 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randn:7 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randn:7 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stateful_randn:7 @@ -9886,6 +11245,8 @@ msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randn:13 #: tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:11 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randn:13 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:11 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randn:13 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randu:11 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randn:13 @@ -9896,6 +11257,7 @@ msgid "only real data type is supported, \"32\" or \"64\", defaults to \"32\"" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:1 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randu:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randu:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stateful_randu:1 @@ -9903,20 +11265,23 @@ msgid "Uniform random sampler from ``low`` to ``high``." msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.stateful_randu:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.stateful_randu:5 #: tensorcircuit.backends.jax_backend.JaxBackend.stateful_randu:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stateful_randu:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stateful_randu:5 msgid "shape of output sampling tensor, defaults to 1" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.std:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.std:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.std:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.std:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.std:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.std:1 msgid "Compute the standard deviation along the specified axis." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.std:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.std:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.std:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.std:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.std:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.std:5 @@ -9925,7 +11290,8 @@ msgid "" "None, implying all axis" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.std:8 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.std:8 +#: tensorcircuit.backends.jax_backend.JaxBackend.std:8 #: tensorcircuit.backends.numpy_backend.NumpyBackend.std:8 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.std:8 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.std:8 @@ -9934,14 +11300,16 @@ msgid "" " as dimensions with size one, defaults to False" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.stop_gradient:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.stop_gradient:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.stop_gradient:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.stop_gradient:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.stop_gradient:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.stop_gradient:1 msgid "Stop backpropagation from ``a``." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.subtraction:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.subtraction:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.subtraction:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.subtraction:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.subtraction:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.subtraction:1 @@ -9950,7 +11318,8 @@ msgid "" "implementation. :param tensor1: A tensor. :param tensor2: A tensor." msgstr "" -#: of tensorcircuit.backends.numpy_backend._sum_numpy:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sum:1 +#: tensorcircuit.backends.numpy_backend._sum_numpy:1 #: tensorcircuit.backends.pytorch_backend._sum_torch:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.sum:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum:1 @@ -9959,7 +11328,8 @@ msgid "" "Tensor with the summed axis removed. :param tensor: An input tensor." msgstr "" -#: of tensorcircuit.backends.numpy_backend._sum_numpy:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sum:5 +#: tensorcircuit.backends.numpy_backend._sum_numpy:5 #: tensorcircuit.backends.pytorch_backend._sum_torch:5 #: tensornetwork.backends.jax.jax_backend.JaxBackend.sum:5 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum:5 @@ -9968,14 +11338,16 @@ msgid "" " reduced by 1." msgstr "" -#: of tensorcircuit.backends.numpy_backend._sum_numpy:7 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sum:7 +#: tensorcircuit.backends.numpy_backend._sum_numpy:7 #: tensorcircuit.backends.pytorch_backend._sum_torch:7 #: tensornetwork.backends.jax.jax_backend.JaxBackend.sum:7 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum:7 msgid "The result of performing the summation. The order of the tensor" msgstr "" -#: of tensorcircuit.backends.numpy_backend._sum_numpy:8 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.sum:8 +#: tensorcircuit.backends.numpy_backend._sum_numpy:8 #: tensorcircuit.backends.pytorch_backend._sum_torch:8 #: tensornetwork.backends.jax.jax_backend.JaxBackend.sum:8 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sum:8 @@ -9983,16 +11355,18 @@ msgid "will be reduced by 1." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:1 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:1 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:1 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:1 msgid "Computes the singular value decomposition (SVD) of a tensor." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:3 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:3 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:3 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:3 msgid "" "The SVD is performed by treating the tensor as a matrix, with an " "effective left (row) index resulting from combining the axes " @@ -10001,9 +11375,10 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:8 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:8 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:8 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:8 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:8 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:8 msgid "" "For example, if `tensor` had a shape (2, 3, 4, 5) and `pivot_axis` was 2," " then `u` would have shape (2, 3, 6), `s` would have shape (6), and `vh` " @@ -10011,18 +11386,20 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:12 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:12 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:12 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:12 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:12 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:12 msgid "" "If `max_singular_values` is set to an integer, the SVD is truncated to " "keep at most this many singular values." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:15 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:15 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:15 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:15 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:15 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:15 msgid "" "If `max_truncation_error > 0`, as many singular values will be truncated " "as possible, so that the truncation error (the norm of discarded singular" @@ -10032,9 +11409,9 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:21 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:21 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:21 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:21 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:21 msgid "" "If both `max_singular_values` and `max_truncation_error` are specified, " "the number of retained singular values will be `min(max_singular_values, " @@ -10044,23 +11421,23 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:27 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:27 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:27 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:27 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:27 msgid "The output consists of three tensors `u, s, vh` such that: ```python" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:29 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:29 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:29 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:29 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:29 msgid "u[i1,...,iN, j] * s[j] * vh[j, k1,...,kM] == tensor[i1,...,iN, k1,...,kM]" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:30 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:30 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:30 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:30 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:30 msgid "" "``` Note that the output ordering matches numpy.linalg.svd rather than " "tf.svd." @@ -10071,9 +11448,9 @@ msgstr "" #: tensorcircuit.backends.pytorch_backend._rq_torch:18 #: tensorcircuit.backends.tensorflow_backend._qr_tf:18 #: tensorcircuit.backends.tensorflow_backend._rq_tf:18 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:33 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:33 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:33 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:33 msgid "A tensor to be decomposed." msgstr "" @@ -10082,39 +11459,39 @@ msgstr "" #: tensorcircuit.backends.pytorch_backend._rq_torch:20 #: tensorcircuit.backends.tensorflow_backend._qr_tf:20 #: tensorcircuit.backends.tensorflow_backend._rq_tf:20 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:34 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:34 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:34 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:34 msgid "Where to split the tensor's axes before flattening into a matrix." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:36 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:36 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:36 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:36 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:36 msgid "The number of singular values to keep, or `None` to keep them all." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:38 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:38 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:38 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:38 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:38 msgid "The maximum allowed truncation error or `None` to not do any truncation." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:40 #: tensorcircuit.cons.split_rules:7 #: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:24 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:40 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:40 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:40 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:40 msgid "Multiply `max_truncation_err` with the largest singular value." msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:42 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:42 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:42 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:42 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:42 msgid "" "Left tensor factor. s: Vector of ordered singular values from largest to " "smallest. vh: Right tensor factor. s_rest: Vector of discarded singular " @@ -10122,9 +11499,9 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:42 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:42 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:42 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:42 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:42 msgid "" "Left tensor factor. s: Vector of ordered singular values from largest to " "smallest. vh: Right tensor factor. s_rest: Vector of discarded singular " @@ -10132,76 +11509,87 @@ msgid "" msgstr "" #: of tensorcircuit.backends.jax_backend._svd_jax:46 +#: tensorcircuit.backends.tensorflow_backend._svd_tf:49 +#: tensornetwork.backends.abstract_backend.AbstractBackend.svd:46 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.svd:46 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.svd:46 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd:46 msgid "truncation)." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.switch:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.switch:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.switch:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.switch:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.switch:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.switch:1 msgid "``branches[index]()``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tan:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tan:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.tan:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tan:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tan:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tan:1 msgid "Return the tan of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tan:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tan:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.tan:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tan:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tan:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tan:5 msgid "tan of ``a``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tanh:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tanh:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.tanh:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tanh:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tanh:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tanh:1 msgid "Return the tanh of a tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tanh:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tanh:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.tanh:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tanh:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tanh:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tanh:5 msgid "tanh of ``a``" msgstr "" -#: of tensorcircuit.backends.tensorflow_backend._tensordot_tf:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tensordot:1 +#: tensorcircuit.backends.tensorflow_backend._tensordot_tf:1 #: tensornetwork.backends.jax.jax_backend.JaxBackend.tensordot:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.tensordot:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.tensordot:1 msgid "Do a tensordot of tensors `a` and `b` over the given axes." msgstr "" -#: of tensorcircuit.backends.tensorflow_backend._tensordot_tf:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tensordot:4 +#: tensorcircuit.backends.tensorflow_backend._tensordot_tf:4 #: tensornetwork.backends.jax.jax_backend.JaxBackend.tensordot:4 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.tensordot:4 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.tensordot:4 msgid "Another tensor." msgstr "" -#: of tensorcircuit.backends.tensorflow_backend._tensordot_tf:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tensordot:5 +#: tensorcircuit.backends.tensorflow_backend._tensordot_tf:5 #: tensornetwork.backends.jax.jax_backend.JaxBackend.tensordot:5 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.tensordot:5 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.tensordot:5 msgid "Two lists of integers. These values are the contraction axes." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tile:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tile:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.tile:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tile:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tile:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tile:1 msgid "Constructs a tensor by tiling a given tensor." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.tile:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.tile:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.tile:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.tile:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.tile:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.tile:5 @@ -10209,6 +11597,7 @@ msgid "1d tensor with length the same as the rank of ``a``" msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.to_dense:1 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense:1 #: tensorcircuit.backends.jax_backend.JaxBackend.to_dense:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.to_dense:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.to_dense:1 @@ -10216,6 +11605,7 @@ msgid "Convert a sparse matrix to dense tensor." msgstr "" #: of tensorcircuit.backends.abstract_backend.ExtendedBackend.to_dense:5 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.to_dense:5 #: tensorcircuit.backends.jax_backend.JaxBackend.to_dense:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.to_dense:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.to_dense:5 @@ -10229,14 +11619,16 @@ msgstr "" msgid "Transform the tensor ``a`` as a dlpack capsule" msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.trace:1 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.trace:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.trace:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace:1 msgid "Return summed entries along diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.trace:3 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.trace:3 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:3 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:3 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.trace:3 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace:3 @@ -10247,14 +11639,16 @@ msgid "" " are used to determine the 2-D sub-array whose diagonal is summed." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.trace:19 +#: of tensornetwork.backends.abstract_backend.AbstractBackend.trace:19 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:19 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:19 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.trace:31 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.trace:28 msgid "The batched summed diagonals." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.transpose:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.transpose:1 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.transpose:1 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.transpose:1 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.transpose:1 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.transpose:1 @@ -10264,7 +11658,8 @@ msgid "" "the axes." msgstr "" -#: of tensornetwork.backends.jax.jax_backend.JaxBackend.transpose:6 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.transpose:6 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.transpose:6 #: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.transpose:6 #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.transpose:6 #: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.transpose:6 @@ -10345,7 +11740,8 @@ msgstr "" msgid "Packed pytree" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.unique_with_counts:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.unique_with_counts:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.unique_with_counts:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.unique_with_counts:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.unique_with_counts:1 @@ -10354,21 +11750,24 @@ msgid "" "tensor ``a``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.unique_with_counts:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.unique_with_counts:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.unique_with_counts:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.unique_with_counts:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.unique_with_counts:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.unique_with_counts:5 msgid "Unique elements, corresponding counts" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.value_and_grad:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.value_and_grad:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.value_and_grad:1 msgid "Return the function which returns the value and grad of ``f``." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:17 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.value_and_grad:17 +#: tensorcircuit.backends.jax_backend.JaxBackend.value_and_grad:17 #: tensorcircuit.backends.numpy_backend.NumpyBackend.value_and_grad:17 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.value_and_grad:17 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.value_and_grad:17 @@ -10377,7 +11776,9 @@ msgid "" "``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:1 +#: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vectorized_value_and_grad:1 @@ -10394,7 +11795,9 @@ msgid "" "for argnum in argnums). The gradient for argnums=k is defined as" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:9 +#: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:9 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:9 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vectorized_value_and_grad:9 @@ -10404,6 +11807,7 @@ msgid "" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:13 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:13 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:13 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:13 @@ -10412,6 +11816,7 @@ msgid "Therefore, if argnums=0, the gradient is reduced to" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:15 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:15 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:15 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:15 @@ -10420,6 +11825,7 @@ msgid "g^0_i = \\frac{\\partial f(vargs[0][i])}{\\partial vargs[0][i]}" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:19 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:19 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:19 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:19 @@ -10430,6 +11836,7 @@ msgid "" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:21 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:21 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:21 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:21 @@ -10438,6 +11845,7 @@ msgid "And if argnums=1, the gradient is like" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:23 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:23 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:23 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:23 @@ -10449,6 +11857,7 @@ msgid "" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:26 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:26 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:26 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vectorized_value_and_grad:26 @@ -10460,6 +11869,8 @@ msgid "" msgstr "" #: of +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vectorized_value_and_grad:33 +#: tensorcircuit.backends.cupy_backend.CuPyBackend.vmap:6 #: tensorcircuit.backends.jax_backend.JaxBackend.vectorized_value_and_grad:33 #: tensorcircuit.backends.jax_backend.JaxBackend.vmap:6 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vectorized_value_and_grad:33 @@ -10473,7 +11884,8 @@ msgid "" "shape in the fist dimension" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vjp:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vjp:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.vjp:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vjp:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vjp:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vjp:1 @@ -10483,14 +11895,16 @@ msgid "" " mode AD relevant) Strictly speaking, this function is value_and_vjp." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vjp:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vjp:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.vjp:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vjp:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vjp:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vjp:5 msgid "the function to carry out vjp calculation" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vjp:9 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vjp:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.vjp:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vjp:9 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vjp:9 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vjp:9 @@ -10499,14 +11913,16 @@ msgid "" "shape as return of function ``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vjp:12 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vjp:12 +#: tensorcircuit.backends.jax_backend.JaxBackend.vjp:12 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vjp:12 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vjp:12 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vjp:12 msgid "(``f(*inputs)``, vjp_tensor), where vjp_tensor is the same shape as inputs" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vmap:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vmap:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.vmap:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vmap:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vmap:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vmap:1 @@ -10516,21 +11932,24 @@ msgid "" "broadcast in the fist dimension." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vmap:4 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vmap:4 +#: tensorcircuit.backends.jax_backend.JaxBackend.vmap:4 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vmap:4 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vmap:4 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vmap:4 msgid "function to be broadcasted." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.vmap:9 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.vmap:9 +#: tensorcircuit.backends.jax_backend.JaxBackend.vmap:9 #: tensorcircuit.backends.numpy_backend.NumpyBackend.vmap:9 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.vmap:9 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.vmap:9 msgid "vmap version of ``f``" msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.zeros:1 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.zeros:1 +#: tensorcircuit.backends.jax_backend.JaxBackend.zeros:1 #: tensorcircuit.backends.numpy_backend.NumpyBackend.zeros:1 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.zeros:1 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.zeros:1 @@ -10540,7 +11959,8 @@ msgid "" " object (for block-sparse backends)." msgstr "" -#: of tensorcircuit.backends.jax_backend.JaxBackend.zeros:5 +#: of tensorcircuit.backends.cupy_backend.CuPyBackend.zeros:5 +#: tensorcircuit.backends.jax_backend.JaxBackend.zeros:5 #: tensorcircuit.backends.numpy_backend.NumpyBackend.zeros:5 #: tensorcircuit.backends.pytorch_backend.PyTorchBackend.zeros:5 #: tensorcircuit.backends.tensorflow_backend.TensorFlowBackend.zeros:5 @@ -10550,317 +11970,382 @@ msgid "" "dtype of the returned matrix." msgstr "" -#: ../../source/api/backends/numpy_backend.rst:2 -msgid "tensorcircuit.backends.numpy_backend" +#: ../../source/api/backends/jax_backend.rst:2 +msgid "tensorcircuit.backends.jax_backend" msgstr "" -#: of tensorcircuit.backends.numpy_backend:1 -msgid "Backend magic inherited from tensornetwork: numpy backend" +#: of tensorcircuit.backends.jax_backend:1 +msgid "Backend magic inherited from tensornetwork: jax backend" msgstr "" -#: of tensorcircuit.backends.numpy_backend.NumpyBackend:1 +#: of tensorcircuit.backends.jax_backend.JaxBackend:1 msgid "" -"Bases: " -":py:class:`tensornetwork.backends.numpy.numpy_backend.NumPyBackend`, " -":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" +"Bases: :py:class:`~tensornetwork.backends.jax.jax_backend.JaxBackend`, " +":py:class:`~tensorcircuit.backends.abstract_backend.ExtendedBackend`" msgstr "" -#: of tensorcircuit.backends.numpy_backend.NumpyBackend:1 +#: of tensorcircuit.backends.jax_backend.JaxBackend:1 msgid "" -"see the original backend API at `numpy backend " -"`_" +"See the original backend API at `jax backend " +"`_" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:16 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.diagonal:19 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:12 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.trace:15 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:16 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.diagonal:19 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:12 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.trace:15 msgid "" "Axis to be used as the first/second axis of the 2D sub-arrays from which " -"the diagonals should be taken. Defaults to second-last/last axis." +"the diagonals should be taken. Defaults to second last/last axis." msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:1 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:1 msgid "" -"Arnoldi method for finding the lowest eigenvector-eigenvalue pairs of a " -"linear operator `A`. If no `initial_state` is provided then `shape` and " -"`dtype` are required so that a suitable initial state can be randomly " -"generated. This is a wrapper for scipy.sparse.linalg.eigs which only " -"supports a subset of the arguments of scipy.sparse.linalg.eigs." -msgstr "" - -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:8 -msgid "A (sparse) implementation of a linear operator" +"Implicitly restarted Arnoldi method for finding the lowest eigenvector-" +"eigenvalue pairs of a linear operator `A`. `A` is a function implementing" +" the matrix-vector product." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:9 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:9 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:11 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:9 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:6 msgid "" -"An initial vector for the algorithm. If `None`, a random initial `Tensor`" -" is created using the `numpy.random.randn` method." +"WARNING: This routine uses jax.jit to reduce runtimes. jitting is " +"triggered at the first invocation of `eigs`, and on any subsequent calls " +"if the python `id` of `A` changes, even if the formal definition of `A` " +"stays the same. Example: the following will jit once at the beginning, " +"and then never again:" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:13 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:13 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:11 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:15 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:13 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:11 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:11 -msgid "" -"The dtype of the input `A`. If both no `initial_state` is provided, a " -"random initial state with shape `shape` and dtype `dtype` is created." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:12 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:12 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:10 +msgid "```python import jax import numpy as np def A(H,x):" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:16 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:16 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:14 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:18 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:16 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:14 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:14 -msgid "" -"The nummber of eigenvector-eigenvalue pairs to be computed. If `numeig > " -"1`, `reorthogonalize` has to be `True`." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:16 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:31 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:16 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:31 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:14 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:29 +msgid "return jax.np.dot(H,x)" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:18 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:18 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:20 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:18 -msgid "The desired precision of the eigenvalus. Uses" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:19 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:19 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:17 +msgid "for n in range(100):" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:21 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:18 msgid "" -"['LM' | 'SM' | 'LR' | 'SR' | 'LI'] Which `k` eigenvectors and eigenvalues" -" to find: 'LM' : largest magnitude 'SM' : smallest magnitude " -"'LR' : largest real part 'SR' : smallest real part 'LI' : largest" -" imaginary part" +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigs(A, [H],x) #jitting is " +"triggerd only at `n=0`" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:21 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:23 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:23 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:21 msgid "" -"['LM' | 'SM' | 'LR' | 'SR' | 'LI'] Which `k` eigenvectors and eigenvalues" -" to find:" +"The following code triggers jitting at every iteration, which results in " +"considerably reduced performance" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:23 -msgid "" -"'LM' : largest magnitude 'SM' : smallest magnitude 'LR' : largest real " -"part 'SR' : smallest real part 'LI' : largest imaginary part" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:26 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:26 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:24 +msgid "```python import jax import numpy as np for n in range(100):" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:28 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:28 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:28 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:28 -msgid "The maximum number of iterations." -msgstr "" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:30 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:30 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:28 +msgid "def A(H,x):" +msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:30 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:30 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:30 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:30 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:32 msgid "" -"An array of `numeig` lowest eigenvalues `list`: A list of `numeig` lowest" -" eigenvectors" +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigs(A, [H],x) #jitting is " +"triggerd at every step `n`" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:32 -msgid "`np.ndarray`" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:37 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:37 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:35 +msgid "" +"A (sparse) implementation of a linear operator. Call signature of `A` is " +"`res = A(vector, *args)`, where `vector` can be an arbitrary `Tensor`, " +"and `res.shape` has to be `vector.shape`." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:1 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:1 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:42 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:42 msgid "" -"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " -"symmetric (hermitian) linear operator `A`. `A` is a callable implementing" -" the matrix-vector product. If no `initial_state` is provided then " -"`shape` and `dtype` have to be passed so that a suitable initial state " -"can be randomly generated. :param A: A (sparse) implementation of a " -"linear operator :param arsg: A list of arguments to `A`. `A` will be " -"called as" +"An initial vector for the algorithm. If `None`, a random initial `Tensor`" +" is created using the `backend.randn` method" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:8 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:8 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:8 -msgid "`res = A(initial_state, *args)`." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:45 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:45 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:43 +msgid "" +"The dtype of the input `A`. If no `initial_state` is provided, a random " +"initial state with shape `shape` and dtype `dtype` is created." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:19 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:19 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:19 -msgid "" -"['LM' | 'SM' | 'LR' | 'SR' | 'LI' | 'SI'] Which `k` eigenvectors and " -"eigenvalues to find: 'LM' : largest magnitude 'SM' : smallest " -"magnitude 'LR' : largest real part 'SR' : smallest real part " -"'LI' : largest imaginary part 'SI' : smallest imaginary part Note " -"that not all of those might be supported by specialized backends." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:48 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:48 +msgid "The number of eigenvector-eigenvalue pairs to be computed." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:19 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:19 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:19 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:49 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:49 msgid "" -"['LM' | 'SM' | 'LR' | 'SR' | 'LI' | 'SI'] Which `k` eigenvectors and " -"eigenvalues to find:" +"The desired precision of the eigenvalues. For the jax backend this has " +"currently no effect, and precision of eigenvalues is not guaranteed. This" +" feature may be added at a later point. To increase precision the caller " +"can either increase `maxiter` or `num_krylov_vecs`." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:21 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:21 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:21 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:53 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:53 msgid "" -"'LM' : largest magnitude 'SM' : smallest magnitude 'LR' : largest real " -"part 'SR' : smallest real part 'LI' : largest imaginary part 'SI' : " -"smallest imaginary part" +"Flag for targetting different types of eigenvalues. Currently supported " +"are `which = 'LR'` (larges real part) and `which = 'LM'` (larges " +"magnitude)." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:27 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:27 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:27 -msgid "Note that not all of those might be supported by specialized backends." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:56 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:56 +msgid "" +"Maximum number of restarts. For `maxiter=0` the routine becomes " +"equivalent to a simple Arnoldi method." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:32 -#: tensornetwork.backends.abstract_backend.AbstractBackend.eigsh:32 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh:32 -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:12 -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:10 -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.position:10 -#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:9 -msgid "`Tensor`" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:59 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:59 +msgid "" +"(eigvals, eigvecs) eigvals: A list of `numeig` eigenvalues eigvecs: A " +"list of `numeig` eigenvectors" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:1 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigs:62 +#: tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:62 msgid "" -"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " -"linear operator `A`. :param A: A (sparse) implementation of a linear " -"operator." +"eigvals: A list of `numeig` eigenvalues eigvecs: A list of `numeig` " +"eigenvectors" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:4 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:4 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:4 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:1 msgid "" -"Call signature of `A` is `res = A(vector, *args)`, where `vector` can be " -"an arbitrary `Tensor`, and `res.shape` has to be `vector.shape`." +"Implicitly restarted Lanczos method for finding the lowest eigenvector-" +"eigenvalue pairs of a symmetric (hermitian) linear operator `A`. `A` is a" +" function implementing the matrix-vector product." msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:16 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:6 msgid "" -"The desired precision of the eigenvalus. Uses " -"`np.linalg.norm(eigvalsnew[0:numeig] - eigvalsold[0:numeig]) < tol` as " -"stopping criterion between two diagonalization steps of the tridiagonal " -"operator." +"WARNING: This routine uses jax.jit to reduce runtimes. jitting is " +"triggered at the first invocation of `eigsh`, and on any subsequent calls" +" if the python `id` of `A` changes, even if the formal definition of `A` " +"stays the same. Example: the following will jit once at the beginning, " +"and then never again:" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:25 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:25 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:25 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:18 msgid "" -"The tridiagonal Operator is diagonalized every `ndiag` iterations to " -"check convergence." +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigsh(A, [H],x) #jitting is " +"triggerd only at `n=0`" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:30 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:30 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:30 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh:32 msgid "" -"(eigvals, eigvecs) eigvals: A list of `numeig` lowest eigenvalues " -"eigvecs: A list of `numeig` lowest eigenvectors" +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigsh(A, [H],x) #jitting is " +"triggerd at every step `n`" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:33 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:33 -#: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:33 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:1 msgid "" -"eigvals: A list of `numeig` lowest eigenvalues eigvecs: A list of " -"`numeig` lowest eigenvectors" +"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " +"hermitian linear operator `A`. `A` is a function implementing the matrix-" +"vector product. WARNING: This routine uses jax.jit to reduce runtimes. " +"jitting is triggered at the first invocation of `eigsh_lanczos`, and on " +"any subsequent calls if the python `id` of `A` changes, even if the " +"formal definition of `A` stays the same. Example: the following will jit " +"once at the beginning, and then never again:" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 -msgid "Returns the exponentiation of tensor a raised to b." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:16 +msgid "" +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigsh_lanczos(A, [H],x) " +"#jitting is triggerd only at `n=0`" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:4 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:4 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:4 -msgid "If b is a tensor, then the exponentiation is element-wise" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:30 +msgid "" +"H = jax.np.array(np.random.rand(10,10)) x = " +"jax.np.array(np.random.rand(10,10)) res = eigsh_lanczos(A, [H],x) " +"#jitting is triggerd at every step `n`" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:3 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:3 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:3 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:46 msgid "" -"between the two tensors, with a as the base and b as the power. Note that" -" a and b must be broadcastable to the same shape if b is a tensor." +"The number of eigenvector-eigenvalue pairs to be computed. If `numeig > " +"1`, `reorthogonalize` has to be `True`." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 -msgid "If b is a scalar, then the exponentiation is each value in a" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:48 +msgid "" +"The desired precision of the eigenvalues. For the jax backend this has " +"currently no effect, and precision of eigenvalues is not guaranteed. This" +" feature may be added at a later point. To increase precision the caller " +"can increase `num_krylov_vecs`." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:7 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:7 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:7 -msgid "raised to the power of b." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:57 +msgid "" +"The tridiagonal Operator is diagonalized every `ndiag` iterations to " +"check convergence. This has currently no effect for the jax backend, but " +"may be added at a later point." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:9 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:9 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:9 -msgid "The tensor containing the bases." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:63 +msgid "" +"(eigvals, eigvecs) eigvals: A jax-array containing `numeig` lowest " +"eigenvalues eigvecs: A list of `numeig` lowest eigenvectors" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:10 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:10 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:10 -msgid "The tensor containing the powers; or a single scalar as the power." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.eigsh_lanczos:66 +msgid "" +"eigvals: A jax-array containing `numeig` lowest eigenvalues eigvecs: A " +"list of `numeig` lowest eigenvectors" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:12 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:12 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:12 +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:1 msgid "" -"The tensor that is each element of a raised to the power of b. Note " -"that the shape of the returned tensor is that produced by the broadcast" -" of a and b." +"Returns the power of tensor a to the value of b. In the case b is a " +"tensor, then the power is by element" msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:15 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:15 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:15 -msgid "The tensor that is each element of a raised to the" +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:3 +msgid "with a as the base and b as the exponent." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.power:15 -#: tensornetwork.backends.numpy.numpy_backend.NumPyBackend.power:15 -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.power:15 -msgid "" -"power of b. Note that the shape of the returned tensor is that produced " -"by the broadcast of a and b." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:5 +msgid "In the case b is a scalar, then the power of each value in a" msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.qr:1 -msgid "Computes the QR decomposition of a tensor." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:5 +msgid "is raised to the exponent of b." msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.rq:1 -msgid "Computes the RQ (reversed QR) decomposition of a tensor." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:7 +msgid "The tensor that contains the base." msgstr "" -#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.sign:1 -msgid "" -"Returns an elementwise tensor with entries y[i] = 1, 0, -1 tensor[i] > 0," -" == 0, and < 0 respectively." +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.power:8 +msgid "The tensor that contains the exponent or a single scalar." +msgstr "" + +#: of tensorcircuit.backends.jax_backend._qr_jax:1 +msgid "" +"Computes the QR decomposition of a tensor. See " +"tensornetwork.backends.tensorflow.decompositions for details." +msgstr "" + +#: of tensorcircuit.backends.jax_backend._rq_jax:1 +msgid "" +"Computes the RQ (reversed QR) decomposition of a tensor. See " +"tensornetwork.backends.tensorflow.decompositions for details." +msgstr "" + +#: of tensornetwork.backends.jax.jax_backend.JaxBackend.sign:4 +msgid "" +"For complex input the behaviour of this function may depend on the " +"backend. The Jax backend version returns y[i] = x[i]/sqrt(x[i]^2)." +msgstr "" + +#: ../../source/api/backends/numpy_backend.rst:2 +msgid "tensorcircuit.backends.numpy_backend" +msgstr "" + +#: of tensorcircuit.backends.numpy_backend:1 +msgid "Backend magic inherited from tensornetwork: numpy backend" +msgstr "" + +#: of tensorcircuit.backends.numpy_backend.NumpyBackend:1 +msgid "" +"Bases: " +":py:class:`~tensornetwork.backends.numpy.numpy_backend.NumPyBackend`, " +":py:class:`~tensorcircuit.backends.abstract_backend.ExtendedBackend`" +msgstr "" + +#: of tensorcircuit.backends.numpy_backend.NumpyBackend:1 +msgid "" +"see the original backend API at `numpy backend " +"`_" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:1 +msgid "" +"Arnoldi method for finding the lowest eigenvector-eigenvalue pairs of a " +"linear operator `A`. If no `initial_state` is provided then `shape` and " +"`dtype` are required so that a suitable initial state can be randomly " +"generated. This is a wrapper for scipy.sparse.linalg.eigs which only " +"supports a subset of the arguments of scipy.sparse.linalg.eigs." +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:8 +msgid "A (sparse) implementation of a linear operator" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:21 +msgid "" +"['LM' | 'SM' | 'LR' | 'SR' | 'LI'] Which `k` eigenvectors and eigenvalues" +" to find: 'LM' : largest magnitude 'SM' : smallest magnitude " +"'LR' : largest real part 'SR' : smallest real part 'LI' : largest" +" imaginary part" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:21 +msgid "" +"['LM' | 'SM' | 'LR' | 'SR' | 'LI'] Which `k` eigenvectors and eigenvalues" +" to find:" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:23 +msgid "" +"'LM' : largest magnitude 'SM' : smallest magnitude 'LR' : largest real " +"part 'SR' : smallest real part 'LI' : largest imaginary part" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigs:32 +msgid "`np.ndarray`" +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:1 +msgid "" +"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of a " +"linear operator `A`. :param A: A (sparse) implementation of a linear " +"operator." +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.eigsh_lanczos:16 +msgid "" +"The desired precision of the eigenvalus. Uses " +"`np.linalg.norm(eigvalsnew[0:numeig] - eigvalsold[0:numeig]) < tol` as " +"stopping criterion between two diagonalization steps of the tridiagonal " +"operator." +msgstr "" + +#: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.sign:1 +msgid "" +"Returns an elementwise tensor with entries y[i] = 1, 0, -1 tensor[i] > 0," +" == 0, and < 0 respectively." msgstr "" #: of tensornetwork.backends.numpy.numpy_backend.NumPyBackend.sign:4 @@ -10880,8 +12365,8 @@ msgstr "" #: of tensorcircuit.backends.pytorch_backend.PyTorchBackend:1 msgid "" "Bases: " -":py:class:`tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend`," -" :py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" +":py:class:`~tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend`," +" :py:class:`~tensorcircuit.backends.abstract_backend.ExtendedBackend`" msgstr "" #: of tensorcircuit.backends.pytorch_backend.PyTorchBackend:1 @@ -10906,16 +12391,6 @@ msgid "" "(note this differs from the NumPy defaults)." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigs:1 -msgid "" -"Arnoldi method for finding the lowest eigenvector-eigenvalue pairs of a " -"linear operator `A`. `A` is a callable implementing the matrix-vector " -"product. If no `initial_state` is provided then `shape` and `dtype` have " -"to be passed so that a suitable initial state can be randomly generated." -" :param A: A (sparse) implementation of a linear operator :param arsg: A " -"list of arguments to `A`. `A` will be called as" -msgstr "" - #: of #: tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend.eigsh_lanczos:1 msgid "" @@ -11032,6 +12507,12 @@ msgid "" "raised if they are specified." msgstr "" +#: of tensorcircuit.backends.pytorch_backend.torch_jit_func:1 +msgid "" +"Delay the tracing of torch jit to the first run time: consistent with tf " +"and jax mechanism" +msgstr "" + #: ../../source/api/backends/tensorflow_backend.rst:2 msgid "tensorcircuit.backends.tensorflow_backend" msgstr "" @@ -11043,8 +12524,8 @@ msgstr "" #: of tensorcircuit.backends.tensorflow_backend.TensorFlowBackend:1 msgid "" "Bases: " -":py:class:`tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend`," -" :py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" +":py:class:`~tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend`," +" :py:class:`~tensorcircuit.backends.abstract_backend.ExtendedBackend`" msgstr "" #: of tensorcircuit.backends.tensorflow_backend.TensorFlowBackend:1 @@ -11072,25 +12553,67 @@ msgid "" "will be raised if they are specified." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:1 +#: of +#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sign:4 msgid "" -"Lanczos method for finding the lowest eigenvector-eigenvalue pairs of " -"`A`. :param A: A (sparse) implementation of a linear operator." +"For complex input the behaviour of this function may depend on the " +"backend. The TensorFlow version returns y[i] = x[i] / abs(x[i])." msgstr "" -#: of tensornetwork.backends.abstract_backend.AbstractBackend.eigsh_lanczos:16 +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:21 msgid "" -"The desired precision of the eigenvalus. Uses " -"`backend.norm(eigvalsnew[0:numeig] - eigvalsold[0:numeig]) < tol` as " -"stopping criterion between two diagonalization steps of the tridiagonal " -"operator." +"If both `max_singular_values` snd `max_truncation_error` are specified, " +"the number of retained singular values will be `min(max_singular_values, " +"nsv_auto_trunc)`, where `nsv_auto_trunc` is the number of singular values" +" that must be kept to maintain a truncation error smaller than " +"`max_truncation_error`." msgstr "" -#: of -#: tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.sign:4 +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:27 msgid "" -"For complex input the behaviour of this function may depend on the " -"backend. The TensorFlow version returns y[i] = x[i] / abs(x[i])." +"The output consists of three tensors `u, s, vh` such that: ```python " +"u[i1,...,iN, j] * s[j] * vh[j, k1,...,kM] == tensor[i1,...,iN, k1,...,kM]" +" ``` Note that the output ordering matches numpy.linalg.svd rather than " +"tf.svd." +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:33 +msgid "" +"Args: tf: The tensorflow module. tensor: A tensor to be decomposed. " +"pivot_axis: Where to split the tensor's axes before flattening into a" +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:37 +msgid "matrix." +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:38 +msgid "max_singular_values: The number of singular values to keep, or `None` to" +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:39 +msgid "keep them all." +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:40 +msgid "" +"max_truncation_error: The maximum allowed truncation error or `None` to " +"not" +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:41 +msgid "do any truncation." +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:42 +msgid "relative: Multiply `max_truncation_err` with the largest singular value." +msgstr "" + +#: of tensorcircuit.backends.tensorflow_backend._svd_tf:44 +msgid "" +"Returns: u: Left tensor factor. s: Vector of ordered singular values from" +" largest to smallest. vh: Right tensor factor. s_rest: Vector of " +"discarded singular values (length zero if no" msgstr "" #: of @@ -11121,7 +12644,7 @@ msgstr "" #: of tensorcircuit.basecircuit.BaseCircuit:1 #: tensorcircuit.mpscircuit.MPSCircuit:1 -msgid "Bases: :py:class:`tensorcircuit.abstractcircuit.AbstractCircuit`" +msgid "Bases: :py:class:`~tensorcircuit.abstractcircuit.AbstractCircuit`" msgstr "" #: of tensorcircuit.basecircuit.BaseCircuit.amplitude:1 @@ -11152,6 +12675,7 @@ msgid "" msgstr "" #: of tensorcircuit.basecircuit.BaseCircuit.expectation_before:4 +#: tensorcircuit.interfaces.torch.torch_interface_kws:24 #: tensorcircuit.quantum.sample2count:7 tensorcircuit.utils.benchmark:7 msgid "_description_, defaults to True" msgstr "" @@ -11265,6 +12789,7 @@ msgid "" msgstr "" #: of tensorcircuit.basecircuit.BaseCircuit.sample:13 +#: tensorcircuit.cloud.abstraction.Task.results:5 #: tensorcircuit.quantum.measurement_counts:45 #: tensorcircuit.quantum.sample2all:10 msgid "alias for the argument ``format``" @@ -11599,7 +13124,8 @@ msgid ":math:`p_z`" msgstr "" #: of tensorcircuit.channels.depolarizingchannel:36 -#: tensorcircuit.channels.generaldepolarizingchannel:15 +#: tensorcircuit.channels.generaldepolarizingchannel:39 +#: tensorcircuit.channels.isotropicdepolarizingchannel:28 msgid "Sequences of Gates" msgstr "" @@ -11628,15 +13154,50 @@ msgid "The dynamic evolution according to Superoperator." msgstr "" #: of tensorcircuit.channels.generaldepolarizingchannel:1 -msgid "Return a Depolarizing Channel for 1 qubit or 2 qubits" +msgid "" +"Return a depolarizing channel. If :math:`p` is a float number, the one " +"qubit channel is" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:4 +msgid "\\mathcal{E}(\\rho) = (1 - 3p)\\rho + p(X\\rho X + Y\\rho Y + Z\\rho Z)" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:8 +msgid "Or alternatively" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:10 +msgid "\\mathcal{E}(\\rho) = 4p \\frac{I}{2} + (1 - 4p) \\rho" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:16 +msgid "" +"The definition of ``p`` in this method is different from " +":func:`isotropicdepolarizingchannel`." msgstr "" -#: of tensorcircuit.channels.generaldepolarizingchannel:11 +#: of tensorcircuit.channels.generaldepolarizingchannel:19 +msgid "And if :math:`p` is a sequence, the one qubit channel is" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:21 +msgid "" +"\\mathcal{E}(\\rho) = (1 - \\sum_i p_i) \\rho + p_1 X\\rho X + p_2 Y\\rho" +" Y + p_3 \\rho Z" +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:25 +msgid "The logic for two-qubit or more-qubit channel follows similarly." +msgstr "" + +#: of tensorcircuit.channels.generaldepolarizingchannel:35 msgid "parameter for each Pauli channel" msgstr "" -#: of tensorcircuit.channels.generaldepolarizingchannel:13 -msgid "number of qubits, 1 and 2 are avaliable, defaults 1" +#: of tensorcircuit.channels.generaldepolarizingchannel:37 +#: tensorcircuit.channels.isotropicdepolarizingchannel:26 +msgid "number of qubits, defaults 1" msgstr "" #: of tensorcircuit.channels.is_hermitian_matrix:1 @@ -11655,6 +13216,36 @@ msgstr "" msgid "_description_, defaults to 1e-5" msgstr "" +#: of tensorcircuit.channels.isotropicdepolarizingchannel:1 +msgid "Return an isotropic depolarizing channel." +msgstr "" + +#: of tensorcircuit.channels.isotropicdepolarizingchannel:3 +msgid "\\mathcal{E}(\\rho) = (1 - p)\\rho + p/(4^n-1)\\sum_j P_j \\rho P_j" +msgstr "" + +#: of tensorcircuit.channels.isotropicdepolarizingchannel:7 +msgid "" +"where $n$ is the number of qubits and $P_j$ are $n$-qubit Pauli strings " +"except $I$. Or alternatively" +msgstr "" + +#: of tensorcircuit.channels.isotropicdepolarizingchannel:10 +msgid "" +"\\mathcal{E}(\\rho) = \\frac{4^n}{4^n-1}p \\frac{I}{2} + (1 - " +"\\frac{4^n}{4^n-1}p) \\rho" +msgstr "" + +#: of tensorcircuit.channels.isotropicdepolarizingchannel:16 +msgid "" +"The definition of ``p`` in this method is different from " +":func:`generaldepolarizingchannel`." +msgstr "" + +#: of tensorcircuit.channels.isotropicdepolarizingchannel:24 +msgid "error probability" +msgstr "" + #: of tensorcircuit.channels.kraus_identity_check:1 msgid "Check identity of Kraus operators." msgstr "" @@ -11885,7 +13476,7 @@ msgid "Quantum circuit: the state simulator" msgstr "" #: of tensorcircuit.circuit.Circuit:1 tensorcircuit.densitymatrix.DMCircuit:1 -msgid "Bases: :py:class:`tensorcircuit.basecircuit.BaseCircuit`" +msgid "Bases: :py:class:`~tensorcircuit.basecircuit.BaseCircuit`" msgstr "" #: of tensorcircuit.circuit.Circuit:1 @@ -11893,15 +13484,15 @@ msgid "``Circuit`` class. Simple usage demo below." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **ANY** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.any_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:4 -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:4 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:5 #: tensorcircuit.circuit.Circuit.apply_general_kraus_delayed..apply:4 #: tensorcircuit.densitymatrix.DMCircuit.apply_general_kraus_delayed..apply:4 #: tensorcircuit.densitymatrix.DMCircuit2.apply_general_kraus_delayed..apply:4 @@ -11909,20 +13500,20 @@ msgid "Qubit number that the gate applies on." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:6 -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:7 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:6 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:7 msgid "Parameters for the gate." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **CNOT** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.cnot_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -11931,12 +13522,12 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "Qubit number that the gate applies on. The matrix for the gate is" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & " "1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j & 1.+0.j\\\\ " @@ -11944,56 +13535,56 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CPHASE** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.cphase_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CR** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.cr_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CRX** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.crx_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CRY** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.cry_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CRZ** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.crz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **CU** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.cu_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **CY** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.cy_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -12002,7 +13593,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & " "1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j & 0.-1.j\\\\ " @@ -12010,14 +13601,14 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **CZ** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.cz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -12026,7 +13617,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & " "1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j\\\\ " @@ -12034,28 +13625,28 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **EXP** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.exp_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **EXP1** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.exp1_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **FREDKIN** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.fredkin_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & " @@ -12071,7 +13662,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j &" " 0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & " @@ -12086,14 +13677,14 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **H** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.h_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.70710677+0.j & 0.70710677+0.j\\\\ " @@ -12101,21 +13692,21 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 0.70710677+0.j & 0.70710677+0.j\\\\ 0.70710677+0.j" " & -0.70710677+0.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **I** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.i_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j " @@ -12123,61 +13714,61 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **ISWAP** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.iswap_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply mpo gate in MPO format on the circuit. See " ":py:meth:`tensorcircuit.gates.mpo_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply multicontrol gate in MPO format on the circuit. See " ":py:meth:`tensorcircuit.gates.multicontrol_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **ORX** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.orx_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **ORY** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.ory_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **ORZ** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.orz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **OX** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.ox_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -12186,7 +13777,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j\\\\ 1.+0.j & " "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j\\\\ " @@ -12194,14 +13785,14 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **OY** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.oy_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.+0.j & 0.-1.j & 0.+0.j & 0.+0.j\\\\" @@ -12210,7 +13801,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 0.+0.j & 0.-1.j & 0.+0.j & 0.+0.j\\\\ 0.+1.j & " "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j\\\\ " @@ -12218,14 +13809,14 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **OZ** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.oz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -12234,7 +13825,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & " "-1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j\\\\" @@ -12242,70 +13833,70 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **PHASE** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.phase_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **R** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.r_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RX** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.rx_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RXX** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.rxx_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RY** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.ry_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RYY** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.ryy_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RZ** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.rz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **RZZ** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.rzz_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **S** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.s_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+1.j " @@ -12313,19 +13904,19 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+1.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **SD** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.sd_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 0.-1.j " @@ -12333,19 +13924,19 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 0.-1.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **SWAP** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.swap_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\" @@ -12354,7 +13945,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j & " "0.+0.j & 1.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j\\\\ " @@ -12362,14 +13953,14 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **T** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.t_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1. & +0.j & 0. & +0.j\\\\ 0. & +0.j " @@ -12377,21 +13968,21 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1. & +0.j & 0. & +0.j\\\\ 0. & +0.j & " "0.70710677+0.70710677j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **TD** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.td_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1. & +0.j & 0. & +0.j\\\\ 0. & +0.j " @@ -12399,21 +13990,21 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1. & +0.j & 0. & +0.j\\\\ 0. & +0.j & " "0.70710677-0.70710677j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **TOFFOLI** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.toffoli_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & " @@ -12429,7 +14020,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j &" " 0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j & " @@ -12444,21 +14035,21 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_variable_gate_delayed..apply_list:1 msgid "" "Apply **U** gate with parameters on the circuit. See " ":py:meth:`tensorcircuit.gates.u_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **WROOT** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.wroot_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.70710677+0.j & -0.5 & -0.5j\\\\ " @@ -12466,21 +14057,21 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "" "\\begin{bmatrix} 0.70710677+0.j & -0.5 & -0.5j\\\\ 0.5 & -0.5j & " "0.70710677+0.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **X** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.x_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.+0.j & 1.+0.j\\\\ 1.+0.j & 0.+0.j " @@ -12488,19 +14079,19 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 0.+0.j & 1.+0.j\\\\ 1.+0.j & 0.+0.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **Y** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.y_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 0.+0.j & 0.-1.j\\\\ 0.+1.j & 0.+0.j " @@ -12508,19 +14099,19 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 0.+0.j & 0.-1.j\\\\ 0.+1.j & 0.+0.j \\end{bmatrix}" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:1 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:1 msgid "" "Apply **Z** gate on the circuit. See " ":py:meth:`tensorcircuit.gates.z_gate`." msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:5 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:5 msgid "" "Qubit number that the gate applies on. The matrix for the gate is .. " "math:: \\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & -1.+0.j" @@ -12528,7 +14119,7 @@ msgid "" msgstr "" #: of -#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply:8 +#: tensorcircuit.abstractcircuit.AbstractCircuit.apply_general_gate_delayed..apply_list:8 msgid "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & -1.+0.j \\end{bmatrix}" msgstr "" @@ -12710,6 +14301,15 @@ msgstr "" msgid "The bool indicating whether the circuit is legal" msgstr "" +#: of +#: tensorcircuit.circuit.Circuit.apply_general_kraus_delayed..apply:1 +#: tensorcircuit.densitymatrix.DMCircuit.apply_general_kraus_delayed..apply:1 +#: tensorcircuit.densitymatrix.DMCircuit2.apply_general_kraus_delayed..apply:1 +msgid "" +"Apply isotropicdepolarizing quantum channel on the circuit. See " +":py:meth:`tensorcircuit.channels.isotropicdepolarizingchannel`" +msgstr "" + #: of tensorcircuit.circuit.Circuit.matrix:1 msgid "" "Get the unitary matrix for the circuit irrespective with the circuit " @@ -12849,9257 +14449,11448 @@ msgstr "" msgid "The result of :math:`\\langle bra\\vert ops \\vert ket\\rangle`." msgstr "" -#: ../../source/api/compiler.rst:2 -msgid "tensorcircuit.compiler" +#: ../../source/api/cloud.rst:2 +msgid "tensorcircuit.cloud" msgstr "" -#: ../../source/api/compiler/qiskit_compiler.rst:2 -msgid "tensorcircuit.compiler.qiskit_compiler" +#: ../../source/api/cloud/abstraction.rst:2 +msgid "tensorcircuit.cloud.abstraction" msgstr "" -#: of tensorcircuit.compiler.qiskit_compiler:1 -msgid "compiler interface via qiskit" +#: of tensorcircuit.cloud.abstraction:1 +msgid "Abstraction for Provider, Device and Task" msgstr "" -#: ../../source/api/cons.rst:2 -msgid "tensorcircuit.cons" +#: of tensorcircuit.cloud.abstraction.Device:1 +msgid "Device abstraction for cloud connection, eg. quantum chips" msgstr "" -#: of tensorcircuit.cons:1 -msgid "Constants and setups" +#: of tensorcircuit.cloud.abstraction.Device.list_properties:1 +msgid "List all device properties in as dict" msgstr "" -#: of tensorcircuit.cons.get_contractor:1 tensorcircuit.cons.set_contractor:1 -msgid "" -"To set runtime contractor of the tensornetwork for a better contraction " -"path. For more information on the usage of contractor, please refer to " -"independent tutorial." +#: of tensorcircuit.cloud.abstraction.Device.native_gates:1 +msgid "List native gates supported for the device, str conforms qiskit convention" msgstr "" -#: of tensorcircuit.cons.get_contractor:4 tensorcircuit.cons.set_contractor:4 -msgid "" -"\"auto\", \"greedy\", \"branch\", \"plain\", \"tng\", \"custom\", " -"\"custom_stateful\". defaults to None (\"auto\")" +#: of tensorcircuit.cloud.abstraction.Device.topology:1 +msgid "Get the bidirectional topology link list of the device" msgstr "" -#: of tensorcircuit.cons.get_contractor:6 tensorcircuit.cons.set_contractor:6 -msgid "Valid for \"custom\" or \"custom_stateful\" as method, defaults to None" +#: of tensorcircuit.cloud.abstraction.Device.topology_graph:1 +msgid "Get the qubit topology in ``nx.Graph`` or directly visualize it" msgstr "" -#: of tensorcircuit.cons.get_contractor:8 tensorcircuit.cons.set_contractor:8 -msgid "" -"It is not very useful, as ``memory_limit`` leads to ``branch`` " -"contraction instead of ``greedy`` which is rather slow, defaults to None" +#: of tensorcircuit.cloud.abstraction.Device.topology_graph:3 +#: tensorcircuit.vis.render_pdf:23 +msgid "[description], defaults to False" msgstr "" -#: of tensorcircuit.cons.get_contractor:11 tensorcircuit.cons.set_contractor:11 -msgid "Tensornetwork version is too low to support some of the contractors." +#: of tensorcircuit.cloud.abstraction.Provider:1 +msgid "Provider abstraction for cloud connection, eg. \"tencent\", \"local\"" msgstr "" -#: of tensorcircuit.cons.get_contractor:12 tensorcircuit.cons.set_contractor:12 -msgid "Unknown method options." +#: of tensorcircuit.cloud.abstraction.TCException:1 +msgid "Bases: :py:class:`BaseException`" msgstr "" -#: of tensorcircuit.cons.get_contractor:13 tensorcircuit.cons.set_contractor:13 -msgid "The new tensornetwork with its contractor set." +#: of tensorcircuit.cloud.abstraction.TCException.with_traceback:1 +#: tensorcircuit.cloud.abstraction.TaskException.with_traceback:1 +#: tensorcircuit.cloud.abstraction.TaskFailed.with_traceback:1 +#: tensorcircuit.cloud.abstraction.TaskUnfinished.with_traceback:1 +#: tensorcircuit.cloud.utils.HttpStatusError.with_traceback:1 +msgid "" +"Exception.with_traceback(tb) -- set self.__traceback__ to tb and return " +"self." msgstr "" -#: of tensorcircuit.cons.get_dtype:1 tensorcircuit.cons.set_dtype:1 -msgid "Set the global runtime numerical dtype of tensors." +#: of tensorcircuit.cloud.abstraction.Task:1 +msgid "Task abstraction for quantum jobs on the cloud" msgstr "" -#: of tensorcircuit.cons.get_dtype:3 tensorcircuit.cons.set_dtype:3 -msgid "" -"\"complex64\"/\"float32\" or \"complex128\"/\"float64\", defaults to " -"None, which is equivalent to \"complex64\"." +#: of tensorcircuit.cloud.abstraction.Task.details:1 +msgid "Get the current task details" msgstr "" -#: of tensorcircuit.cons.get_dtype:6 tensorcircuit.cons.set_dtype:6 -msgid "complex dtype str and the corresponding real dtype str" +#: of tensorcircuit.cloud.abstraction.Task.details:4 +msgid "whether return until task is finished, defaults to False" msgstr "" -#: of tensorcircuit.cons.plain_contractor:1 -msgid "The naive state-vector simulator contraction path." +#: of tensorcircuit.cloud.abstraction.Task.details:6 +#: tensorcircuit.cloud.abstraction.Task.results:10 +msgid "alias for the argument ``blocked``" msgstr "" -#: of tensorcircuit.cons.plain_contractor:3 -msgid "The list of ``tn.Node``." +#: of tensorcircuit.cloud.abstraction.Task.get_device:1 +msgid "Query which device the task is run on" msgstr "" -#: of tensorcircuit.cons.plain_contractor:5 -msgid "The list of dangling node edges, defaults to be None." +#: of tensorcircuit.cloud.abstraction.Task.resubmit:1 +msgid "resubmit the task" msgstr "" -#: of tensorcircuit.cons.plain_contractor:7 -msgid "The ``tn.Node`` after contraction" +#: of tensorcircuit.cloud.abstraction.Task.resubmit:3 +msgid "the resubmitted task" msgstr "" -#: of tensorcircuit.cons.runtime_backend:1 -msgid "Context manager to set with-level runtime backend" +#: of tensorcircuit.cloud.abstraction.Task.results:1 +msgid "get task results of the qjob" msgstr "" -#: of tensorcircuit.cons.runtime_backend:3 -#: tensorcircuit.cons.set_function_backend:3 -msgid "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\", defaults to None" +#: of tensorcircuit.cloud.abstraction.Task.results:3 +msgid "unsupported now, defaults to None, which is \"count_dict_bin\"" msgstr "" -#: of tensorcircuit.cons.runtime_backend tensorcircuit.cons.runtime_contractor -#: tensorcircuit.cons.runtime_dtype -msgid "yield" +#: of tensorcircuit.cloud.abstraction.Task.results:7 +msgid "" +"whether blocked to wait until the result is returned, defaults to False, " +"which raise error when the task is unfinished" msgstr "" -#: of tensorcircuit.cons.runtime_backend:5 -msgid "the backend object" +#: of tensorcircuit.cloud.abstraction.Task.results:12 +msgid "whether enable readout error mitigation, defaults to False" msgstr "" -#: of tensorcircuit.cons.runtime_contractor:1 -msgid "Context manager to change with-levek contractor" +#: of tensorcircuit.cloud.abstraction.Task.results:14 +msgid "option dict for ``ReadoutMit.cals_from_system``, defaults to None" msgstr "" -#: of tensorcircuit.cons.runtime_dtype:1 -msgid "Context manager to set with-level runtime dtype" +#: of tensorcircuit.cloud.abstraction.Task.results:17 +msgid "" +"if given, directly use the calibriation info on ``readout_mit``, defaults" +" to None" msgstr "" -#: of tensorcircuit.cons.runtime_dtype:3 -msgid "\"complex64\" or \"complex128\", defaults to None (\"complex64\")" +#: of tensorcircuit.cloud.abstraction.Task.results:20 +msgid "option dict for ``ReadoutMit.apply_correction``, defaults to None" msgstr "" -#: of tensorcircuit.cons.runtime_dtype:5 -msgid "complex dtype str and real dtype str" -msgstr "" - -#: of tensorcircuit.cons.set_tensornetwork_backend:1 -msgid "To set the runtime backend of tensorcircuit." +#: of tensorcircuit.cloud.abstraction.Task.results:22 +msgid "count dict results" msgstr "" -#: of tensorcircuit.cons.set_tensornetwork_backend:3 -msgid "" -"Note: ``tc.set_backend`` and ``tc.cons.set_tensornetwork_backend`` are " -"the same." +#: of tensorcircuit.cloud.abstraction.Task.state:1 +msgid "Query the current task status" msgstr "" -#: of tensorcircuit.cons.set_tensornetwork_backend:27 -msgid "" -"\"numpy\", \"tensorflow\", \"jax\", \"pytorch\". defaults to None, which " -"gives the same behavior as " -"``tensornetwork.backend_contextmanager.get_default_backend()``." +#: of tensorcircuit.cloud.abstraction.TaskException:1 +msgid "Bases: :py:class:`~tensorcircuit.cloud.abstraction.TCException`" msgstr "" -#: of tensorcircuit.cons.set_tensornetwork_backend:30 -msgid "Whether the object should be set as global." +#: of tensorcircuit.cloud.abstraction.TaskFailed:1 +#: tensorcircuit.cloud.abstraction.TaskUnfinished:1 +msgid "Bases: :py:class:`~tensorcircuit.cloud.abstraction.TaskException`" msgstr "" -#: of tensorcircuit.cons.set_function_backend:1 -msgid "Function decorator to set function-level runtime backend" +#: ../../source/api/cloud/apis.rst:2 +msgid "tensorcircuit.cloud.apis" msgstr "" -#: of tensorcircuit.cons.set_function_backend:5 -msgid "Decorated function" +#: of tensorcircuit.cloud.apis:1 +msgid "main entrypoints of cloud module" msgstr "" -#: of tensorcircuit.cons.set_function_contractor:1 -msgid "Function decorate to change function-level contractor" +#: of tensorcircuit.cloud.apis.get_device:1 +#: tensorcircuit.cloud.apis.set_device:1 +msgid "set the default device" msgstr "" -#: of tensorcircuit.cons.set_function_dtype:1 -msgid "Function decorator to set function-level numerical dtype" +#: of tensorcircuit.cloud.apis.get_device:3 +#: tensorcircuit.cloud.apis.set_device:3 +msgid "provider of the device, defaults to None" msgstr "" -#: of tensorcircuit.cons.set_function_dtype:3 -msgid "\"complex64\" or \"complex128\", defaults to None" +#: of tensorcircuit.cloud.apis.get_device:5 +#: tensorcircuit.cloud.apis.set_device:5 +msgid "the device, defaults to None" msgstr "" -#: of tensorcircuit.cons.set_function_dtype:5 -msgid "The decorated function" +#: of tensorcircuit.cloud.apis.get_device:7 +#: tensorcircuit.cloud.apis.set_device:7 +msgid "" +"whether set, defaults to True, if False, equivalent to ``get_device``, " +"defaults to True" msgstr "" -#: of tensorcircuit.cons.split_rules:1 -msgid "Obtain the direcionary of truncation rules" +#: of tensorcircuit.cloud.apis.get_provider:1 +#: tensorcircuit.cloud.apis.set_provider:1 +msgid "set default provider for the program" msgstr "" -#: of tensorcircuit.cons.split_rules:3 -#: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:11 -msgid "The maximum number of singular values to keep." +#: of tensorcircuit.cloud.apis.get_provider:5 +#: tensorcircuit.cloud.apis.set_provider:5 +msgid "whether set, defaults to True, if False, equivalent to ``get_provider``" msgstr "" -#: of tensorcircuit.cons.split_rules:5 -#: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:13 -msgid "The maximum allowed truncation error." +#: of tensorcircuit.cloud.apis.get_task:1 +msgid "" +"Get ``Task`` object from task string, the binding device can also be " +"provided" msgstr "" -#: ../../source/api/densitymatrix.rst:2 -msgid "tensorcircuit.densitymatrix" +#: of tensorcircuit.cloud.apis.get_task_details:1 +msgid "Get task details dict given task id" msgstr "" -#: of tensorcircuit.densitymatrix:1 -msgid "Quantum circuit class but with density matrix simulator" +#: of tensorcircuit.cloud.apis.get_task_details:7 +msgid "" +"whether make the returned dict more readable and more phythonic, defaults" +" to False" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:1 -msgid "The density matrix simulator based on tensornetwork engine." +#: of tensorcircuit.cloud.apis.get_token:1 +msgid "" +"Get API token setted for given provider or device, if no device token " +"saved, the corresponding provider tken is returned" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:3 -msgid "Number of qubits" +#: of tensorcircuit.cloud.apis.list_devices:1 +msgid "List all devices under a provider" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:5 -msgid "if True, nothing initialized, only for internal use, defaults to False" +#: of tensorcircuit.cloud.apis.list_properties:1 +msgid "List properties of a given device" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:7 -msgid "the state input for the circuit, defaults to None" +#: of tensorcircuit.cloud.apis.list_properties:9 +msgid "Propeties dict" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:9 -msgid "QuVector for a MPS like initial pure state." +#: of tensorcircuit.cloud.apis.list_providers:1 +msgid "list all cloud providers that tensorcircuit supports" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:11 -msgid "the density matrix input for the circuit, defaults to None" +#: of tensorcircuit.cloud.apis.list_tasks:1 +msgid "List tasks based on given filters" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.__init__:13 -msgid "QuOperator for a MPO like initial density matrix." +#: of tensorcircuit.cloud.apis.list_tasks:9 +msgid "list of task object that satisfy these filter criteria" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:1 -msgid "Return the output density matrix of the circuit." +#: of tensorcircuit.cloud.apis.resubmit_task:1 +msgid "Rerun the given task" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:3 -msgid "" -"check whether the final return is a legal density matrix, defaults to " -"False" +#: of tensorcircuit.cloud.apis.set_token:1 +msgid "Set API token for given provider or specifically to given device" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:5 -msgid "whether to reuse previous results, defaults to True" +#: of tensorcircuit.cloud.apis.set_token:3 +msgid "the API token, defaults to None" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:7 -msgid "The output densitymatrix in 2D shape tensor form" +#: of tensorcircuit.cloud.apis.set_token:9 +msgid "whether save on the disk, defaults to True" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.expectation:6 -msgid "whether contract the density matrix in advance, defaults to True" +#: of tensorcircuit.cloud.apis.set_token:11 +msgid "if True, clear all token saved, defaults to False" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator:1 -msgid "" -"Get the representation of the output state in the form of ``QuOperator`` " -"while maintaining the circuit uncomputed" +#: of tensorcircuit.cloud.apis.submit_task:1 +msgid "submit task to the cloud platform, batch submission default enabled" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator:4 -msgid "``QuOperator`` representation of the output state from the circuit" +#: of tensorcircuit.cloud.apis.submit_task:5 +msgid ":py:meth:`tensorcircuit.cloud.tencent.submit_task`" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:1 +#: of tensorcircuit.cloud.apis.submit_task:13 msgid "" -"convert into state simulator (current implementation ignores all noise " -"channels)" +"all necessary keywords arguments for task submission, see detailed API in" +" each provider backend: 1. tencent - " +":py:meth:`tensorcircuit.cloud.tencent.submit_task`" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:4 -msgid "kws to initialize circuit object, defaults to None" +#: of tensorcircuit.cloud.apis.submit_task:17 +msgid "The task object" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:7 -msgid "Circuit with no noise" +#: ../../source/api/cloud/config.rst:2 +msgid "tensorcircuit.cloud.config" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.wavefunction:1 -msgid "" -"get the wavefunction of outputs, raise error if the final state is not " -"purified [Experimental: the phase factor is not fixed for different " -"backend]" +#: ../../source/api/cloud/local.rst:2 +msgid "tensorcircuit.cloud.local" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit.wavefunction:5 -msgid "wavefunction vector" +#: of tensorcircuit.cloud.local:1 +msgid "Cloud provider from local machine" msgstr "" -#: of tensorcircuit.densitymatrix.DMCircuit2:1 -msgid "Bases: :py:class:`tensorcircuit.densitymatrix.DMCircuit`" +#: ../../source/api/cloud/quafu_provider.rst:2 +msgid "tensorcircuit.cloud.quafu_provider" msgstr "" -#: ../../source/api/experimental.rst:2 -msgid "tensorcircuit.experimental" +#: ../../source/api/cloud/tencent.rst:2 +msgid "tensorcircuit.cloud.tencent" msgstr "" -#: of tensorcircuit.experimental:1 -msgid "Experimental features" +#: of tensorcircuit.cloud.tencent:1 +msgid "Cloud provider from Tencent" msgstr "" -#: of tensorcircuit.experimental.hamiltonian_evol:1 +#: of tensorcircuit.cloud.tencent.submit_task:1 msgid "" -"Fast implementation of static full Hamiltonian evolution (default as " -"imaginary time)" +"Submit task via tencent provider, we suggest to enable one of the " +"compiling functionality: either in tc: frontend or in qos: backend. If " +"both are enabled, try on your own risk, some qubit mapping may fail " +"silently. If the user directly provide ``source`` or qiskit Circuit in " +"``circuit``, the qubit mapping should be taken care of by the users." msgstr "" -#: of tensorcircuit.experimental.hamiltonian_evol:13 -msgid "result dynamics on ``tlist``" +#: of tensorcircuit.cloud.tencent.submit_task:10 +msgid "language choice for ``source``, defaults to \"OPENQASM\"" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:1 -msgid "" -"similar to `grad` function but using parameter shift internally instead " -"of AD, vmap is utilized for evaluation, so the speed is still ok" +#: of tensorcircuit.cloud.tencent.submit_task:12 +msgid "number of measurement shots, defaults to 1024" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:4 -#: tensorcircuit.experimental.parameter_shift_grad_v2:6 -msgid "quantum function with weights in and expectation out" +#: of tensorcircuit.cloud.tencent.submit_task:14 +msgid "submit task protocol version, defaults to \"1\"" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:6 -#: tensorcircuit.experimental.parameter_shift_grad_v2:8 -msgid "label which args should be differentiated, defaults to 0" +#: of tensorcircuit.cloud.tencent.submit_task:16 +msgid "priority for the task queue, defaults to 1" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:9 -#: tensorcircuit.experimental.parameter_shift_grad_v2:11 -msgid "whether jit the original function `f` at the beginning, defaults to False" +#: of tensorcircuit.cloud.tencent.submit_task:18 +msgid "tensorcircuit or qiskit circuit object, defaults to None" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:12 -#: tensorcircuit.experimental.parameter_shift_grad_v2:14 -msgid "" -"two floats for the delta shift on the numerator and dominator, defaults " -"to (pi/2, 2) for parameter shift" +#: of tensorcircuit.cloud.tencent.submit_task:20 +msgid "directly given circuit representation, defaults to None" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad:15 -#: tensorcircuit.experimental.parameter_shift_grad_v2:17 -msgid "the grad function" +#: of tensorcircuit.cloud.tencent.submit_task:22 +msgid "remarks on the task, defaults to None" msgstr "" -#: of tensorcircuit.experimental.parameter_shift_grad_v2:1 -msgid "" -"similar to `grad` function but using parameter shift internally instead " -"of AD, vmap is utilized for evaluation, v2 also supports random generator" -" for finite measurememt shot, only jax backend is supported, since no " -"vmap randomness is available in tensorflow" +#: of tensorcircuit.cloud.tencent.submit_task:24 +msgid "whether compiling in tc via qiskit compiling system, defaults to False" msgstr "" -#: ../../source/api/gates.rst:2 -msgid "tensorcircuit.gates" +#: of tensorcircuit.cloud.tencent.submit_task:27 +msgid "alias for the argument ``compiling``" msgstr "" -#: of tensorcircuit.gates:1 -msgid "" -"Declarations of single-qubit and two-qubit gates and their corresponding " -"matrix." +#: of tensorcircuit.cloud.tencent.submit_task:29 +msgid "compiling options for qiskit ``transpile`` method, defaults to None" msgstr "" -#: of tensorcircuit.gates.Gate:1 -msgid "Bases: :py:class:`tensornetwork.network_components.Node`" +#: of tensorcircuit.cloud.tencent.submit_task:32 +msgid "alias for the argument ``compiled_options``" msgstr "" -#: of tensorcircuit.gates.Gate:1 -msgid "Wrapper of tn.Node, quantum gate" +#: of tensorcircuit.cloud.tencent.submit_task:34 +msgid "whether to insert swap if necessary in qos, defaults to True" msgstr "" -#: of tensornetwork.network_components.Node.__init__:1 -msgid "Create a node." +#: of tensorcircuit.cloud.tencent.submit_task:36 +msgid "whether to compile the gate in qos, defaults to True" msgstr "" -#: of tensornetwork.network_components.Node.__init__:3 -msgid "" -"The concrete that is represented by this node, or a `AbstractNode` " -"object. If a tensor is passed, it can be be either a numpy array or the " -"tensor-type of the used backend. If a `AbstractNode` is passed, the " -"passed node has to have the same backend as given by `backend`." +#: of tensorcircuit.cloud.tencent.submit_task:38 +msgid "whether to run an initial qubit mapping in qos, defaults to False" msgstr "" -#: of tensornetwork.network_components.Node.__init__:7 -msgid "Name of the node. Used primarily for debugging." +#: of tensorcircuit.cloud.tencent.submit_task:41 +msgid "" +"when dry run, only compiled circuit is returned (no real circuit " +"execution), defaults to False" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_axis_names:3 -#: tensornetwork.network_components.Node.__init__:8 -msgid "List of names for each of the tensor's axes." +#: of tensorcircuit.cloud.tencent.submit_task:44 +msgid "Task object or List of Task for batch submission" msgstr "" -#: of tensornetwork.network_components.Node.__init__:9 -msgid "The name of the backend or an instance of a `AbstractBackend`." +#: ../../source/api/cloud/utils.rst:2 +msgid "tensorcircuit.cloud.utils" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_axis_names:5 -#: tensornetwork.network_components.Node.__init__:11 -msgid "" -"If there is a repeated name in `axis_names` or if the length doesn't " -"match the shape of the tensor." +#: of tensorcircuit.cloud.utils:1 +msgid "utility functions for cloud connection" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_axis_names:1 -msgid "Add axis names to a Node." +#: of tensorcircuit.cloud.utils.HttpStatusError:1 +msgid "Bases: :py:class:`Exception`" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_edge:1 -msgid "Add an edge to the node on the given axis." +#: of tensorcircuit.cloud.utils.HttpStatusError:1 +msgid "Used when the return request has http code beyond 200" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_edge:3 -msgid "The edge to add." +#: of tensorcircuit.cloud.utils.set_proxy:1 +msgid "" +"str. format as \"http://user:passwd@host:port\" user passwd part can be " +"omitted if not set. None for turning off the proxy." msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_edge:4 -msgid "The axis the edge points to." +#: ../../source/api/cloud/wrapper.rst:2 +msgid "tensorcircuit.cloud.wrapper" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_edge:5 -msgid "If true, replace the existing edge with the new one." +#: of tensorcircuit.cloud.wrapper:1 +msgid "higher level wrapper shortcut for submit_task" msgstr "" -#: of tensornetwork.network_components.AbstractNode.add_edge:7 -msgid "If the edge on axis is not dangling." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:1 +msgid "" +"Unified interface to compute the Pauli string expectation lists or sums " +"via simulation or on real qpu. Error mitigation, circuit compilation and " +"Pauli string grouping are all built-in." msgstr "" -#: of tensornetwork.network_components.Node.from_serial_dict:1 -msgid "Return a node given a serialized dict representing it." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:4 +msgid "" +"One line access to unlock the whole power or real quantum hardware on " +"quantum cloud." msgstr "" -#: of tensornetwork.network_components.Node.from_serial_dict:3 -msgid "A python dict representing a serialized node." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:18 +msgid "The target circuit to compute expectation" msgstr "" -#: of tensornetwork.network_components.Node.from_serial_dict:5 -msgid "A node." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:20 +msgid "" +"List of Pauli string list, eg. [[0, 1, 0], [2, 3, 3]] represents [X1, " +"Y0Z1Z2]." msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_all_dangling:1 -msgid "Return the set of dangling edges connected to this node." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:22 +msgid "" +"The device str or object for quantum cloud module, defaults to None, None" +" is for analytical exact simulation" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_all_nondangling:1 -msgid "Return the set of nondangling edges connected to this node." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:25 +msgid "" +"List of float to indicate the final return is the weighted sum of Pauli " +"string expectations, e.g. [2., -0.3] represents the final results is 2* " +"``pss`` [0]-0.3* ``pss`` [1] defaults to None, None indicate the list of " +"expectations for ``pss`` are all returned" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_axis_number:1 -msgid "Get the axis number for a given axis name or value." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:29 +msgid "measurement shots for each expectation estimation, defaults to 8192" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_dimension:1 -msgid "Get the dimension of the given axis." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:31 +msgid "whether enable readout error mitigation for the result, defaults to True" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_dimension:3 -msgid "The axis of the underlying tensor." +#: of tensorcircuit.cloud.wrapper.batch_expectation_ps:33 +msgid "" +"List of Pauli string expectation or a weighted sum float for Pauli " +"strings, depending on ``ws``" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_dimension:5 -msgid "The dimension of the given axis." +#: of tensorcircuit.cloud.wrapper.sample_expectation_ps:1 +msgid "" +"Deprecated, please use " +":py:meth:`tensorcircuit.cloud.wrapper.batch_expectation_ps`." msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_dimension:7 -msgid "if axis isn't an int or if axis is too large or small." +#: ../../source/api/compiler.rst:2 +msgid "tensorcircuit.compiler" msgstr "" -#: of tensornetwork.network_components.AbstractNode.get_rank:1 -msgid "Return rank of tensor represented by self." +#: ../../source/api/compiler/composed_compiler.rst:2 +msgid "tensorcircuit.compiler.composed_compiler" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_axes:1 -msgid "Reorder axes of the node's tensor." +#: of tensorcircuit.compiler.composed_compiler:1 +msgid "object oriented compiler pipeline" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_axes:3 -msgid "This will also update all of the node's edges." +#: of tensorcircuit.compiler.composed_compiler.DefaultCompiler:1 +msgid "Bases: :py:class:`~tensorcircuit.compiler.composed_compiler.Compiler`" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_axes:5 -msgid "Permutation of the dimensions of the node's tensor." +#: of tensorcircuit.compiler.composed_compiler.DefaultCompiler.__init__:1 +msgid "" +"A fallback choice to compile circuit running on tencent quantum cloud " +"with rz as native gate" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_axes:7 -#: tensornetwork.network_components.AbstractNode.reorder_edges:9 -msgid "This node post reordering." +#: of tensorcircuit.compiler.composed_compiler.DefaultCompiler.__init__:3 +msgid "" +"qiskit compiled options to be added options documented in " +"`qiskit.transpile` method, to use tencent quantum cloud, " +"`{\"coupling_map\": d.topology()}` is in general enough, where d is a " +"device object, defaults to None, i.e. no qubit mapping is applied" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_axes:9 -#: tensornetwork.network_components.AbstractNode.reorder_edges:12 -msgid "If the Node has no tensor." +#: ../../source/api/compiler/qiskit_compiler.rst:2 +msgid "tensorcircuit.compiler.qiskit_compiler" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_edges:1 -msgid "Reorder the edges for this given Node." +#: of tensorcircuit.compiler.qiskit_compiler:1 +msgid "compiler interface via qiskit" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_edges:3 +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:1 msgid "" -"This will reorder the node's edges and transpose the underlying tensor " -"accordingly." +"compile the circuit using ``qiskit.transpile`` method with some tricks " +"and hacks" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_edges:6 -msgid "List of edges. The order in the list determines the new edge ordering." +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:3 +msgid "circuit in ``tc.Circuit`` or ``qiskit.QuantumCircuit`` form" msgstr "" -#: of tensornetwork.network_components.AbstractNode.reorder_edges:11 -msgid "" -"If either the list of edges is not the same as expected or if you try" -" to reorder with a trace edge." +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:5 +msgid "info for qubit mappings, defaults to None" msgstr "" -#: of tensornetwork.network_components.Node.to_serial_dict:1 -msgid "Return a serializable dict representing the node." +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:7 +msgid "output circuit format, defaults to \"tc\"" msgstr "" -#: of tensornetwork.network_components.Node.to_serial_dict:3 -msgid "Returns: A dict object." +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:9 +msgid "``qiskit.transpile`` options in a dict, defaults to None" msgstr "" -#: of tensorcircuit.gates.GateVF:1 -msgid "Bases: :py:class:`tensorcircuit.gates.GateF`" +#: of tensorcircuit.compiler.qiskit_compiler.qiskit_compile:11 +msgid "Tuple containing the output circuit and the qubit mapping info dict" msgstr "" -#: of tensorcircuit.gates.any_gate:1 -msgid "Note one should provide the gate with properly reshaped." +#: ../../source/api/compiler/simple_compiler.rst:2 +msgid "tensorcircuit.compiler.simple_compiler" msgstr "" -#: of tensorcircuit.gates.any_gate:3 -msgid "corresponding gate" +#: of tensorcircuit.compiler.simple_compiler:1 +msgid "Very simple transformations that qiskit may even fail or hard to control" msgstr "" -#: of tensorcircuit.gates.any_gate:5 -msgid "The name of the gate." +#: ../../source/api/cons.rst:2 +msgid "tensorcircuit.cons" msgstr "" -#: of tensorcircuit.gates.any_gate:7 -msgid "the resulted gate" +#: of tensorcircuit.cons:1 +msgid "Constants and setups" msgstr "" -#: of tensorcircuit.gates.num_to_tensor:1 -msgid "Convert the inputs to Tensor with specified dtype." +#: of tensorcircuit.cons.get_contractor:1 tensorcircuit.cons.set_contractor:1 +msgid "" +"To set runtime contractor of the tensornetwork for a better contraction " +"path. For more information on the usage of contractor, please refer to " +"independent tutorial." msgstr "" -#: of tensorcircuit.gates.num_to_tensor:35 -msgid "inputs" +#: of tensorcircuit.cons.get_contractor:4 tensorcircuit.cons.set_contractor:4 +msgid "" +"\"auto\", \"greedy\", \"branch\", \"plain\", \"tng\", \"custom\", " +"\"custom_stateful\". defaults to None (\"auto\")" msgstr "" -#: of tensorcircuit.gates.num_to_tensor:37 -msgid "dtype of the output Tensors" +#: of tensorcircuit.cons.get_contractor:6 tensorcircuit.cons.set_contractor:6 +msgid "Valid for \"custom\" or \"custom_stateful\" as method, defaults to None" msgstr "" -#: of tensorcircuit.gates.num_to_tensor:39 -msgid "List of Tensors" +#: of tensorcircuit.cons.get_contractor:8 tensorcircuit.cons.set_contractor:8 +msgid "" +"It is not very useful, as ``memory_limit`` leads to ``branch`` " +"contraction instead of ``greedy`` which is rather slow, defaults to None" msgstr "" -#: of tensorcircuit.gates.bmatrix:1 -msgid "Returns a :math:`\\LaTeX` bmatrix." +#: of tensorcircuit.cons.get_contractor:11 tensorcircuit.cons.set_contractor:11 +msgid "Tensornetwork version is too low to support some of the contractors." msgstr "" -#: of tensorcircuit.gates.bmatrix:13 -msgid "Formatted Display:" +#: of tensorcircuit.cons.get_contractor:12 tensorcircuit.cons.set_contractor:12 +msgid "Unknown method options." msgstr "" -#: of tensorcircuit.gates.bmatrix:15 +#: of tensorcircuit.cons.get_contractor:13 tensorcircuit.cons.set_contractor:13 +msgid "The new tensornetwork with its contractor set." +msgstr "" + +#: of tensorcircuit.cons.get_dtype:1 tensorcircuit.cons.set_dtype:1 +msgid "Set the global runtime numerical dtype of tensors." +msgstr "" + +#: of tensorcircuit.cons.get_dtype:3 tensorcircuit.cons.set_dtype:3 msgid "" -"\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j \\end{bmatrix}" -"\n" -"\n" +"\"complex64\"/\"float32\" or \"complex128\"/\"float64\", defaults to " +"None, which is equivalent to \"complex64\"." msgstr "" -#: of tensorcircuit.gates.bmatrix:18 -msgid "2D numpy array" +#: of tensorcircuit.cons.get_dtype:6 tensorcircuit.cons.set_dtype:6 +msgid "complex dtype str and the corresponding real dtype str" msgstr "" -#: of tensorcircuit.gates.bmatrix:20 -msgid "ValueError(\"bmatrix can at most display two dimensions\")" +#: of tensorcircuit.cons.plain_contractor:1 +msgid "The naive state-vector simulator contraction path." msgstr "" -#: of tensorcircuit.gates.bmatrix:21 -msgid ":math:`\\LaTeX`-formatted string for bmatrix of the array a" +#: of tensorcircuit.cons.plain_contractor:3 +msgid "The list of ``tn.Node``." msgstr "" -#: of tensorcircuit.gates.cr_gate:1 -msgid "" -"Controlled rotation gate. When the control qubit is 1, `rgate` is applied" -" to the target qubit." +#: of tensorcircuit.cons.plain_contractor:5 +msgid "The list of dangling node edges, defaults to be None." msgstr "" -#: of tensorcircuit.gates.cr_gate:3 tensorcircuit.gates.cr_gate:5 -#: tensorcircuit.gates.cr_gate:7 tensorcircuit.gates.exponential_gate:12 -#: tensorcircuit.gates.exponential_gate_unity:13 -#: tensorcircuit.gates.iswap_gate:12 tensorcircuit.gates.r_gate:9 -#: tensorcircuit.gates.r_gate:11 tensorcircuit.gates.r_gate:13 -#: tensorcircuit.gates.rgate_theoretical:8 -#: tensorcircuit.gates.rgate_theoretical:10 -#: tensorcircuit.gates.rgate_theoretical:12 tensorcircuit.gates.rx_gate:6 -#: tensorcircuit.gates.rxx_gate:13 tensorcircuit.gates.ry_gate:6 -#: tensorcircuit.gates.ryy_gate:13 tensorcircuit.gates.rz_gate:6 -#: tensorcircuit.gates.rzz_gate:13 -msgid "angle in radians" +#: of tensorcircuit.cons.plain_contractor:7 +msgid "The ``tn.Node`` after contraction" msgstr "" -#: of tensorcircuit.gates.cr_gate:10 -msgid "CR Gate" +#: of tensorcircuit.cons.runtime_backend:1 +msgid "Context manager to set with-level runtime backend" msgstr "" -#: of tensorcircuit.gates.exponential_gate_unity:1 -#: tensorcircuit.gates.rxx_gate:1 tensorcircuit.gates.ryy_gate:1 -#: tensorcircuit.gates.rzz_gate:1 -msgid "" -"Faster exponential gate directly implemented based on RHS. Only works " -"when :math:`U^2 = I` is an identity matrix." +#: of tensorcircuit.cons.runtime_backend:3 +#: tensorcircuit.cons.set_function_backend:3 +msgid "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\", defaults to None" msgstr "" -#: of tensorcircuit.gates.exponential_gate_unity:3 -#: tensorcircuit.gates.rxx_gate:3 tensorcircuit.gates.ryy_gate:3 -#: tensorcircuit.gates.rzz_gate:3 -msgid "" -"\\textrm{exp}(U) &= e^{-j \\theta U} \\\\\n" -" &= \\cos(\\theta) I - j \\sin(\\theta) U \\\\\n" -"\n" +#: of tensorcircuit.cons.runtime_backend tensorcircuit.cons.runtime_contractor +#: tensorcircuit.cons.runtime_dtype +msgid "yield" msgstr "" -#: of tensorcircuit.gates.exponential_gate:6 -#: tensorcircuit.gates.exponential_gate_unity:7 -#: tensorcircuit.gates.multicontrol_gate:7 tensorcircuit.gates.rxx_gate:7 -#: tensorcircuit.gates.ryy_gate:7 tensorcircuit.gates.rzz_gate:7 -msgid "input unitary :math:`U`" +#: of tensorcircuit.cons.runtime_backend:5 +msgid "the backend object" msgstr "" -#: of tensorcircuit.gates.exponential_gate:8 -#: tensorcircuit.gates.exponential_gate:10 -#: tensorcircuit.gates.exponential_gate_unity:9 -#: tensorcircuit.gates.exponential_gate_unity:11 tensorcircuit.gates.rxx_gate:9 -#: tensorcircuit.gates.rxx_gate:11 tensorcircuit.gates.ryy_gate:9 -#: tensorcircuit.gates.ryy_gate:11 tensorcircuit.gates.rzz_gate:9 -#: tensorcircuit.gates.rzz_gate:11 -msgid "alias for the argument ``unitary``" +#: of tensorcircuit.cons.runtime_contractor:1 +msgid "Context manager to change with-levek contractor" msgstr "" -#: of tensorcircuit.gates.exponential_gate_unity:15 -#: tensorcircuit.gates.rxx_gate:15 tensorcircuit.gates.ryy_gate:15 -#: tensorcircuit.gates.rzz_gate:15 -msgid "if True, the angel theta is mutiplied by 1/2, defaults to False" +#: of tensorcircuit.cons.runtime_dtype:1 +msgid "Context manager to set with-level runtime dtype" msgstr "" -#: of tensorcircuit.gates.exponential_gate:14 -#: tensorcircuit.gates.exponential_gate_unity:18 -#: tensorcircuit.gates.rxx_gate:18 tensorcircuit.gates.ryy_gate:18 -#: tensorcircuit.gates.rzz_gate:18 -msgid "suffix of Gate name" +#: of tensorcircuit.cons.runtime_dtype:3 +msgid "\"complex64\" or \"complex128\", defaults to None (\"complex64\")" msgstr "" -#: of tensorcircuit.gates.exponential_gate:15 -#: tensorcircuit.gates.exponential_gate_unity:20 -#: tensorcircuit.gates.rxx_gate:20 tensorcircuit.gates.ryy_gate:20 -#: tensorcircuit.gates.rzz_gate:20 -msgid "Exponential Gate" +#: of tensorcircuit.cons.runtime_dtype:5 +msgid "complex dtype str and real dtype str" msgstr "" -#: of tensorcircuit.gates.exponential_gate:1 -msgid "Exponential gate." +#: of tensorcircuit.cons.set_tensornetwork_backend:1 +msgid "To set the runtime backend of tensorcircuit." msgstr "" -#: of tensorcircuit.gates.exponential_gate:3 +#: of tensorcircuit.cons.set_tensornetwork_backend:3 msgid "" -"\\textrm{exp}(U) = e^{-j \\theta U}\n" -"\n" +"Note: ``tc.set_backend`` and ``tc.cons.set_tensornetwork_backend`` are " +"the same." msgstr "" -#: of tensorcircuit.gates.get_u_parameter:1 -msgid "From the single qubit unitary to infer three angles of IBMUgate," +#: of tensorcircuit.cons.set_tensornetwork_backend:27 +msgid "" +"\"numpy\", \"tensorflow\", \"jax\", \"pytorch\". defaults to None, which " +"gives the same behavior as " +"``tensornetwork.backend_contextmanager.get_default_backend()``." msgstr "" -#: of tensorcircuit.gates.get_u_parameter:3 -msgid "numpy array, no backend agnostic version for now" +#: of tensorcircuit.cons.set_tensornetwork_backend:30 +msgid "Whether the object should be set as global." msgstr "" -#: of tensorcircuit.gates.get_u_parameter:5 -msgid "theta, phi, lbd" +#: of tensorcircuit.cons.set_function_backend:1 +msgid "Function decorator to set function-level runtime backend" msgstr "" -#: of tensorcircuit.gates.iswap_gate:1 -msgid "iSwap gate." +#: of tensorcircuit.cons.set_function_backend:5 +msgid "Decorated function" msgstr "" -#: of tensorcircuit.gates.iswap_gate:3 -msgid "" -"\\textrm{iSwap}(\\theta) =\n" -"\\begin{pmatrix}\n" -" 1 & 0 & 0 & 0\\\\\n" -" 0 & \\cos(\\frac{\\pi}{2} \\theta ) & j \\sin(\\frac{\\pi}{2} \\theta" -" ) & 0\\\\\n" -" 0 & j \\sin(\\frac{\\pi}{2} \\theta ) & \\cos(\\frac{\\pi}{2} \\theta" -" ) & 0\\\\\n" -" 0 & 0 & 0 & 1\\\\\n" -"\\end{pmatrix}\n" -"\n" +#: of tensorcircuit.cons.set_function_contractor:1 +msgid "Function decorate to change function-level contractor" msgstr "" -#: of tensorcircuit.gates.iswap_gate:14 -msgid "iSwap Gate" +#: of tensorcircuit.cons.set_function_dtype:1 +msgid "Function decorator to set function-level numerical dtype" msgstr "" -#: of tensorcircuit.gates.matrix_for_gate:1 -msgid "Convert Gate to numpy array." +#: of tensorcircuit.cons.set_function_dtype:3 +msgid "\"complex64\" or \"complex128\", defaults to None" msgstr "" -#: of tensorcircuit.gates.matrix_for_gate:10 -msgid "input Gate" +#: of tensorcircuit.cons.set_function_dtype:5 +msgid "The decorated function" msgstr "" -#: of tensorcircuit.gates.matrix_for_gate:12 -msgid "Corresponding Tensor" +#: of tensorcircuit.cons.split_rules:1 +msgid "Obtain the direcionary of truncation rules" msgstr "" -#: of tensorcircuit.gates.meta_gate:1 -msgid "" -"Inner helper function to generate gate functions, such as ``z()`` from " -"``_z_matrix``" +#: of tensorcircuit.cons.split_rules:3 +#: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:11 +msgid "The maximum number of singular values to keep." msgstr "" -#: of tensorcircuit.gates.multicontrol_gate:1 -msgid "" -"Multicontrol gate. If the control qubits equal to ``ctrl``, :math:`U` is " -"applied to the target qubits." +#: of tensorcircuit.cons.split_rules:5 +#: tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:13 +msgid "The maximum allowed truncation error." msgstr "" -#: of tensorcircuit.gates.multicontrol_gate:5 -msgid "" -"E.g., ``multicontrol_gate(tc.gates._zz_matrix, [1, 0, 1])`` returns a " -"gate of 5 qubits," +#: ../../source/api/densitymatrix.rst:2 +msgid "tensorcircuit.densitymatrix" msgstr "" -#: of tensorcircuit.gates.multicontrol_gate:4 -msgid "" -"where the last 2 qubits are applied :math:`ZZ` gate, if the first 3 " -"qubits are :math:`\\ket{101}`." +#: of tensorcircuit.densitymatrix:1 +msgid "Quantum circuit class but with density matrix simulator" msgstr "" -#: of tensorcircuit.gates.multicontrol_gate:9 -msgid "control bit sequence" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:1 +msgid "The density matrix simulator based on tensornetwork engine." msgstr "" -#: of tensorcircuit.gates.multicontrol_gate:11 -msgid "Multicontrol Gate" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:3 +msgid "Number of qubits" msgstr "" -#: of tensorcircuit.gates.phase_gate:1 -msgid "The phase gate" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:5 +msgid "if True, nothing initialized, only for internal use, defaults to False" msgstr "" -#: of tensorcircuit.gates.phase_gate:3 -msgid "" -"\\textrm{phase}(\\theta) =\n" -"\\begin{pmatrix}\n" -" 1 & 0 \\\\\n" -" 0 & e^{i\\theta} \\\\\n" -"\\end{pmatrix}\n" -"\n" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:7 +msgid "the state input for the circuit, defaults to None" msgstr "" -#: of tensorcircuit.gates.phase_gate:10 -msgid "angle in radians, defaults to 0" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:9 +msgid "QuVector for a MPS like initial pure state." msgstr "" -#: of tensorcircuit.gates.phase_gate:12 -msgid "phase gate" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:11 +msgid "the density matrix input for the circuit, defaults to None" msgstr "" -#: of tensorcircuit.gates.r_gate:1 -msgid "General single qubit rotation gate" +#: of tensorcircuit.densitymatrix.DMCircuit.__init__:13 +msgid "QuOperator for a MPO like initial density matrix." msgstr "" -#: of tensorcircuit.gates.r_gate:3 +#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:1 +msgid "Return the output density matrix of the circuit." +msgstr "" + +#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:3 msgid "" -"R(\\theta, \\alpha, \\phi) = j \\cos(\\theta) I\n" -"- j \\cos(\\phi) \\sin(\\alpha) \\sin(\\theta) X\n" -"- j \\sin(\\phi) \\sin(\\alpha) \\sin(\\theta) Y\n" -"- j \\sin(\\theta) \\cos(\\alpha) Z\n" -"\n" -msgstr "" - -#: of tensorcircuit.gates.r_gate:16 -msgid "R Gate" +"check whether the final return is a legal density matrix, defaults to " +"False" msgstr "" -#: of tensorcircuit.gates.random_single_qubit_gate:1 -msgid "Random single qubit gate described in https://arxiv.org/abs/2002.07730." +#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:5 +msgid "whether to reuse previous results, defaults to True" msgstr "" -#: of tensorcircuit.gates.random_single_qubit_gate:3 -msgid "A random single-qubit gate" +#: of tensorcircuit.densitymatrix.DMCircuit.densitymatrix:7 +msgid "The output densitymatrix in 2D shape tensor form" msgstr "" -#: of tensorcircuit.gates.random_two_qubit_gate:1 -msgid "Returns a random two-qubit gate." +#: of tensorcircuit.densitymatrix.DMCircuit.expectation:6 +msgid "whether contract the density matrix in advance, defaults to True" msgstr "" -#: of tensorcircuit.gates.random_two_qubit_gate:3 -msgid "A random two-qubit gate" +#: of tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator:1 +msgid "" +"Get the representation of the output state in the form of ``QuOperator`` " +"while maintaining the circuit uncomputed" msgstr "" -#: of tensorcircuit.gates.rgate_theoretical:1 -msgid "" -"Rotation gate implemented by matrix exponential. The output is the same " -"as `rgate`." +#: of tensorcircuit.densitymatrix.DMCircuit.get_dm_as_quoperator:4 +msgid "``QuOperator`` representation of the output state from the circuit" msgstr "" -#: of tensorcircuit.gates.rgate_theoretical:3 +#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:1 msgid "" -"R(\\theta, \\alpha, \\phi) = e^{-j \\theta \\left[\\sin(\\alpha) " -"\\cos(\\phi) X\n" -" + \\sin(\\alpha) \\sin(\\phi) " -"Y\n" -" + \\cos(\\alpha) Z\\right]}\n" -"\n" +"convert into state simulator (current implementation ignores all noise " +"channels)" msgstr "" -#: of tensorcircuit.gates.rgate_theoretical:14 -msgid "Rotation Gate" +#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:4 +msgid "kws to initialize circuit object, defaults to None" msgstr "" -#: of tensorcircuit.gates.rx_gate:1 -msgid "Rotation gate along :math:`x` axis." +#: of tensorcircuit.densitymatrix.DMCircuit.to_circuit:7 +msgid "Circuit with no noise" msgstr "" -#: of tensorcircuit.gates.rx_gate:3 +#: of tensorcircuit.densitymatrix.DMCircuit.wavefunction:1 msgid "" -"RX(\\theta) = e^{-j\\frac{\\theta}{2}X}\n" -"\n" +"get the wavefunction of outputs, raise error if the final state is not " +"purified [Experimental: the phase factor is not fixed for different " +"backend]" msgstr "" -#: of tensorcircuit.gates.rx_gate:8 -msgid "RX Gate" +#: of tensorcircuit.densitymatrix.DMCircuit.wavefunction:5 +msgid "wavefunction vector" msgstr "" -#: of tensorcircuit.gates.ry_gate:1 -msgid "Rotation gate along :math:`y` axis." +#: of tensorcircuit.densitymatrix.DMCircuit2:1 +msgid "Bases: :py:class:`~tensorcircuit.densitymatrix.DMCircuit`" msgstr "" -#: of tensorcircuit.gates.ry_gate:3 -msgid "" -"RY(\\theta) = e^{-j\\frac{\\theta}{2}Y}\n" -"\n" +#: ../../source/api/experimental.rst:2 +msgid "tensorcircuit.experimental" msgstr "" -#: of tensorcircuit.gates.ry_gate:8 -msgid "RY Gate" +#: of tensorcircuit.experimental:1 +msgid "Experimental features" msgstr "" -#: of tensorcircuit.gates.rz_gate:1 -msgid "Rotation gate along :math:`z` axis." +#: of tensorcircuit.experimental.evol_global:1 +msgid "" +"ode evolution of time dependent Hamiltonian on circuit of all qubits " +"[only jax backend support for now]" msgstr "" -#: of tensorcircuit.gates.rz_gate:3 +#: of tensorcircuit.experimental.evol_global:6 msgid "" -"RZ(\\theta) = e^{-j\\frac{\\theta}{2}Z}\n" -"\n" +"h_fun should return a **SPARSE** Hamiltonian matrix with input arguments " +"time and *args" msgstr "" -#: of tensorcircuit.gates.rz_gate:8 -msgid "RZ Gate" +#: of tensorcircuit.experimental.evol_local:1 +msgid "" +"ode evolution of time dependent Hamiltonian on circuit of given indices " +"[only jax backend support for now]" msgstr "" -#: of tensorcircuit.gates.u_gate:1 +#: of tensorcircuit.experimental.evol_local:8 msgid "" -"IBMQ U gate following the converntion of OpenQASM3.0. See `OpenQASM doc " -"`_" +"h_fun should return a dense Hamiltonian matrix with input arguments time " +"and *args" msgstr "" -#: of tensorcircuit.gates.u_gate:4 +#: of tensorcircuit.experimental.evol_local:11 +msgid "evolution time" +msgstr "" + +#: of tensorcircuit.experimental.hamiltonian_evol:1 msgid "" -"\\begin{split}U(\\theta,\\phi,\\lambda) := \\left(\\begin{array}{cc}\n" -"\\cos(\\theta/2) & -e^{i\\lambda}\\sin(\\theta/2) \\\\\n" -"e^{i\\phi}\\sin(\\theta/2) & e^{i(\\phi+\\lambda)}\\cos(\\theta/2) " -"\\end{array}\\right).\\end{split}" +"Fast implementation of static full Hamiltonian evolution (default as " +"imaginary time)" msgstr "" -#: of tensorcircuit.gates.u_gate:10 tensorcircuit.gates.u_gate:12 -#: tensorcircuit.gates.u_gate:14 -msgid "_description_, defaults to 0" +#: of tensorcircuit.experimental.hamiltonian_evol:13 +msgid "result dynamics on ``tlist``" msgstr "" -#: ../../source/api/interfaces.rst:2 -msgid "tensorcircuit.interfaces" +#: of tensorcircuit.experimental.parameter_shift_grad:1 +msgid "" +"similar to `grad` function but using parameter shift internally instead " +"of AD, vmap is utilized for evaluation, so the speed is still ok" msgstr "" -#: ../../source/api/interfaces/numpy.rst:2 -msgid "tensorcircuit.interfaces.numpy" +#: of tensorcircuit.experimental.parameter_shift_grad:4 +#: tensorcircuit.experimental.parameter_shift_grad_v2:6 +msgid "quantum function with weights in and expectation out" msgstr "" -#: of tensorcircuit.interfaces.numpy:1 -msgid "Interface wraps quantum function as a numpy function" +#: of tensorcircuit.experimental.parameter_shift_grad:6 +#: tensorcircuit.experimental.parameter_shift_grad_v2:8 +msgid "label which args should be differentiated, defaults to 0" msgstr "" -#: of tensorcircuit.interfaces.numpy.numpy_interface:1 -msgid "Convert ``fun`` on ML backend into a numpy function" +#: of tensorcircuit.experimental.parameter_shift_grad:9 +#: tensorcircuit.experimental.parameter_shift_grad_v2:11 +msgid "whether jit the original function `f` at the beginning, defaults to False" msgstr "" -#: of tensorcircuit.interfaces.numpy.numpy_interface:23 -msgid "The quantum function" +#: of tensorcircuit.experimental.parameter_shift_grad:12 +#: tensorcircuit.experimental.parameter_shift_grad_v2:14 +msgid "" +"two floats for the delta shift on the numerator and dominator, defaults " +"to (pi/2, 2) for parameter shift" msgstr "" -#: of tensorcircuit.interfaces.numpy.numpy_interface:25 -#: tensorcircuit.interfaces.scipy.scipy_optimize_interface:39 -msgid "whether to jit ``fun``, defaults to True" +#: of tensorcircuit.experimental.parameter_shift_grad:15 +#: tensorcircuit.experimental.parameter_shift_grad_v2:17 +msgid "the grad function" msgstr "" -#: of tensorcircuit.interfaces.numpy.numpy_interface:27 -msgid "The numpy interface compatible version of ``fun``" +#: of tensorcircuit.experimental.parameter_shift_grad_v2:1 +msgid "" +"similar to `grad` function but using parameter shift internally instead " +"of AD, vmap is utilized for evaluation, v2 also supports random generator" +" for finite measurememt shot, only jax backend is supported, since no " +"vmap randomness is available in tensorflow" msgstr "" -#: ../../source/api/interfaces/scipy.rst:2 -msgid "tensorcircuit.interfaces.scipy" +#: ../../source/api/gates.rst:2 +msgid "tensorcircuit.gates" msgstr "" -#: of tensorcircuit.interfaces.scipy:1 -msgid "Interface wraps quantum function as a scipy function for optimization" +#: of tensorcircuit.gates:1 +msgid "" +"Declarations of single-qubit and two-qubit gates and their corresponding " +"matrix." msgstr "" -#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:1 -msgid "Convert ``fun`` into a scipy optimize interface compatible version" +#: of tensorcircuit.gates.Gate:1 +msgid "Bases: :py:class:`~tensornetwork.network_components.Node`" msgstr "" -#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:35 -msgid "The quantum function with scalar out that to be optimized" +#: of tensorcircuit.gates.Gate:1 +msgid "Wrapper of tn.Node, quantum gate" msgstr "" -#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:37 -msgid "the shape of parameters that ``fun`` accepts, defaults to None" +#: of tensornetwork.network_components.Node.__init__:1 +msgid "Create a node." msgstr "" -#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:41 +#: of tensornetwork.network_components.Node.__init__:3 msgid "" -"whether using gradient-based or gradient free scipy optimize interface, " -"defaults to True" +"The concrete that is represented by this node, or a `AbstractNode` " +"object. If a tensor is passed, it can be be either a numpy array or the " +"tensor-type of the used backend. If a `AbstractNode` is passed, the " +"passed node has to have the same backend as given by `backend`." msgstr "" -#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:44 -msgid "The scipy interface compatible version of ``fun``" +#: of tensornetwork.network_components.Node.__init__:7 +msgid "Name of the node. Used primarily for debugging." msgstr "" -#: ../../source/api/interfaces/tensorflow.rst:2 -msgid "tensorcircuit.interfaces.tensorflow" +#: of tensornetwork.network_components.AbstractNode.add_axis_names:3 +#: tensornetwork.network_components.Node.__init__:8 +msgid "List of names for each of the tensor's axes." msgstr "" -#: of tensorcircuit.interfaces.tensorflow:1 -msgid "Interface wraps quantum function as a tensorflow function" +#: of tensornetwork.network_components.Node.__init__:9 +msgid "The name of the backend or an instance of a `AbstractBackend`." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:1 +#: of tensornetwork.network_components.AbstractNode.add_axis_names:5 +#: tensornetwork.network_components.Node.__init__:11 msgid "" -"Wrap a quantum function on different ML backend with a tensorflow " -"interface." +"If there is a repeated name in `axis_names` or if the length doesn't " +"match the shape of the tensor." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:22 -#: tensorcircuit.interfaces.torch.torch_interface:28 -msgid "The quantum function with tensor in and tensor out" +#: of tensornetwork.network_components.AbstractNode.add_axis_names:1 +msgid "Add axis names to a Node." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:24 -msgid "output tf dtype or in str" +#: of tensornetwork.network_components.AbstractNode.add_edge:1 +msgid "Add an edge to the node on the given axis." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:26 -#: tensorcircuit.interfaces.torch.torch_interface:30 -msgid "whether to jit ``fun``, defaults to False" +#: of tensornetwork.network_components.AbstractNode.add_edge:3 +msgid "The edge to add." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:28 -#: tensorcircuit.interfaces.torch.torch_interface:32 -msgid "whether transform tensor backend via dlpack, defaults to False" +#: of tensornetwork.network_components.AbstractNode.add_edge:4 +msgid "The axis the edge points to." msgstr "" -#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:30 -#: tensorcircuit.interfaces.torch.torch_interface:34 -msgid "" -"The same quantum function but now with torch tensor in and torch tensor " -"out while AD is also supported" +#: of tensornetwork.network_components.AbstractNode.add_edge:5 +msgid "If true, replace the existing edge with the new one." msgstr "" -#: ../../source/api/interfaces/tensortrans.rst:2 -msgid "tensorcircuit.interfaces.tensortrans" +#: of tensornetwork.network_components.AbstractNode.add_edge:7 +msgid "If the edge on axis is not dangling." msgstr "" -#: of tensorcircuit.interfaces.tensortrans:1 -msgid "general function for interfaces transformation" +#: of tensornetwork.network_components.Node.from_serial_dict:1 +msgid "Return a node given a serialized dict representing it." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:1 -msgid "" -"Function decorator that automatically convert inputs to tensors on " -"current backend" +#: of tensornetwork.network_components.Node.from_serial_dict:3 +msgid "A python dict representing a serialized node." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:63 -msgid "" -"the wrapped function whose arguments in ``argnums`` position are expected" -" to be tensor format" +#: of tensornetwork.network_components.Node.from_serial_dict:5 +msgid "A node." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:66 -msgid "position of args under the auto conversion, defaults to 0" +#: of tensornetwork.network_components.AbstractNode.get_all_dangling:1 +msgid "Return the set of dangling edges connected to this node." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:68 -msgid "" -"try reshape all input tensor as matrix with shape rank 2, defaults to " -"False" +#: of tensornetwork.network_components.AbstractNode.get_all_nondangling:1 +msgid "Return the set of nondangling edges connected to this node." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:71 -msgid "convert ``Gate`` to tensor, defaults to False" +#: of tensornetwork.network_components.AbstractNode.get_axis_number:1 +msgid "Get the axis number for a given axis name or value." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:73 -msgid "reshape tensor from ``Gate`` input as matrix, defaults to True" -msgstr "" - -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:75 -msgid "convert ``QuOperator`` to tensor, defaults to False" +#: of tensornetwork.network_components.AbstractNode.get_dimension:1 +msgid "Get the dimension of the given axis." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:77 -msgid "reshape tensor from ``QuOperator`` input as matrix, defaults to True" +#: of tensornetwork.network_components.AbstractNode.get_dimension:3 +msgid "The axis of the underlying tensor." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:79 -msgid "whether cast to backend dtype, defaults to True" +#: of tensornetwork.network_components.AbstractNode.get_dimension:5 +msgid "The dimension of the given axis." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:81 -msgid "The wrapped function" +#: of tensornetwork.network_components.AbstractNode.get_dimension:7 +msgid "if axis isn't an int or if axis is too large or small." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:1 -msgid "Given a pytree, get the corresponding numpy array pytree" +#: of tensornetwork.network_components.AbstractNode.get_rank:1 +msgid "Return rank of tensor represented by self." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:3 -msgid "pytree" +#: of tensornetwork.network_components.AbstractNode.reorder_axes:1 +msgid "Reorder axes of the node's tensor." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:5 -msgid "the same format pytree with all tensor replaced by numpy array" +#: of tensornetwork.network_components.AbstractNode.reorder_axes:3 +msgid "This will also update all of the node's edges." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:1 -msgid "Given a pytree of numpy arrays, get the corresponding tensor pytree" +#: of tensornetwork.network_components.AbstractNode.reorder_axes:5 +msgid "Permutation of the dimensions of the node's tensor." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:3 -msgid "pytree of numpy arrays" +#: of tensornetwork.network_components.AbstractNode.reorder_axes:7 +#: tensornetwork.network_components.AbstractNode.reorder_edges:9 +msgid "This node post reordering." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:5 -msgid "str of str of the same pytree shape as args, defaults to None" +#: of tensornetwork.network_components.AbstractNode.reorder_axes:9 +#: tensornetwork.network_components.AbstractNode.reorder_edges:12 +msgid "If the Node has no tensor." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:7 -msgid "" -"str or backend object, defaults to None, indicating the current default " -"backend" +#: of tensornetwork.network_components.AbstractNode.reorder_edges:1 +msgid "Reorder the edges for this given Node." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:10 +#: of tensornetwork.network_components.AbstractNode.reorder_edges:3 msgid "" -"the same format pytree with all numpy array replaced by the tensors in " -"the target backend" +"This will reorder the node's edges and transpose the underlying tensor " +"accordingly." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.which_backend:1 -msgid "Given a tensor ``a``, return the corresponding backend" +#: of tensornetwork.network_components.AbstractNode.reorder_edges:6 +msgid "List of edges. The order in the list determines the new edge ordering." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.which_backend:5 +#: of tensornetwork.network_components.AbstractNode.reorder_edges:11 msgid "" -"if true, return backend object, if false, return backend str, defaults to" -" True" +"If either the list of edges is not the same as expected or if you try" +" to reorder with a trace edge." msgstr "" -#: of tensorcircuit.interfaces.tensortrans.which_backend:8 -msgid "the backend object or backend str" +#: of tensornetwork.network_components.Node.to_serial_dict:1 +msgid "Return a serializable dict representing the node." msgstr "" -#: ../../source/api/interfaces/torch.rst:2 -msgid "tensorcircuit.interfaces.torch" +#: of tensornetwork.network_components.Node.to_serial_dict:3 +msgid "Returns: A dict object." msgstr "" -#: of tensorcircuit.interfaces.torch:1 -msgid "Interface wraps quantum function as a torch function" +#: of tensorcircuit.gates.GateVF:1 +msgid "Bases: :py:class:`~tensorcircuit.gates.GateF`" msgstr "" -#: of tensorcircuit.interfaces.torch.torch_interface:1 -msgid "Wrap a quantum function on different ML backend with a pytorch interface." +#: of tensorcircuit.gates.any_gate:1 +msgid "Note one should provide the gate with properly reshaped." msgstr "" -#: ../../source/api/keras.rst:2 -msgid "tensorcircuit.keras" +#: of tensorcircuit.gates.any_gate:3 +msgid "corresponding gate" msgstr "" -#: of tensorcircuit.keras:1 -msgid "Keras layer for tc quantum function" +#: of tensorcircuit.gates.any_gate:5 +msgid "The name of the gate." msgstr "" -#: of tensorcircuit.keras.QuantumLayer.__init__:1 -msgid "" -"`QuantumLayer` wraps the quantum function `f` as a `keras.Layer` so that " -"tensorcircuit is better integrated with tensorflow. Note that the input " -"of the layer can be tensors or even list/dict of tensors." +#: of tensorcircuit.gates.any_gate:7 +msgid "the resulted gate" msgstr "" -#: of tensorcircuit.keras.QuantumLayer.__init__:5 -msgid "Callabel function." +#: of tensorcircuit.gates.num_to_tensor:1 +msgid "Convert the inputs to Tensor with specified dtype." msgstr "" -#: of tensorcircuit.keras.QuantumLayer.__init__:7 -msgid "The shape of the weights." +#: of tensorcircuit.gates.num_to_tensor:35 +msgid "inputs" msgstr "" -#: of tensorcircuit.keras.QuantumLayer.__init__:9 -msgid "The initializer of the weights, defaults to \"glorot_uniform\"" +#: of tensorcircuit.gates.num_to_tensor:37 +msgid "dtype of the output Tensors" msgstr "" -#: of tensorcircuit.keras.load_func:1 -msgid "" -"Load function from the files in the ``tf.savedmodel`` format. We can load" -" several functions at the same time, as they can be the same function of " -"different input shapes." +#: of tensorcircuit.gates.num_to_tensor:39 +msgid "List of Tensors" msgstr "" -#: of tensorcircuit.keras.load_func:24 -msgid "" -"The fallback function when all functions loaded are failed, defaults to " -"None" +#: of tensorcircuit.gates.bmatrix:1 +msgid "Returns a :math:`\\LaTeX` bmatrix." msgstr "" -#: of tensorcircuit.keras.load_func:26 -msgid "" -"When there is not legal loaded function of the input shape and no " -"fallback callable." +#: of tensorcircuit.gates.bmatrix:13 +msgid "Formatted Display:" msgstr "" -#: of tensorcircuit.keras.load_func:27 +#: of tensorcircuit.gates.bmatrix:15 msgid "" -"A function that tries all loaded function against the input until the " -"first success one." +"\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j \\end{bmatrix}" +"\n" +"\n" msgstr "" -#: of tensorcircuit.keras.output_asis_loss:1 -msgid "The keras loss function that directly taking the model output as the loss." +#: of tensorcircuit.gates.bmatrix:18 +msgid "2D numpy array" msgstr "" -#: of tensorcircuit.keras.output_asis_loss:3 -msgid "Ignoring this parameter." +#: of tensorcircuit.gates.bmatrix:20 +msgid "ValueError(\"bmatrix can at most display two dimensions\")" msgstr "" -#: of tensorcircuit.keras.output_asis_loss:5 -msgid "Model output." +#: of tensorcircuit.gates.bmatrix:21 +msgid ":math:`\\LaTeX`-formatted string for bmatrix of the array a" msgstr "" -#: of tensorcircuit.keras.output_asis_loss:7 -msgid "Model output, which is y_pred." +#: of tensorcircuit.gates.cr_gate:1 +msgid "" +"Controlled rotation gate. When the control qubit is 1, `rgate` is applied" +" to the target qubit." msgstr "" -#: of tensorcircuit.keras.save_func:1 -msgid "Save tf function in the file (``tf.savedmodel`` format)." +#: of tensorcircuit.gates.cr_gate:3 tensorcircuit.gates.cr_gate:5 +#: tensorcircuit.gates.cr_gate:7 tensorcircuit.gates.exponential_gate:12 +#: tensorcircuit.gates.exponential_gate_unity:13 +#: tensorcircuit.gates.iswap_gate:12 tensorcircuit.gates.r_gate:9 +#: tensorcircuit.gates.r_gate:11 tensorcircuit.gates.r_gate:13 +#: tensorcircuit.gates.rgate_theoretical:8 +#: tensorcircuit.gates.rgate_theoretical:10 +#: tensorcircuit.gates.rgate_theoretical:12 tensorcircuit.gates.rx_gate:6 +#: tensorcircuit.gates.rxx_gate:13 tensorcircuit.gates.ry_gate:6 +#: tensorcircuit.gates.ryy_gate:13 tensorcircuit.gates.rz_gate:6 +#: tensorcircuit.gates.rzz_gate:13 +msgid "angle in radians" msgstr "" -#: of tensorcircuit.keras.save_func:30 -msgid "``tf.function`` ed function with graph building" +#: of tensorcircuit.gates.cr_gate:10 +msgid "CR Gate" msgstr "" -#: of tensorcircuit.keras.save_func:32 -msgid "the dir path to save the function" +#: of tensorcircuit.gates.exponential_gate_unity:1 +#: tensorcircuit.gates.rxx_gate:1 tensorcircuit.gates.ryy_gate:1 +#: tensorcircuit.gates.rzz_gate:1 +msgid "" +"Faster exponential gate directly implemented based on RHS. Only works " +"when :math:`U^2 = I` is an identity matrix." msgstr "" -#: ../../source/api/mps_base.rst:2 -msgid "tensorcircuit.mps_base" +#: of tensorcircuit.gates.exponential_gate_unity:3 +#: tensorcircuit.gates.rxx_gate:3 tensorcircuit.gates.ryy_gate:3 +#: tensorcircuit.gates.rzz_gate:3 +msgid "" +"\\textrm{exp}(U) &= e^{-j \\theta U} \\\\\n" +" &= \\cos(\\theta) I - j \\sin(\\theta) U \\\\\n" +"\n" msgstr "" -#: of tensorcircuit.mps_base:1 -msgid "FiniteMPS from tensornetwork with bug fixed" +#: of tensorcircuit.gates.exponential_gate:6 +#: tensorcircuit.gates.exponential_gate_unity:7 +#: tensorcircuit.gates.multicontrol_gate:7 tensorcircuit.gates.rxx_gate:7 +#: tensorcircuit.gates.ryy_gate:7 tensorcircuit.gates.rzz_gate:7 +msgid "input unitary :math:`U`" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS:1 -msgid "Bases: :py:class:`tensornetwork.matrixproductstates.finite_mps.FiniteMPS`" +#: of tensorcircuit.gates.exponential_gate:8 +#: tensorcircuit.gates.exponential_gate:10 +#: tensorcircuit.gates.exponential_gate_unity:9 +#: tensorcircuit.gates.exponential_gate_unity:11 tensorcircuit.gates.rxx_gate:9 +#: tensorcircuit.gates.rxx_gate:11 tensorcircuit.gates.ryy_gate:9 +#: tensorcircuit.gates.ryy_gate:11 tensorcircuit.gates.rzz_gate:9 +#: tensorcircuit.gates.rzz_gate:11 +msgid "alias for the argument ``unitary``" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:4 -msgid "Initialize a `FiniteMPS`. If `canonicalize` is `True` the state" +#: of tensorcircuit.gates.exponential_gate_unity:15 +#: tensorcircuit.gates.rxx_gate:15 tensorcircuit.gates.ryy_gate:15 +#: tensorcircuit.gates.rzz_gate:15 +msgid "if True, the angel theta is mutiplied by 1/2, defaults to False" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:2 -msgid "" -"is brought into canonical form, with `BaseMPS.center_position` at " -"`center_position`. if `center_position` is `None` and `canonicalize = " -"True`, `BaseMPS.center_position` is set to 0." +#: of tensorcircuit.gates.exponential_gate:14 +#: tensorcircuit.gates.exponential_gate_unity:18 +#: tensorcircuit.gates.rxx_gate:18 tensorcircuit.gates.ryy_gate:18 +#: tensorcircuit.gates.rzz_gate:18 +msgid "suffix of Gate name" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:6 -msgid "A list of `Tensor` objects." +#: of tensorcircuit.gates.exponential_gate:15 +#: tensorcircuit.gates.exponential_gate_unity:20 +#: tensorcircuit.gates.rxx_gate:20 tensorcircuit.gates.ryy_gate:20 +#: tensorcircuit.gates.rzz_gate:20 +msgid "Exponential Gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:7 -msgid "The initial position of the center site." +#: of tensorcircuit.gates.exponential_gate:1 +msgid "Exponential gate." msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:8 -msgid "If `True` the mps is canonicalized at initialization." +#: of tensorcircuit.gates.exponential_gate:3 +msgid "" +"\\textrm{exp}(U) = e^{-j \\theta U}\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:9 -msgid "" -"The name of the backend that should be used to perform contractions. " -"Available backends are currently 'numpy', 'tensorflow', 'pytorch', 'jax'" +#: of tensorcircuit.gates.get_u_parameter:1 +msgid "From the single qubit unitary to infer three angles of IBMUgate," msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_one_site_gate:1 -msgid "" -"Apply a one-site gate to an MPS. This routine will in general destroy any" -" canonical form of the state. If a canonical form is needed, the user can" -" restore it using `FiniteMPS.position` :param gate: a one-body gate " -":param site: the site where the gate should be applied" +#: of tensorcircuit.gates.get_u_parameter:3 +msgid "numpy array, no backend agnostic version for now" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:1 -msgid "Compute the action of the MPS transfer-operator at site `site`." +#: of tensorcircuit.gates.get_u_parameter:5 +msgid "theta, phi, lbd" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:3 -msgid "A site of the MPS" +#: of tensorcircuit.gates.iswap_gate:1 +msgid "iSwap gate." msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:4 +#: of tensorcircuit.gates.iswap_gate:3 msgid "" -"* if `1, 'l'` or `'left'`: compute the left-action of the MPS transfer-" -"operator at `site` on the input `matrix`. * if `-1, 'r'` or `'right'`: " -"compute the right-action of the MPS transfer-operator at `site` on the " -"input `matrix`" +"\\textrm{iSwap}(\\theta) =\n" +"\\begin{pmatrix}\n" +" 1 & 0 & 0 & 0\\\\\n" +" 0 & \\cos(\\frac{\\pi}{2} \\theta ) & j \\sin(\\frac{\\pi}{2} \\theta" +" ) & 0\\\\\n" +" 0 & j \\sin(\\frac{\\pi}{2} \\theta ) & \\cos(\\frac{\\pi}{2} \\theta" +" ) & 0\\\\\n" +" 0 & 0 & 0 & 1\\\\\n" +"\\end{pmatrix}\n" +"\n" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:5 -msgid "" -"if `1, 'l'` or `'left'`: compute the left-action of the MPS transfer-" -"operator at `site` on the input `matrix`." +#: of tensorcircuit.gates.iswap_gate:14 +msgid "iSwap Gate" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:7 -msgid "" -"if `-1, 'r'` or `'right'`: compute the right-action of the MPS transfer-" -"operator at `site` on the input `matrix`" +#: of tensorcircuit.gates.matrix_for_gate:1 +msgid "Convert Gate to numpy array." msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:9 -msgid "A rank-2 tensor or matrix." +#: of tensorcircuit.gates.matrix_for_gate:10 +msgid "input Gate" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:11 -msgid "The result of applying the MPS transfer-operator to `matrix`" +#: of tensorcircuit.gates.matrix_for_gate:12 +msgid "Corresponding Tensor" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:1 +#: of tensorcircuit.gates.meta_gate:1 msgid "" -"Apply a two-site gate to an MPS. This routine will in general destroy any" -" canonical form of the state. If a canonical form is needed, the user can" -" restore it using `FiniteMPS.position`." -msgstr "" - -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:5 -msgid "A two-body gate." -msgstr "" - -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:7 -msgid "The first site where the gate acts." +"Inner helper function to generate gate functions, such as ``z()`` from " +"``_z_matrix``" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:9 -msgid "The second site where the gate acts." +#: of tensorcircuit.gates.multicontrol_gate:1 +msgid "" +"Multicontrol gate. If the control qubits equal to ``ctrl``, :math:`U` is " +"applied to the target qubits." msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:15 +#: of tensorcircuit.gates.multicontrol_gate:5 msgid "" -"An optional value to choose the MPS tensor at `center_position` to be " -"isometric after the application of the gate. Defaults to `site1`. If the " -"MPS is canonical (i.e.`BaseMPS.center_position != None`), and if the " -"orthogonality center coincides with either `site1` or `site2`, the " -"orthogonality center will be shifted to `center_position` (`site1` by " -"default). If the orthogonality center does not coincide with `(site1, " -"site2)` then `MPS.center_position` is set to `None`." +"E.g., ``multicontrol_gate(tc.gates._zz_matrix, [1, 0, 1])`` returns a " +"gate of 5 qubits," msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:26 +#: of tensorcircuit.gates.multicontrol_gate:4 msgid "" -"\"rank of gate is {} but has to be 4\", \"site1 = {} is not between 0 <= " -"site < N - 1 = {}\", \"site2 = {} is not between 1 <= site < N = " -"{}\",\"Found site2 ={}, site1={}. Only nearest neighbor gates are " -"currently supported\", \"f center_position = {center_position} not f in " -"{(site1, site2)} \", or \"center_position = {}, but gate is applied at " -"sites {}, {}. Truncation should only be done if the gate is applied at " -"the center position of the MPS.\"" +"where the last 2 qubits are applied :math:`ZZ` gate, if the first 3 " +"qubits are :math:`\\ket{101}`." msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:32 -msgid "A scalar tensor containing the truncated weight of the truncation." +#: of tensorcircuit.gates.multicontrol_gate:9 +msgid "control bit sequence" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.bond_dimension:1 -msgid "The bond dimension of `bond`" +#: of tensorcircuit.gates.multicontrol_gate:11 +msgid "Multicontrol Gate" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.bond_dimensions:1 -msgid "A list of bond dimensions of `BaseMPS`" +#: of tensorcircuit.gates.phase_gate:1 +msgid "The phase gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:1 +#: of tensorcircuit.gates.phase_gate:3 msgid "" -"Bring the MPS into canonical form according to `center_position`. If " -"`center_position` is `None`, the MPS is canonicalized with " -"`center_position = 0`." +"\\textrm{phase}(\\theta) =\n" +"\\begin{pmatrix}\n" +" 1 & 0 \\\\\n" +" 0 & e^{i\\theta} \\\\\n" +"\\end{pmatrix}\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:5 -msgid "If `True`, normalize matrices when shifting the orthogonality center." +#: of tensorcircuit.gates.phase_gate:10 +msgid "angle in radians, defaults to 0" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:8 -msgid "The norm of the MPS." +#: of tensorcircuit.gates.phase_gate:12 +msgid "phase gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.check_canonical:1 -msgid "Check whether the MPS is in the expected canonical form." +#: of tensorcircuit.gates.r_gate:1 +msgid "General single qubit rotation gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.check_canonical:3 -msgid "The L2 norm of the vector of local deviations." +#: of tensorcircuit.gates.r_gate:3 +msgid "" +"R(\\theta, \\alpha, \\phi) = j \\cos(\\theta) I\n" +"- j \\cos(\\phi) \\sin(\\alpha) \\sin(\\theta) X\n" +"- j \\sin(\\phi) \\sin(\\alpha) \\sin(\\theta) Y\n" +"- j \\sin(\\theta) \\cos(\\alpha) Z\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:1 -msgid "Check orthonormality of tensor at site `site`." +#: of tensorcircuit.gates.r_gate:16 +msgid "R Gate" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:3 -msgid "" -"* if `'l'` or `'left'`: check left orthogonality * if `'r`' or `'right'`:" -" check right orthogonality" +#: of tensorcircuit.gates.random_single_qubit_gate:1 +msgid "Random single qubit gate described in https://arxiv.org/abs/2002.07730." msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:4 -msgid "if `'l'` or `'left'`: check left orthogonality" +#: of tensorcircuit.gates.random_single_qubit_gate:3 +msgid "A random single-qubit gate" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:5 -msgid "if `'r`' or `'right'`: check right orthogonality" +#: of tensorcircuit.gates.random_two_qubit_gate:1 +msgid "Returns a random two-qubit gate." msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:6 -msgid "The site of the tensor." +#: of tensorcircuit.gates.random_two_qubit_gate:3 +msgid "A random two-qubit gate" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:8 -msgid "The L2 norm of the deviation from identity." +#: of tensorcircuit.gates.rgate_theoretical:1 +msgid "" +"Rotation gate implemented by matrix exponential. The output is the same " +"as `rgate`." msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:9 -msgid "scalar `Tensor`" +#: of tensorcircuit.gates.rgate_theoretical:3 +msgid "" +"R(\\theta, \\alpha, \\phi) = e^{-j \\theta \\left[\\sin(\\alpha) " +"\\cos(\\phi) X\n" +" + \\sin(\\alpha) \\sin(\\phi) " +"Y\n" +" + \\cos(\\alpha) Z\\right]}\n" +"\n" msgstr "" -#: of -#: tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:11 -msgid "If which is different from 'l','left', 'r' or 'right'." +#: of tensorcircuit.gates.rgate_theoretical:14 +msgid "Rotation Gate" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:1 -msgid "Returns the `Tensor` object at `site`." +#: of tensorcircuit.gates.rx_gate:1 +msgid "Rotation gate along :math:`x` axis." msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:3 +#: of tensorcircuit.gates.rx_gate:3 msgid "" -"If `site==len(self) - 1` `BaseMPS.connector_matrix` is absorbed fromt the" -" right-hand side into the returned `Tensor` object." +"RX(\\theta) = e^{-j\\frac{\\theta}{2}X}\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:7 -msgid "The site for which to return the `Node`." +#: of tensorcircuit.gates.rx_gate:8 +msgid "RX Gate" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:9 -msgid "The tensor at `site`." +#: of tensorcircuit.gates.ry_gate:1 +msgid "Rotation gate along :math:`y` axis." msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:1 +#: of tensorcircuit.gates.ry_gate:3 msgid "" -"Compute left reduced density matrices for site `sites`. This returns a " -"dict `left_envs` mapping sites (int) to Tensors. `left_envs[site]` is the" -" left-reduced density matrix to the left of site `site`." +"RY(\\theta) = e^{-j\\frac{\\theta}{2}Y}\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:5 -#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:5 -msgid "A list of sites of the MPS." +#: of tensorcircuit.gates.ry_gate:8 +msgid "RY Gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:8 -msgid "The left-reduced density matrices at each site in `sites`." +#: of tensorcircuit.gates.rz_gate:1 +msgid "Rotation gate along :math:`z` axis." msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:10 -msgid "The left-reduced density matrices" +#: of tensorcircuit.gates.rz_gate:3 +msgid "" +"RZ(\\theta) = e^{-j\\frac{\\theta}{2}Z}\n" +"\n" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:11 -#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:11 -msgid "at each site in `sites`." +#: of tensorcircuit.gates.rz_gate:8 +msgid "RZ Gate" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:12 -#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:12 -msgid "`dict` mapping `int` to `Tensor`" +#: of tensorcircuit.gates.u_gate:1 +msgid "" +"IBMQ U gate following the converntion of OpenQASM3.0. See `OpenQASM doc " +"`_" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:1 -msgid "Measure the expectation value of local operators `ops` site `sites`." +#: of tensorcircuit.gates.u_gate:4 +msgid "" +"\\begin{split}U(\\theta,\\phi,\\lambda) := \\left(\\begin{array}{cc}\n" +"\\cos(\\theta/2) & -e^{i\\lambda}\\sin(\\theta/2) \\\\\n" +"e^{i\\phi}\\sin(\\theta/2) & e^{i(\\phi+\\lambda)}\\cos(\\theta/2) " +"\\end{array}\\right).\\end{split}" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:3 -msgid "A list Tensors of rank 2; the local operators to be measured." +#: of tensorcircuit.gates.u_gate:10 tensorcircuit.gates.u_gate:12 +#: tensorcircuit.gates.u_gate:14 +msgid "_description_, defaults to 0" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:5 -msgid "Sites where `ops` act." +#: ../../source/api/interfaces.rst:2 +msgid "tensorcircuit.interfaces" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:7 -msgid "measurements :math:`\\langle` `ops[n]`:math:`\\rangle` for n in `sites`" +#: ../../source/api/interfaces/numpy.rst:2 +msgid "tensorcircuit.interfaces.numpy" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:1 -msgid "" -"Compute the correlator :math:`\\langle` `op1[site1], " -"op2[s]`:math:`\\rangle` between `site1` and all sites `s` in `sites2`. If" -" `s == site1`, `op2[s]` will be applied first." +#: of tensorcircuit.interfaces.numpy:1 +msgid "Interface wraps quantum function as a numpy function" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:6 -msgid "Tensor of rank 2; the local operator at `site1`." +#: of tensorcircuit.interfaces.numpy.numpy_interface:1 +msgid "Convert ``fun`` on ML backend into a numpy function" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:8 -msgid "Tensor of rank 2; the local operator at `sites2`." +#: of tensorcircuit.interfaces.numpy.numpy_interface:23 +msgid "The quantum function" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:10 -msgid "The site where `op1` acts" +#: of tensorcircuit.interfaces.numpy.numpy_interface:25 +#: tensorcircuit.interfaces.scipy.scipy_optimize_interface:39 +msgid "whether to jit ``fun``, defaults to True" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:12 -msgid "Sites where operator `op2` acts." +#: of tensorcircuit.interfaces.numpy.numpy_interface:27 +msgid "The numpy interface compatible version of ``fun``" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:14 -msgid "" -"Correlator :math:`\\langle` `op1[site1], op2[s]`:math:`\\rangle` for `s` " -":math:`\\in` `sites2`." +#: ../../source/api/interfaces/scipy.rst:2 +msgid "tensorcircuit.interfaces.scipy" msgstr "" -#: of tensorcircuit.mps_base.FiniteMPS.physical_dimensions:1 -msgid "A list of physical Hilbert-space dimensions of `BaseMPS`" +#: of tensorcircuit.interfaces.scipy:1 +msgid "Interface wraps quantum function as a scipy function for optimization" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:1 -msgid "Shift `center_position` to `site`." +#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:1 +msgid "Convert ``fun`` into a scipy optimize interface compatible version" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:3 -msgid "The site to which FiniteMPS.center_position should be shifted" +#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:35 +msgid "The quantum function with scalar out that to be optimized" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:4 -msgid "If `True`, normalize matrices when shifting." +#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:37 +msgid "the shape of parameters that ``fun`` accepts, defaults to None" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:5 -msgid "If not `None`, truncate the MPS bond dimensions to `D`." +#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:41 +msgid "" +"whether using gradient-based or gradient free scipy optimize interface, " +"defaults to True" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:6 -msgid "" -"if not `None`, truncate each bond dimension, but keeping the truncation " -"error below `max_truncation_err`." +#: of tensorcircuit.interfaces.scipy.scipy_optimize_interface:44 +msgid "The scipy interface compatible version of ``fun``" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:9 -msgid "The norm of the tensor at `FiniteMPS.center_position`" +#: ../../source/api/interfaces/tensorflow.rst:2 +msgid "tensorcircuit.interfaces.tensorflow" msgstr "" -#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:12 -msgid "If `center_position` is `None`." +#: of tensorcircuit.interfaces.tensorflow:1 +msgid "Interface wraps quantum function as a tensorflow function" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:1 +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:1 msgid "" -"Initialize a random `FiniteMPS`. The resulting state is normalized. Its " -"center-position is at 0." +"Wrap a quantum function on different ML backend with a tensorflow " +"interface." msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:4 -msgid "A list of physical dimensions." +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:22 +#: tensorcircuit.interfaces.torch.torch_interface:28 +msgid "The quantum function with tensor in and tensor out" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:5 -msgid "A list of bond dimensions." +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:24 +msgid "output tf dtype or in str" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:6 -msgid "A numpy dtype." +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:26 +#: tensorcircuit.interfaces.torch.torch_interface:30 +msgid "whether to jit ``fun``, defaults to False" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:7 -msgid "An optional backend." +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:28 +#: tensorcircuit.interfaces.torch.torch_interface:32 +msgid "whether transform tensor backend via dlpack, defaults to False" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:9 -msgid "`FiniteMPS`" +#: of tensorcircuit.interfaces.tensorflow.tensorflow_interface:30 +#: tensorcircuit.interfaces.torch.torch_interface:34 +msgid "" +"The same quantum function but now with torch tensor in and torch tensor " +"out while AD is also supported" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:1 -msgid "" -"Compute right reduced density matrices for site `sites. This returns a " -"dict `right_envs` mapping sites (int) to Tensors. `right_envs[site]` is " -"the right-reduced density matrix to the right of site `site`." +#: ../../source/api/interfaces/tensortrans.rst:2 +msgid "tensorcircuit.interfaces.tensortrans" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:8 -msgid "The right-reduced density matrices at each site in `sites`." +#: of tensorcircuit.interfaces.tensortrans:1 +msgid "general function for interfaces transformation" msgstr "" -#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:10 -msgid "The right-reduced density matrices" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:1 +msgid "" +"Function decorator that automatically convert inputs to tensors on " +"current backend" msgstr "" -#: ../../source/api/mpscircuit.rst:2 -msgid "tensorcircuit.mpscircuit" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:63 +msgid "" +"the wrapped function whose arguments in ``argnums`` position are expected" +" to be tensor format" msgstr "" -#: of tensorcircuit.mpscircuit:1 -msgid "Quantum circuit: MPS state simulator" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:66 +msgid "position of args under the auto conversion, defaults to 0" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit:1 -msgid "``MPSCircuit`` class. Simple usage demo below." +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:68 +msgid "" +"try reshape all input tensor as matrix with shape rank 2, defaults to " +"False" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.MPO_to_gate:1 -msgid "Convert MPO to gate" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:71 +msgid "convert ``Gate`` to tensor, defaults to False" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:1 -msgid "MPSCircuit object based on state simulator." +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:73 +msgid "reshape tensor from ``Gate`` input as matrix, defaults to True" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:5 -msgid "The center position of MPS, default to 0" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:75 +msgid "convert ``QuOperator`` to tensor, defaults to False" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:7 -msgid "" -"If not None, the initial state of the circuit is taken as ``tensors`` " -"instead of :math:`\\vert 0\\rangle^n` qubits, defaults to None. When " -"``tensors`` are specified, if ``center_position`` is None, then the " -"tensors are canonicalized, otherwise it is assumed the tensors are " -"already canonicalized at the ``center_position``" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:77 +msgid "reshape tensor from ``QuOperator`` input as matrix, defaults to True" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:12 -msgid "" -"If not None, it is transformed to the MPS form according to the split " -"rules" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:79 +msgid "whether cast to backend dtype, defaults to True" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:14 -msgid "Split rules" +#: of tensorcircuit.interfaces.tensortrans.args_to_tensor:81 +msgid "The wrapped function" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:1 -msgid "Apply a general qubit gate on MPS." +#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:1 +msgid "Given a pytree, get the corresponding numpy array pytree" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:3 -#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:3 -#: tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:3 -msgid "The Gate to be applied" +#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:3 +msgid "pytree" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:6 -msgid "Qubit indices of the gate" +#: of tensorcircuit.interfaces.tensortrans.general_args_to_numpy:5 +msgid "the same format pytree with all tensor replaced by numpy array" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:5 -msgid "\"MPS does not support application of gate on > 2 qubits.\"" +#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:1 +msgid "Given a pytree of numpy arrays, get the corresponding tensor pytree" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_MPO:1 -msgid "Apply a MPO to the MPS" +#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:3 +msgid "pytree of numpy arrays" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:1 -msgid "" -"Apply a double qubit gate on adjacent qubits of Matrix Product States " -"(MPS)." +#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:5 +msgid "str of str of the same pytree shape as args, defaults to None" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:5 -#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:5 -msgid "The first qubit index of the gate" +#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:7 +msgid "" +"str or backend object, defaults to None, indicating the current default " +"backend" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:7 -#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:7 -msgid "The second qubit index of the gate" +#: of tensorcircuit.interfaces.tensortrans.numpy_args_to_backend:10 +msgid "" +"the same format pytree with all numpy array replaced by the tensors in " +"the target backend" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:9 -msgid "Center position of MPS, default is None" +#: of tensorcircuit.interfaces.tensortrans.which_backend:1 +msgid "Given a tensor ``a``, return the corresponding backend" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:1 -msgid "Apply a double qubit gate on MPS." +#: of tensorcircuit.interfaces.tensortrans.which_backend:5 +msgid "" +"if true, return backend object, if false, return backend str, defaults to" +" True" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_nqubit_gate:1 -msgid "Apply a n-qubit gate by transforming the gate to MPO" +#: of tensorcircuit.interfaces.tensortrans.which_backend:8 +msgid "the backend object or backend str" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:1 -msgid "Apply a single qubit gate on MPS; no truncation is needed." +#: ../../source/api/interfaces/torch.rst:2 +msgid "tensorcircuit.interfaces.torch" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:3 -msgid "gate to be applied" +#: of tensorcircuit.interfaces.torch:1 +msgid "Interface wraps quantum function as a torch function" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:5 -msgid "Qubit index of the gate" +#: of tensorcircuit.interfaces.torch.torch_interface:1 +msgid "Wrap a quantum function on different ML backend with a pytorch interface." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.conj:1 -msgid "Compute the conjugate of the current MPS." +#: of tensorcircuit.interfaces.torch.torch_interface_kws:1 +msgid "" +"similar to py:meth:`tensorcircuit.interfaces.torch.torch_interface`, but " +"now the interface support static arguments for function ``f``, which is " +"not a tensor and can be used with keyword arguments" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.conj:3 -#: tensorcircuit.mpscircuit.MPSCircuit.copy:3 -#: tensorcircuit.mpscircuit.MPSCircuit.copy_without_tensor:3 -msgid "The constructed MPS" +#: ../../source/api/keras.rst:2 +msgid "tensorcircuit.keras" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.copy:1 -msgid "Copy the current MPS." +#: of tensorcircuit.keras:1 +msgid "Keras layer for tc quantum function" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.copy_without_tensor:1 -msgid "Copy the current MPS without the tensors." +#: of tensorcircuit.keras.HardwareLayer:1 +msgid "Bases: :py:class:`~tensorcircuit.keras.QuantumLayer`" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:1 -msgid "Compute the expectation of corresponding operators in the form of tensor." +#: of tensorcircuit.keras.HardwareLayer:1 +msgid "" +"Keras Layer wrapping quantum function with cloud qpu access (using " +":py:mod:`tensorcircuit.cloud` module)" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:3 +#: of tensorcircuit.keras.QuantumLayer.__init__:1 msgid "" -"Operator and its position on the circuit, eg. ``(gates.Z(), [1]), " -"(gates.X(), [2])`` is for operator :math:`Z_1X_2`" +"`QuantumLayer` wraps the quantum function `f` as a `keras.Layer` so that " +"tensorcircuit is better integrated with tensorflow. Note that the input " +"of the layer can be tensors or even list/dict of tensors." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:9 -msgid "If not None, will be used as bra" +#: of tensorcircuit.keras.QuantumLayer.__init__:5 +msgid "Callabel function." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:11 -msgid "Whether to conjugate the bra state" +#: of tensorcircuit.keras.QuantumLayer.__init__:7 +msgid "The shape of the weights." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:13 -msgid "Whether to normalize the MPS" +#: of tensorcircuit.keras.QuantumLayer.__init__:9 +msgid "The initializer of the weights, defaults to \"glorot_uniform\"" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:15 -#: tensorcircuit.mpscircuit.MPSCircuit.set_split_rules:5 -#: tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:5 -msgid "Truncation split" +#: of tensorcircuit.keras.QuantumLayer.__init__:13 +msgid "The regularizer of the weights, defaults to None" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:17 -msgid "The expectation of corresponding operators" +#: of tensorcircuit.keras.load_func:1 +msgid "" +"Load function from the files in the ``tf.savedmodel`` format. We can load" +" several functions at the same time, as they can be the same function of " +"different input shapes." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.gate_to_MPO:1 -msgid "Convert gate to MPO form with identities at empty sites" +#: of tensorcircuit.keras.load_func:24 +msgid "" +"The fallback function when all functions loaded are failed, defaults to " +"None" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_bond_dimensions:1 -msgid "Get the MPS bond dimensions" +#: of tensorcircuit.keras.load_func:26 +msgid "" +"When there is not legal loaded function of the input shape and no " +"fallback callable." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_bond_dimensions:3 -#: tensorcircuit.mpscircuit.MPSCircuit.get_tensors:3 -msgid "MPS tensors" +#: of tensorcircuit.keras.load_func:27 +msgid "" +"A function that tries all loaded function against the input until the " +"first success one." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_center_position:1 -msgid "Get the center position of the MPS" +#: of tensorcircuit.keras.output_asis_loss:1 +msgid "The keras loss function that directly taking the model output as the loss." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_center_position:3 -msgid "center position" +#: of tensorcircuit.keras.output_asis_loss:3 +msgid "Ignoring this parameter." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_norm:1 -msgid "Get the normalized Center Position." +#: of tensorcircuit.keras.output_asis_loss:5 +msgid "Model output." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_norm:3 -msgid "Normalized Center Position." +#: of tensorcircuit.keras.output_asis_loss:7 +msgid "Model output, which is y_pred." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_quvector:2 -msgid "Get the representation of the output state in the form of ``QuVector``" +#: of tensorcircuit.keras.save_func:1 +msgid "Save tf function in the file (``tf.savedmodel`` format)." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_quvector:2 -msgid "has to be full contracted in MPS" +#: of tensorcircuit.keras.save_func:30 +msgid "``tf.function`` ed function with graph building" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.get_tensors:1 -msgid "Get the MPS tensors" +#: of tensorcircuit.keras.save_func:32 +msgid "the dir path to save the function" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.is_valid:1 -msgid "Check whether the circuit is legal." +#: ../../source/api/mps_base.rst:2 +msgid "tensorcircuit.mps_base" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.is_valid:3 -msgid "Whether the circuit is legal." +#: of tensorcircuit.mps_base:1 +msgid "FiniteMPS from tensornetwork with bug fixed" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.measure:1 -msgid "Take measurement to the given quantum lines." +#: of tensorcircuit.mps_base.FiniteMPS:1 +msgid "Bases: :py:class:`~tensornetwork.matrixproductstates.finite_mps.FiniteMPS`" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:1 -msgid "" -"Middle measurement in the z-basis on the circuit, note the wavefunction " -"output is not normalized with ``mid_measurement`` involved, one should " -"normalized the state manually if needed." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:4 +msgid "Initialize a `FiniteMPS`. If `canonicalize` is `True` the state" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:4 -msgid "The index of qubit that the Z direction postselection applied on" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:2 +msgid "" +"is brought into canonical form, with `BaseMPS.center_position` at " +"`center_position`. if `center_position` is `None` and `canonicalize = " +"True`, `BaseMPS.center_position` is set to 0." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:6 -msgid "0 for spin up, 1 for spin down, defaults to 0" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:6 +msgid "A list of `Tensor` objects." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.normalize:1 -msgid "Normalize MPS Circuit according to the center position." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:7 +msgid "The initial position of the center site." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.position:1 -msgid "Wrapper of tn.FiniteMPS.position. Set orthogonality center." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:8 +msgid "If `True` the mps is canonicalized at initialization." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.position:4 -msgid "The orthogonality center" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.__init__:9 +msgid "" +"The name of the backend that should be used to perform contractions. " +"Available backends are currently 'numpy', 'tensorflow', 'pytorch', 'jax'" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:1 -msgid "Compute the projection between `other` as bra and `self` as ket." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_one_site_gate:1 +msgid "" +"Apply a one-site gate to an MPS. This routine will in general destroy any" +" canonical form of the state. If a canonical form is needed, the user can" +" restore it using `FiniteMPS.position` :param gate: a one-body gate " +":param site: the site where the gate should be applied" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:3 -msgid "ket of the other MPS, which will be converted to bra automatically" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:1 +msgid "Compute the action of the MPS transfer-operator at site `site`." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:5 -msgid "The projection in form of tensor" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:3 +msgid "A site of the MPS" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.reduce_dimension:1 -msgid "Reduce the bond dimension between two adjacent sites by SVD" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:4 +msgid "" +"* if `1, 'l'` or `'left'`: compute the left-action of the MPS transfer-" +"operator at `site` on the input `matrix`. * if `-1, 'r'` or `'right'`: " +"compute the right-action of the MPS transfer-operator at `site` on the " +"input `matrix`" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.reduce_tensor_dimension:1 -msgid "Reduce the bond dimension between two general tensors by SVD" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:5 +msgid "" +"if `1, 'l'` or `'left'`: compute the left-action of the MPS transfer-" +"operator at `site` on the input `matrix`." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.set_split_rules:1 +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:7 msgid "" -"Set truncation split when double qubit gates are applied. If nothing is " -"specified, no truncation will take place and the bond dimension will keep" -" growing. For more details, refer to `split_tensor`." +"if `-1, 'r'` or `'right'`: compute the right-action of the MPS transfer-" +"operator at `site` on the input `matrix`" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.slice:1 -msgid "Get a slice of the MPS (only for internal use)" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:9 +msgid "A rank-2 tensor or matrix." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:3 -msgid "the str indicating the form of the output wavefunction" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.apply_transfer_operator:11 +msgid "The result of applying the MPS transfer-operator to `matrix`" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:5 -msgid "Tensor with shape [1, -1]" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:1 +msgid "" +"Apply a two-site gate to an MPS. This routine will in general destroy any" +" canonical form of the state. If a canonical form is needed, the user can" +" restore it using `FiniteMPS.position`." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:9 -msgid "i--A--B--j -> i--XX--j" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:5 +msgid "A two-body gate." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:1 -msgid "Construct the MPS tensors from a given wavefunction." +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:7 +msgid "The first site where the gate acts." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:3 -msgid "The given wavefunction (any shape is OK)" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:9 +msgid "The second site where the gate acts." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:7 -msgid "Physical dimension, 2 for MPS and 4 for MPO" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:15 +msgid "" +"An optional value to choose the MPS tensor at `center_position` to be " +"isometric after the application of the gate. Defaults to `site1`. If the " +"MPS is canonical (i.e.`BaseMPS.center_position != None`), and if the " +"orthogonality center coincides with either `site1` or `site2`, the " +"orthogonality center will be shifted to `center_position` (`site1` by " +"default). If the orthogonality center does not coincide with `(site1, " +"site2)` then `MPS.center_position` is set to `None`." msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:9 -msgid "Whether to normalize the wavefunction" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:26 +msgid "" +"\"rank of gate is {} but has to be 4\", \"site1 = {} is not between 0 <= " +"site < N - 1 = {}\", \"site2 = {} is not between 1 <= site < N = " +"{}\",\"Found site2 ={}, site1={}. Only nearest neighbor gates are " +"currently supported\", \"f center_position = {center_position} not f in " +"{(site1, site2)} \", or \"center_position = {}, but gate is applied at " +"sites {}, {}. Truncation should only be done if the gate is applied at " +"the center position of the MPS.\"" msgstr "" -#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:11 -msgid "The tensors" +#: of tensorcircuit.mps_base.FiniteMPS.apply_two_site_gate:32 +msgid "A scalar tensor containing the truncated weight of the truncation." msgstr "" -#: of tensorcircuit.mpscircuit.split_tensor:1 -msgid "Split the tensor by SVD or QR depends on whether a truncation is required." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.bond_dimension:1 +msgid "The bond dimension of `bond`" msgstr "" -#: of tensorcircuit.mpscircuit.split_tensor:3 -msgid "The input tensor to split." +#: of tensorcircuit.mps_base.FiniteMPS.bond_dimensions:1 +msgid "A list of bond dimensions of `BaseMPS`" msgstr "" -#: of tensorcircuit.mpscircuit.split_tensor:5 -msgid "Determine the orthogonal center is on the left tensor or the right tensor." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:1 +msgid "" +"Bring the MPS into canonical form according to `center_position`. If " +"`center_position` is `None`, the MPS is canonicalized with " +"`center_position = 0`." msgstr "" -#: of tensorcircuit.mpscircuit.split_tensor:7 -msgid "Two tensors after splitting" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:5 +msgid "If `True`, normalize matrices when shifting the orthogonality center." msgstr "" -#: ../../source/api/noisemodel.rst:2 -msgid "tensorcircuit.noisemodel" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.canonicalize:8 +msgid "The norm of the MPS." msgstr "" -#: of tensorcircuit.noisemodel:1 -msgid "General Noise Model Construction." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.check_canonical:1 +msgid "Check whether the MPS is in the expected canonical form." msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf:1 -msgid "``Noise Configuration`` class." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.check_canonical:3 +msgid "The L2 norm of the vector of local deviations." msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf.__init__:1 -msgid "Establish a noise configuration." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:1 +msgid "Check orthonormality of tensor at site `site`." msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf.add_noise:1 +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:3 msgid "" -"Add noise channels on specific gates and specific qubits in form of Kraus" -" operators." +"* if `'l'` or `'left'`: check left orthogonality * if `'r`' or `'right'`:" +" check right orthogonality" msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf.add_noise:3 -msgid "noisy gate" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:4 +msgid "if `'l'` or `'left'`: check left orthogonality" msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf.add_noise:5 -msgid "noise channel" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:5 +msgid "if `'r`' or `'right'`: check right orthogonality" msgstr "" -#: of tensorcircuit.noisemodel.NoiseConf.add_noise:7 -msgid "" -"the list of noisy qubit, defaults to None, indicating applying the noise " -"channel on all qubits" -msgstr "" - -#: of tensorcircuit.noisemodel.apply_qir_with_noise:1 -msgid "A newly defined circuit" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:6 +msgid "The site of the tensor." msgstr "" -#: of tensorcircuit.noisemodel.apply_qir_with_noise:3 -msgid "The qir of the clean circuit" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:8 +msgid "The L2 norm of the deviation from identity." msgstr "" -#: of tensorcircuit.noisemodel.apply_qir_with_noise:5 -#: tensorcircuit.noisemodel.circuit_with_noise:5 -msgid "Noise Configuration" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:9 +msgid "scalar `Tensor`" msgstr "" -#: of tensorcircuit.noisemodel.apply_qir_with_noise:7 -#: tensorcircuit.noisemodel.circuit_with_noise:7 -msgid "The status for Monte Carlo sampling, defaults to None" +#: of +#: tensornetwork.matrixproductstates.base_mps.BaseMPS.check_orthonormality:11 +msgid "If which is different from 'l','left', 'r' or 'right'." msgstr "" -#: of tensorcircuit.noisemodel.apply_qir_with_noise:9 -#: tensorcircuit.noisemodel.circuit_with_noise:9 -msgid "A newly constructed circuit with noise" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:1 +msgid "Returns the `Tensor` object at `site`." msgstr "" -#: of tensorcircuit.noisemodel.circuit_with_noise:1 -msgid "Noisify a clean circuit." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:3 +msgid "" +"If `site==len(self) - 1` `BaseMPS.connector_matrix` is absorbed fromt the" +" right-hand side into the returned `Tensor` object." msgstr "" -#: of tensorcircuit.noisemodel.circuit_with_noise:3 -msgid "A clean circuit" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:7 +msgid "The site for which to return the `Node`." msgstr "" -#: of tensorcircuit.noisemodel.expectation_noisfy:1 -msgid "Calculate expectation value with noise configuration." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.get_tensor:9 +msgid "The tensor at `site`." msgstr "" -#: of tensorcircuit.noisemodel.expectation_noisfy:3 -#: tensorcircuit.noisemodel.sample_expectation_ps_noisfy:3 -msgid "The clean circuit" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:1 +msgid "" +"Compute left reduced density matrices for site `sites`. This returns a " +"dict `left_envs` mapping sites (int) to Tensors. `left_envs[site]` is the" +" left-reduced density matrix to the left of site `site`." msgstr "" -#: of tensorcircuit.noisemodel.expectation_noisfy:12 -msgid "expectation value with noise" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:5 +#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:5 +msgid "A list of sites of the MPS." msgstr "" -#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:1 -msgid "Calculate sample_expectation_ps with noise configuration." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:8 +msgid "The left-reduced density matrices at each site in `sites`." msgstr "" -#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:13 -msgid "" -"repetition time for Monte Carlo sampling for noisfy calculation, " -"defaults to 1000" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:10 +msgid "The left-reduced density matrices" msgstr "" -#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:20 -msgid "" -"external randomness given by tensor uniformly from [0, 1], defaults to " -"None, used for measurement sampling" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:11 +#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:11 +msgid "at each site in `sites`." msgstr "" -#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:23 -msgid "sample expectation value with noise" +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.left_envs:12 +#: tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:12 +msgid "`dict` mapping `int` to `Tensor`" msgstr "" -#: ../../source/api/quantum.rst:2 -msgid "tensorcircuit.quantum" +#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:1 +msgid "Measure the expectation value of local operators `ops` site `sites`." msgstr "" -#: of tensorcircuit.quantum:1 -msgid "Quantum state and operator class backend by tensornetwork" +#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:3 +msgid "A list Tensors of rank 2; the local operators to be measured." msgstr "" -#: of tensorcircuit.quantum -msgid "IMPORT" +#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:5 +msgid "Sites where `ops` act." msgstr "" -#: of tensorcircuit.quantum.PauliString2COO:1 -#: tensorcircuit.quantum.PauliStringSum2COO_tf:1 -msgid "Generate tensorflow sparse matrix from Pauli string sum" +#: of tensorcircuit.mps_base.FiniteMPS.measure_local_operator:7 +msgid "measurements :math:`\\langle` `ops[n]`:math:`\\rangle` for n in `sites`" msgstr "" -#: of tensorcircuit.quantum.PauliString2COO:3 +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:1 msgid "" -"1D Tensor representing for a Pauli string, e.g. [1, 0, 0, 3, 2] is for " -":math:`X_0Z_3Y_4`" +"Compute the correlator :math:`\\langle` `op1[site1], " +"op2[s]`:math:`\\rangle` between `site1` and all sites `s` in `sites2`. If" +" `s == site1`, `op2[s]` will be applied first." msgstr "" -#: of tensorcircuit.quantum.PauliString2COO:6 -msgid "" -"the weight for the Pauli string defaults to None (all Pauli strings " -"weight 1.0)" +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:6 +msgid "Tensor of rank 2; the local operator at `site1`." msgstr "" -#: of tensorcircuit.quantum.PauliString2COO:9 -msgid "the tensorflow sparse matrix" +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:8 +msgid "Tensor of rank 2; the local operator at `sites2`." msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO:1 -#: tensorcircuit.quantum.PauliStringSum2COO_numpy:1 -msgid "" -"Generate sparse tensor from Pauli string sum. Currently requires " -"tensorflow installed" +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:10 +msgid "The site where `op1` acts" msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO:4 -#: tensorcircuit.quantum.PauliStringSum2COO_numpy:4 -#: tensorcircuit.quantum.PauliStringSum2COO_tf:3 -#: tensorcircuit.quantum.PauliStringSum2Dense:5 -msgid "" -"2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for " -":math:`X_0Z_3Y_4`" +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:12 +msgid "Sites where operator `op2` acts." msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO:7 -#: tensorcircuit.quantum.PauliStringSum2COO_numpy:7 -#: tensorcircuit.quantum.PauliStringSum2COO_tf:6 -#: tensorcircuit.quantum.PauliStringSum2Dense:8 +#: of tensorcircuit.mps_base.FiniteMPS.measure_two_body_correlator:14 msgid "" -"1D Tensor, each element corresponds the weight for each Pauli string " -"defaults to None (all Pauli strings weight 1.0)" +"Correlator :math:`\\langle` `op1[site1], op2[s]`:math:`\\rangle` for `s` " +":math:`\\in` `sites2`." msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO:10 -#: tensorcircuit.quantum.PauliStringSum2COO_numpy:10 -#: tensorcircuit.quantum.PauliStringSum2Dense:11 -msgid "" -"default False. If True, return numpy coo else return backend compatible " -"sparse tensor" +#: of tensorcircuit.mps_base.FiniteMPS.physical_dimensions:1 +msgid "A list of physical Hilbert-space dimensions of `BaseMPS`" msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO:13 -#: tensorcircuit.quantum.PauliStringSum2COO_numpy:13 -msgid "the scipy coo sparse matrix" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:1 +msgid "Shift `center_position` to `site`." msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2COO_tf:9 -msgid "the tensorflow coo sparse matrix" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:3 +msgid "The site to which FiniteMPS.center_position should be shifted" msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2Dense:1 -msgid "" -"Generate dense matrix from Pauli string sum. Currently requires " -"tensorflow installed." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:4 +msgid "If `True`, normalize matrices when shifting." msgstr "" -#: of tensorcircuit.quantum.PauliStringSum2Dense:14 -msgid "the tensorflow dense matrix" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:5 +msgid "If not `None`, truncate the MPS bond dimensions to `D`." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector:1 tensorcircuit.quantum.QuScalar:1 -#: tensorcircuit.quantum.QuVector:1 -msgid "Bases: :py:class:`tensorcircuit.quantum.QuOperator`" +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:6 +msgid "" +"if not `None`, truncate each bond dimension, but keeping the truncation " +"error below `max_truncation_err`." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector:1 -msgid "Represents an adjoint (row) vector via a tensor network." +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:9 +msgid "The norm of the tensor at `FiniteMPS.center_position`" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.__init__:1 +#: of tensornetwork.matrixproductstates.base_mps.BaseMPS.position:12 +msgid "If `center_position` is `None`." +msgstr "" + +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:1 msgid "" -"Constructs a new `QuAdjointVector` from a tensor network. This " -"encapsulates an existing tensor network, interpreting it as an adjoint " -"vector (row vector)." +"Initialize a random `FiniteMPS`. The resulting state is normalized. Its " +"center-position is at 0." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.__init__:5 -#: tensorcircuit.quantum.QuOperator.__init__:9 -msgid "The edges of the network to be used as the input edges." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:4 +msgid "A list of physical dimensions." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.__init__:7 -#: tensorcircuit.quantum.QuOperator.__init__:11 -#: tensorcircuit.quantum.QuVector.__init__:6 -msgid "" -"Nodes used to refer to parts of the tensor network that are not connected" -" to any input or output edges (for example: a scalar factor)." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:5 +msgid "A list of bond dimensions." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.__init__:10 -#: tensorcircuit.quantum.QuScalar.__init__:7 -#: tensorcircuit.quantum.QuVector.__init__:9 -msgid "Optional collection of edges to ignore when performing consistency checks." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:6 +msgid "A numpy dtype." msgstr "" -#: of tensorcircuit.quantum.QuOperator.adjoint:1 -msgid "" -"The adjoint of the operator. This creates a new `QuOperator` with " -"complex-conjugate copies of all tensors in the network and with the input" -" and output edges switched." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:7 +msgid "An optional backend." msgstr "" -#: of tensorcircuit.quantum.QuOperator.adjoint:5 -msgid "The adjoint of the operator." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.random:9 +msgid "`FiniteMPS`" msgstr "" -#: of tensorcircuit.quantum.QuOperator.check_network:1 +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:1 msgid "" -"Check that the network has the expected dimensionality. This checks that " -"all input and output edges are dangling and that there are no other " -"dangling edges (except any specified in `ignore_edges`). If not, an " -"exception is raised." +"Compute right reduced density matrices for site `sites. This returns a " +"dict `right_envs` mapping sites (int) to Tensors. `right_envs[site]` is " +"the right-reduced density matrix to the right of site `site`." msgstr "" -#: of tensorcircuit.quantum.QuOperator.contract:1 -msgid "" -"Contract the tensor network in place. This modifies the tensor network " -"representation of the operator (or vector, or scalar), reducing it to a " -"single tensor, without changing the value." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:8 +msgid "The right-reduced density matrices at each site in `sites`." msgstr "" -#: of tensorcircuit.quantum.QuOperator.contract:5 -msgid "Manually specify the axis ordering of the final tensor." +#: of tensornetwork.matrixproductstates.finite_mps.FiniteMPS.right_envs:10 +msgid "The right-reduced density matrices" msgstr "" -#: of tensorcircuit.quantum.QuOperator.contract:7 -msgid "The present object." +#: ../../source/api/mpscircuit.rst:2 +msgid "tensorcircuit.mpscircuit" msgstr "" -#: of tensorcircuit.quantum.QuOperator.copy:1 -msgid "The deep copy of the operator." +#: of tensorcircuit.mpscircuit:1 +msgid "Quantum circuit: MPS state simulator" msgstr "" -#: of tensorcircuit.quantum.QuOperator.copy:3 -msgid "The new copy of the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit:1 +msgid "``MPSCircuit`` class. Simple usage demo below." msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval:1 -msgid "" -"Contracts the tensor network in place and returns the final tensor. Note " -"that this modifies the tensor network representing the operator. The " -"default ordering for the axes of the final tensor is: `*out_edges, " -"*in_edges`. If there are any \"ignored\" edges, their axes come first: " -"`*ignored_edges, *out_edges, *in_edges`." +#: of tensorcircuit.mpscircuit.MPSCircuit.MPO_to_gate:1 +msgid "Convert MPO to gate" msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval:8 -#: tensorcircuit.quantum.QuOperator.eval_matrix:6 -msgid "" -"Manually specify the axis ordering of the final tensor. The default " -"ordering is determined by `out_edges` and `in_edges` (see above)." +#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:1 +msgid "MPSCircuit object based on state simulator." msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval:11 -#: tensorcircuit.quantum.QuOperator.eval_matrix:9 -msgid "Node count '{}' > 1 after contraction!" +#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:5 +msgid "The center position of MPS, default to 0" msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval:12 -msgid "The final tensor representing the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:7 +msgid "" +"If not None, the initial state of the circuit is taken as ``tensors`` " +"instead of :math:`\\vert 0\\rangle^n` qubits, defaults to None. When " +"``tensors`` are specified, if ``center_position`` is None, then the " +"tensors are canonicalized, otherwise it is assumed the tensors are " +"already canonicalized at the ``center_position``" msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval_matrix:1 +#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:12 msgid "" -"Contracts the tensor network in place and returns the final tensor in two" -" dimentional matrix. The default ordering for the axes of the final " -"tensor is: (:math:`\\prod` dimension of out_edges, :math:`\\prod` " -"dimension of in_edges)" +"If not None, it is transformed to the MPS form according to the split " +"rules" msgstr "" -#: of tensorcircuit.quantum.QuOperator.eval_matrix:10 -msgid "The two-dimentional tensor representing the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.__init__:14 +msgid "Split rules" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:1 -msgid "" -"Construct a `QuAdjointVector` directly from a single tensor. This first " -"wraps the tensor in a `Node`, then constructs the `QuAdjointVector` from " -"that `Node`." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:1 +msgid "Apply a general qubit gate on MPS." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:27 -msgid "The tensor for constructing an QuAdjointVector." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:3 +#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:3 +#: tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:3 +msgid "The Gate to be applied" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:29 -msgid "" -"Sequence of integer indices specifying the order in which to interpret " -"the axes as subsystems (input edges). If not specified, the axes are " -"taken in ascending order." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:6 +msgid "Qubit indices of the gate" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:33 -msgid "The new constructed QuAdjointVector give from the given tensor." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_general_gate:5 +msgid "\"MPS does not support application of gate on > 2 qubits.\"" msgstr "" -#: of tensorcircuit.quantum.QuOperator.is_adjoint_vector:1 -msgid "" -"Returns a bool indicating if QuOperator is an adjoint vector. Examples " -"can be found in the `QuOperator.from_tensor`." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_MPO:1 +msgid "Apply a MPO to the MPS" msgstr "" -#: of tensorcircuit.quantum.QuOperator.is_scalar:1 +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:1 msgid "" -"Returns a bool indicating if QuOperator is a scalar. Examples can be " -"found in the `QuOperator.from_tensor`." +"Apply a double qubit gate on adjacent qubits of Matrix Product States " +"(MPS)." msgstr "" -#: of tensorcircuit.quantum.QuOperator.is_vector:1 -msgid "" -"Returns a bool indicating if QuOperator is a vector. Examples can be " -"found in the `QuOperator.from_tensor`." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:5 +#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:5 +msgid "The first qubit index of the gate" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.nodes:1 -#: tensorcircuit.quantum.QuOperator.nodes:1 -#: tensorcircuit.quantum.QuScalar.nodes:1 -#: tensorcircuit.quantum.QuVector.nodes:1 -msgid "All tensor-network nodes involved in the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:7 +#: tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:7 +msgid "The second qubit index of the gate" msgstr "" -#: of tensorcircuit.quantum.QuOperator.norm:1 -msgid "" -"The norm of the operator. This is the 2-norm (also known as the Frobenius" -" or Hilbert-Schmidt norm)." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_adjacent_double_gate:9 +msgid "Center position of MPS, default is None" msgstr "" -#: of tensorcircuit.quantum.QuOperator.partial_trace:1 -msgid "" -"The partial trace of the operator. Subsystems to trace out are supplied " -"as indices, so that dangling edges are connected to each other as: " -"`out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out` This does " -"not modify the original network. The original ordering of the remaining " -"subsystems is maintained." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_double_gate:1 +msgid "Apply a double qubit gate on MPS." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:16 -#: tensorcircuit.quantum.QuOperator.partial_trace:8 -#: tensorcircuit.quantum.QuVector.reduced_density:16 -msgid "Indices of subsystems to trace out." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_nqubit_gate:1 +msgid "Apply a n-qubit gate by transforming the gate to MPO" msgstr "" -#: of tensorcircuit.quantum.QuOperator.partial_trace:10 -msgid "A new QuOperator or QuScalar representing the result." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:1 +msgid "Apply a single qubit gate on MPS; no truncation is needed." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.projector:1 -#: tensorcircuit.quantum.QuVector.projector:1 -msgid "" -"The projector of the operator. The operator, as a linear operator, on the" -" adjoint of the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:3 +msgid "gate to be applied" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.projector:4 -msgid "" -"Set :math:`A` is the operator in matrix form, then the projector of " -"operator is defined as: :math:`A^\\dagger A`" +#: of tensorcircuit.mpscircuit.MPSCircuit.apply_single_gate:5 +msgid "Qubit index of the gate" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.projector:6 -#: tensorcircuit.quantum.QuVector.projector:6 -msgid "The projector of the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.conj:1 +msgid "Compute the conjugate of the current MPS." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:1 -#: tensorcircuit.quantum.QuVector.reduced_density:1 -msgid "The reduced density of the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.conj:3 +#: tensorcircuit.mpscircuit.MPSCircuit.copy:3 +#: tensorcircuit.mpscircuit.MPSCircuit.copy_without_tensor:3 +msgid "The constructed MPS" msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:3 -#: tensorcircuit.quantum.QuVector.reduced_density:3 -msgid "" -"Set :math:`A` is the matrix of the operator, then the reduced density is " -"defined as:" +#: of tensorcircuit.mpscircuit.MPSCircuit.copy:1 +msgid "Copy the current MPS." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:5 -msgid "\\mathrm{Tr}_{subsystems}(A^\\dagger A)" +#: of tensorcircuit.mpscircuit.MPSCircuit.copy_without_tensor:1 +msgid "Copy the current MPS without the tensors." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:9 -#: tensorcircuit.quantum.QuVector.reduced_density:9 -msgid "" -"Firstly, take the projector of the operator, then trace out the " -"subsystems to trace out are supplied as indices, so that dangling edges " -"are connected to each other as: `out_edges[i] ^ in_edges[i] for i in " -"subsystems_to_trace_out` This does not modify the original network. The " -"original ordering of the remaining subsystems is maintained." +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:1 +msgid "Compute the expectation of corresponding operators in the form of tensor." msgstr "" -#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:18 -#: tensorcircuit.quantum.QuVector.reduced_density:18 +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:3 msgid "" -"The QuOperator of the reduced density of the operator with given " -"subsystems." +"Operator and its position on the circuit, eg. ``(gates.Z(), [1]), " +"(gates.X(), [2])`` is for operator :math:`Z_1X_2`" msgstr "" -#: of tensorcircuit.quantum.QuOperator.tensor_product:1 -msgid "" -"Tensor product with another operator. Given two operators `A` and `B`, " -"produces a new operator `AB` representing :math:`A ⊗ B`. The `out_edges` " -"(`in_edges`) of `AB` is simply the concatenation of the `out_edges` " -"(`in_edges`) of `A.copy()` with that of `B.copy()`: `new_out_edges = " -"[*out_edges_A_copy, *out_edges_B_copy]` `new_in_edges = " -"[*in_edges_A_copy, *in_edges_B_copy]`" +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:9 +msgid "If not None, will be used as bra" msgstr "" -#: of tensorcircuit.quantum.QuOperator.tensor_product:20 -msgid "The other operator (`B`)." +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:11 +msgid "Whether to conjugate the bra state" msgstr "" -#: of tensorcircuit.quantum.QuOperator.tensor_product:22 -msgid "The result (`AB`)." +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:13 +msgid "Whether to normalize the MPS" msgstr "" -#: of tensorcircuit.quantum.QuOperator.trace:1 -msgid "The trace of the operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:15 +#: tensorcircuit.mpscircuit.MPSCircuit.set_split_rules:5 +#: tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:5 +msgid "Truncation split" msgstr "" -#: of tensorcircuit.quantum.QuOperator:1 -msgid "" -"Represents a linear operator via a tensor network. To interpret a tensor " -"network as a linear operator, some of the dangling edges must be " -"designated as `out_edges` (output edges) and the rest as `in_edges` " -"(input edges). Considered as a matrix, the `out_edges` represent the row " -"index and the `in_edges` represent the column index. The (right) action " -"of the operator on another then consists of connecting the `in_edges` of " -"the first operator to the `out_edges` of the second. Can be used to do " -"simple linear algebra with tensor networks." +#: of tensorcircuit.mpscircuit.MPSCircuit.expectation:17 +msgid "The expectation of corresponding operators" msgstr "" -#: of tensorcircuit.quantum.QuOperator.__init__:1 -msgid "" -"Creates a new `QuOperator` from a tensor network. This encapsulates an " -"existing tensor network, interpreting it as a linear operator. The " -"network is checked for consistency: All dangling edges must either be in " -"`out_edges`, `in_edges`, or `ignore_edges`." +#: of tensorcircuit.mpscircuit.MPSCircuit.gate_to_MPO:1 +msgid "Convert gate to MPO form with identities at empty sites" msgstr "" -#: of tensorcircuit.quantum.QuOperator.__init__:7 -#: tensorcircuit.quantum.QuVector.__init__:4 -msgid "The edges of the network to be used as the output edges." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_bond_dimensions:1 +msgid "Get the MPS bond dimensions" msgstr "" -#: of tensorcircuit.quantum.QuOperator.__init__:15 -msgid "" -"Optional collection of dangling edges to ignore when performing " -"consistency checks." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_bond_dimensions:3 +#: tensorcircuit.mpscircuit.MPSCircuit.get_tensors:3 +msgid "MPS tensors" msgstr "" -#: of tensorcircuit.quantum.QuOperator.__init__:18 -msgid "" -"At least one reference node is required to specify a scalar. None " -"provided!" +#: of tensorcircuit.mpscircuit.MPSCircuit.get_center_position:1 +msgid "Get the center position of the MPS" msgstr "" -#: of tensorcircuit.quantum.QuOperator.from_tensor:1 -msgid "" -"Construct a `QuOperator` directly from a single tensor. This first wraps " -"the tensor in a `Node`, then constructs the `QuOperator` from that " -"`Node`." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_center_position:3 +msgid "center position" msgstr "" -#: of tensorcircuit.quantum.QuOperator.from_tensor:28 -msgid "The tensor." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_norm:1 +msgid "Get the normalized Center Position." msgstr "" -#: of tensorcircuit.quantum.QuOperator.from_tensor:30 -msgid "The axis indices of `tensor` to use as `out_edges`." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_norm:3 +msgid "Normalized Center Position." msgstr "" -#: of tensorcircuit.quantum.QuOperator.from_tensor:32 -msgid "The axis indices of `tensor` to use as `in_edges`." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_quvector:2 +msgid "Get the representation of the output state in the form of ``QuVector``" msgstr "" -#: of tensorcircuit.quantum.QuOperator.from_tensor:34 -msgid "The new operator." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_quvector:2 +msgid "has to be full contracted in MPS" msgstr "" -#: of tensorcircuit.quantum.QuScalar:1 -msgid "Represents a scalar via a tensor network." +#: of tensorcircuit.mpscircuit.MPSCircuit.get_tensors:1 +msgid "Get the MPS tensors" msgstr "" -#: of tensorcircuit.quantum.QuScalar.__init__:1 -msgid "" -"Constructs a new `QuScalar` from a tensor network. This encapsulates an " -"existing tensor network, interpreting it as a scalar." +#: of tensorcircuit.mpscircuit.MPSCircuit.is_valid:1 +msgid "Check whether the circuit is legal." msgstr "" -#: of tensorcircuit.quantum.QuScalar.__init__:4 -msgid "" -"Nodes used to refer to the tensor network (need not be exhaustive - one " -"node from each disconnected subnetwork is sufficient)." -msgstr "" - -#: of tensorcircuit.quantum.QuScalar.from_tensor:1 -msgid "" -"Construct a `QuScalar` directly from a single tensor. This first wraps " -"the tensor in a `Node`, then constructs the `QuScalar` from that `Node`." +#: of tensorcircuit.mpscircuit.MPSCircuit.is_valid:3 +msgid "Whether the circuit is legal." msgstr "" -#: of tensorcircuit.quantum.QuScalar.from_tensor:22 -msgid "The tensor for constructing a new QuScalar." +#: of tensorcircuit.mpscircuit.MPSCircuit.measure:1 +msgid "Take measurement to the given quantum lines." msgstr "" -#: of tensorcircuit.quantum.QuScalar.from_tensor:24 -msgid "The new constructed QuScalar from the given tensor." +#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:1 +msgid "" +"Middle measurement in the z-basis on the circuit, note the wavefunction " +"output is not normalized with ``mid_measurement`` involved, one should " +"normalized the state manually if needed." msgstr "" -#: of tensorcircuit.quantum.QuVector:1 -msgid "Represents a (column) vector via a tensor network." +#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:4 +msgid "The index of qubit that the Z direction postselection applied on" msgstr "" -#: of tensorcircuit.quantum.QuVector.__init__:1 -msgid "" -"Constructs a new `QuVector` from a tensor network. This encapsulates an " -"existing tensor network, interpreting it as a (column) vector." +#: of tensorcircuit.mpscircuit.MPSCircuit.mid_measurement:6 +msgid "0 for spin up, 1 for spin down, defaults to 0" msgstr "" -#: of tensorcircuit.quantum.QuVector.from_tensor:1 -msgid "" -"Construct a `QuVector` directly from a single tensor. This first wraps " -"the tensor in a `Node`, then constructs the `QuVector` from that `Node`." +#: of tensorcircuit.mpscircuit.MPSCircuit.normalize:1 +msgid "Normalize MPS Circuit according to the center position." msgstr "" -#: of tensorcircuit.quantum.QuVector.from_tensor:28 -msgid "The tensor for constructing a \"QuVector\"." +#: of tensorcircuit.mpscircuit.MPSCircuit.position:1 +msgid "Wrapper of tn.FiniteMPS.position. Set orthogonality center." msgstr "" -#: of tensorcircuit.quantum.QuVector.from_tensor:30 -msgid "" -"Sequence of integer indices specifying the order in which to interpret " -"the axes as subsystems (output edges). If not specified, the axes are " -"taken in ascending order." +#: of tensorcircuit.mpscircuit.MPSCircuit.position:4 +msgid "The orthogonality center" msgstr "" -#: of tensorcircuit.quantum.QuVector.from_tensor:34 -msgid "The new constructed QuVector from the given tensor." +#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:1 +msgid "Compute the projection between `other` as bra and `self` as ket." msgstr "" -#: of tensorcircuit.quantum.QuVector.projector:4 -msgid "" -"Set :math:`A` is the operator in matrix form, then the projector of " -"operator is defined as: :math:`A A^\\dagger`" +#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:3 +msgid "ket of the other MPS, which will be converted to bra automatically" msgstr "" -#: of tensorcircuit.quantum.QuVector.reduced_density:5 -msgid "\\mathrm{Tr}_{subsystems}(A A^\\dagger)" +#: of tensorcircuit.mpscircuit.MPSCircuit.proj_with_mps:5 +msgid "The projection in form of tensor" msgstr "" -#: of tensorcircuit.quantum.check_spaces:1 -msgid "" -"Check the vector spaces represented by two lists of edges are compatible." -" The number of edges must be the same and the dimensions of each pair of " -"edges must match. Otherwise, an exception is raised." +#: of tensorcircuit.mpscircuit.MPSCircuit.reduce_dimension:1 +msgid "Reduce the bond dimension between two adjacent sites by SVD" msgstr "" -#: of tensorcircuit.quantum.check_spaces:5 tensorcircuit.quantum.check_spaces:7 -msgid "List of edges representing a many-body Hilbert space." +#: of tensorcircuit.mpscircuit.MPSCircuit.reduce_tensor_dimension:1 +msgid "Reduce the bond dimension between two general tensors by SVD" msgstr "" -#: of tensorcircuit.quantum.check_spaces:10 +#: of tensorcircuit.mpscircuit.MPSCircuit.set_split_rules:1 msgid "" -"Hilbert-space mismatch: \"Cannot connect {} subsystems with {} " -"subsystems\", or \"Input dimension {} != output dimension {}.\"" +"Set truncation split when double qubit gates are applied. If nothing is " +"specified, no truncation will take place and the bond dimension will keep" +" growing. For more details, refer to `split_tensor`." msgstr "" -#: of tensorcircuit.quantum.correlation_from_counts:1 -msgid "" -"Compute :math:`\\prod_{i\\in \\\\text{index}} s_i`, where the probability" -" for each bitstring is given as a vector ``results``. Results is in the " -"format of \"count_vector\"" +#: of tensorcircuit.mpscircuit.MPSCircuit.slice:1 +msgid "Get a slice of the MPS (only for internal use)" msgstr "" -#: of tensorcircuit.quantum.correlation_from_counts:13 -#: tensorcircuit.quantum.correlation_from_samples:4 -msgid "list of int, indicating the position in the bitstring" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:3 +msgid "the str indicating the form of the output wavefunction" msgstr "" -#: of tensorcircuit.quantum.correlation_from_counts:15 -msgid "probability vector of shape 2^n" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:5 +msgid "Tensor with shape [1, -1]" msgstr "" -#: of tensorcircuit.quantum.correlation_from_counts:17 -msgid "Correlation expectation from measurement shots." +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction:9 +msgid "i--A--B--j -> i--XX--j" msgstr "" -#: of tensorcircuit.quantum.correlation_from_samples:1 -msgid "" -"Compute :math:`\\prod_{i\\in \\\\text{index}} s_i (s=\\pm 1)`, Results is" -" in the format of \"sample_int\" or \"sample_bin\"" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:1 +msgid "Construct the MPS tensors from a given wavefunction." msgstr "" -#: of tensorcircuit.quantum.correlation_from_samples:6 -msgid "sample tensor" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:3 +msgid "The given wavefunction (any shape is OK)" msgstr "" -#: of tensorcircuit.quantum.correlation_from_samples:10 -msgid "Correlation expectation from measurement shots" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:7 +msgid "Physical dimension, 2 for MPS and 4 for MPO" msgstr "" -#: of tensorcircuit.quantum.count_d2s:1 -msgid "" -"measurement shots results, dense representation to sparse tuple " -"representation non-jittable due to the non fixed return shape count_tuple" -" to count_vector" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:9 +msgid "Whether to normalize the wavefunction" msgstr "" -#: of tensorcircuit.quantum.count_d2s:12 -msgid "cutoff to determine nonzero elements, defaults to 1e-7" +#: of tensorcircuit.mpscircuit.MPSCircuit.wavefunction_to_tensors:11 +msgid "The tensors" msgstr "" -#: of tensorcircuit.quantum.count_s2d:1 -msgid "" -"measurement shots results, sparse tuple representation to dense " -"representation count_vector to count_tuple" +#: of tensorcircuit.mpscircuit.split_tensor:1 +msgid "Split the tensor by SVD or QR depends on whether a truncation is required." msgstr "" -#: of tensorcircuit.quantum.count_tuple2dict:1 -msgid "count_tuple to count_dict_bin or count_dict_int" +#: of tensorcircuit.mpscircuit.split_tensor:3 +msgid "The input tensor to split." msgstr "" -#: of tensorcircuit.quantum.count_tuple2dict:3 -msgid "count_tuple format" +#: of tensorcircuit.mpscircuit.split_tensor:5 +msgid "Determine the orthogonal center is on the left tensor or the right tensor." msgstr "" -#: of tensorcircuit.quantum.count_tuple2dict:7 -#: tensorcircuit.quantum.count_vector2dict:7 -msgid "can be \"int\" or \"bin\", defaults to \"bin\"" +#: of tensorcircuit.mpscircuit.split_tensor:7 +msgid "Two tensors after splitting" msgstr "" -#: of tensorcircuit.quantum.count_tuple2dict:9 -msgid "count_dict" +#: ../../source/api/noisemodel.rst:2 +msgid "tensorcircuit.noisemodel" msgstr "" -#: of tensorcircuit.quantum.count_vector2dict:1 -msgid "convert_vector to count_dict_bin or count_dict_int" +#: of tensorcircuit.noisemodel:1 +msgid "General Noise Model Construction." msgstr "" -#: of tensorcircuit.quantum.count_vector2dict:3 -msgid "tensor in shape [2**n]" +#: of tensorcircuit.noisemodel.NoiseConf:1 +msgid "``Noise Configuration`` class." msgstr "" -#: of tensorcircuit.quantum.double_state:1 -msgid "Compute the double state of the given Hamiltonian operator ``h``." +#: of tensorcircuit.noisemodel.NoiseConf.__init__:1 +msgid "Establish a noise configuration." msgstr "" -#: of tensorcircuit.quantum.double_state:3 tensorcircuit.quantum.gibbs_state:3 -#: tensorcircuit.quantum.truncated_free_energy:5 -msgid "Hamiltonian operator in form of Tensor." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise:1 +msgid "" +"Add noise channels on specific gates and specific qubits in form of Kraus" +" operators." msgstr "" -#: of tensorcircuit.quantum.double_state:5 tensorcircuit.quantum.free_energy:17 -#: tensorcircuit.quantum.gibbs_state:5 -#: tensorcircuit.quantum.renyi_free_energy:16 -#: tensorcircuit.quantum.truncated_free_energy:7 -msgid "Constant for the optimization, default is 1." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise:3 +msgid "noisy gate" msgstr "" -#: of tensorcircuit.quantum.double_state:7 -msgid "The double state of ``h`` with the given ``beta``." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise:5 +msgid "noise channel" msgstr "" -#: of tensorcircuit.quantum.eliminate_identities:1 +#: of tensorcircuit.noisemodel.NoiseConf.add_noise:7 msgid "" -"Eliminates any connected CopyNodes that are identity matrices. This will " -"modify the network represented by `nodes`. Only identities that are " -"connected to other nodes are eliminated." +"the list of noisy qubit, defaults to None, indicating applying the noise " +"channel on all qubits" msgstr "" -#: of tensorcircuit.quantum.eliminate_identities:5 -msgid "Collection of nodes to search." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise_by_condition:1 +msgid "Add noise based on specified condition" msgstr "" -#: of tensorcircuit.quantum.eliminate_identities:7 -msgid "" -"The Dictionary mapping remaining Nodes to any replacements, Dictionary " -"specifying all dangling-edge replacements." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise_by_condition:3 +msgid "a function to decide if the noise should be added to the qir." msgstr "" -#: of tensorcircuit.quantum.entropy:1 -msgid "Compute the entropy from the given density matrix ``rho``." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise_by_condition:5 +msgid "the error channel" msgstr "" -#: of tensorcircuit.quantum.entropy:30 tensorcircuit.quantum.free_energy:13 -#: tensorcircuit.quantum.renyi_entropy:3 -#: tensorcircuit.quantum.renyi_free_energy:12 -msgid "The density matrix in form of Tensor or QuOperator." +#: of tensorcircuit.noisemodel.NoiseConf.add_noise_by_condition:7 +msgid "the name of the condition. A metadata that does not affect the numerics." msgstr "" -#: of tensorcircuit.quantum.entropy:32 tensorcircuit.quantum.free_energy:19 -msgid "Epsilon, default is 1e-12." +#: of tensorcircuit.noisemodel.NoiseConf.channel_count:1 +msgid "Count the total number of channels in a given circuit" msgstr "" -#: of tensorcircuit.quantum.entropy:34 -msgid "Entropy on the given density matrix." +#: of tensorcircuit.noisemodel.NoiseConf.channel_count:3 +msgid "the circuit to be counted" msgstr "" -#: of tensorcircuit.quantum.fidelity:1 -msgid "Return fidelity scalar between two states rho and rho0." +#: of tensorcircuit.noisemodel.NoiseConf.channel_count:5 +msgid "the count" msgstr "" -#: of tensorcircuit.quantum.fidelity:3 -msgid "\\operatorname{Tr}(\\sqrt{\\sqrt{rho} rho_0 \\sqrt{rho}})" +#: of tensorcircuit.noisemodel.apply_qir_with_noise:1 +msgid "A newly defined circuit" msgstr "" -#: of tensorcircuit.quantum.fidelity:7 tensorcircuit.quantum.fidelity:9 -#: tensorcircuit.quantum.mutual_information:3 tensorcircuit.quantum.taylorlnm:3 -#: tensorcircuit.quantum.trace_distance:3 -#: tensorcircuit.quantum.trace_distance:5 -#: tensorcircuit.quantum.truncated_free_energy:3 -msgid "The density matrix in form of Tensor." +#: of tensorcircuit.noisemodel.apply_qir_with_noise:3 +msgid "The qir of the clean circuit" msgstr "" -#: of tensorcircuit.quantum.fidelity:11 -msgid "The sqrtm of a Hermitian matrix ``a``." +#: of tensorcircuit.noisemodel.apply_qir_with_noise:5 +#: tensorcircuit.noisemodel.circuit_with_noise:5 +msgid "Noise Configuration" msgstr "" -#: of tensorcircuit.quantum.free_energy:1 -msgid "Compute the free energy of the given density matrix." +#: of tensorcircuit.noisemodel.apply_qir_with_noise:7 +#: tensorcircuit.noisemodel.circuit_with_noise:7 +msgid "The status for Monte Carlo sampling, defaults to None" msgstr "" -#: of tensorcircuit.quantum.free_energy:15 -#: tensorcircuit.quantum.renyi_free_energy:14 -msgid "Hamiltonian operator in form of Tensor or QuOperator." +#: of tensorcircuit.noisemodel.apply_qir_with_noise:9 +#: tensorcircuit.noisemodel.circuit_with_noise:9 +msgid "A newly constructed circuit with noise" msgstr "" -#: of tensorcircuit.quantum.free_energy:22 -msgid "The free energy of the given density matrix with the Hamiltonian operator." +#: of tensorcircuit.noisemodel.circuit_with_noise:1 +msgid "Noisify a clean circuit." msgstr "" -#: of tensorcircuit.quantum.generate_local_hamiltonian:1 -msgid "" -"Generate a local Hamiltonian operator based on the given sequence of " -"Tensor. Note: further jit is recommended. For large Hilbert space, sparse" -" Hamiltonian is recommended" +#: of tensorcircuit.noisemodel.circuit_with_noise:3 +msgid "A clean circuit" msgstr "" -#: of tensorcircuit.quantum.generate_local_hamiltonian:5 -msgid "A sequence of Tensor." +#: of tensorcircuit.noisemodel.expectation_noisfy:1 +msgid "Calculate expectation value with noise configuration." msgstr "" -#: of tensorcircuit.quantum.generate_local_hamiltonian:7 -msgid "Return Hamiltonian operator in form of matrix, defaults to True." +#: of tensorcircuit.noisemodel.expectation_noisfy:3 +#: tensorcircuit.noisemodel.sample_expectation_ps_noisfy:3 +msgid "The clean circuit" msgstr "" -#: of tensorcircuit.quantum.generate_local_hamiltonian:9 -msgid "The Hamiltonian operator in form of QuOperator or matrix." +#: of tensorcircuit.noisemodel.expectation_noisfy:12 +msgid "expectation value with noise" msgstr "" -#: of tensorcircuit.quantum.gibbs_state:1 -msgid "Compute the Gibbs state of the given Hamiltonian operator ``h``." +#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:1 +msgid "Calculate sample_expectation_ps with noise configuration." msgstr "" -#: of tensorcircuit.quantum.gibbs_state:7 -msgid "The Gibbs state of ``h`` with the given ``beta``." +#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:13 +msgid "" +"repetition time for Monte Carlo sampling for noisfy calculation, " +"defaults to 1000" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:1 +#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:20 msgid "" -"Generate Heisenberg Hamiltonian with possible external fields. Currently " -"requires tensorflow installed" +"external randomness given by tensor uniformly from [0, 1], defaults to " +"None, used for measurement sampling" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:13 -msgid "input circuit graph" +#: of tensorcircuit.noisemodel.sample_expectation_ps_noisfy:23 +msgid "sample expectation value with noise" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:15 -msgid "zz coupling, default is 1.0" +#: ../../source/api/quantum.rst:2 +msgid "tensorcircuit.quantum" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:17 -msgid "xx coupling, default is 1.0" +#: of tensorcircuit.quantum:1 +msgid "Quantum state and operator class backend by tensornetwork" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:19 -msgid "yy coupling, default is 1.0" +#: of tensorcircuit.quantum +msgid "IMPORT" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:21 -msgid "External field on z direction, default is 0.0" +#: of tensorcircuit.quantum.PauliString2COO:1 +#: tensorcircuit.quantum.PauliStringSum2COO_tf:1 +msgid "Generate tensorflow sparse matrix from Pauli string sum" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:23 -msgid "External field on y direction, default is 0.0" +#: of tensorcircuit.quantum.PauliString2COO:3 +msgid "" +"1D Tensor representing for a Pauli string, e.g. [1, 0, 0, 3, 2] is for " +":math:`X_0Z_3Y_4`" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:25 -msgid "External field on x direction, default is 0.0" +#: of tensorcircuit.quantum.PauliString2COO:6 +msgid "" +"the weight for the Pauli string defaults to None (all Pauli strings " +"weight 1.0)" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:27 -msgid "Whether to return sparse Hamiltonian operator, default is True." +#: of tensorcircuit.quantum.PauliString2COO:9 +msgid "the tensorflow sparse matrix" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:29 -msgid "whether return the matrix in numpy or tensorflow form" +#: of tensorcircuit.quantum.PauliStringSum2COO:1 +#: tensorcircuit.quantum.PauliStringSum2COO_numpy:1 +msgid "" +"Generate sparse tensor from Pauli string sum. Currently requires " +"tensorflow installed" msgstr "" -#: of tensorcircuit.quantum.heisenberg_hamiltonian:32 -msgid "Hamiltonian measurements" +#: of tensorcircuit.quantum.PauliStringSum2COO:4 +#: tensorcircuit.quantum.PauliStringSum2COO_numpy:4 +#: tensorcircuit.quantum.PauliStringSum2COO_tf:3 +#: tensorcircuit.quantum.PauliStringSum2Dense:5 +msgid "" +"2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for " +":math:`X_0Z_3Y_4`" msgstr "" -#: of tensorcircuit.quantum.identity:1 +#: of tensorcircuit.quantum.PauliStringSum2COO:7 +#: tensorcircuit.quantum.PauliStringSum2COO_numpy:7 +#: tensorcircuit.quantum.PauliStringSum2COO_tf:6 +#: tensorcircuit.quantum.PauliStringSum2Dense:8 msgid "" -"Construct a 'QuOperator' representing the identity on a given space. " -"Internally, this is done by constructing 'CopyNode's for each edge, with " -"dimension according to 'space'." +"1D Tensor, each element corresponds the weight for each Pauli string " +"defaults to None (all Pauli strings weight 1.0)" msgstr "" -#: of tensorcircuit.quantum.identity:26 +#: of tensorcircuit.quantum.PauliStringSum2COO:10 +#: tensorcircuit.quantum.PauliStringSum2COO_numpy:10 +#: tensorcircuit.quantum.PauliStringSum2Dense:11 msgid "" -"A sequence of integers for the dimensions of the tensor product factors " -"of the space (the edges in the tensor network)." +"default False. If True, return numpy coo else return backend compatible " +"sparse tensor" msgstr "" -#: of tensorcircuit.quantum.identity:29 -msgid "" -"The data type by np.* (for conversion to dense). defaults None to tc " -"dtype." +#: of tensorcircuit.quantum.PauliStringSum2COO:13 +#: tensorcircuit.quantum.PauliStringSum2COO_numpy:13 +msgid "the scipy coo sparse matrix" msgstr "" -#: of tensorcircuit.quantum.identity:31 -msgid "The desired identity operator." +#: of tensorcircuit.quantum.PauliStringSum2COO_tf:9 +msgid "the tensorflow coo sparse matrix" msgstr "" -#: of tensorcircuit.quantum.measurement_counts:1 +#: of tensorcircuit.quantum.PauliStringSum2Dense:1 msgid "" -"Simulate the measuring of each qubit of ``p`` in the computational basis," -" thus producing output like that of ``qiskit``." +"Generate dense matrix from Pauli string sum. Currently requires " +"tensorflow installed." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:4 -msgid "Six formats of measurement counts results:" +#: of tensorcircuit.quantum.PauliStringSum2Dense:14 +msgid "the tensorflow dense matrix" msgstr "" -#: of tensorcircuit.quantum.measurement_counts:6 -msgid "\"sample_int\": # np.array([0, 0])" +#: of tensorcircuit.quantum.QuAdjointVector:1 tensorcircuit.quantum.QuScalar:1 +#: tensorcircuit.quantum.QuVector:1 +msgid "Bases: :py:class:`~tensorcircuit.quantum.QuOperator`" msgstr "" -#: of tensorcircuit.quantum.measurement_counts:8 -msgid "\"sample_bin\": # [np.array([1, 0]), np.array([1, 0])]" +#: of tensorcircuit.quantum.QuAdjointVector:1 +msgid "Represents an adjoint (row) vector via a tensor network." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:10 -msgid "\"count_vector\": # np.array([2, 0, 0, 0])" +#: of tensorcircuit.quantum.QuAdjointVector.__init__:1 +msgid "" +"Constructs a new `QuAdjointVector` from a tensor network. This " +"encapsulates an existing tensor network, interpreting it as an adjoint " +"vector (row vector)." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:12 -msgid "\"count_tuple\": # (np.array([0]), np.array([2]))" +#: of tensorcircuit.quantum.QuAdjointVector.__init__:5 +#: tensorcircuit.quantum.QuOperator.__init__:9 +msgid "The edges of the network to be used as the input edges." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:14 -msgid "\"count_dict_bin\": # {\"00\": 2, \"01\": 0, \"10\": 0, \"11\": 0}" +#: of tensorcircuit.quantum.QuAdjointVector.__init__:7 +#: tensorcircuit.quantum.QuOperator.__init__:11 +#: tensorcircuit.quantum.QuVector.__init__:6 +msgid "" +"Nodes used to refer to parts of the tensor network that are not connected" +" to any input or output edges (for example: a scalar factor)." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:16 -msgid "\"count_dict_int\": # {0: 2, 1: 0, 2: 0, 3: 0}" +#: of tensorcircuit.quantum.QuAdjointVector.__init__:10 +#: tensorcircuit.quantum.QuScalar.__init__:7 +#: tensorcircuit.quantum.QuVector.__init__:9 +msgid "Optional collection of edges to ignore when performing consistency checks." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:37 +#: of tensorcircuit.quantum.QuOperator.adjoint:1 msgid "" -"The quantum state, assumed to be normalized, as either a ket or density " -"operator." -msgstr "" - -#: of tensorcircuit.quantum.measurement_counts:39 -msgid "The number of counts to perform." +"The adjoint of the operator. This creates a new `QuOperator` with " +"complex-conjugate copies of all tensors in the network and with the input" +" and output edges switched." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:41 -msgid "alias for the argument ``counts``" +#: of tensorcircuit.quantum.QuOperator.adjoint:5 +msgid "The adjoint of the operator." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:43 -msgid "defaults to be \"direct\", see supported format above" +#: of tensorcircuit.quantum.QuOperator.check_network:1 +msgid "" +"Check that the network has the expected dimensionality. This checks that " +"all input and output edges are dangling and that there are no other " +"dangling edges (except any specified in `ignore_edges`). If not, an " +"exception is raised." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:47 +#: of tensorcircuit.quantum.QuOperator.contract:1 msgid "" -"if True, the `state` is directly regarded as a probability list, defaults" -" to be False" +"Contract the tensor network in place. This modifies the tensor network " +"representation of the operator (or vector, or scalar), reducing it to a " +"single tensor, without changing the value." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:55 -msgid "if True, jax backend try using a jittable count, defaults to False" +#: of tensorcircuit.quantum.QuOperator.contract:5 +msgid "Manually specify the axis ordering of the final tensor." msgstr "" -#: of tensorcircuit.quantum.measurement_counts:57 -msgid "The counts for each bit string measured." +#: of tensorcircuit.quantum.QuOperator.contract:7 +msgid "The present object." msgstr "" -#: of tensorcircuit.quantum.mutual_information:1 -msgid "Mutual information between AB subsystem described by ``cut``." +#: of tensorcircuit.quantum.QuOperator.copy:1 +msgid "The deep copy of the operator." msgstr "" -#: of tensorcircuit.quantum.mutual_information:5 -msgid "The AB subsystem." +#: of tensorcircuit.quantum.QuOperator.copy:3 +msgid "The new copy of the operator." msgstr "" -#: of tensorcircuit.quantum.mutual_information:7 -msgid "The mutual information between AB subsystem described by ``cut``." +#: of tensorcircuit.quantum.QuOperator.eval:1 +msgid "" +"Contracts the tensor network in place and returns the final tensor. Note " +"that this modifies the tensor network representing the operator. The " +"default ordering for the axes of the final tensor is: `*out_edges, " +"*in_edges`. If there are any \"ignored\" edges, their axes come first: " +"`*ignored_edges, *out_edges, *in_edges`." msgstr "" -#: of tensorcircuit.quantum.quantum_constructor:1 +#: of tensorcircuit.quantum.QuOperator.eval:8 +#: tensorcircuit.quantum.QuOperator.eval_matrix:6 msgid "" -"Constructs an appropriately specialized QuOperator. If there are no " -"edges, creates a QuScalar. If the are only output (input) edges, creates " -"a QuVector (QuAdjointVector). Otherwise creates a QuOperator." +"Manually specify the axis ordering of the final tensor. The default " +"ordering is determined by `out_edges` and `in_edges` (see above)." msgstr "" -#: of tensorcircuit.quantum.quantum_constructor:48 -msgid "A list of output edges." +#: of tensorcircuit.quantum.QuOperator.eval:11 +#: tensorcircuit.quantum.QuOperator.eval_matrix:9 +msgid "Node count '{}' > 1 after contraction!" msgstr "" -#: of tensorcircuit.quantum.quantum_constructor:50 -msgid "A list of input edges." +#: of tensorcircuit.quantum.QuOperator.eval:12 +msgid "The final tensor representing the operator." msgstr "" -#: of tensorcircuit.quantum.quantum_constructor:52 +#: of tensorcircuit.quantum.QuOperator.eval_matrix:1 msgid "" -"Reference nodes for the tensor network (needed if there is a. scalar " -"component)." -msgstr "" - -#: of tensorcircuit.quantum.quantum_constructor:55 -msgid "Edges to ignore when checking the dimensionality of the tensor network." +"Contracts the tensor network in place and returns the final tensor in two" +" dimentional matrix. The default ordering for the axes of the final " +"tensor is: (:math:`\\prod` dimension of out_edges, :math:`\\prod` " +"dimension of in_edges)" msgstr "" -#: of tensorcircuit.quantum.quantum_constructor:58 -msgid "The new created QuOperator object." +#: of tensorcircuit.quantum.QuOperator.eval_matrix:10 +msgid "The two-dimentional tensor representing the operator." msgstr "" -#: of tensorcircuit.quantum.quimb2qop:1 -msgid "Convert MPO in Quimb package to QuOperator." +#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:1 +msgid "" +"Construct a `QuAdjointVector` directly from a single tensor. This first " +"wraps the tensor in a `Node`, then constructs the `QuAdjointVector` from " +"that `Node`." msgstr "" -#: of tensorcircuit.quantum.quimb2qop:3 -msgid "MPO in the form of Quimb package" +#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:27 +msgid "The tensor for constructing an QuAdjointVector." msgstr "" -#: of tensorcircuit.quantum.quimb2qop:5 tensorcircuit.quantum.tn2qop:5 -msgid "MPO in the form of QuOperator" +#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:29 +msgid "" +"Sequence of integer indices specifying the order in which to interpret " +"the axes as subsystems (input edges). If not specified, the axes are " +"taken in ascending order." msgstr "" -#: of tensorcircuit.quantum.reduced_density_matrix:1 -msgid "Compute the reduced density matrix from the quantum state ``state``." +#: of tensorcircuit.quantum.QuAdjointVector.from_tensor:33 +msgid "The new constructed QuAdjointVector give from the given tensor." msgstr "" -#: of tensorcircuit.quantum.reduced_density_matrix:3 -msgid "The quantum state in form of Tensor or QuOperator." +#: of tensorcircuit.quantum.QuOperator.is_adjoint_vector:1 +msgid "" +"Returns a bool indicating if QuOperator is an adjoint vector. Examples " +"can be found in the `QuOperator.from_tensor`." msgstr "" -#: of tensorcircuit.quantum.reduced_density_matrix:5 +#: of tensorcircuit.quantum.QuOperator.is_scalar:1 msgid "" -"the index list that is traced out, if cut is a int, it indicates [0, cut]" -" as the traced out region" +"Returns a bool indicating if QuOperator is a scalar. Examples can be " +"found in the `QuOperator.from_tensor`." msgstr "" -#: of tensorcircuit.quantum.reduced_density_matrix:8 -msgid "probability decoration, default is None." +#: of tensorcircuit.quantum.QuOperator.is_vector:1 +msgid "" +"Returns a bool indicating if QuOperator is a vector. Examples can be " +"found in the `QuOperator.from_tensor`." msgstr "" -#: of tensorcircuit.quantum.reduced_density_matrix:10 -msgid "The reduced density matrix." +#: of tensorcircuit.quantum.QuAdjointVector.nodes:1 +#: tensorcircuit.quantum.QuOperator.nodes:1 +#: tensorcircuit.quantum.QuScalar.nodes:1 +#: tensorcircuit.quantum.QuVector.nodes:1 +msgid "All tensor-network nodes involved in the operator." msgstr "" -#: of tensorcircuit.quantum.renyi_entropy:1 -msgid "Compute the Rényi entropy of order :math:`k` by given density matrix." +#: of tensorcircuit.quantum.QuOperator.norm:1 +msgid "" +"The norm of the operator. This is the 2-norm (also known as the Frobenius" +" or Hilbert-Schmidt norm)." msgstr "" -#: of tensorcircuit.quantum.renyi_entropy:5 -#: tensorcircuit.quantum.renyi_free_energy:18 -msgid "The order of Rényi entropy, default is 2." +#: of tensorcircuit.quantum.QuOperator.partial_trace:1 +msgid "" +"The partial trace of the operator. Subsystems to trace out are supplied " +"as indices, so that dangling edges are connected to each other as: " +"`out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out` This does " +"not modify the original network. The original ordering of the remaining " +"subsystems is maintained." msgstr "" -#: of tensorcircuit.quantum.renyi_entropy:7 -#: tensorcircuit.quantum.renyi_free_energy:20 -msgid "The :math:`k` th order of Rényi entropy." +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:16 +#: tensorcircuit.quantum.QuOperator.partial_trace:8 +#: tensorcircuit.quantum.QuVector.reduced_density:16 +msgid "Indices of subsystems to trace out." msgstr "" -#: of tensorcircuit.quantum.renyi_free_energy:1 +#: of tensorcircuit.quantum.QuOperator.partial_trace:10 +msgid "A new QuOperator or QuScalar representing the result." +msgstr "" + +#: of tensorcircuit.quantum.QuAdjointVector.projector:1 +#: tensorcircuit.quantum.QuVector.projector:1 msgid "" -"Compute the Rényi free energy of the corresponding density matrix and " -"Hamiltonian." +"The projector of the operator. The operator, as a linear operator, on the" +" adjoint of the operator." msgstr "" -#: of tensorcircuit.quantum.sample2all:1 +#: of tensorcircuit.quantum.QuAdjointVector.projector:4 msgid "" -"transform ``sample_int`` or ``sample_bin`` form results to other forms " -"specified by ``format``" +"Set :math:`A` is the operator in matrix form, then the projector of " +"operator is defined as: :math:`A^\\dagger A`" msgstr "" -#: of tensorcircuit.quantum.sample2all:3 -msgid "measurement shots results in ``sample_int`` or ``sample_bin`` format" +#: of tensorcircuit.quantum.QuAdjointVector.projector:6 +#: tensorcircuit.quantum.QuVector.projector:6 +msgid "The projector of the operator." msgstr "" -#: of tensorcircuit.quantum.sample2all:7 -msgid "" -"see the doc in the doc in " -":py:meth:`tensorcircuit.quantum.measurement_results`, defaults to " -"\"count_vector\"" +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:1 +#: tensorcircuit.quantum.QuVector.reduced_density:1 +msgid "The reduced density of the operator." msgstr "" -#: of tensorcircuit.quantum.sample2all:12 -msgid "only applicable to count transformation in jax backend, defaults to False" +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:3 +#: tensorcircuit.quantum.QuVector.reduced_density:3 +msgid "" +"Set :math:`A` is the matrix of the operator, then the reduced density is " +"defined as:" msgstr "" -#: of tensorcircuit.quantum.sample2all:14 -msgid "measurement results specified as ``format``" +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:5 +msgid "\\mathrm{Tr}_{subsystems}(A^\\dagger A)" msgstr "" -#: of tensorcircuit.quantum.sample2count:1 -msgid "sample_int to count_tuple" +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:9 +#: tensorcircuit.quantum.QuVector.reduced_density:9 +msgid "" +"Firstly, take the projector of the operator, then trace out the " +"subsystems to trace out are supplied as indices, so that dangling edges " +"are connected to each other as: `out_edges[i] ^ in_edges[i] for i in " +"subsystems_to_trace_out` This does not modify the original network. The " +"original ordering of the remaining subsystems is maintained." msgstr "" -#: of tensorcircuit.quantum.sample_bin2int:1 -msgid "bin sample to int sample" +#: of tensorcircuit.quantum.QuAdjointVector.reduced_density:18 +#: tensorcircuit.quantum.QuVector.reduced_density:18 +msgid "" +"The QuOperator of the reduced density of the operator with given " +"subsystems." msgstr "" -#: of tensorcircuit.quantum.sample_bin2int:3 -msgid "in shape [trials, n] of elements (0, 1)" +#: of tensorcircuit.quantum.QuOperator.tensor_product:1 +msgid "" +"Tensor product with another operator. Given two operators `A` and `B`, " +"produces a new operator `AB` representing :math:`A ⊗ B`. The `out_edges` " +"(`in_edges`) of `AB` is simply the concatenation of the `out_edges` " +"(`in_edges`) of `A.copy()` with that of `B.copy()`: `new_out_edges = " +"[*out_edges_A_copy, *out_edges_B_copy]` `new_in_edges = " +"[*in_edges_A_copy, *in_edges_B_copy]`" msgstr "" -#: of tensorcircuit.quantum.sample_bin2int:7 -msgid "in shape [trials]" +#: of tensorcircuit.quantum.QuOperator.tensor_product:20 +msgid "The other operator (`B`)." msgstr "" -#: of tensorcircuit.quantum.sample_int2bin:1 -msgid "int sample to bin sample" +#: of tensorcircuit.quantum.QuOperator.tensor_product:22 +msgid "The result (`AB`)." msgstr "" -#: of tensorcircuit.quantum.sample_int2bin:3 -msgid "in shape [trials] of int elements in the range [0, 2**n)" +#: of tensorcircuit.quantum.QuOperator.trace:1 +msgid "The trace of the operator." msgstr "" -#: of tensorcircuit.quantum.sample_int2bin:7 -msgid "in shape [trials, n] of element (0, 1)" +#: of tensorcircuit.quantum.QuOperator:1 +msgid "" +"Represents a linear operator via a tensor network. To interpret a tensor " +"network as a linear operator, some of the dangling edges must be " +"designated as `out_edges` (output edges) and the rest as `in_edges` " +"(input edges). Considered as a matrix, the `out_edges` represent the row " +"index and the `in_edges` represent the column index. The (right) action " +"of the operator on another then consists of connecting the `in_edges` of " +"the first operator to the `out_edges` of the second. Can be used to do " +"simple linear algebra with tensor networks." msgstr "" -#: of tensorcircuit.quantum.spin_by_basis:1 +#: of tensorcircuit.quantum.QuOperator.__init__:1 msgid "" -"Generate all n-bitstrings as an array, each row is a bitstring basis. " -"Return m-th col." +"Creates a new `QuOperator` from a tensor network. This encapsulates an " +"existing tensor network, interpreting it as a linear operator. The " +"network is checked for consistency: All dangling edges must either be in " +"`out_edges`, `in_edges`, or `ignore_edges`." msgstr "" -#: of tensorcircuit.quantum.spin_by_basis:9 -msgid "length of a bitstring" +#: of tensorcircuit.quantum.QuOperator.__init__:7 +#: tensorcircuit.quantum.QuVector.__init__:4 +msgid "The edges of the network to be used as the output edges." msgstr "" -#: of tensorcircuit.quantum.spin_by_basis:11 -msgid "m is transformed as " -"(01>-|10>)" +#: of tensorcircuit.quantum.measurement_counts:10 +msgid "\"count_vector\": # np.array([2, 0, 0, 0])" msgstr "" -#: of tensorcircuit.templates.blocks.Bell_pair_block:3 -#: tensorcircuit.templates.blocks.qft:3 -msgid "Circuit in" +#: of tensorcircuit.quantum.measurement_counts:12 +msgid "\"count_tuple\": # (np.array([0]), np.array([2]))" msgstr "" -#: of tensorcircuit.templates.blocks.Bell_pair_block:5 -msgid "" -"pairs indices for Bell pairs, defaults to None, corresponds to neighbor " -"links" +#: of tensorcircuit.quantum.measurement_counts:14 +msgid "\"count_dict_bin\": # {\"00\": 2, \"01\": 0, \"10\": 0, \"11\": 0}" msgstr "" -#: of tensorcircuit.templates.blocks.Bell_pair_block:7 -msgid "Circuit out" +#: of tensorcircuit.quantum.measurement_counts:16 +msgid "\"count_dict_int\": # {0: 2, 1: 0, 2: 0, 3: 0}" msgstr "" -#: of tensorcircuit.templates.blocks.example_block:1 +#: of tensorcircuit.quantum.measurement_counts:37 msgid "" -"The circuit ansatz is firstly one layer of Hadamard gates and then we " -"have ``nlayers`` blocks of :math:`e^{i\\theta Z_iZ_{i+1}}` two-qubit gate" -" in ladder layout, following rx gate." +"The quantum state, assumed to be normalized, as either a ket or density " +"operator." msgstr "" -#: of tensorcircuit.templates.blocks.example_block:5 -msgid "The circuit" +#: of tensorcircuit.quantum.measurement_counts:39 +msgid "The number of counts to perform." msgstr "" -#: of tensorcircuit.templates.blocks.example_block:7 -msgid "paramter tensor with 2*nlayer*n elements" +#: of tensorcircuit.quantum.measurement_counts:41 +msgid "alias for the argument ``counts``" msgstr "" -#: of tensorcircuit.templates.blocks.example_block:9 -msgid "number of ZZ+RX blocks, defaults to 2" +#: of tensorcircuit.quantum.measurement_counts:43 +msgid "defaults to be \"direct\", see supported format above" msgstr "" -#: of tensorcircuit.templates.blocks.example_block:11 -msgid "whether use SVD split to reduce ZZ gate bond dimension, defaults to False" +#: of tensorcircuit.quantum.measurement_counts:47 +msgid "" +"if True, the `state` is directly regarded as a probability list, defaults" +" to be False" msgstr "" -#: of tensorcircuit.templates.blocks.example_block:14 -msgid "The circuit with example ansatz attached" +#: of tensorcircuit.quantum.measurement_counts:55 +msgid "if True, jax backend try using a jittable count, defaults to False" msgstr "" -#: of tensorcircuit.templates.blocks.qft:1 -msgid "" -"This function applies quantum fourier transformation (QFT) to the " -"selected circuit lines" +#: of tensorcircuit.quantum.measurement_counts:57 +msgid "The counts for each bit string measured." msgstr "" -#: of tensorcircuit.templates.blocks.qft:5 -msgid "the indices of the circuit lines to apply QFT" +#: of tensorcircuit.quantum.mutual_information:1 +msgid "Mutual information between AB subsystem described by ``cut``." msgstr "" -#: of tensorcircuit.templates.blocks.qft:7 -msgid "Whether to include the final swaps in the QFT" +#: of tensorcircuit.quantum.mutual_information:5 +msgid "The AB subsystem." msgstr "" -#: of tensorcircuit.templates.blocks.qft:9 -msgid "If True, the inverse Fourier transform is constructed" +#: of tensorcircuit.quantum.mutual_information:7 +msgid "The mutual information between AB subsystem described by ``cut``." msgstr "" -#: of tensorcircuit.templates.blocks.qft:11 -msgid "If True, barriers are inserted as visualization improvement" +#: of tensorcircuit.quantum.ps2xyz:1 +msgid "pauli string list to xyz dict" msgstr "" -#: of tensorcircuit.templates.blocks.qft:13 -msgid "Circuit c" +#: of tensorcircuit.quantum.ps2xyz:3 +msgid "# ps2xyz([1, 2, 2, 0]) = {\"x\": [0], \"y\": [1, 2], \"z\": []}" msgstr "" -#: of tensorcircuit.templates.blocks.state_centric:1 +#: of tensorcircuit.quantum.quantum_constructor:1 msgid "" -"Function decorator wraps the function with the first input and output in " -"the format of circuit, the wrapped function has the first input and the " -"output as the state tensor." +"Constructs an appropriately specialized QuOperator. If there are no " +"edges, creates a QuScalar. If the are only output (input) edges, creates " +"a QuVector (QuAdjointVector). Otherwise creates a QuOperator." msgstr "" -#: of tensorcircuit.templates.blocks.state_centric:4 -msgid "Function with the fist input and the output as ``Circuit`` object." +#: of tensorcircuit.quantum.quantum_constructor:48 +msgid "A list of output edges." msgstr "" -#: of tensorcircuit.templates.blocks.state_centric:6 +#: of tensorcircuit.quantum.quantum_constructor:50 +msgid "A list of input edges." +msgstr "" + +#: of tensorcircuit.quantum.quantum_constructor:52 msgid "" -"Wrapped function with the first input and the output as the state tensor " -"correspondingly." +"Reference nodes for the tensor network (needed if there is a. scalar " +"component)." msgstr "" -#: ../../source/api/templates/chems.rst:2 -msgid "tensorcircuit.templates.chems" +#: of tensorcircuit.quantum.quantum_constructor:55 +msgid "Edges to ignore when checking the dimensionality of the tensor network." msgstr "" -#: of tensorcircuit.templates.chems:1 -msgid "Useful utilities for quantum chemistry related task" +#: of tensorcircuit.quantum.quantum_constructor:58 +msgid "The new created QuOperator object." msgstr "" -#: of tensorcircuit.templates.chems.get_ps:1 -msgid "" -"Get Pauli string array and weights array for a qubit Hamiltonian as a sum" -" of Pauli strings defined in openfermion ``QubitOperator``." +#: of tensorcircuit.quantum.quimb2qop:1 +msgid "Convert MPO in Quimb package to QuOperator." msgstr "" -#: of tensorcircuit.templates.chems.get_ps:4 -msgid "``openfermion.ops.operators.qubit_operator.QubitOperator``" +#: of tensorcircuit.quantum.quimb2qop:3 +msgid "MPO in the form of Quimb package" msgstr "" -#: of tensorcircuit.templates.chems.get_ps:6 -msgid "The number of qubits" +#: of tensorcircuit.quantum.quimb2qop:5 tensorcircuit.quantum.tn2qop:5 +msgid "MPO in the form of QuOperator" msgstr "" -#: of tensorcircuit.templates.chems.get_ps:8 -msgid "Pauli String array and weights array" +#: of tensorcircuit.quantum.reduced_density_matrix:1 +msgid "Compute the reduced density matrix from the quantum state ``state``." msgstr "" -#: ../../source/api/templates/dataset.rst:2 -msgid "tensorcircuit.templates.dataset" +#: of tensorcircuit.quantum.reduced_density_matrix:3 +msgid "The quantum state in form of Tensor or QuOperator." msgstr "" -#: of tensorcircuit.templates.dataset:1 -msgid "Quantum machine learning related data preprocessing and embedding" +#: of tensorcircuit.quantum.reduced_density_matrix:5 +msgid "" +"the index list that is traced out, if cut is a int, it indicates [0, cut]" +" as the traced out region" msgstr "" -#: ../../source/api/templates/graphs.rst:2 -msgid "tensorcircuit.templates.graphs" +#: of tensorcircuit.quantum.reduced_density_matrix:8 +msgid "probability decoration, default is None." msgstr "" -#: of tensorcircuit.templates.graphs:1 -msgid "Some common graphs and lattices" +#: of tensorcircuit.quantum.reduced_density_matrix:10 +msgid "The reduced density matrix." msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord:1 -msgid "Two-dimensional grid lattice" +#: of tensorcircuit.quantum.renyi_entropy:1 +msgid "Compute the Rényi entropy of order :math:`k` by given density matrix." msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.__init__:1 -msgid "number of rows" +#: of tensorcircuit.quantum.renyi_entropy:5 +#: tensorcircuit.quantum.renyi_free_energy:18 +msgid "The order of Rényi entropy, default is 2." msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.__init__:3 -msgid "number of cols" +#: of tensorcircuit.quantum.renyi_entropy:7 +#: tensorcircuit.quantum.renyi_free_energy:20 +msgid "The :math:`k` th order of Rényi entropy." msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:1 -msgid "return all col edge with 1d index encoding" +#: of tensorcircuit.quantum.renyi_free_energy:1 +msgid "" +"Compute the Rényi free energy of the corresponding density matrix and " +"Hamiltonian." msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:3 -#: tensorcircuit.templates.graphs.Grid2DCoord.all_rows:3 +#: of tensorcircuit.quantum.sample2all:1 msgid "" -"whether to include pbc edges (periodic boundary condition), defaults to " -"False" +"transform ``sample_int`` or ``sample_bin`` form results to other forms " +"specified by ``format``" msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:6 -msgid "list of col edge" +#: of tensorcircuit.quantum.sample2all:3 +msgid "measurement shots results in ``sample_int`` or ``sample_bin`` format" msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.all_rows:1 -msgid "return all row edge with 1d index encoding" +#: of tensorcircuit.quantum.sample2all:7 +msgid "" +"see the doc in the doc in " +":py:meth:`tensorcircuit.quantum.measurement_results`, defaults to " +"\"count_vector\"" msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.all_rows:6 -msgid "list of row edge" +#: of tensorcircuit.quantum.sample2all:12 +msgid "only applicable to count transformation in jax backend, defaults to False" msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph:1 -msgid "Get the 2D grid lattice in ``nx.Graph`` format" +#: of tensorcircuit.quantum.sample2all:14 +msgid "measurement results specified as ``format``" msgstr "" -#: of tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph:3 -msgid "" -"whether to include pbc edges (periodic boundary condition), defaults to " -"True" +#: of tensorcircuit.quantum.sample2count:1 +msgid "sample_int to count_tuple" msgstr "" -#: of tensorcircuit.templates.graphs.Line1D:1 -msgid "1D chain with ``n`` sites" +#: of tensorcircuit.quantum.sample_bin2int:1 +msgid "bin sample to int sample" msgstr "" -#: of tensorcircuit.templates.graphs.Line1D:5 -#: tensorcircuit.templates.measurements.heisenberg_measurements:34 -msgid "[description], defaults to True" +#: of tensorcircuit.quantum.sample_bin2int:3 +msgid "in shape [trials, n] of elements (0, 1)" msgstr "" -#: ../../source/api/templates/measurements.rst:2 -msgid "tensorcircuit.templates.measurements" +#: of tensorcircuit.quantum.sample_bin2int:7 +msgid "in shape [trials]" msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:1 -msgid "" -"This measurements pattern is specifically suitable for vmap. Parameterize" -" the local Pauli string to be measured." +#: of tensorcircuit.quantum.sample_int2bin:1 +msgid "int sample to bin sample" msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:19 -#: tensorcircuit.templates.measurements.any_measurements:26 -msgid "The circuit to be measured" +#: of tensorcircuit.quantum.sample_int2bin:3 +msgid "in shape [trials] of int elements in the range [0, 2**n)" msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:21 -#: tensorcircuit.templates.measurements.any_measurements:28 -msgid "" -"parameter tensors determines what Pauli string to be measured, shape is " -"[nwires, 4] if ``onehot`` is False and [nwires] if ``onehot`` is True." +#: of tensorcircuit.quantum.sample_int2bin:7 +msgid "in shape [trials, n] of element (0, 1)" msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:24 -#: tensorcircuit.templates.measurements.any_measurements:31 +#: of tensorcircuit.quantum.spin_by_basis:1 msgid "" -"defaults to False. If set to be True, structures will first go through " -"onehot procedure." +"Generate all n-bitstrings as an array, each row is a bitstring basis. " +"Return m-th col." msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:27 -msgid "" -"reuse the wavefunction when computing the expectations, defaults to be " -"True" +#: of tensorcircuit.quantum.spin_by_basis:9 +msgid "length of a bitstring" msgstr "" -#: of tensorcircuit.templates.measurements.any_local_measurements:29 -#: tensorcircuit.templates.measurements.any_measurements:36 -msgid "The expectation value of given Pauli string by the tensor ``structures``." +#: of tensorcircuit.quantum.spin_by_basis:11 +msgid "m`." +#: ../../source/api/results/readout_mitigation.rst:2 +msgid "tensorcircuit.results.readout_mitigation" msgstr "" -#: of torch.nn.modules.module.Module.eval:10 -msgid "" -"See :ref:`locally-disable-grad-doc` for a comparison between `.eval()` " -"and several similar mechanisms that may be confused with it." +#: of tensorcircuit.results.readout_mitigation:1 +msgid "readout error mitigation functionalities" msgstr "" -#: of torch.nn.modules.module.Module.extra_repr:1 -msgid "Set the extra representation of the module" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.__init__:1 +msgid "The Class for readout error mitigation" msgstr "" -#: of torch.nn.modules.module.Module.extra_repr:3 -msgid "" -"To print customized extra information, you should re-implement this " -"method in your own modules. Both single-line and multi-line strings are " -"acceptable." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.__init__:3 +msgid "execute function to run the cirucit" msgstr "" -#: of torch.nn.modules.module.Module.float:1 -msgid "Casts all floating point parameters and buffers to ``float`` datatype." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.__init__:5 +msgid "iteration threshold, defaults to 4096" msgstr "" -#: of tensorcircuit.torchnn.QuantumNet.forward:1 -msgid "Defines the computation performed at every call." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:1 +msgid "Main readout mitigation program for all methods." msgstr "" -#: of tensorcircuit.torchnn.QuantumNet.forward:3 -msgid "Should be overridden by all subclasses." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:3 +msgid "raw count" msgstr "" -#: of tensorcircuit.torchnn.QuantumNet.forward:6 -msgid "" -"Although the recipe for forward pass needs to be defined within this " -"function, one should call the :class:`Module` instance afterwards instead" -" of this since the former takes care of running the registered hooks " -"while the latter silently ignores them." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:5 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:6 +msgid "user-defined logical qubits to show final mitted results" msgstr "" -#: of torch.nn.modules.module.Module.get_buffer:1 -msgid "" -"Returns the buffer given by ``target`` if it exists, otherwise throws an " -"error." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:7 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:11 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:8 +msgid "positional_logical_mapping, defaults to None." msgstr "" -#: of torch.nn.modules.module.Module.get_buffer:4 -#: torch.nn.modules.module.Module.get_parameter:4 -msgid "" -"See the docstring for ``get_submodule`` for a more detailed explanation " -"of this method's functionality as well as how to correctly specify " -"``target``." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:9 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:13 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:10 +msgid "logical_physical_mapping, defaults to None" msgstr "" -#: of torch.nn.modules.module.Module.get_buffer:8 -msgid "" -"The fully-qualified string name of the buffer to look for. (See " -"``get_submodule`` for how to specify a fully-qualified string.)" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:11 +msgid "defaults to None" msgstr "" -#: of torch.nn.modules.module.Module.get_buffer:12 -msgid "The buffer referenced by ``target``" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:13 +msgid "mitigation method, defaults to \"square\"" msgstr "" -#: of torch.nn.modules.module.Module.get_buffer:15 -msgid "" -"If the target string references an invalid path or resolves to " -"something that is not a buffer" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:15 +msgid "defaults to 25" msgstr "" -#: of torch.nn.modules.module.Module.get_extra_state:1 -msgid "" -"Returns any extra state to include in the module's state_dict. Implement " -"this and a corresponding :func:`set_extra_state` for your module if you " -"need to store extra state. This function is called when building the " -"module's `state_dict()`." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:17 +msgid "defaults to 1e-5" msgstr "" -#: of torch.nn.modules.module.Module.get_extra_state:6 +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.apply_correction:19 msgid "" -"Note that extra state should be pickleable to ensure working " -"serialization of the state_dict. We only provide provide backwards " -"compatibility guarantees for serializing Tensors; other objects may break" -" backwards compatibility if their serialized pickled form changes." +":param return_mitigation_overhead:defaults to False :type " +"return_mitigation_overhead: bool, optional :param details: defaults to " +"False :type details: bool, optional :return: mitigated count :rtype: ct" msgstr "" -#: of torch.nn.modules.module.Module.get_extra_state:11 -msgid "Any extra state to store in the module's state_dict" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation:1 +msgid "Main readout mitigation program for method=\"inverse\" or \"square\"" msgstr "" -#: of torch.nn.modules.module.Module.get_parameter:1 -msgid "" -"Returns the parameter given by ``target`` if it exists, otherwise throws " -"an error." +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation:3 +msgid "the raw count" msgstr "" -#: of torch.nn.modules.module.Module.get_parameter:8 -msgid "" -"The fully-qualified string name of the Parameter to look for. (See " -"``get_submodule`` for how to specify a fully-qualified string.)" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation:5 +msgid "mitigation method, defaults to \"inverse\"" msgstr "" -#: of torch.nn.modules.module.Module.get_parameter:12 -msgid "The Parameter referenced by ``target``" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.apply_readout_mitigation:7 +msgid "mitigated count" msgstr "" -#: of torch.nn.modules.module.Module.get_parameter:15 -msgid "" -"If the target string references an invalid path or resolves to " -"something that is not an ``nn.Parameter``" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_api:1 +msgid "Get local calibriation matrix from cloud API from tc supported providers" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:1 -msgid "" -"Returns the submodule given by ``target`` if it exists, otherwise throws " -"an error." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_api:3 +msgid "list of physical qubits to be calibriated" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:4 -msgid "" -"For example, let's say you have an ``nn.Module`` ``A`` that looks like " -"this:" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_api:5 +msgid "the device str to qurey for the info, defaults to None" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:18 -msgid "" -"(The diagram shows an ``nn.Module`` ``A``. ``A`` has a nested submodule " -"``net_b``, which itself has two submodules ``net_c`` and ``linear``. " -"``net_c`` then has a submodule ``conv``.)" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_system:1 +msgid "Get calibrattion information from system." msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:22 -msgid "" -"To check whether or not we have the ``linear`` submodule, we would call " -"``get_submodule(\"net_b.linear\")``. To check whether we have the " -"``conv`` submodule, we would call " -"``get_submodule(\"net_b.net_c.conv\")``." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_system:3 +msgid "calibration qubit list (physical qubits on device)" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:27 -msgid "" -"The runtime of ``get_submodule`` is bounded by the degree of module " -"nesting in ``target``. A query against ``named_modules`` achieves the " -"same result, but it is O(N) in the number of transitive modules. So, for " -"a simple check to see if some submodule exists, ``get_submodule`` should " -"always be used." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_system:5 +msgid "shots used for runing the circuit, defaults to 8192" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:34 -msgid "" -"The fully-qualified string name of the submodule to look for. (See above " -"example for how to specify a fully-qualified string.)" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.cals_from_system:7 +msgid "calibration method, defaults to \"local\", it can also be \"global\"" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:38 -msgid "The submodule referenced by ``target``" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:1 +msgid "Calculate expectation value after readout error mitigation" msgstr "" -#: of torch.nn.modules.module.Module.get_submodule:41 -msgid "" -"If the target string references an invalid path or resolves to " -"something that is not an ``nn.Module``" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:3 +msgid "raw counts" msgstr "" -#: of torch.nn.modules.module.Module.half:1 -msgid "Casts all floating point parameters and buffers to ``half`` datatype." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:15 +msgid "readout mitigation method, defaults to \"constrained_least_square\"" msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:1 -msgid "" -"Copies parameters and buffers from :attr:`state_dict` into this module " -"and its descendants. If :attr:`strict` is ``True``, then the keys of " -":attr:`state_dict` must exactly match the keys returned by this module's " -":meth:`~torch.nn.Module.state_dict` function." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.expectation:17 +msgid "expectation value after readout error mitigation" msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:6 -msgid "a dict containing parameters and persistent buffers." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.get_matrix:1 +msgid "Calculate cal_matrix according to use qubit list." msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:9 -msgid "" -"whether to strictly enforce that the keys in :attr:`state_dict` match the" -" keys returned by this module's :meth:`~torch.nn.Module.state_dict` " -"function. Default: ``True``" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.get_matrix:3 +msgid "used qubit list, defaults to None" msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:14 -msgid "" -"* **missing_keys** is a list of str containing the missing keys * " -"**unexpected_keys** is a list of str containing the unexpected keys" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.get_matrix:5 +msgid "cal_matrix" msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:14 -msgid "**missing_keys** is a list of str containing the missing keys" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.global_miti_readout_circ:1 +msgid "Generate circuits for global calibration." msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:15 -msgid "**unexpected_keys** is a list of str containing the unexpected keys" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.global_miti_readout_circ:3 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.local_miti_readout_circ:3 +msgid "circuit list" msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:16 -msgid "``NamedTuple`` with ``missing_keys`` and ``unexpected_keys`` fields" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.local_miti_readout_circ:1 +msgid "Generate circuits for local calibration." msgstr "" -#: of torch.nn.modules.module.Module.load_state_dict:20 +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:1 msgid "" -"If a parameter or buffer is registered as ``None`` and its corresponding " -"key exists in :attr:`state_dict`, :meth:`load_state_dict` will raise a " -"``RuntimeError``." +"Preprocessing to deal with qubit mapping, including " +"positional_logical_mapping and logical_physical_mapping. Return " +"self.use_qubits(physical) and corresponding counts." msgstr "" -#: of torch.nn.modules.module.Module.modules:1 -msgid "Returns an iterator over all modules in the network." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:4 +msgid "raw_counts on positional_qubits" msgstr "" -#: of torch.nn.modules.module.Module.modules:3 -msgid "*Module* -- a module in the network" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.mapping_preprocess:12 +msgid "counts on self.use_qubit(physical)" msgstr "" -#: of torch.nn.modules.module.Module.modules:7 -#: torch.nn.modules.module.Module.named_modules:13 -msgid "" -"Duplicate modules are returned only once. In the following example, ``l``" -" will be returned only once." +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mitigate_probability:1 +msgid "Get the mitigated probability." msgstr "" -#: of torch.nn.modules.module.Module.named_buffers:1 -msgid "" -"Returns an iterator over module buffers, yielding both the name of the " -"buffer as well as the buffer itself." +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mitigate_probability:3 +msgid "probability of raw count" msgstr "" -#: of torch.nn.modules.module.Module.named_buffers:4 -msgid "prefix to prepend to all buffer names." +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mitigate_probability:5 +msgid "mitigation methods, defaults to \"inverse\", it can also be \"square\"" msgstr "" -#: of torch.nn.modules.module.Module.named_buffers:11 -msgid "*(string, torch.Tensor)* -- Tuple containing the name and buffer" +#: of +#: tensorcircuit.results.readout_mitigation.ReadoutMit.mitigate_probability:7 +msgid "mitigated probability" msgstr "" -#: of torch.nn.modules.module.Module.named_children:1 -msgid "" -"Returns an iterator over immediate children modules, yielding both the " -"name of the module as well as the module itself." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.newrange:1 +msgid "Rerange the order according to used qubit list." msgstr "" -#: of torch.nn.modules.module.Module.named_children:4 -msgid "*(string, Module)* -- Tuple containing a name and child module" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.newrange:3 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.ubs:3 +msgid "index" msgstr "" -#: of torch.nn.modules.module.Module.named_modules:1 -msgid "" -"Returns an iterator over all modules in the network, yielding both the " -"name of the module as well as the module itself." +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.newrange:5 +#: tensorcircuit.results.readout_mitigation.ReadoutMit.ubs:5 +msgid "used qubit list" msgstr "" -#: of torch.nn.modules.module.Module.named_modules:4 -msgid "a memo to store the set of modules already added to the result" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.newrange:7 +msgid "new index" msgstr "" -#: of torch.nn.modules.module.Module.named_modules:5 -msgid "a prefix that will be added to the name of the module" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.ubs:1 +msgid "Help omit calibration results that not in used qubit list." msgstr "" -#: of torch.nn.modules.module.Module.named_modules:6 -msgid "whether to remove the duplicated module instances in the result or not" +#: of tensorcircuit.results.readout_mitigation.ReadoutMit.ubs:7 +msgid "omitation related value" msgstr "" -#: of torch.nn.modules.module.Module.named_modules:9 -msgid "*(string, Module)* -- Tuple of name and module" +#: ../../source/api/simplify.rst:2 +msgid "tensorcircuit.simplify" msgstr "" -#: of torch.nn.modules.module.Module.named_parameters:1 +#: of tensorcircuit.simplify:1 +msgid "Tensornetwork Simplification" +msgstr "" + +#: of tensorcircuit.simplify.infer_new_shape:1 msgid "" -"Returns an iterator over module parameters, yielding both the name of the" -" parameter as well as the parameter itself." +"Get the new shape of two nodes, also supporting to return original shapes" +" of two nodes." msgstr "" -#: of torch.nn.modules.module.Module.named_parameters:4 -msgid "prefix to prepend to all parameter names." +#: of tensorcircuit.simplify.infer_new_shape:13 +msgid "node one" msgstr "" -#: of torch.nn.modules.module.Module.named_parameters:6 -#: torch.nn.modules.module.Module.parameters:5 -msgid "" -"if True, then yields parameters of this module and all submodules. " -"Otherwise, yields only parameters that are direct members of this module." +#: of tensorcircuit.simplify.infer_new_shape:15 +msgid "node two" msgstr "" -#: of torch.nn.modules.module.Module.named_parameters:11 -msgid "*(string, Parameter)* -- Tuple containing the name and parameter" +#: of tensorcircuit.simplify.infer_new_shape:17 +msgid "Whether to include original shape of two nodes, default is True." msgstr "" -#: of torch.nn.modules.module.Module.parameters:1 -msgid "Returns an iterator over module parameters." +#: of tensorcircuit.simplify.infer_new_shape:19 +msgid "The new shape of the two nodes." msgstr "" -#: of torch.nn.modules.module.Module.parameters:3 -msgid "This is typically passed to an optimizer." +#: of tensorcircuit.simplify.pseudo_contract_between:1 +msgid "" +"Contract between Node ``a`` and ``b``, with correct shape only and no " +"calculation" msgstr "" -#: of torch.nn.modules.module.Module.parameters:10 -msgid "*Parameter* -- module parameter" +#: ../../source/api/templates.rst:2 +msgid "tensorcircuit.templates" msgstr "" -#: of torch.nn.modules.module.Module.register_backward_hook:1 -#: torch.nn.modules.module.Module.register_full_backward_hook:1 -msgid "Registers a backward hook on the module." +#: ../../source/api/templates/blocks.rst:2 +msgid "tensorcircuit.templates.blocks" msgstr "" -#: of torch.nn.modules.module.Module.register_backward_hook:3 -msgid "" -"This function is deprecated in favor of " -":meth:`~torch.nn.Module.register_full_backward_hook` and the behavior of " -"this function will change in future versions." +#: of tensorcircuit.templates.blocks:1 tensorcircuit.templates.measurements:1 +msgid "Shortcuts for measurement patterns on circuit" msgstr "" -#: of torch.nn.modules.module.Module.register_backward_hook:6 -#: torch.nn.modules.module.Module.register_forward_hook:14 -#: torch.nn.modules.module.Module.register_forward_pre_hook:14 -#: torch.nn.modules.module.Module.register_full_backward_hook:25 +#: of tensorcircuit.templates.blocks.Bell_pair_block:1 msgid "" -"a handle that can be used to remove the added hook by calling " -"``handle.remove()``" +"For each pair in links, the input product state |00> is transformed as " +"(01>-|10>)" msgstr "" -#: of torch.nn.modules.module.Module.register_backward_hook:8 -#: torch.nn.modules.module.Module.register_forward_hook:16 -#: torch.nn.modules.module.Module.register_forward_pre_hook:16 -#: torch.nn.modules.module.Module.register_full_backward_hook:27 -msgid ":class:`torch.utils.hooks.RemovableHandle`" +#: of tensorcircuit.templates.blocks.Bell_pair_block:3 +#: tensorcircuit.templates.blocks.qft:3 +msgid "Circuit in" msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:1 -msgid "Adds a buffer to the module." +#: of tensorcircuit.templates.blocks.Bell_pair_block:5 +msgid "" +"pairs indices for Bell pairs, defaults to None, corresponds to neighbor " +"links" msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:3 +#: of tensorcircuit.templates.blocks.Bell_pair_block:7 +msgid "Circuit out" +msgstr "" + +#: of tensorcircuit.templates.blocks.example_block:1 msgid "" -"This is typically used to register a buffer that should not to be " -"considered a model parameter. For example, BatchNorm's ``running_mean`` " -"is not a parameter, but is part of the module's state. Buffers, by " -"default, are persistent and will be saved alongside parameters. This " -"behavior can be changed by setting :attr:`persistent` to ``False``. The " -"only difference between a persistent buffer and a non-persistent buffer " -"is that the latter will not be a part of this module's " -":attr:`state_dict`." +"The circuit ansatz is firstly one layer of Hadamard gates and then we " +"have ``nlayers`` blocks of :math:`e^{i\\theta Z_iZ_{i+1}}` two-qubit gate" +" in ladder layout, following rx gate." msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:12 -msgid "Buffers can be accessed as attributes using given names." +#: of tensorcircuit.templates.blocks.example_block:5 +msgid "The circuit" msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:14 -msgid "" -"name of the buffer. The buffer can be accessed from this module using the" -" given name" +#: of tensorcircuit.templates.blocks.example_block:7 +msgid "paramter tensor with 2*nlayer*n elements" msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:17 -msgid "" -"buffer to be registered. If ``None``, then operations that run on " -"buffers, such as :attr:`cuda`, are ignored. If ``None``, the buffer is " -"**not** included in the module's :attr:`state_dict`." +#: of tensorcircuit.templates.blocks.example_block:9 +msgid "number of ZZ+RX blocks, defaults to 2" msgstr "" -#: of torch.nn.modules.module.Module.register_buffer:21 -msgid "whether the buffer is part of this module's :attr:`state_dict`." +#: of tensorcircuit.templates.blocks.example_block:11 +msgid "whether use SVD split to reduce ZZ gate bond dimension, defaults to False" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_hook:1 -msgid "Registers a forward hook on the module." +#: of tensorcircuit.templates.blocks.example_block:14 +msgid "The circuit with example ansatz attached" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_hook:3 +#: of tensorcircuit.templates.blocks.qft:1 msgid "" -"The hook will be called every time after :func:`forward` has computed an " -"output. It should have the following signature::" +"This function applies quantum fourier transformation (QFT) to the " +"selected circuit lines" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_hook:8 -msgid "" -"The input contains only the positional arguments given to the module. " -"Keyword arguments won't be passed to the hooks and only to the " -"``forward``. The hook can modify the output. It can modify the input " -"inplace but it will not have effect on forward since this is called after" -" :func:`forward` is called." +#: of tensorcircuit.templates.blocks.qft:5 +msgid "the indices of the circuit lines to apply QFT" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_pre_hook:1 -msgid "Registers a forward pre-hook on the module." +#: of tensorcircuit.templates.blocks.qft:7 +msgid "Whether to include the final swaps in the QFT" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_pre_hook:3 -msgid "" -"The hook will be called every time before :func:`forward` is invoked. It " -"should have the following signature::" +#: of tensorcircuit.templates.blocks.qft:9 +msgid "If True, the inverse Fourier transform is constructed" msgstr "" -#: of torch.nn.modules.module.Module.register_forward_pre_hook:8 -msgid "" -"The input contains only the positional arguments given to the module. " -"Keyword arguments won't be passed to the hooks and only to the " -"``forward``. The hook can modify the input. User can either return a " -"tuple or a single modified value in the hook. We will wrap the value into" -" a tuple if a single value is returned(unless that value is already a " -"tuple)." +#: of tensorcircuit.templates.blocks.qft:11 +msgid "If True, barriers are inserted as visualization improvement" msgstr "" -#: of torch.nn.modules.module.Module.register_full_backward_hook:3 -msgid "" -"The hook will be called every time the gradients with respect to module " -"inputs are computed. The hook should have the following signature::" +#: of tensorcircuit.templates.blocks.qft:13 +msgid "Circuit c" msgstr "" -#: of torch.nn.modules.module.Module.register_full_backward_hook:8 +#: of tensorcircuit.templates.blocks.state_centric:1 msgid "" -"The :attr:`grad_input` and :attr:`grad_output` are tuples that contain " -"the gradients with respect to the inputs and outputs respectively. The " -"hook should not modify its arguments, but it can optionally return a new " -"gradient with respect to the input that will be used in place of " -":attr:`grad_input` in subsequent computations. :attr:`grad_input` will " -"only correspond to the inputs given as positional arguments and all kwarg" -" arguments are ignored. Entries in :attr:`grad_input` and " -":attr:`grad_output` will be ``None`` for all non-Tensor arguments." +"Function decorator wraps the function with the first input and output in " +"the format of circuit, the wrapped function has the first input and the " +"output as the state tensor." msgstr "" -#: of torch.nn.modules.module.Module.register_full_backward_hook:17 -msgid "" -"For technical reasons, when this hook is applied to a Module, its forward" -" function will receive a view of each Tensor passed to the Module. " -"Similarly the caller will receive a view of each Tensor returned by the " -"Module's forward function." +#: of tensorcircuit.templates.blocks.state_centric:4 +msgid "Function with the fist input and the output as ``Circuit`` object." msgstr "" -#: of torch.nn.modules.module.Module.register_full_backward_hook:22 +#: of tensorcircuit.templates.blocks.state_centric:6 msgid "" -"Modifying inputs or outputs inplace is not allowed when using backward " -"hooks and will raise an error." +"Wrapped function with the first input and the output as the state tensor " +"correspondingly." msgstr "" -#: of torch.nn.modules.module.Module.register_module:1 -msgid "Alias for :func:`add_module`." +#: ../../source/api/templates/chems.rst:2 +msgid "tensorcircuit.templates.chems" msgstr "" -#: of torch.nn.modules.module.Module.register_parameter:1 -msgid "Adds a parameter to the module." +#: of tensorcircuit.templates.chems:1 +msgid "Useful utilities for quantum chemistry related task" msgstr "" -#: of torch.nn.modules.module.Module.register_parameter:3 -msgid "The parameter can be accessed as an attribute using given name." +#: ../../source/api/templates/dataset.rst:2 +msgid "tensorcircuit.templates.dataset" msgstr "" -#: of torch.nn.modules.module.Module.register_parameter:5 -msgid "" -"name of the parameter. The parameter can be accessed from this module " -"using the given name" +#: of tensorcircuit.templates.dataset:1 +msgid "Quantum machine learning related data preprocessing and embedding" msgstr "" -#: of torch.nn.modules.module.Module.register_parameter:8 -msgid "" -"parameter to be added to the module. If ``None``, then operations that " -"run on parameters, such as :attr:`cuda`, are ignored. If ``None``, the " -"parameter is **not** included in the module's :attr:`state_dict`." +#: ../../source/api/templates/ensemble.rst:2 +msgid "tensorcircuit.templates.ensemble" msgstr "" -#: of torch.nn.modules.module.Module.requires_grad_:1 -msgid "Change if autograd should record operations on parameters in this module." +#: of tensorcircuit.templates.ensemble:1 +msgid "Useful utilities for ensemble" msgstr "" -#: of torch.nn.modules.module.Module.requires_grad_:4 -msgid "" -"This method sets the parameters' :attr:`requires_grad` attributes in-" -"place." +#: of tensorcircuit.templates.ensemble.bagging.append:1 +msgid "Add model to the voting method" msgstr "" -#: of torch.nn.modules.module.Module.requires_grad_:7 +#: of tensorcircuit.templates.ensemble.bagging.eval:1 msgid "" -"This method is helpful for freezing part of the module for finetuning or " -"training parts of a model individually (e.g., GAN training)." +"Expect input data to be a 2D array which a 1D array of yTrue followed by " +"a 1D array of yPred is expected to be the components of the 2D array" msgstr "" -#: of torch.nn.modules.module.Module.requires_grad_:10 +#: of tensorcircuit.templates.ensemble.bagging.predict:1 msgid "" -"See :ref:`locally-disable-grad-doc` for a comparison between " -"`.requires_grad_()` and several similar mechanisms that may be confused " -"with it." +"Input data is expected to be a 2D array that the first layer is different" +" input data (into the trained models)" msgstr "" -#: of torch.nn.modules.module.Module.requires_grad_:13 +#: of tensorcircuit.templates.ensemble.bagging.train:1 msgid "" -"whether autograd should record operations on parameters in this module. " -"Default: ``True``." +"Train all models in the class, **kwargs expect to receive the argus that " +"can be directly sent to tf.fit Expected to be run after finishing compile" msgstr "" -#: of torch.nn.modules.module.Module.set_extra_state:1 -msgid "" -"This function is called from :func:`load_state_dict` to handle any extra " -"state found within the `state_dict`. Implement this function and a " -"corresponding :func:`get_extra_state` for your module if you need to " -"store extra state within its `state_dict`." +#: ../../source/api/templates/graphs.rst:2 +msgid "tensorcircuit.templates.graphs" msgstr "" -#: of torch.nn.modules.module.Module.set_extra_state:6 -msgid "Extra state from the `state_dict`" +#: of tensorcircuit.templates.graphs:1 +msgid "Some common graphs and lattices" msgstr "" -#: of torch.nn.modules.module.Module.share_memory:1 -msgid "See :meth:`torch.Tensor.share_memory_`" +#: of tensorcircuit.templates.graphs.Grid2DCoord:1 +msgid "Two-dimensional grid lattice" msgstr "" -#: of torch.nn.modules.module.Module.state_dict:1 -msgid "Returns a dictionary containing a whole state of the module." +#: of tensorcircuit.templates.graphs.Grid2DCoord.__init__:1 +msgid "number of rows" msgstr "" -#: of torch.nn.modules.module.Module.state_dict:3 -msgid "" -"Both parameters and persistent buffers (e.g. running averages) are " -"included. Keys are corresponding parameter and buffer names. Parameters " -"and buffers set to ``None`` are not included." +#: of tensorcircuit.templates.graphs.Grid2DCoord.__init__:3 +msgid "number of cols" msgstr "" -#: of torch.nn.modules.module.Module.state_dict:7 -msgid "a dictionary containing a whole state of the module" +#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:1 +msgid "return all col edge with 1d index encoding" msgstr "" -#: of torch.nn.modules.module.Module.to:1 -msgid "Moves and/or casts the parameters and buffers." +#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:3 +#: tensorcircuit.templates.graphs.Grid2DCoord.all_rows:3 +msgid "" +"whether to include pbc edges (periodic boundary condition), defaults to " +"False" msgstr "" -#: of torch.nn.modules.module.Module.to:3 -msgid "This can be called as" +#: of tensorcircuit.templates.graphs.Grid2DCoord.all_cols:6 +msgid "list of col edge" msgstr "" -#: of torch.nn.modules.module.Module.to:17 -msgid "" -"Its signature is similar to :meth:`torch.Tensor.to`, but only accepts " -"floating point or complex :attr:`dtype`\\ s. In addition, this method " -"will only cast the floating point or complex parameters and buffers to " -":attr:`dtype` (if given). The integral parameters and buffers will be " -"moved :attr:`device`, if that is given, but with dtypes unchanged. When " -":attr:`non_blocking` is set, it tries to convert/move asynchronously with" -" respect to the host if possible, e.g., moving CPU Tensors with pinned " -"memory to CUDA devices." +#: of tensorcircuit.templates.graphs.Grid2DCoord.all_rows:1 +msgid "return all row edge with 1d index encoding" msgstr "" -#: of torch.nn.modules.module.Module.to:26 -msgid "See below for examples." +#: of tensorcircuit.templates.graphs.Grid2DCoord.all_rows:6 +msgid "list of row edge" msgstr "" -#: of torch.nn.modules.module.Module.to:31 -msgid "the desired device of the parameters and buffers in this module" +#: of tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph:1 +msgid "Get the 2D grid lattice in ``nx.Graph`` format" msgstr "" -#: of torch.nn.modules.module.Module.to:34 +#: of tensorcircuit.templates.graphs.Grid2DCoord.lattice_graph:3 msgid "" -"the desired floating point or complex dtype of the parameters and buffers" -" in this module" +"whether to include pbc edges (periodic boundary condition), defaults to " +"True" msgstr "" -#: of torch.nn.modules.module.Module.to:37 -msgid "" -"Tensor whose dtype and device are the desired dtype and device for all " -"parameters and buffers in this module" +#: of tensorcircuit.templates.graphs.Line1D:1 +msgid "1D chain with ``n`` sites" msgstr "" -#: of torch.nn.modules.module.Module.to:40 -msgid "" -"the desired memory format for 4D parameters and buffers in this module " -"(keyword only argument)" +#: of tensorcircuit.templates.graphs.Line1D:5 +#: tensorcircuit.templates.measurements.heisenberg_measurements:34 +msgid "[description], defaults to True" msgstr "" -#: of torch.nn.modules.module.Module.to:48 -msgid "Examples::" +#: ../../source/api/templates/measurements.rst:2 +msgid "tensorcircuit.templates.measurements" msgstr "" -#: of torch.nn.modules.module.Module.to_empty:1 +#: of tensorcircuit.templates.measurements.any_local_measurements:1 msgid "" -"Moves the parameters and buffers to the specified device without copying " -"storage." +"This measurements pattern is specifically suitable for vmap. Parameterize" +" the local Pauli string to be measured." msgstr "" -#: of torch.nn.modules.module.Module.to_empty:3 -msgid "The desired device of the parameters and buffers in this module." +#: of tensorcircuit.templates.measurements.any_local_measurements:19 +#: tensorcircuit.templates.measurements.any_measurements:26 +msgid "The circuit to be measured" msgstr "" -#: of torch.nn.modules.module.Module.train:1 -msgid "Sets the module in training mode." +#: of tensorcircuit.templates.measurements.any_local_measurements:21 +#: tensorcircuit.templates.measurements.any_measurements:28 +msgid "" +"parameter tensors determines what Pauli string to be measured, shape is " +"[nwires, 4] if ``onehot`` is False and [nwires] if ``onehot`` is True." msgstr "" -#: of torch.nn.modules.module.Module.train:8 +#: of tensorcircuit.templates.measurements.any_local_measurements:24 +#: tensorcircuit.templates.measurements.any_measurements:31 msgid "" -"whether to set training mode (``True``) or evaluation mode (``False``). " -"Default: ``True``." +"defaults to False. If set to be True, structures will first go through " +"onehot procedure." msgstr "" -#: of torch.nn.modules.module.Module.type:1 -msgid "Casts all parameters and buffers to :attr:`dst_type`." +#: of tensorcircuit.templates.measurements.any_local_measurements:27 +msgid "" +"reuse the wavefunction when computing the expectations, defaults to be " +"True" msgstr "" -#: of torch.nn.modules.module.Module.type:6 -msgid "the desired type" +#: of tensorcircuit.templates.measurements.any_local_measurements:29 +#: tensorcircuit.templates.measurements.any_measurements:36 +msgid "The expectation value of given Pauli string by the tensor ``structures``." msgstr "" -#: of torch.nn.modules.module.Module.xpu:1 -msgid "Moves all model parameters and buffers to the XPU." +#: of tensorcircuit.templates.measurements.any_measurements:1 +msgid "" +"This measurements pattern is specifically suitable for vmap. Parameterize" +" the Pauli string to be measured." msgstr "" -#: of torch.nn.modules.module.Module.xpu:3 +#: of tensorcircuit.templates.measurements.any_measurements:34 msgid "" -"This also makes associated parameters and buffers different objects. So " -"it should be called before constructing optimizer if the module will live" -" on XPU while being optimized." +"reuse the wavefunction when computing the expectations, defaults to be " +"False" msgstr "" -#: of torch.nn.modules.module.Module.zero_grad:1 +#: of tensorcircuit.templates.measurements.heisenberg_measurements:1 msgid "" -"Sets gradients of all model parameters to zero. See similar function " -"under :class:`torch.optim.Optimizer` for more context." +"Evaluate Heisenberg energy expectation, whose Hamiltonian is defined on " +"the lattice graph ``g`` as follows: (e are edges in graph ``g`` where e1 " +"and e2 are two nodes for edge e and v are nodes in graph ``g``)" msgstr "" -#: of torch.nn.modules.module.Module.zero_grad:4 +#: of tensorcircuit.templates.measurements.heisenberg_measurements:4 msgid "" -"instead of setting to zero, set the grads to None. See " -":meth:`torch.optim.Optimizer.zero_grad` for details." +"H = \\sum_{e\\in g} w_e (h_{xx} X_{e1}X_{e2} + h_{yy} Y_{e1}Y_{e2} + " +"h_{zz} Z_{e1}Z_{e2})\n" +" + \\sum_{v\\in g} (h_x X_v + h_y Y_v + h_z Z_v)" msgstr "" -#: ../../source/api/translation.rst:2 -msgid "tensorcircuit.translation" +#: of tensorcircuit.templates.measurements.heisenberg_measurements:18 +msgid "Circuit to be measured" msgstr "" -#: of tensorcircuit.translation:1 -msgid "Circuit object translation in different packages" +#: of tensorcircuit.templates.measurements.heisenberg_measurements:20 +msgid "Lattice graph defining Heisenberg Hamiltonian" msgstr "" -#: of tensorcircuit.translation.eqasm2tc:1 -msgid "Translation qexe/eqasm instruction to tensorcircuit Circuit object" +#: of tensorcircuit.templates.measurements.heisenberg_measurements:22 +#: tensorcircuit.templates.measurements.heisenberg_measurements:24 +#: tensorcircuit.templates.measurements.heisenberg_measurements:26 +msgid "[description], defaults to 1.0" msgstr "" -#: of tensorcircuit.translation.eqasm2tc:7 -msgid "lines of ignored code at the head and the tail, defaults to (6, 1)" +#: of tensorcircuit.templates.measurements.heisenberg_measurements:28 +#: tensorcircuit.templates.measurements.heisenberg_measurements:30 +#: tensorcircuit.templates.measurements.heisenberg_measurements:32 +msgid "[description], defaults to 0.0" msgstr "" -#: of tensorcircuit.translation.perm_matrix:1 +#: of tensorcircuit.templates.measurements.heisenberg_measurements:36 +msgid "Value of Heisenberg energy" +msgstr "" + +#: of tensorcircuit.templates.measurements.mpo_expectation:1 msgid "" -"Generate a permutation matrix P. Due to the different convention or " -"qubits' order in qiskit and tensorcircuit, the unitary represented by the" -" same circuit is different. They are related by this permutation matrix " -"P: P @ U_qiskit @ P = U_tc" +"Evaluate expectation of operator ``mpo`` defined in ``QuOperator`` MPO " +"format with the output quantum state from circuit ``c``." msgstr "" -#: of tensorcircuit.translation.perm_matrix:7 -#: tensorcircuit.translation.qir2cirq:15 -#: tensorcircuit.translation.qir2qiskit:16 -#: tensorcircuit.translation.qiskit2tc:14 tensorcircuit.vis.qir2tex:12 -msgid "# of qubits" +#: of tensorcircuit.templates.measurements.mpo_expectation:4 +msgid "The circuit for the output state" msgstr "" -#: of tensorcircuit.translation.perm_matrix:9 -msgid "The permutation matrix P" +#: of tensorcircuit.templates.measurements.mpo_expectation:6 +msgid "MPO operator" msgstr "" -#: of tensorcircuit.translation.qir2cirq:1 -msgid "" -"Generate a cirq circuit using the quantum intermediate representation " -"(qir) in tensorcircuit." +#: of tensorcircuit.templates.measurements.mpo_expectation:8 +#: tensorcircuit.templates.measurements.operator_expectation:7 +#: tensorcircuit.templates.measurements.sparse_expectation:7 +msgid "a real and scalar tensor of shape [] as the expectation value" msgstr "" -#: of tensorcircuit.translation.qir2cirq:17 -#: tensorcircuit.translation.qir2qiskit:18 +#: of tensorcircuit.templates.measurements.operator_expectation:1 msgid "" -"The extra quantum IR of tc circuit including measure and reset on " -"hardware, defaults to None" +"Evaluate Hamiltonian expectation where ``hamiltonian`` can be dense " +"matrix, sparse matrix or MPO." msgstr "" -#: of tensorcircuit.translation.qir2cirq:20 -msgid "qiskit cirq object" +#: of tensorcircuit.templates.measurements.operator_expectation:3 +#: tensorcircuit.templates.measurements.sparse_expectation:3 +msgid "The circuit whose output state is used to evaluate the expectation" msgstr "" -#: of tensorcircuit.translation.qir2cirq:23 -msgid "" -"#TODO(@erertertet): add default theta to iswap gate add more cirq built-" -"in gate instead of customized add unitary test with tolerance add support" -" of cirq built-in ControlledGate for multiplecontroll support more " -"element in qir, e.g. barrier, measure..." +#: of tensorcircuit.templates.measurements.operator_expectation:5 +#: tensorcircuit.templates.measurements.sparse_expectation:5 +msgid "Hamiltonian matrix in COO_sparse_matrix form" msgstr "" -#: of tensorcircuit.translation.qir2json:1 +#: of tensorcircuit.templates.measurements.sparse_expectation:1 msgid "" -"transform qir to json compatible list of dict where array is replaced by " -"real and imaginary list" +"Evaluate Hamiltonian expectation where ``hamiltonian`` is kept in sparse " +"matrix form to save space" msgstr "" -#: of tensorcircuit.translation.qir2qiskit:1 +#: of tensorcircuit.templates.measurements.spin_glass_measurements:1 msgid "" -"Generate a qiskit quantum circuit using the quantum intermediate " -"representation (qir) in tensorcircuit." +"Compute spin glass energy defined on graph ``g`` expectation for output " +"state of the circuit ``c``. The Hamiltonian to be evaluated is defined as" +" (first term is determined by node weights while the second term is " +"determined by edge weights of the graph):" msgstr "" -#: of tensorcircuit.translation.qir2qiskit:21 -msgid "qiskit QuantumCircuit object" +#: of tensorcircuit.templates.measurements.spin_glass_measurements:5 +msgid "H = \\sum_{v\\in g} w_v Z_v + \\sum_{e\\in g} w_e Z_{e1} Z_{e2}" msgstr "" -#: of tensorcircuit.translation.qiskit2tc:1 -msgid "Generate a tensorcircuit circuit using the quantum circuit data in qiskit." +#: of tensorcircuit.templates.measurements.spin_glass_measurements:28 +msgid "The quantum circuit" msgstr "" -#: of tensorcircuit.translation.qiskit2tc:12 -msgid "Quantum circuit data from qiskit." +#: of tensorcircuit.templates.measurements.spin_glass_measurements:30 +msgid "The graph for spin glass Hamiltonian definition" msgstr "" -#: of tensorcircuit.translation.qiskit2tc:16 -msgid "Input state of the circuit. Default is None." -msgstr "" +#: of tensorcircuit.templates.measurements.spin_glass_measurements:32 +msgid "" +"Whether measure the circuit with reusing the wavefunction, defaults to " +"True" +msgstr "" -#: of tensorcircuit.translation.qiskit2tc:18 -msgid "``Circuit``, ``DMCircuit`` or ``MPSCircuit``" +#: of tensorcircuit.templates.measurements.spin_glass_measurements:34 +msgid "The spin glass energy expectation value" msgstr "" -#: of tensorcircuit.translation.qiskit2tc:26 -msgid "A quantum circuit in tensorcircuit" +#: ../../source/api/torchnn.rst:2 +msgid "tensorcircuit.torchnn" msgstr "" -#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:1 -msgid "" -"qiskit ``from_qasm_str`` method cannot keep the order of measure as the " -"qasm file, we provide this alternative function in case the order of " -"measure instruction matters" +#: of tensorcircuit.torchnn:1 +msgid "PyTorch nn Module wrapper for quantum function" msgstr "" -#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:4 -msgid "open qasm str" +#: of tensorcircuit.torchnn.HardwareNet:1 +msgid "Bases: :py:class:`~tensorcircuit.torchnn.QuantumNet`" msgstr "" -#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:6 -msgid "``qiskit.circuit.QuantumCircuit``" +#: of tensorcircuit.torchnn.HardwareNet:1 +msgid "" +"PyTorch Layer wrapping quantum function with cloud qpu access (using " +":py:mod:`tensorcircuit.cloud` module)" msgstr "" -#: ../../source/api/utils.rst:2 -msgid "tensorcircuit.utils" +#: of tensorcircuit.torchnn.HardwareNet.__init__:1 +#: tensorcircuit.torchnn.QuantumNet.__init__:1 +msgid "PyTorch nn Module wrapper on quantum function ``f``." msgstr "" -#: of tensorcircuit.utils:1 -msgid "Helper functions" +#: of tensorcircuit.torchnn.HardwareNet.__init__:32 +#: tensorcircuit.torchnn.QuantumNet.__init__:32 +msgid "Quantum function with tensor in (input and weights) and tensor out." msgstr "" -#: of tensorcircuit.utils.append:1 -msgid "Functional programming paradigm to build function pipeline" +#: of tensorcircuit.torchnn.HardwareNet.__init__:34 +#: tensorcircuit.torchnn.QuantumNet.__init__:34 +msgid "" +"list of shape tuple for different weights as the non-first parameters for" +" ``f``" msgstr "" -#: of tensorcircuit.utils.append:9 -msgid "The function which are attached with other functions" +#: of tensorcircuit.torchnn.HardwareNet.__init__:36 +#: tensorcircuit.torchnn.QuantumNet.__init__:36 +msgid "function that gives the shape tuple returns torch tensor, defaults to None" msgstr "" -#: of tensorcircuit.utils.append:11 -msgid "Function to be attached" +#: of tensorcircuit.torchnn.HardwareNet.__init__:38 +#: tensorcircuit.torchnn.QuantumNet.__init__:38 +msgid "whether apply vmap (batch input) on ``f``, defaults to True" msgstr "" -#: of tensorcircuit.utils.append:13 -msgid "The final results after function pipeline" +#: of tensorcircuit.torchnn.HardwareNet.__init__:40 +#: tensorcircuit.torchnn.QuantumNet.__init__:40 +msgid "" +"which position of input should be batched, need to be customized when " +"multiple inputs for the torch model, defaults to be 0." msgstr "" -#: of tensorcircuit.utils.arg_alias:1 -msgid "function argument alias decorator with new docstring" +#: of tensorcircuit.torchnn.HardwareNet.__init__:43 +#: tensorcircuit.torchnn.QuantumNet.__init__:43 +msgid "whether transform ``f`` with torch interface, defaults to True" msgstr "" -#: of tensorcircuit.utils.arg_alias:7 -msgid "whether to add doc for these new alias arguments, defaults True" +#: of tensorcircuit.torchnn.HardwareNet.__init__:45 +#: tensorcircuit.torchnn.QuantumNet.__init__:45 +msgid "whether jit ``f``, defaults to True" msgstr "" -#: of tensorcircuit.utils.arg_alias:9 -msgid "the decorated function" +#: of tensorcircuit.torchnn.HardwareNet.__init__:47 +#: tensorcircuit.torchnn.QuantumNet.__init__:47 +msgid "whether enbale dlpack in interfaces, defaults to False" msgstr "" -#: of tensorcircuit.utils.benchmark:1 -msgid "benchmark jittable function with staging time and running time" +#: of torch.nn.modules.module.Module.add_module:1 +msgid "Adds a child module to the current module." msgstr "" -#: of tensorcircuit.utils.benchmark:5 -msgid "_description_, defaults to 5" +#: of torch.nn.modules.module.Module.add_module:3 +msgid "The module can be accessed as an attribute using the given name." msgstr "" -#: of tensorcircuit.utils.is_m1mac:1 -msgid "check whether the running platform is MAC with M1 chip" +#: of torch.nn.modules.module.Module.add_module:5 +msgid "" +"name of the child module. The child module can be accessed from this " +"module using the given name" msgstr "" -#: of tensorcircuit.utils.is_m1mac:3 -msgid "True for MAC M1 platform" +#: of torch.nn.modules.module.Module.add_module:8 +msgid "child module to be added to the module." msgstr "" -#: of tensorcircuit.utils.return_partial:1 +#: of torch.nn.modules.module.Module.apply:1 msgid "" -"Return a callable function for output ith parts of the original output " -"along the first axis. Original output supports List and Tensor." +"Applies ``fn`` recursively to every submodule (as returned by " +"``.children()``) as well as self. Typical use includes initializing the " +"parameters of a model (see also :ref:`nn-init-doc`)." msgstr "" -#: of tensorcircuit.utils.return_partial:20 -msgid "The function to be applied this method" +#: of torch.nn.modules.module.Module.apply:5 +msgid "function to be applied to each submodule" msgstr "" -#: of tensorcircuit.utils.return_partial:22 -msgid "The ith parts of original output along the first axis (axis=0 or dim=0)" +#: of torch.nn.modules.module.Module.apply:8 +#: torch.nn.modules.module.Module.bfloat16:6 +#: torch.nn.modules.module.Module.cpu:6 torch.nn.modules.module.Module.cuda:14 +#: torch.nn.modules.module.Module.double:6 +#: torch.nn.modules.module.Module.eval:13 +#: torch.nn.modules.module.Module.float:6 torch.nn.modules.module.Module.half:6 +#: torch.nn.modules.module.Module.ipu:14 +#: torch.nn.modules.module.Module.requires_grad_:17 +#: torch.nn.modules.module.Module.to:45 +#: torch.nn.modules.module.Module.to_empty:7 +#: torch.nn.modules.module.Module.train:12 +#: torch.nn.modules.module.Module.type:9 torch.nn.modules.module.Module.xpu:14 +msgid "self" msgstr "" -#: of tensorcircuit.utils.return_partial:24 -msgid "The modified callable function" +#: of torch.nn.modules.module.Module.apply:11 +#: torch.nn.modules.module.Module.buffers:10 +#: torch.nn.modules.module.Module.modules:10 +#: torch.nn.modules.module.Module.named_buffers:15 +#: torch.nn.modules.module.Module.named_children:6 +#: torch.nn.modules.module.Module.named_modules:16 +#: torch.nn.modules.module.Module.named_parameters:16 +#: torch.nn.modules.module.Module.parameters:12 +#: torch.nn.modules.module.Module.register_buffer:25 +#: torch.nn.modules.module.Module.state_dict:38 +msgid "Example::" msgstr "" -#: ../../source/api/vis.rst:2 -msgid "tensorcircuit.vis" +#: of torch.nn.modules.module.Module.bfloat16:1 +msgid "Casts all floating point parameters and buffers to ``bfloat16`` datatype." msgstr "" -#: of tensorcircuit.vis:1 -msgid "Visualization on circuits" +#: of torch.nn.modules.module.Module.bfloat16:4 +#: torch.nn.modules.module.Module.cpu:4 torch.nn.modules.module.Module.cuda:8 +#: torch.nn.modules.module.Module.double:4 +#: torch.nn.modules.module.Module.float:4 torch.nn.modules.module.Module.half:4 +#: torch.nn.modules.module.Module.ipu:8 torch.nn.modules.module.Module.to:29 +#: torch.nn.modules.module.Module.type:4 torch.nn.modules.module.Module.xpu:8 +msgid "This method modifies the module in-place." msgstr "" -#: of tensorcircuit.vis.gate_name_trans:1 +#: of torch.nn.modules.module.Module.buffers:1 +msgid "Returns an iterator over module buffers." +msgstr "" + +#: of torch.nn.modules.module.Module.buffers:3 msgid "" -"Translating from the gate name to gate information including the number " -"of control qubits and the reduced gate name." +"if True, then yields buffers of this module and all submodules. " +"Otherwise, yields only buffers that are direct members of this module." msgstr "" -#: of tensorcircuit.vis.gate_name_trans:10 -msgid "String of gate name" +#: of torch.nn.modules.module.Module.buffers +#: torch.nn.modules.module.Module.children +#: torch.nn.modules.module.Module.modules +#: torch.nn.modules.module.Module.named_buffers +#: torch.nn.modules.module.Module.named_children +#: torch.nn.modules.module.Module.named_modules +#: torch.nn.modules.module.Module.named_parameters +#: torch.nn.modules.module.Module.parameters +msgid "Yields" msgstr "" -#: of tensorcircuit.vis.gate_name_trans:12 -msgid "# of control qubits, reduced gate name" +#: of torch.nn.modules.module.Module.buffers:8 +msgid "*torch.Tensor* -- module buffer" msgstr "" -#: of tensorcircuit.vis.qir2tex:1 +#: of torch.nn.modules.module.Module.children:1 +msgid "Returns an iterator over immediate children modules." +msgstr "" + +#: of torch.nn.modules.module.Module.children:3 +msgid "*Module* -- a child module" +msgstr "" + +#: of torch.nn.modules.module.Module.cpu:1 +msgid "Moves all model parameters and buffers to the CPU." +msgstr "" + +#: of torch.nn.modules.module.Module.cuda:1 +msgid "Moves all model parameters and buffers to the GPU." +msgstr "" + +#: of torch.nn.modules.module.Module.cuda:3 msgid "" -"Generate Tex code from 'qir' string to illustrate the circuit structure. " -"This visualization is based on quantikz package." +"This also makes associated parameters and buffers different objects. So " +"it should be called before constructing optimizer if the module will live" +" on GPU while being optimized." msgstr "" -#: of tensorcircuit.vis.qir2tex:10 -msgid "The quantum intermediate representation of a circuit in tensorcircuit." +#: of torch.nn.modules.module.Module.cuda:10 +#: torch.nn.modules.module.Module.ipu:10 torch.nn.modules.module.Module.xpu:10 +msgid "if specified, all parameters will be copied to that device" msgstr "" -#: of tensorcircuit.vis.qir2tex:14 -msgid "Initial state, default is an all zero state '000...000'." +#: of torch.nn.modules.module.Module.double:1 +msgid "Casts all floating point parameters and buffers to ``double`` datatype." msgstr "" -#: of tensorcircuit.vis.qir2tex:16 +#: of torch.nn.modules.module.Module.eval:1 +msgid "Sets the module in evaluation mode." +msgstr "" + +#: of torch.nn.modules.module.Module.eval:3 +#: torch.nn.modules.module.Module.train:3 msgid "" -"Measurement Basis, default is None which means no measurement in the end " -"of the circuit." +"This has any effect only on certain modules. See documentations of " +"particular modules for details of their behaviors in training/evaluation " +"mode, if they are affected, e.g. :class:`Dropout`, :class:`BatchNorm`, " +"etc." msgstr "" -#: of tensorcircuit.vis.qir2tex:19 +#: of torch.nn.modules.module.Module.eval:8 +msgid "This is equivalent with :meth:`self.train(False) `." +msgstr "" + +#: of torch.nn.modules.module.Module.eval:10 msgid "" -"If true, a right compression of the circuit will be conducted. A right " -"compression means we will try to shift gates from right to left if " -"possible." +"See :ref:`locally-disable-grad-doc` for a comparison between `.eval()` " +"and several similar mechanisms that may be confused with it." msgstr "" -#: of tensorcircuit.vis.qir2tex:21 +#: of torch.nn.modules.module.Module.extra_repr:1 +msgid "Set the extra representation of the module" +msgstr "" + +#: of torch.nn.modules.module.Module.extra_repr:3 msgid "" -"Default is false. :type rcompress: bool :param lcompress: If true, a left" -" compression of the circuit will be conducted." +"To print customized extra information, you should re-implement this " +"method in your own modules. Both single-line and multi-line strings are " +"acceptable." msgstr "" -#: of tensorcircuit.vis.qir2tex:24 +#: of torch.nn.modules.module.Module.float:1 +msgid "Casts all floating point parameters and buffers to ``float`` datatype." +msgstr "" + +#: of tensorcircuit.torchnn.HardwareNet.forward:1 +#: tensorcircuit.torchnn.QuantumNet.forward:1 +msgid "Defines the computation performed at every call." +msgstr "" + +#: of tensorcircuit.torchnn.HardwareNet.forward:3 +#: tensorcircuit.torchnn.QuantumNet.forward:3 +msgid "Should be overridden by all subclasses." +msgstr "" + +#: of tensorcircuit.torchnn.HardwareNet.forward:6 +#: tensorcircuit.torchnn.QuantumNet.forward:6 msgid "" -"A left compression means we will try to shift gates from left to right if" -" possible. Default is false." +"Although the recipe for forward pass needs to be defined within this " +"function, one should call the :class:`Module` instance afterwards instead" +" of this since the former takes care of running the registered hooks " +"while the latter silently ignores them." msgstr "" -#: of tensorcircuit.vis.qir2tex:27 +#: of torch.nn.modules.module.Module.get_buffer:1 msgid "" -"If true, the tex code will be designed to generate a standalone document." -" Default is false which means the generated tex code is just a quantikz " -"code block." +"Returns the buffer given by ``target`` if it exists, otherwise throws an " +"error." msgstr "" -#: of tensorcircuit.vis.qir2tex:30 +#: of torch.nn.modules.module.Module.get_buffer:4 +#: torch.nn.modules.module.Module.get_parameter:4 msgid "" -"If true, a string table of tex code will also be returned. Default is " -"false." +"See the docstring for ``get_submodule`` for a more detailed explanation " +"of this method's functionality as well as how to correctly specify " +"``target``." msgstr "" -#: of tensorcircuit.vis.qir2tex:33 +#: of torch.nn.modules.module.Module.get_buffer:8 msgid "" -"Tex code of circuit visualization based on quantikz package. If " -"return_string_table is true, a string table of tex code will also be " -"returned." +"The fully-qualified string name of the buffer to look for. (See " +"``get_submodule`` for how to specify a fully-qualified string.)" +msgstr "" + +#: of torch.nn.modules.module.Module.get_buffer:12 +msgid "The buffer referenced by ``target``" msgstr "" -#: of tensorcircuit.vis.render_pdf:1 -msgid "" -"Generate the PDF file with given latex string and filename. Latex command" -" and file path can be specified. When notebook is True, convert the " -"output PDF file to image and return a Image object." -msgstr "" +#: of torch.nn.modules.module.Module.get_buffer:15 +msgid "" +"If the target string references an invalid path or resolves to " +"something that is not a buffer" +msgstr "" + +#: of torch.nn.modules.module.Module.get_extra_state:1 +msgid "" +"Returns any extra state to include in the module's state_dict. Implement " +"this and a corresponding :func:`set_extra_state` for your module if you " +"need to store extra state. This function is called when building the " +"module's `state_dict()`." +msgstr "" + +#: of torch.nn.modules.module.Module.get_extra_state:6 +msgid "" +"Note that extra state should be picklable to ensure working serialization" +" of the state_dict. We only provide provide backwards compatibility " +"guarantees for serializing Tensors; other objects may break backwards " +"compatibility if their serialized pickled form changes." +msgstr "" + +#: of torch.nn.modules.module.Module.get_extra_state:11 +msgid "Any extra state to store in the module's state_dict" +msgstr "" + +#: of torch.nn.modules.module.Module.get_parameter:1 +msgid "" +"Returns the parameter given by ``target`` if it exists, otherwise throws " +"an error." +msgstr "" + +#: of torch.nn.modules.module.Module.get_parameter:8 +msgid "" +"The fully-qualified string name of the Parameter to look for. (See " +"``get_submodule`` for how to specify a fully-qualified string.)" +msgstr "" + +#: of torch.nn.modules.module.Module.get_parameter:12 +msgid "The Parameter referenced by ``target``" +msgstr "" + +#: of torch.nn.modules.module.Module.get_parameter:15 +msgid "" +"If the target string references an invalid path or resolves to " +"something that is not an ``nn.Parameter``" +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:1 +msgid "" +"Returns the submodule given by ``target`` if it exists, otherwise throws " +"an error." +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:4 +msgid "" +"For example, let's say you have an ``nn.Module`` ``A`` that looks like " +"this:" +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:18 +msgid "" +"(The diagram shows an ``nn.Module`` ``A``. ``A`` has a nested submodule " +"``net_b``, which itself has two submodules ``net_c`` and ``linear``. " +"``net_c`` then has a submodule ``conv``.)" +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:22 +msgid "" +"To check whether or not we have the ``linear`` submodule, we would call " +"``get_submodule(\"net_b.linear\")``. To check whether we have the " +"``conv`` submodule, we would call " +"``get_submodule(\"net_b.net_c.conv\")``." +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:27 +msgid "" +"The runtime of ``get_submodule`` is bounded by the degree of module " +"nesting in ``target``. A query against ``named_modules`` achieves the " +"same result, but it is O(N) in the number of transitive modules. So, for " +"a simple check to see if some submodule exists, ``get_submodule`` should " +"always be used." +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:34 +msgid "" +"The fully-qualified string name of the submodule to look for. (See above " +"example for how to specify a fully-qualified string.)" +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:38 +msgid "The submodule referenced by ``target``" +msgstr "" + +#: of torch.nn.modules.module.Module.get_submodule:41 +msgid "" +"If the target string references an invalid path or resolves to " +"something that is not an ``nn.Module``" +msgstr "" + +#: of torch.nn.modules.module.Module.half:1 +msgid "Casts all floating point parameters and buffers to ``half`` datatype." +msgstr "" + +#: of torch.nn.modules.module.Module.ipu:1 +msgid "Moves all model parameters and buffers to the IPU." +msgstr "" + +#: of torch.nn.modules.module.Module.ipu:3 +msgid "" +"This also makes associated parameters and buffers different objects. So " +"it should be called before constructing optimizer if the module will live" +" on IPU while being optimized." +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:1 +msgid "" +"Copies parameters and buffers from :attr:`state_dict` into this module " +"and its descendants. If :attr:`strict` is ``True``, then the keys of " +":attr:`state_dict` must exactly match the keys returned by this module's " +":meth:`~torch.nn.Module.state_dict` function." +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:6 +msgid "a dict containing parameters and persistent buffers." +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:9 +msgid "" +"whether to strictly enforce that the keys in :attr:`state_dict` match the" +" keys returned by this module's :meth:`~torch.nn.Module.state_dict` " +"function. Default: ``True``" +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:14 +msgid "" +"* **missing_keys** is a list of str containing the missing keys * " +"**unexpected_keys** is a list of str containing the unexpected keys" +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:14 +msgid "**missing_keys** is a list of str containing the missing keys" +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:15 +msgid "**unexpected_keys** is a list of str containing the unexpected keys" +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:16 +msgid "``NamedTuple`` with ``missing_keys`` and ``unexpected_keys`` fields" +msgstr "" + +#: of torch.nn.modules.module.Module.load_state_dict:20 +msgid "" +"If a parameter or buffer is registered as ``None`` and its corresponding " +"key exists in :attr:`state_dict`, :meth:`load_state_dict` will raise a " +"``RuntimeError``." +msgstr "" + +#: of torch.nn.modules.module.Module.modules:1 +msgid "Returns an iterator over all modules in the network." +msgstr "" + +#: of torch.nn.modules.module.Module.modules:3 +msgid "*Module* -- a module in the network" +msgstr "" + +#: of torch.nn.modules.module.Module.modules:7 +#: torch.nn.modules.module.Module.named_modules:13 +msgid "" +"Duplicate modules are returned only once. In the following example, ``l``" +" will be returned only once." +msgstr "" + +#: of torch.nn.modules.module.Module.named_buffers:1 +msgid "" +"Returns an iterator over module buffers, yielding both the name of the " +"buffer as well as the buffer itself." +msgstr "" + +#: of torch.nn.modules.module.Module.named_buffers:4 +msgid "prefix to prepend to all buffer names." +msgstr "" + +#: of torch.nn.modules.module.Module.named_buffers:6 +msgid "" +"if True, then yields buffers of this module and all submodules. " +"Otherwise, yields only buffers that are direct members of this module. " +"Defaults to True." +msgstr "" + +#: of torch.nn.modules.module.Module.named_buffers:10 +msgid "whether to remove the duplicated buffers in the result. Defaults to True." +msgstr "" + +#: of torch.nn.modules.module.Module.named_buffers:13 +msgid "*(str, torch.Tensor)* -- Tuple containing the name and buffer" +msgstr "" + +#: of torch.nn.modules.module.Module.named_children:1 +msgid "" +"Returns an iterator over immediate children modules, yielding both the " +"name of the module as well as the module itself." +msgstr "" + +#: of torch.nn.modules.module.Module.named_children:4 +msgid "*(str, Module)* -- Tuple containing a name and child module" +msgstr "" + +#: of torch.nn.modules.module.Module.named_modules:1 +msgid "" +"Returns an iterator over all modules in the network, yielding both the " +"name of the module as well as the module itself." +msgstr "" + +#: of torch.nn.modules.module.Module.named_modules:4 +msgid "a memo to store the set of modules already added to the result" +msgstr "" + +#: of torch.nn.modules.module.Module.named_modules:5 +msgid "a prefix that will be added to the name of the module" +msgstr "" + +#: of torch.nn.modules.module.Module.named_modules:6 +msgid "whether to remove the duplicated module instances in the result or not" +msgstr "" + +#: of torch.nn.modules.module.Module.named_modules:9 +msgid "*(str, Module)* -- Tuple of name and module" +msgstr "" + +#: of torch.nn.modules.module.Module.named_parameters:1 +msgid "" +"Returns an iterator over module parameters, yielding both the name of the" +" parameter as well as the parameter itself." +msgstr "" + +#: of torch.nn.modules.module.Module.named_parameters:4 +msgid "prefix to prepend to all parameter names." +msgstr "" + +#: of torch.nn.modules.module.Module.named_parameters:6 +#: torch.nn.modules.module.Module.parameters:5 +msgid "" +"if True, then yields parameters of this module and all submodules. " +"Otherwise, yields only parameters that are direct members of this module." +msgstr "" + +#: of torch.nn.modules.module.Module.named_parameters:10 +msgid "" +"whether to remove the duplicated parameters in the result. Defaults to " +"True." +msgstr "" + +#: of torch.nn.modules.module.Module.named_parameters:14 +msgid "*(str, Parameter)* -- Tuple containing the name and parameter" +msgstr "" + +#: of torch.nn.modules.module.Module.parameters:1 +msgid "Returns an iterator over module parameters." +msgstr "" + +#: of torch.nn.modules.module.Module.parameters:3 +msgid "This is typically passed to an optimizer." +msgstr "" + +#: of torch.nn.modules.module.Module.parameters:10 +msgid "*Parameter* -- module parameter" +msgstr "" + +#: of torch.nn.modules.module.Module.register_backward_hook:1 +#: torch.nn.modules.module.Module.register_full_backward_hook:1 +msgid "Registers a backward hook on the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_backward_hook:3 +msgid "" +"This function is deprecated in favor of " +":meth:`~torch.nn.Module.register_full_backward_hook` and the behavior of " +"this function will change in future versions." +msgstr "" + +#: of torch.nn.modules.module.Module.register_backward_hook:6 +#: torch.nn.modules.module.Module.register_forward_hook:37 +#: torch.nn.modules.module.Module.register_forward_pre_hook:40 +#: torch.nn.modules.module.Module.register_full_backward_hook:39 +#: torch.nn.modules.module.Module.register_full_backward_pre_hook:34 +#: torch.nn.modules.module.Module.register_load_state_dict_post_hook:21 +msgid "" +"a handle that can be used to remove the added hook by calling " +"``handle.remove()``" +msgstr "" + +#: of torch.nn.modules.module.Module.register_backward_hook:8 +#: torch.nn.modules.module.Module.register_forward_hook:39 +#: torch.nn.modules.module.Module.register_forward_pre_hook:42 +#: torch.nn.modules.module.Module.register_full_backward_hook:41 +#: torch.nn.modules.module.Module.register_full_backward_pre_hook:36 +#: torch.nn.modules.module.Module.register_load_state_dict_post_hook:23 +msgid ":class:`torch.utils.hooks.RemovableHandle`" +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:1 +msgid "Adds a buffer to the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:3 +msgid "" +"This is typically used to register a buffer that should not to be " +"considered a model parameter. For example, BatchNorm's ``running_mean`` " +"is not a parameter, but is part of the module's state. Buffers, by " +"default, are persistent and will be saved alongside parameters. This " +"behavior can be changed by setting :attr:`persistent` to ``False``. The " +"only difference between a persistent buffer and a non-persistent buffer " +"is that the latter will not be a part of this module's " +":attr:`state_dict`." +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:12 +msgid "Buffers can be accessed as attributes using given names." +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:14 +msgid "" +"name of the buffer. The buffer can be accessed from this module using the" +" given name" +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:17 +msgid "" +"buffer to be registered. If ``None``, then operations that run on " +"buffers, such as :attr:`cuda`, are ignored. If ``None``, the buffer is " +"**not** included in the module's :attr:`state_dict`." +msgstr "" + +#: of torch.nn.modules.module.Module.register_buffer:21 +msgid "whether the buffer is part of this module's :attr:`state_dict`." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:1 +msgid "Registers a forward hook on the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:3 +msgid "" +"The hook will be called every time after :func:`forward` has computed an " +"output." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:5 +msgid "" +"If ``with_kwargs`` is ``False`` or not specified, the input contains only" +" the positional arguments given to the module. Keyword arguments won't be" +" passed to the hooks and only to the ``forward``. The hook can modify the" +" output. It can modify the input inplace but it will not have effect on " +"forward since this is called after :func:`forward` is called. The hook " +"should have the following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:14 +msgid "" +"If ``with_kwargs`` is ``True``, the forward hook will be passed the " +"``kwargs`` given to the forward function and be expected to return the " +"output possibly modified. The hook should have the following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:20 +#: torch.nn.modules.module.Module.register_forward_pre_hook:23 +msgid "The user defined hook to be registered." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:22 +msgid "" +"If ``True``, the provided ``hook`` will be fired before all existing " +"``forward`` hooks on this :class:`torch.nn.modules.Module`. Otherwise, " +"the provided ``hook`` will be fired after all existing ``forward`` hooks " +"on this :class:`torch.nn.modules.Module`. Note that global ``forward`` " +"hooks registered with :func:`register_module_forward_hook` will fire " +"before all hooks registered by this method. Default: ``False``" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_hook:32 +msgid "" +"If ``True``, the ``hook`` will be passed the kwargs given to the forward " +"function. Default: ``False``" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:1 +msgid "Registers a forward pre-hook on the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:3 +msgid "The hook will be called every time before :func:`forward` is invoked." +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:6 +msgid "" +"If ``with_kwargs`` is false or not specified, the input contains only the" +" positional arguments given to the module. Keyword arguments won't be " +"passed to the hooks and only to the ``forward``. The hook can modify the " +"input. User can either return a tuple or a single modified value in the " +"hook. We will wrap the value into a tuple if a single value is returned " +"(unless that value is already a tuple). The hook should have the " +"following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:16 +msgid "" +"If ``with_kwargs`` is true, the forward pre-hook will be passed the " +"kwargs given to the forward function. And if the hook modifies the input," +" both the args and kwargs should be returned. The hook should have the " +"following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:25 +msgid "" +"If true, the provided ``hook`` will be fired before all existing " +"``forward_pre`` hooks on this :class:`torch.nn.modules.Module`. " +"Otherwise, the provided ``hook`` will be fired after all existing " +"``forward_pre`` hooks on this :class:`torch.nn.modules.Module`. Note that" +" global ``forward_pre`` hooks registered with " +":func:`register_module_forward_pre_hook` will fire before all hooks " +"registered by this method. Default: ``False``" +msgstr "" + +#: of torch.nn.modules.module.Module.register_forward_pre_hook:35 +msgid "" +"If true, the ``hook`` will be passed the kwargs given to the forward " +"function. Default: ``False``" +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:3 +msgid "" +"The hook will be called every time the gradients with respect to a module" +" are computed, i.e. the hook will execute if and only if the gradients " +"with respect to module outputs are computed. The hook should have the " +"following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:10 +msgid "" +"The :attr:`grad_input` and :attr:`grad_output` are tuples that contain " +"the gradients with respect to the inputs and outputs respectively. The " +"hook should not modify its arguments, but it can optionally return a new " +"gradient with respect to the input that will be used in place of " +":attr:`grad_input` in subsequent computations. :attr:`grad_input` will " +"only correspond to the inputs given as positional arguments and all kwarg" +" arguments are ignored. Entries in :attr:`grad_input` and " +":attr:`grad_output` will be ``None`` for all non-Tensor arguments." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:19 +#: torch.nn.modules.module.Module.register_full_backward_pre_hook:14 +msgid "" +"For technical reasons, when this hook is applied to a Module, its forward" +" function will receive a view of each Tensor passed to the Module. " +"Similarly the caller will receive a view of each Tensor returned by the " +"Module's forward function." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:24 +msgid "" +"Modifying inputs or outputs inplace is not allowed when using backward " +"hooks and will raise an error." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:27 +#: torch.nn.modules.module.Module.register_full_backward_pre_hook:22 +msgid "The user-defined hook to be registered." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_hook:29 +msgid "" +"If true, the provided ``hook`` will be fired before all existing " +"``backward`` hooks on this :class:`torch.nn.modules.Module`. Otherwise, " +"the provided ``hook`` will be fired after all existing ``backward`` hooks" +" on this :class:`torch.nn.modules.Module`. Note that global ``backward`` " +"hooks registered with :func:`register_module_full_backward_hook` will " +"fire before all hooks registered by this method." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_pre_hook:1 +msgid "Registers a backward pre-hook on the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_pre_hook:3 +msgid "" +"The hook will be called every time the gradients for the module are " +"computed. The hook should have the following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_pre_hook:8 +msgid "" +"The :attr:`grad_output` is a tuple. The hook should not modify its " +"arguments, but it can optionally return a new gradient with respect to " +"the output that will be used in place of :attr:`grad_output` in " +"subsequent computations. Entries in :attr:`grad_output` will be ``None`` " +"for all non-Tensor arguments." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_pre_hook:19 +msgid "" +"Modifying inputs inplace is not allowed when using backward hooks and " +"will raise an error." +msgstr "" + +#: of torch.nn.modules.module.Module.register_full_backward_pre_hook:24 +msgid "" +"If true, the provided ``hook`` will be fired before all existing " +"``backward_pre`` hooks on this :class:`torch.nn.modules.Module`. " +"Otherwise, the provided ``hook`` will be fired after all existing " +"``backward_pre`` hooks on this :class:`torch.nn.modules.Module`. Note " +"that global ``backward_pre`` hooks registered with " +":func:`register_module_full_backward_pre_hook` will fire before all hooks" +" registered by this method." +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:1 +msgid "" +"Registers a post hook to be run after module's ``load_state_dict`` is " +"called." +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:5 +msgid "It should have the following signature::" +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:5 +msgid "hook(module, incompatible_keys) -> None" +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:7 +msgid "" +"The ``module`` argument is the current module that this hook is " +"registered on, and the ``incompatible_keys`` argument is a ``NamedTuple``" +" consisting of attributes ``missing_keys`` and ``unexpected_keys``. " +"``missing_keys`` is a ``list`` of ``str`` containing the missing keys and" +" ``unexpected_keys`` is a ``list`` of ``str`` containing the unexpected " +"keys." +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:13 +msgid "The given incompatible_keys can be modified inplace if needed." +msgstr "" + +#: of torch.nn.modules.module.Module.register_load_state_dict_post_hook:15 +msgid "" +"Note that the checks performed when calling :func:`load_state_dict` with " +"``strict=True`` are affected by modifications the hook makes to " +"``missing_keys`` or ``unexpected_keys``, as expected. Additions to either" +" set of keys will result in an error being thrown when ``strict=True``, " +"and clearing out both missing and unexpected keys will avoid an error." +msgstr "" + +#: of torch.nn.modules.module.Module.register_module:1 +msgid "Alias for :func:`add_module`." +msgstr "" + +#: of torch.nn.modules.module.Module.register_parameter:1 +msgid "Adds a parameter to the module." +msgstr "" + +#: of torch.nn.modules.module.Module.register_parameter:3 +msgid "The parameter can be accessed as an attribute using given name." +msgstr "" + +#: of torch.nn.modules.module.Module.register_parameter:5 +msgid "" +"name of the parameter. The parameter can be accessed from this module " +"using the given name" +msgstr "" + +#: of torch.nn.modules.module.Module.register_parameter:8 +msgid "" +"parameter to be added to the module. If ``None``, then operations that " +"run on parameters, such as :attr:`cuda`, are ignored. If ``None``, the " +"parameter is **not** included in the module's :attr:`state_dict`." +msgstr "" + +#: of torch.nn.modules.module.Module.register_state_dict_pre_hook:1 +msgid "" +"These hooks will be called with arguments: ``self``, ``prefix``, and " +"``keep_vars`` before calling ``state_dict`` on ``self``. The registered " +"hooks can be used to perform pre-processing before the ``state_dict`` " +"call is made." +msgstr "" + +#: of torch.nn.modules.module.Module.requires_grad_:1 +msgid "Change if autograd should record operations on parameters in this module." +msgstr "" + +#: of torch.nn.modules.module.Module.requires_grad_:4 +msgid "" +"This method sets the parameters' :attr:`requires_grad` attributes in-" +"place." +msgstr "" + +#: of torch.nn.modules.module.Module.requires_grad_:7 +msgid "" +"This method is helpful for freezing part of the module for finetuning or " +"training parts of a model individually (e.g., GAN training)." +msgstr "" + +#: of torch.nn.modules.module.Module.requires_grad_:10 +msgid "" +"See :ref:`locally-disable-grad-doc` for a comparison between " +"`.requires_grad_()` and several similar mechanisms that may be confused " +"with it." +msgstr "" + +#: of torch.nn.modules.module.Module.requires_grad_:13 +msgid "" +"whether autograd should record operations on parameters in this module. " +"Default: ``True``." +msgstr "" + +#: of torch.nn.modules.module.Module.set_extra_state:1 +msgid "" +"This function is called from :func:`load_state_dict` to handle any extra " +"state found within the `state_dict`. Implement this function and a " +"corresponding :func:`get_extra_state` for your module if you need to " +"store extra state within its `state_dict`." +msgstr "" + +#: of torch.nn.modules.module.Module.set_extra_state:6 +msgid "Extra state from the `state_dict`" +msgstr "" + +#: of torch.nn.modules.module.Module.share_memory:1 +msgid "See :meth:`torch.Tensor.share_memory_`" +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:1 +msgid "" +"Returns a dictionary containing references to the whole state of the " +"module." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:3 +msgid "" +"Both parameters and persistent buffers (e.g. running averages) are " +"included. Keys are corresponding parameter and buffer names. Parameters " +"and buffers set to ``None`` are not included." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:8 +msgid "" +"The returned object is a shallow copy. It contains references to the " +"module's parameters and buffers." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:12 +msgid "" +"Currently ``state_dict()`` also accepts positional arguments for " +"``destination``, ``prefix`` and ``keep_vars`` in order. However, this is " +"being deprecated and keyword arguments will be enforced in future " +"releases." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:18 +msgid "" +"Please avoid the use of argument ``destination`` as it is not designed " +"for end-users." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:21 +msgid "" +"If provided, the state of module will be updated into the dict and the " +"same object is returned. Otherwise, an ``OrderedDict`` will be created " +"and returned. Default: ``None``." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:26 +msgid "" +"a prefix added to parameter and buffer names to compose the keys in " +"state_dict. Default: ``''``." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:29 +msgid "" +"by default the :class:`~torch.Tensor` s returned in the state dict are " +"detached from autograd. If it's set to ``True``, detaching will not be " +"performed. Default: ``False``." +msgstr "" + +#: of torch.nn.modules.module.Module.state_dict:35 +msgid "a dictionary containing a whole state of the module" +msgstr "" + +#: of torch.nn.modules.module.Module.to:1 +msgid "Moves and/or casts the parameters and buffers." +msgstr "" + +#: of torch.nn.modules.module.Module.to:3 +msgid "This can be called as" +msgstr "" + +#: of torch.nn.modules.module.Module.to:17 +msgid "" +"Its signature is similar to :meth:`torch.Tensor.to`, but only accepts " +"floating point or complex :attr:`dtype`\\ s. In addition, this method " +"will only cast the floating point or complex parameters and buffers to " +":attr:`dtype` (if given). The integral parameters and buffers will be " +"moved :attr:`device`, if that is given, but with dtypes unchanged. When " +":attr:`non_blocking` is set, it tries to convert/move asynchronously with" +" respect to the host if possible, e.g., moving CPU Tensors with pinned " +"memory to CUDA devices." +msgstr "" + +#: of torch.nn.modules.module.Module.to:26 +msgid "See below for examples." +msgstr "" + +#: of torch.nn.modules.module.Module.to:31 +msgid "the desired device of the parameters and buffers in this module" +msgstr "" + +#: of torch.nn.modules.module.Module.to:34 +msgid "" +"the desired floating point or complex dtype of the parameters and buffers" +" in this module" +msgstr "" + +#: of torch.nn.modules.module.Module.to:37 +msgid "" +"Tensor whose dtype and device are the desired dtype and device for all " +"parameters and buffers in this module" +msgstr "" + +#: of torch.nn.modules.module.Module.to:40 +msgid "" +"the desired memory format for 4D parameters and buffers in this module " +"(keyword only argument)" +msgstr "" + +#: of torch.nn.modules.module.Module.to:48 +msgid "Examples::" +msgstr "" + +#: of torch.nn.modules.module.Module.to_empty:1 +msgid "" +"Moves the parameters and buffers to the specified device without copying " +"storage." +msgstr "" + +#: of torch.nn.modules.module.Module.to_empty:3 +msgid "The desired device of the parameters and buffers in this module." +msgstr "" + +#: of torch.nn.modules.module.Module.train:1 +msgid "Sets the module in training mode." +msgstr "" + +#: of torch.nn.modules.module.Module.train:8 +msgid "" +"whether to set training mode (``True``) or evaluation mode (``False``). " +"Default: ``True``." +msgstr "" + +#: of torch.nn.modules.module.Module.type:1 +msgid "Casts all parameters and buffers to :attr:`dst_type`." +msgstr "" + +#: of torch.nn.modules.module.Module.type:6 +msgid "the desired type" +msgstr "" + +#: of torch.nn.modules.module.Module.xpu:1 +msgid "Moves all model parameters and buffers to the XPU." +msgstr "" + +#: of torch.nn.modules.module.Module.xpu:3 +msgid "" +"This also makes associated parameters and buffers different objects. So " +"it should be called before constructing optimizer if the module will live" +" on XPU while being optimized." +msgstr "" + +#: of torch.nn.modules.module.Module.zero_grad:1 +msgid "" +"Sets gradients of all model parameters to zero. See similar function " +"under :class:`torch.optim.Optimizer` for more context." +msgstr "" + +#: of torch.nn.modules.module.Module.zero_grad:4 +msgid "" +"instead of setting to zero, set the grads to None. See " +":meth:`torch.optim.Optimizer.zero_grad` for details." +msgstr "" + +#: of tensorcircuit.torchnn.QuantumNet:1 +msgid "Bases: :py:class:`~torch.nn.modules.module.Module`" +msgstr "" + +#: ../../source/api/translation.rst:2 +msgid "tensorcircuit.translation" +msgstr "" + +#: of tensorcircuit.translation:1 +msgid "Circuit object translation in different packages" +msgstr "" + +#: of tensorcircuit.translation.eqasm2tc:1 +msgid "Translation qexe/eqasm instruction to tensorcircuit Circuit object" +msgstr "" + +#: of tensorcircuit.translation.eqasm2tc:7 +msgid "lines of ignored code at the head and the tail, defaults to (6, 1)" +msgstr "" + +#: of tensorcircuit.translation.perm_matrix:1 +msgid "" +"Generate a permutation matrix P. Due to the different convention or " +"qubits' order in qiskit and tensorcircuit, the unitary represented by the" +" same circuit is different. They are related by this permutation matrix " +"P: P @ U_qiskit @ P = U_tc" +msgstr "" + +#: of tensorcircuit.translation.perm_matrix:7 +#: tensorcircuit.translation.qir2cirq:15 +#: tensorcircuit.translation.qir2qiskit:16 +#: tensorcircuit.translation.qiskit2tc:14 tensorcircuit.vis.qir2tex:12 +msgid "# of qubits" +msgstr "" + +#: of tensorcircuit.translation.perm_matrix:9 +msgid "The permutation matrix P" +msgstr "" + +#: of tensorcircuit.translation.qir2cirq:1 +msgid "" +"Generate a cirq circuit using the quantum intermediate representation " +"(qir) in tensorcircuit." +msgstr "" + +#: of tensorcircuit.translation.qir2cirq:17 +#: tensorcircuit.translation.qir2qiskit:18 +msgid "" +"The extra quantum IR of tc circuit including measure and reset on " +"hardware, defaults to None" +msgstr "" + +#: of tensorcircuit.translation.qir2cirq:20 +msgid "qiskit cirq object" +msgstr "" + +#: of tensorcircuit.translation.qir2cirq:23 +msgid "" +"#TODO(@erertertet): add default theta to iswap gate add more cirq built-" +"in gate instead of customized add unitary test with tolerance add support" +" of cirq built-in ControlledGate for multiplecontroll support more " +"element in qir, e.g. barrier, measure..." +msgstr "" + +#: of tensorcircuit.translation.qir2json:1 +msgid "" +"transform qir to json compatible list of dict where array is replaced by " +"real and imaginary list" +msgstr "" + +#: of tensorcircuit.translation.qir2qiskit:1 +msgid "" +"Generate a qiskit quantum circuit using the quantum intermediate " +"representation (qir) in tensorcircuit." +msgstr "" + +#: of tensorcircuit.translation.qir2qiskit:21 +msgid "Circuit initial state in qiskit format" +msgstr "" + +#: of tensorcircuit.translation.qir2qiskit:23 +msgid "qiskit QuantumCircuit object" +msgstr "" + +#: of tensorcircuit.translation.qiskit2tc:1 +msgid "Generate a tensorcircuit circuit using the quantum circuit data in qiskit." +msgstr "" + +#: of tensorcircuit.translation.qiskit2tc:12 +msgid "Quantum circuit data from qiskit." +msgstr "" + +#: of tensorcircuit.translation.qiskit2tc:16 +msgid "Input state of the circuit. Default is None." +msgstr "" + +#: of tensorcircuit.translation.qiskit2tc:18 +msgid "``Circuit``, ``DMCircuit`` or ``MPSCircuit``" +msgstr "" + +#: of tensorcircuit.translation.qiskit2tc:26 +msgid "A quantum circuit in tensorcircuit" +msgstr "" + +#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:1 +msgid "" +"qiskit ``from_qasm_str`` method cannot keep the order of measure as the " +"qasm file, we provide this alternative function in case the order of " +"measure instruction matters" +msgstr "" + +#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:4 +msgid "open qasm str" +msgstr "" + +#: of tensorcircuit.translation.qiskit_from_qasm_str_ordered_measure:6 +msgid "``qiskit.circuit.QuantumCircuit``" +msgstr "" + +#: ../../source/api/utils.rst:2 +msgid "tensorcircuit.utils" +msgstr "" + +#: of tensorcircuit.utils:1 +msgid "Helper functions" +msgstr "" + +#: of tensorcircuit.utils.append:1 +msgid "Functional programming paradigm to build function pipeline" +msgstr "" + +#: of tensorcircuit.utils.append:9 +msgid "The function which are attached with other functions" +msgstr "" + +#: of tensorcircuit.utils.append:11 +msgid "Function to be attached" +msgstr "" + +#: of tensorcircuit.utils.append:13 +msgid "The final results after function pipeline" +msgstr "" + +#: of tensorcircuit.utils.arg_alias:1 +msgid "function argument alias decorator with new docstring" +msgstr "" + +#: of tensorcircuit.utils.arg_alias:7 +msgid "whether to add doc for these new alias arguments, defaults True" +msgstr "" + +#: of tensorcircuit.utils.arg_alias:9 +msgid "the decorated function" +msgstr "" + +#: of tensorcircuit.utils.benchmark:1 +msgid "benchmark jittable function with staging time and running time" +msgstr "" + +#: of tensorcircuit.utils.benchmark:5 +msgid "_description_, defaults to 5" +msgstr "" + +#: of tensorcircuit.utils.is_m1mac:1 +msgid "check whether the running platform is MAC with M1 chip" +msgstr "" + +#: of tensorcircuit.utils.is_m1mac:3 +msgid "True for MAC M1 platform" +msgstr "" + +#: of tensorcircuit.utils.return_partial:1 +msgid "" +"Return a callable function for output ith parts of the original output " +"along the first axis. Original output supports List and Tensor." +msgstr "" + +#: of tensorcircuit.utils.return_partial:20 +msgid "The function to be applied this method" +msgstr "" + +#: of tensorcircuit.utils.return_partial:22 +msgid "The ith parts of original output along the first axis (axis=0 or dim=0)" +msgstr "" + +#: of tensorcircuit.utils.return_partial:24 +msgid "The modified callable function" +msgstr "" + +#: ../../source/api/vis.rst:2 +msgid "tensorcircuit.vis" +msgstr "" + +#: of tensorcircuit.vis:1 +msgid "Visualization on circuits" +msgstr "" + +#: of tensorcircuit.vis.gate_name_trans:1 +msgid "" +"Translating from the gate name to gate information including the number " +"of control qubits and the reduced gate name." +msgstr "" + +#: of tensorcircuit.vis.gate_name_trans:10 +msgid "String of gate name" +msgstr "" + +#: of tensorcircuit.vis.gate_name_trans:12 +msgid "# of control qubits, reduced gate name" +msgstr "" + +#: of tensorcircuit.vis.qir2tex:1 +msgid "" +"Generate Tex code from 'qir' string to illustrate the circuit structure. " +"This visualization is based on quantikz package." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:10 +msgid "The quantum intermediate representation of a circuit in tensorcircuit." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:14 +msgid "Initial state, default is an all zero state '000...000'." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:16 +msgid "" +"Measurement Basis, default is None which means no measurement in the end " +"of the circuit." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:19 +msgid "" +"If true, a right compression of the circuit will be conducted. A right " +"compression means we will try to shift gates from right to left if " +"possible." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:21 +msgid "" +"Default is false. :type rcompress: bool :param lcompress: If true, a left" +" compression of the circuit will be conducted." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:24 +msgid "" +"A left compression means we will try to shift gates from left to right if" +" possible. Default is false." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:27 +msgid "" +"If true, the tex code will be designed to generate a standalone document." +" Default is false which means the generated tex code is just a quantikz " +"code block." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:30 +msgid "" +"If true, a string table of tex code will also be returned. Default is " +"false." +msgstr "" + +#: of tensorcircuit.vis.qir2tex:33 +msgid "" +"Tex code of circuit visualization based on quantikz package. If " +"return_string_table is true, a string table of tex code will also be " +"returned." +msgstr "" + +#: of tensorcircuit.vis.render_pdf:1 +msgid "" +"Generate the PDF file with given latex string and filename. Latex command" +" and file path can be specified. When notebook is True, convert the " +"output PDF file to image and return a Image object." +msgstr "" + +#: of tensorcircuit.vis.render_pdf:15 +msgid "String of latex content" +msgstr "" + +#: of tensorcircuit.vis.render_pdf:17 +msgid "File name, defaults to random UUID `str(uuid4())`" +msgstr "" + +#: of tensorcircuit.vis.render_pdf:19 +msgid "Executable Latex command, defaults to `pdflatex`" +msgstr "" + +#: of tensorcircuit.vis.render_pdf:21 +msgid "File path, defaults to current working place `os.getcwd()`" +msgstr "" + +#: of tensorcircuit.vis.render_pdf:25 +msgid "if notebook is True, return `Image` object; otherwise return `None`" +msgstr "" + +#~ msgid "" +#~ "This is a method that implementers " +#~ "of subclasses of `Layer` or `Model` " +#~ "can override if they need a " +#~ "state-creation step in-between layer " +#~ "instantiation and layer call." +#~ msgstr "" + +#~ msgid "This is typically used to create the weights of `Layer` subclasses." +#~ msgstr "" + +#~ msgid "" +#~ "Note here that `call()` method in " +#~ "`tf.keras` is little bit different from" +#~ " `keras` API. In `keras` API, you " +#~ "can pass support masking for layers " +#~ "as additional arguments. Whereas `tf.keras`" +#~ " has `compute_mask()` method to support " +#~ "masking." +#~ msgstr "" + +#~ msgid "Modules for DQAS framework" +#~ msgstr "" + +#~ msgid "DQAS framework entrypoint" +#~ msgstr "" + +#~ msgid "Parameters" +#~ msgstr "" + +#~ msgid "" +#~ "function with input of data instance," +#~ " circuit parameters theta and structural" +#~ " paramter k, return tuple of " +#~ "objective value and gradient with " +#~ "respect to theta" +#~ msgstr "" + +#~ msgid "data generator as dataset" +#~ msgstr "" + +#~ msgid "list of operations as primitive operator pool" +#~ msgstr "" + +#~ msgid "the default layer number of the circuit ansatz" +#~ msgstr "" + +#~ msgid "" +#~ "shape of circuit parameter pool, in " +#~ "general p_stp*l, where l is the " +#~ "max number of circuit parameters for " +#~ "op in the operator pool" +#~ msgstr "" + +#~ msgid "the same as p in the most times" +#~ msgstr "" + +#~ msgid "batch size of one epoch" +#~ msgstr "" + +#~ msgid "prethermal update times" +#~ msgstr "" + +#~ msgid "training epochs" +#~ msgstr "" + +#~ msgid "parallel thread number, 0 to disable multiprocessing model by default" +#~ msgstr "" + +#~ msgid "set verbose log to print" +#~ msgstr "" + +#~ msgid "function to output verbose information" +#~ msgstr "" + +#~ msgid "function return intermiediate result for final history list" +#~ msgstr "" + +#~ msgid "cutoff probability to avoid peak distribution" +#~ msgstr "" + +#~ msgid "" +#~ "function accepting list of objective " +#~ "values and return the baseline value " +#~ "used in the next round" +#~ msgstr "" + +#~ msgid "return noise with the same shape as circuit parameter pool" +#~ msgstr "" + +#~ msgid "initial values for circuit parameter pool" +#~ msgstr "" + +#~ msgid "initial values for probabilistic model parameters" +#~ msgstr "" + +#~ msgid "optimizer for circuit parameters theta" +#~ msgstr "" + +#~ msgid "optimizer for model parameters alpha" +#~ msgstr "" + +#~ msgid "optimizer for circuit parameters in prethermal stage" +#~ msgstr "" + +#~ msgid "fixed structural parameters for prethermal training" +#~ msgstr "" + +#~ msgid "regularization function for model parameters alpha" +#~ msgstr "" + +#~ msgid "regularization function for circuit parameters theta" +#~ msgstr "" + +#~ msgid "Returns" +#~ msgstr "" + +#~ msgid "" +#~ "The probabilistic model based DQAS, can" +#~ " use extensively for DQAS case for" +#~ " ``NMF`` probabilistic model." +#~ msgstr "" + +#~ msgid "vag func, return loss and nabla lnp" +#~ msgstr "" + +#~ msgid "keras model" +#~ msgstr "" + +#~ msgid "sample func of logic with keras model input" +#~ msgstr "" + +#~ msgid "input data pipeline generator" +#~ msgstr "" + +#~ msgid "operation pool" +#~ msgstr "" + +#~ msgid "depth for DQAS" +#~ msgstr "" + +#~ msgid "parallel kernels" +#~ msgstr "" + +#~ msgid "final loss function in terms of average of sub loss for each circuit" +#~ msgstr "" + +#~ msgid "derivative function for ``loss_func``" +#~ msgstr "" + +#~ msgid "" +#~ "Call in customized functions and grab" +#~ " variables within DQAS framework function" +#~ " by var name str." +#~ msgstr "" + +#~ msgid "The DQAS framework function" +#~ msgstr "" + +#~ msgid "Variables within the DQAS framework" +#~ msgstr "" + +#~ msgid "Return type" +#~ msgstr "" + +#~ msgid "" +#~ "This function works only when nnp " +#~ "has the same shape as stp, i.e." +#~ " one parameter for each op." +#~ msgstr "" + +#~ msgid "The kernel for multiprocess to run parallel in DQAS function/" +#~ msgstr "" + +#~ msgid "" +#~ "parallel variational parameter training and" +#~ " search to avoid local minimum not" +#~ " limited to qaoa setup as the " +#~ "function name indicates, as long as " +#~ "you provided suitable `vag_func`" +#~ msgstr "" + +#~ msgid "data input generator for vag_func" +#~ msgstr "" + +#~ msgid "vag_kernel" +#~ msgstr "" + +#~ msgid "number of tries" +#~ msgstr "" + +#~ msgid "" +#~ "for optimization problem the input is" +#~ " in general fixed so batch is " +#~ "often 1" +#~ msgstr "" + +#~ msgid "number of parallel jobs" +#~ msgstr "" + +#~ msgid "mean value of normal distribution for nnp" +#~ msgstr "" + +#~ msgid "std deviation of normal distribution for nnp" +#~ msgstr "" + +#~ msgid "Doesn't support prob model DQAS search." +#~ msgstr "" + +#~ msgid "Modules for graph instance data and more" +#~ msgstr "" + +#~ msgid "```python d = nx.to_dict_of_dicts(g) ```" +#~ msgstr "" + +#~ msgid "1D PBC chain with n sites." +#~ msgstr "" + +#~ msgid "The number of nodes" +#~ msgstr "" + +#~ msgid "The resulted graph g" +#~ msgstr "" + +#~ msgid "all graphs with m edge out from g" +#~ msgstr "" + +#~ msgid "" +#~ "Generate a reduced graph with given " +#~ "ratio of edges compared to the " +#~ "original graph g." +#~ msgstr "" + +#~ msgid "The base graph" +#~ msgstr "" + +#~ msgid "number of edges kept, default half of the edges" +#~ msgstr "" + +#~ msgid "The resulted reduced graph" +#~ msgstr "" + +#~ msgid "Split the graph in exactly ``split`` piece evenly." +#~ msgstr "" + +#~ msgid "The mother graph" +#~ msgstr "" + +#~ msgid "The number of the graph we want to divide into, defaults to 2" +#~ msgstr "" + +#~ msgid "List of graph instance of size ``split``" +#~ msgstr "" + +#~ msgid "Module for functions adding layers of circuits" +#~ msgstr "" + +#~ msgid "Hlayer" +#~ msgstr "" + +#~ msgid "anyrxlayer" +#~ msgstr "" + +#~ msgid "anyrylayer" +#~ msgstr "" + +#~ msgid "anyrzlayer" +#~ msgstr "" + +#~ msgid "anyswaplayer" +#~ msgstr "" + +#~ msgid "anyxxlayer" +#~ msgstr "" + +#~ msgid "anyxylayer" +#~ msgstr "" + +#~ msgid "anyxzlayer" +#~ msgstr "" + +#~ msgid "anyyxlayer" +#~ msgstr "" + +#~ msgid "anyyylayer" +#~ msgstr "" + +#~ msgid "anyyzlayer" +#~ msgstr "" + +#~ msgid "anyzxlayer" +#~ msgstr "" + +#~ msgid "anyzylayer" +#~ msgstr "" + +#~ msgid "anyzzlayer" +#~ msgstr "" + +#~ msgid "cnotlayer" +#~ msgstr "" + +#~ msgid "rxlayer" +#~ msgstr "" + +#~ msgid "rylayer" +#~ msgstr "" + +#~ msgid "rzlayer" +#~ msgstr "" + +#~ msgid "swaplayer" +#~ msgstr "" + +#~ msgid "xxgate" +#~ msgstr "" + +#~ msgid "xxlayer" +#~ msgstr "" + +#~ msgid "xygate" +#~ msgstr "" + +#~ msgid "xylayer" +#~ msgstr "" + +#~ msgid "xzgate" +#~ msgstr "" + +#~ msgid "xzlayer" +#~ msgstr "" + +#~ msgid "yxgate" +#~ msgstr "" + +#~ msgid "yxlayer" +#~ msgstr "" + +#~ msgid "yygate" +#~ msgstr "" + +#~ msgid "yylayer" +#~ msgstr "" + +#~ msgid "yzgate" +#~ msgstr "" + +#~ msgid "yzlayer" +#~ msgstr "" + +#~ msgid "zxgate" +#~ msgstr "" + +#~ msgid "zxlayer" +#~ msgstr "" + +#~ msgid "zygate" +#~ msgstr "" + +#~ msgid "zylayer" +#~ msgstr "" + +#~ msgid "zzgate" +#~ msgstr "" + +#~ msgid "zzlayer" +#~ msgstr "" + +#~ msgid "$$e^{-i heta_i \\sigma}$$" +#~ msgstr "" + +#~ msgid "" +#~ "The following function should be used" +#~ " to generate layers with special " +#~ "case. As its soundness depends on " +#~ "the nature of the task or problem," +#~ " it doesn't always make sense." +#~ msgstr "" + +#~ msgid "$$e^{-i heta \\sigma}$$" +#~ msgstr "" + +#~ msgid "$$e^{-i heta \\sigma}$$" +#~ msgstr "" + +#~ msgid "" +#~ "A collection of useful function snippets" +#~ " that irrelevant with the main " +#~ "modules or await for furthere refactor" +#~ msgstr "" + +#~ msgid "Bases: :py:class:`object`" +#~ msgstr "" + +#~ msgid "" +#~ "color cirq circuit SVG for given " +#~ "gates, a small tool to hack the" +#~ " cirq SVG" +#~ msgstr "" + +#~ msgid "integer coordinate which gate is colored" +#~ msgstr "" + +#~ msgid "transform repr form of an array to real numpy array" +#~ msgstr "" + +#~ msgid "DQAS application kernels as vag functions" +#~ msgstr "" + +#~ msgid "1D array for full wavefunction, the basis is in lexcical order" +#~ msgstr "" + +#~ msgid "nx.Graph" +#~ msgstr "" + +#~ msgid "transformation functions before averaged" +#~ msgstr "" + +#~ msgid "as f3" +#~ msgstr "" + +#~ msgid "maxcut energy for n qubit wavefunction i-th basis" +#~ msgstr "" + +#~ msgid "ranged from 0 to 2**n-1" +#~ msgstr "" + +#~ msgid "number of qubits" +#~ msgstr "" + +#~ msgid "" +#~ "deprecated as non tf and non " +#~ "flexible, use the combination of " +#~ "``reduced_density_matrix`` and ``entropy`` instead." +#~ msgstr "" + +#~ msgid "deprecated, current version in tc.quantum" +#~ msgstr "" + +#~ msgid "" +#~ "value and gradient, currently only " +#~ "tensorflow backend is supported jax and" +#~ " numpy seems to be slow in " +#~ "circuit simulation anyhow. *deprecated*" +#~ msgstr "" + +#~ msgid "if lbd=0, take energy as objective" +#~ msgstr "" + +#~ msgid "if as default 0, overlap will not compute in the process" +#~ msgstr "" + +#~ msgid "Fill single qubit gates according to placeholder on circuit" +#~ msgstr "" + +#~ msgid "Hamiltonian measurements for Heisenberg model on graph lattice g" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:15 -msgid "String of latex content" -msgstr "" +#~ msgid "short cut for ``cirq.LineQubit(i)``" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:17 -msgid "File name, defaults to random UUID `str(uuid4())`" -msgstr "" +#~ msgid "QAOA block encoding kernel, support 2 params in one op" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:19 -msgid "Executable Latex command, defaults to `pdflatex`" -msgstr "" +#~ msgid "" +#~ "training QAOA with only optimizing " +#~ "circuit parameters, can be well replaced" +#~ " with more general function `DQAS_search`" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:21 -msgid "File path, defaults to current working place `os.getcwd()`" -msgstr "" +#~ msgid "multi parameter for one layer" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:23 -msgid "[description], defaults to False" -msgstr "" +#~ msgid "kw arguments for measurements_func" +#~ msgstr "" -#: of tensorcircuit.vis.render_pdf:25 -msgid "if notebook is True, return `Image` object; otherwise return `None`" -msgstr "" +#~ msgid "loss function, gradient of nnp" +#~ msgstr "" #~ msgid "" -#~ "This is a method that implementers " -#~ "of subclasses of `Layer` or `Model` " -#~ "can override if they need a " -#~ "state-creation step in-between layer " -#~ "instantiation and layer call." +#~ "tensorflow quantum backend compare to " +#~ "qaoa_vag which is tensorcircuit backend" #~ msgstr "" -#~ msgid "This is typically used to create the weights of `Layer` subclasses." +#~ msgid "Hamiltonian for tfim on lattice defined by graph g" +#~ msgstr "" + +#~ msgid "cirq.PauliSum as operators for tfq expectation layer" #~ msgstr "" #~ msgid "" -#~ "Note here that `call()` method in " -#~ "`tf.keras` is little bit different from" -#~ " `keras` API. In `keras` API, you " -#~ "can pass support masking for layers " -#~ "as additional arguments. Whereas `tf.keras`" -#~ " has `compute_mask()` method to support " -#~ "masking." +#~ "generate random wavefunction from " +#~ "approximately Haar measure, reference: " +#~ "https://doi.org/10.1063/1.4983266" #~ msgstr "" -#~ msgid "Modules for DQAS framework" +#~ msgid "repetition of the blocks" #~ msgstr "" -#~ msgid "DQAS framework entrypoint" +#~ msgid "random Haar measure approximation" #~ msgstr "" -#~ msgid "Parameters" +#~ msgid "cirq.Circuit, empty circuit" +#~ msgstr "" + +#~ msgid "# of qubit" #~ msgstr "" #~ msgid "" -#~ "function with input of data instance," -#~ " circuit parameters theta and structural" -#~ " paramter k, return tuple of " -#~ "objective value and gradient with " -#~ "respect to theta" +#~ "One-hot variational autoregressive models " +#~ "for multiple categorical choices beyond " +#~ "binary" #~ msgstr "" -#~ msgid "data generator as dataset" +#~ msgid "Bases: :py:class:`keras.engine.training.Model`" #~ msgstr "" -#~ msgid "list of operations as primitive operator pool" +#~ msgid "Calls the model on new inputs and returns the outputs as tensors." #~ msgstr "" -#~ msgid "the default layer number of the circuit ansatz" +#~ msgid "" +#~ "In this case `call()` just reapplies " +#~ "all ops in the graph to the " +#~ "new inputs (e.g. build a new " +#~ "computational graph from the provided " +#~ "inputs)." #~ msgstr "" #~ msgid "" -#~ "shape of circuit parameter pool, in " -#~ "general p_stp*l, where l is the " -#~ "max number of circuit parameters for " -#~ "op in the operator pool" +#~ "Note: This method should not be " +#~ "called directly. It is only meant " +#~ "to be overridden when subclassing " +#~ "`tf.keras.Model`. To call a model on " +#~ "an input, always use the `__call__()`" +#~ " method, i.e. `model(inputs)`, which relies" +#~ " on the underlying `call()` method." #~ msgstr "" -#~ msgid "the same as p in the most times" +#~ msgid "Args:" #~ msgstr "" -#~ msgid "batch size of one epoch" +#~ msgid "" +#~ "inputs: Input tensor, or dict/list/tuple " +#~ "of input tensors. training: Boolean or" +#~ " boolean scalar tensor, indicating whether" +#~ " to run" #~ msgstr "" -#~ msgid "prethermal update times" +#~ msgid "the `Network` in training mode or inference mode." #~ msgstr "" -#~ msgid "training epochs" +#~ msgid "mask: A mask or list of masks. A mask can be either a boolean tensor or" #~ msgstr "" -#~ msgid "parallel thread number, 0 to disable multiprocessing model by default" +#~ msgid "None (no mask). For more details, check the guide" #~ msgstr "" -#~ msgid "set verbose log to print" +#~ msgid "[here](https://www.tensorflow.org/guide/keras/masking_and_padding)." #~ msgstr "" -#~ msgid "function to output verbose information" +#~ msgid "Returns:" #~ msgstr "" -#~ msgid "function return intermiediate result for final history list" +#~ msgid "" +#~ "A tensor if there is a single " +#~ "output, or a list of tensors if" +#~ " there are more than one outputs." #~ msgstr "" -#~ msgid "cutoff probability to avoid peak distribution" +#~ msgid "Bases: :py:class:`keras.engine.base_layer.Layer`" #~ msgstr "" #~ msgid "" -#~ "function accepting list of objective " -#~ "values and return the baseline value " -#~ "used in the next round" +#~ "Creates the variables of the layer " +#~ "(optional, for subclass implementers)." #~ msgstr "" -#~ msgid "return noise with the same shape as circuit parameter pool" +#~ msgid "" +#~ "This is a method that implementers " +#~ "of subclasses of `Layer` or `Model` " +#~ "can override if they need a " +#~ "state-creation step in-between layer " +#~ "instantiation and layer call. It is " +#~ "invoked automatically before the first " +#~ "execution of `call()`." #~ msgstr "" -#~ msgid "initial values for circuit parameter pool" +#~ msgid "" +#~ "This is typically used to create " +#~ "the weights of `Layer` subclasses (at" +#~ " the discretion of the subclass " +#~ "implementer)." #~ msgstr "" -#~ msgid "initial values for probabilistic model parameters" +#~ msgid "input_shape: Instance of `TensorShape`, or list of instances of" #~ msgstr "" -#~ msgid "optimizer for circuit parameters theta" +#~ msgid "" +#~ "`TensorShape` if the layer expects a " +#~ "list of inputs (one instance per " +#~ "input)." #~ msgstr "" -#~ msgid "optimizer for model parameters alpha" +#~ msgid "This is where the layer's logic lives." #~ msgstr "" -#~ msgid "optimizer for circuit parameters in prethermal stage" +#~ msgid "" +#~ "The `call()` method may not create " +#~ "state (except in its first invocation," +#~ " wrapping the creation of variables " +#~ "or other resources in `tf.init_scope()`). " +#~ "It is recommended to create state " +#~ "in `__init__()`, or the `build()` method" +#~ " that is called automatically before " +#~ "`call()` executes the first time." #~ msgstr "" -#~ msgid "fixed structural parameters for prethermal training" +#~ msgid "inputs: Input tensor, or dict/list/tuple of input tensors." #~ msgstr "" -#~ msgid "regularization function for model parameters alpha" +#~ msgid "" +#~ "The first positional `inputs` argument " +#~ "is subject to special rules: - " +#~ "`inputs` must be explicitly passed. A" +#~ " layer cannot have zero" #~ msgstr "" -#~ msgid "regularization function for circuit parameters theta" +#~ msgid "" +#~ "arguments, and `inputs` cannot be " +#~ "provided via the default value of " +#~ "a keyword argument." #~ msgstr "" -#~ msgid "Returns" +#~ msgid "NumPy array or Python scalar values in `inputs` get cast as tensors." +#~ msgstr "" + +#~ msgid "Keras mask metadata is only collected from `inputs`." #~ msgstr "" #~ msgid "" -#~ "The probabilistic model based DQAS, can" -#~ " use extensively for DQAS case for" -#~ " ``NMF`` probabilistic model." +#~ "Layers are built (`build(input_shape)` method)" +#~ " using shape info from `inputs` only." #~ msgstr "" -#~ msgid "vag func, return loss and nabla lnp" +#~ msgid "`input_spec` compatibility is only checked against `inputs`." #~ msgstr "" -#~ msgid "keras model" +#~ msgid "" +#~ "Mixed precision input casting is only" +#~ " applied to `inputs`. If a layer " +#~ "has tensor arguments in `*args` or " +#~ "`**kwargs`, their casting behavior in " +#~ "mixed precision should be handled " +#~ "manually." #~ msgstr "" -#~ msgid "sample func of logic with keras model input" +#~ msgid "The SavedModel input specification is generated using `inputs` only." #~ msgstr "" -#~ msgid "input data pipeline generator" +#~ msgid "" +#~ "Integration with various ecosystem packages" +#~ " like TFMOT, TFLite, TF.js, etc is" +#~ " only supported for `inputs` and not" +#~ " for tensors in positional and " +#~ "keyword arguments." #~ msgstr "" -#~ msgid "operation pool" +#~ msgid "*args: Additional positional arguments. May contain tensors, although" #~ msgstr "" -#~ msgid "depth for DQAS" +#~ msgid "this is not recommended, for the reasons above." #~ msgstr "" -#~ msgid "parallel kernels" +#~ msgid "**kwargs: Additional keyword arguments. May contain tensors, although" #~ msgstr "" -#~ msgid "final loss function in terms of average of sub loss for each circuit" +#~ msgid "" +#~ "this is not recommended, for the " +#~ "reasons above. The following optional " +#~ "keyword arguments are reserved: - " +#~ "`training`: Boolean scalar tensor of " +#~ "Python boolean indicating" #~ msgstr "" -#~ msgid "derivative function for ``loss_func``" +#~ msgid "whether the `call` is meant for training or inference." #~ msgstr "" #~ msgid "" -#~ "Call in customized functions and grab" -#~ " variables within DQAS framework function" -#~ " by var name str." +#~ "`mask`: Boolean input mask. If the " +#~ "layer's `call()` method takes a `mask`" +#~ " argument, its default value will be" +#~ " set to the mask generated for " +#~ "`inputs` by the previous layer (if " +#~ "`input` did come from a layer that" +#~ " generated a corresponding mask, i.e. " +#~ "if it came from a Keras layer " +#~ "with masking support)." #~ msgstr "" -#~ msgid "The DQAS framework function" +#~ msgid "A tensor or list/tuple of tensors." #~ msgstr "" -#~ msgid "Variables within the DQAS framework" +#~ msgid "Relevant classes for VQNHE" #~ msgstr "" -#~ msgid "Return type" +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule`" #~ msgstr "" -#~ msgid "" -#~ "This function works only when nnp " -#~ "has the same shape as stp, i.e." -#~ " one parameter for each op." +#~ msgid "Dense layer but with complex weights, used for building complex RBM" #~ msgstr "" -#~ msgid "The kernel for multiprocess to run parallel in DQAS function/" +#~ msgid "VQNHE" #~ msgstr "" -#~ msgid "" -#~ "parallel variational parameter training and" -#~ " search to avoid local minimum not" -#~ " limited to qaoa setup as the " -#~ "function name indicates, as long as " -#~ "you provided suitable `vag_func`" +#~ msgid "[description]" #~ msgstr "" -#~ msgid "data input generator for vag_func" +#~ msgid "VQE" #~ msgstr "" -#~ msgid "vag_kernel" +#~ msgid "Backend register" #~ msgstr "" -#~ msgid "number of tries" +#~ msgid "Get the `tc.backend` object." #~ msgstr "" -#~ msgid "" -#~ "for optimization problem the input is" -#~ " in general fixed so batch is " -#~ "often 1" +#~ msgid "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\"" #~ msgstr "" -#~ msgid "number of parallel jobs" +#~ msgid "Raises" #~ msgstr "" -#~ msgid "mean value of normal distribution for nnp" +#~ msgid "Backend doesn't exist for `backend` argument." #~ msgstr "" -#~ msgid "std deviation of normal distribution for nnp" +#~ msgid "The `tc.backend` object that with all registered universal functions." #~ msgstr "" -#~ msgid "Doesn't support prob model DQAS search." +#~ msgid "Backend magic inherited from tensornetwork: jax backend" #~ msgstr "" -#~ msgid "Modules for graph instance data and more" +#~ msgid "Bases: :py:class:`tensornetwork.backends.jax.jax_backend.JaxBackend`" #~ msgstr "" -#~ msgid "```python d = nx.to_dict_of_dicts(g) ```" +#~ msgid "" +#~ "See the original backend API at " +#~ "``jax backend``. " +#~ "`_" #~ msgstr "" -#~ msgid "1D PBC chain with n sites." +#~ msgid "Returns the elementwise absolute value of tensor. Args:" #~ msgstr "" -#~ msgid "The number of nodes" +#~ msgid "tensor: An input tensor." #~ msgstr "" -#~ msgid "The resulted graph g" +#~ msgid "tensor: Its elementwise absolute value." #~ msgstr "" -#~ msgid "all graphs with m edge out from g" +#~ msgid "Return the index of maximum of an array an axis." #~ msgstr "" -#~ msgid "" -#~ "Generate a reduced graph with given " -#~ "ratio of edges compared to the " -#~ "original graph g." +#~ msgid "[description], defaults to 0, different behavior from numpy defaults!" #~ msgstr "" -#~ msgid "The base graph" +#~ msgid "Return the index of minimum of an array an axis." #~ msgstr "" -#~ msgid "number of edges kept, default half of the edges" +#~ msgid "Cast the tensor dtype of a ``a``." #~ msgstr "" -#~ msgid "The resulted reduced graph" +#~ msgid "tensor" #~ msgstr "" -#~ msgid "Split the graph in exactly ``split`` piece evenly." +#~ msgid "\"float32\", \"float64\", \"complex64\", \"complex128\"" #~ msgstr "" -#~ msgid "The mother graph" +#~ msgid "``a`` of new dtype" #~ msgstr "" -#~ msgid "The number of the graph we want to divide into, defaults to 2" +#~ msgid "Join a sequence of arrays along an existing axis." #~ msgstr "" -#~ msgid "List of graph instance of size ``split``" +#~ msgid "[description], defaults to 0" #~ msgstr "" -#~ msgid "Module for functions adding layers of circuits" +#~ msgid "" +#~ "The native cond for XLA compiling, " +#~ "wrapper for ``tf.cond`` and limited " +#~ "functionality of ``jax.lax.cond``." #~ msgstr "" -#~ msgid "Hlayer" +#~ msgid "Convert a np.array or a tensor to a tensor type for the backend." #~ msgstr "" -#~ msgid "anyrxlayer" +#~ msgid "" +#~ "Generate the coo format sparse matrix" +#~ " from indices and values, which is" +#~ " the only sparse format supported in" +#~ " different ML backends." #~ msgstr "" -#~ msgid "anyrylayer" +#~ msgid "shape [n, 2] for n non zero values in the returned matrix" #~ msgstr "" -#~ msgid "anyrzlayer" +#~ msgid "shape [n]" #~ msgstr "" -#~ msgid "anyswaplayer" +#~ msgid "Tuple[int, ...]" #~ msgstr "" -#~ msgid "anyxxlayer" +#~ msgid "Return the expm of ``a``, matrix exponential." #~ msgstr "" -#~ msgid "anyxylayer" +#~ msgid "tensor in matrix form" #~ msgstr "" -#~ msgid "anyxzlayer" +#~ msgid "matrix exponential of matrix ``a``" #~ msgstr "" -#~ msgid "anyyxlayer" +#~ msgid "Return the cosine of a tensor ``a``." #~ msgstr "" -#~ msgid "anyyylayer" +#~ msgid "cosine of ``a``" #~ msgstr "" -#~ msgid "anyyzlayer" +#~ msgid "Return the cumulative sum of the elements along a given axis." #~ msgstr "" -#~ msgid "anyzxlayer" +#~ msgid "" +#~ "The default behavior is the same " +#~ "as numpy, different from tf/torch as " +#~ "cumsum of the flatten 1D array, " +#~ "defaults to None" #~ msgstr "" -#~ msgid "anyzylayer" +#~ msgid "Return the copy of tensor ''a''." #~ msgstr "" -#~ msgid "anyzzlayer" +#~ msgid "Return an identity matrix of dimension `dim`" #~ msgstr "" -#~ msgid "cnotlayer" +#~ msgid "" +#~ "Depending on specific backends, `dim` " +#~ "has to be either an int (numpy," +#~ " torch, tensorflow) or a `ShapeType` " +#~ "object (for block-sparse backends). " +#~ "Block-sparse behavior is currently not " +#~ "supported" #~ msgstr "" -#~ msgid "rxlayer" +#~ msgid "" +#~ "N (int): The dimension of the " +#~ "returned matrix. dtype: The dtype of " +#~ "the returned matrix. M (int): The " +#~ "dimension of the returned matrix." #~ msgstr "" -#~ msgid "rylayer" +#~ msgid "Return the function which is the grad function of input ``f``." #~ msgstr "" -#~ msgid "rzlayer" +#~ msgid "Example" #~ msgstr "" -#~ msgid "swaplayer" +#~ msgid "the function to be differentiated" #~ msgstr "" -#~ msgid "xxgate" +#~ msgid "" +#~ "the position of args in ``f`` that" +#~ " are to be differentiated, defaults " +#~ "to be 0" #~ msgstr "" -#~ msgid "xxlayer" +#~ msgid "the grad function of ``f`` with the same set of arguments as ``f``" #~ msgstr "" -#~ msgid "xygate" +#~ msgid "Return 1.j in as a tensor compatible with the backend." #~ msgstr "" -#~ msgid "xylayer" +#~ msgid "\"complex64\" or \"complex128\"" #~ msgstr "" -#~ msgid "xzgate" +#~ msgid "1.j tensor" #~ msgstr "" -#~ msgid "xzlayer" +#~ msgid "Return the elementwise imaginary value of a tensor ``a``." #~ msgstr "" -#~ msgid "yxgate" +#~ msgid "imaginary value of ``a``" #~ msgstr "" -#~ msgid "yxlayer" +#~ msgid "[summary]" #~ msgstr "" -#~ msgid "yygate" +#~ msgid "The possible options" #~ msgstr "" -#~ msgid "yylayer" +#~ msgid "Sampling output shape" #~ msgstr "" -#~ msgid "yzgate" +#~ msgid "" +#~ "probability for each option in a, " +#~ "defaults to None, as equal probability" +#~ " distribution" #~ msgstr "" -#~ msgid "yzlayer" +#~ msgid "" +#~ "Call the random normal function with " +#~ "the random state management behind the" +#~ " scene." #~ msgstr "" -#~ msgid "zxgate" +#~ msgid "[description], defaults to 1" #~ msgstr "" -#~ msgid "zxlayer" +#~ msgid "[description], defaults to \"32\"" #~ msgstr "" -#~ msgid "zygate" +#~ msgid "Determine whether the type of input ``a`` is ``sparse``." #~ msgstr "" -#~ msgid "zylayer" +#~ msgid "input matrix ``a``" #~ msgstr "" -#~ msgid "zzgate" +#~ msgid "a bool indicating whether the matrix ``a`` is sparse" #~ msgstr "" -#~ msgid "zzlayer" +#~ msgid "Return a boolean on whether ``a`` is a tensor in backend package." #~ msgstr "" -#~ msgid "$$e^{-i heta_i \\sigma}$$" +#~ msgid "a tensor to be determined" #~ msgstr "" -#~ msgid "" -#~ "The following function should be used" -#~ " to generate layers with special " -#~ "case. As its soundness depends on " -#~ "the nature of the task or problem," -#~ " it doesn't always make sense." +#~ msgid "whether ``a`` is a tensor" #~ msgstr "" -#~ msgid "$$e^{-i heta \\sigma}$$" +#~ msgid "Return the jitted version of function ``f``." #~ msgstr "" -#~ msgid "$$e^{-i heta \\sigma}$$" +#~ msgid "function to be jitted" #~ msgstr "" #~ msgid "" -#~ "A collection of useful function snippets" -#~ " that irrelevant with the main " -#~ "modules or await for furthere refactor" +#~ "index of args that doesn't regarded " +#~ "as tensor, only work for jax " +#~ "backend" #~ msgstr "" -#~ msgid "Bases: :py:class:`object`" +#~ msgid "" +#~ "whether open XLA compilation, only works" +#~ " for tensorflow backend, defaults False " +#~ "since several ops has no XLA " +#~ "correspondence" #~ msgstr "" -#~ msgid "" -#~ "color cirq circuit SVG for given " -#~ "gates, a small tool to hack the" -#~ " cirq SVG" +#~ msgid "jitted version of ``f``" #~ msgstr "" -#~ msgid "integer coordinate which gate is colored" +#~ msgid "" +#~ "Function that computes a (forward-mode)" +#~ " Jacobian-vector product of ``f``. " +#~ "Strictly speaking, this function is " +#~ "value_and_jvp." #~ msgstr "" -#~ msgid "transform repr form of an array to real numpy array" +#~ msgid "The function to compute jvp" #~ msgstr "" -#~ msgid "DQAS application kernels as vag functions" +#~ msgid "input for ``f``" #~ msgstr "" -#~ msgid "1D array for full wavefunction, the basis is in lexcical order" +#~ msgid "tangents" #~ msgstr "" -#~ msgid "nx.Graph" +#~ msgid "" +#~ "(``f(*inputs)``, jvp_tensor), where jvp_tensor " +#~ "is the same shape as the output" +#~ " of ``f``" #~ msgstr "" -#~ msgid "transformation functions before averaged" +#~ msgid "Return the kronecker product of two matrices ``a`` and ``b``." #~ msgstr "" -#~ msgid "as f3" +#~ msgid "kronecker product of ``a`` and ``b``" #~ msgstr "" -#~ msgid "maxcut energy for n qubit wavefunction i-th basis" +#~ msgid "Return the maximum of an array or maximum along an axis." #~ msgstr "" -#~ msgid "ranged from 0 to 2**n-1" +#~ msgid "[description], defaults to None" #~ msgstr "" -#~ msgid "number of qubits" +#~ msgid "Return the minimum of an array or minimum along an axis." #~ msgstr "" #~ msgid "" -#~ "deprecated as non tf and non " -#~ "flexible, use the combination of " -#~ "``reduced_density_matrix`` and ``entropy`` instead." +#~ "Return the numpy array of a tensor" +#~ " ``a``, but may not work in a" +#~ " jitted function." #~ msgstr "" -#~ msgid "deprecated, current version in tc.quantum" +#~ msgid "numpy array of ``a``" #~ msgstr "" #~ msgid "" -#~ "value and gradient, currently only " -#~ "tensorflow backend is supported jax and" -#~ " numpy seems to be slow in " -#~ "circuit simulation anyhow. *deprecated*" -#~ msgstr "" - -#~ msgid "if lbd=0, take energy as objective" +#~ "One-hot encodes the given ``a``. " +#~ "Each index in the input ``a`` is" +#~ " encoded as a vector of zeros " +#~ "of length ``num`` with the element " +#~ "at index set to one:" #~ msgstr "" -#~ msgid "if as default 0, overlap will not compute in the process" +#~ msgid "input tensor" #~ msgstr "" -#~ msgid "Fill single qubit gates according to placeholder on circuit" +#~ msgid "number of features in onehot dimension" #~ msgstr "" -#~ msgid "Hamiltonian measurements for Heisenberg model on graph lattice g" +#~ msgid "onehot tensor with the last extra dimension" #~ msgstr "" -#~ msgid "short cut for ``cirq.LineQubit(i)``" +#~ msgid "" +#~ "Return an ones-matrix of dimension " +#~ "`dim` Depending on specific backends, " +#~ "`dim` has to be either an int " +#~ "(numpy, torch, tensorflow) or a " +#~ "`ShapeType` object (for block-sparse " +#~ "backends). Block-sparse behavior is " +#~ "currently not supported Args:" #~ msgstr "" -#~ msgid "QAOA block encoding kernel, support 2 params in one op" +#~ msgid "" +#~ "shape (int): The dimension of the " +#~ "returned matrix. dtype: The dtype of " +#~ "the returned matrix." #~ msgstr "" #~ msgid "" -#~ "training QAOA with only optimizing " -#~ "circuit parameters, can be well replaced" -#~ " with more general function `DQAS_search`" +#~ "A jax like split API, but it " +#~ "doesn't split the key generator for " +#~ "other backends. It is just for a" +#~ " consistent interface of random code; " +#~ "make sure you know what the " +#~ "function actually does. This function is" +#~ " mainly a utility to write backend" +#~ " agnostic code instead of doing magic" +#~ " things." #~ msgstr "" -#~ msgid "multi parameter for one layer" +#~ msgid "Return the elementwise real value of a tensor ``a``." #~ msgstr "" -#~ msgid "kw arguments for measurements_func" +#~ msgid "real value of ``a``" #~ msgstr "" -#~ msgid "loss function, gradient of nnp" +#~ msgid "" +#~ "Rectified linear unit activation function. " +#~ "Computes the element-wise function:" #~ msgstr "" -#~ msgid "" -#~ "tensorflow quantum backend compare to " -#~ "qaoa_vag which is tensorcircuit backend" +#~ msgid "\\mathrm{relu}(x)=\\max(x,0)" #~ msgstr "" -#~ msgid "Hamiltonian for tfim on lattice defined by graph g" +#~ msgid "Input tensor" #~ msgstr "" -#~ msgid "cirq.PauliSum as operators for tfq expectation layer" +#~ msgid "Tensor after relu" #~ msgstr "" #~ msgid "" -#~ "generate random wavefunction from " -#~ "approximately Haar measure, reference: " -#~ "https://doi.org/10.1063/1.4983266" +#~ "Roughly equivalent to operand[indices] = " +#~ "updates, indices only support shape with" +#~ " rank 2 for now." #~ msgstr "" -#~ msgid "repetition of the blocks" +#~ msgid "Set the random state attached to the backend." #~ msgstr "" -#~ msgid "random Haar measure approximation" +#~ msgid "the random seed, defaults to be None" #~ msgstr "" -#~ msgid "cirq.Circuit, empty circuit" +#~ msgid "" +#~ "If set to be true, only get " +#~ "the random state in return instead " +#~ "of setting the state on the " +#~ "backend" #~ msgstr "" -#~ msgid "# of qubit" +#~ msgid "Return the elementwise sine of a tensor ``a``." #~ msgstr "" -#~ msgid "" -#~ "One-hot variational autoregressive models " -#~ "for multiple categorical choices beyond " -#~ "binary" +#~ msgid "sine of ``a``" #~ msgstr "" -#~ msgid "Bases: :py:class:`keras.engine.training.Model`" +#~ msgid "Return the total number of elements in ``a`` in tensor form." #~ msgstr "" -#~ msgid "Calls the model on new inputs and returns the outputs as tensors." +#~ msgid "the total number of elements in ``a``" #~ msgstr "" #~ msgid "" -#~ "In this case `call()` just reapplies " -#~ "all ops in the graph to the " -#~ "new inputs (e.g. build a new " -#~ "computational graph from the provided " -#~ "inputs)." +#~ "Softmax function. Computes the function " +#~ "which rescales elements to the range " +#~ "[0,1] such that the elements along " +#~ "axis sum to 1." #~ msgstr "" -#~ msgid "" -#~ "Note: This method should not be " -#~ "called directly. It is only meant " -#~ "to be overridden when subclassing " -#~ "`tf.keras.Model`. To call a model on " -#~ "an input, always use the `__call__()`" -#~ " method, i.e. `model(inputs)`, which relies" -#~ " on the underlying `call()` method." +#~ msgid "\\mathrm{softmax}(x) = \\frac{\\exp(x_i)}{\\sum_j \\exp(x_j)}" #~ msgstr "" -#~ msgid "Args:" +#~ msgid "Tensor" #~ msgstr "" #~ msgid "" -#~ "inputs: Input tensor, or dict/list/tuple " -#~ "of input tensors. training: Boolean or" -#~ " boolean scalar tensor, indicating whether" -#~ " to run" +#~ "A dimension along which Softmax will " +#~ "be computed , defaults to None for" +#~ " all axis sum." #~ msgstr "" -#~ msgid "the `Network` in training mode or inference mode." +#~ msgid "concatenated tensor" #~ msgstr "" -#~ msgid "mask: A mask or list of masks. A mask can be either a boolean tensor or" +#~ msgid "Solve the linear system Ax=b and return the solution x." #~ msgstr "" -#~ msgid "None (no mask). For more details, check the guide" +#~ msgid "The multiplied matrix." #~ msgstr "" -#~ msgid "[here](https://www.tensorflow.org/guide/keras/masking_and_padding)." +#~ msgid "The resulted matrix." #~ msgstr "" -#~ msgid "Returns:" +#~ msgid "The solution of the linear system." #~ msgstr "" -#~ msgid "" -#~ "A tensor if there is a single " -#~ "output, or a list of tensors if" -#~ " there are more than one outputs." +#~ msgid "A sparse matrix multiplies a dense matrix." #~ msgstr "" -#~ msgid "Bases: :py:class:`keras.engine.base_layer.Layer`" +#~ msgid "a sparse matrix" #~ msgstr "" -#~ msgid "" -#~ "Creates the variables of the layer " -#~ "(optional, for subclass implementers)." +#~ msgid "a dense matrix" #~ msgstr "" -#~ msgid "" -#~ "This is a method that implementers " -#~ "of subclasses of `Layer` or `Model` " -#~ "can override if they need a " -#~ "state-creation step in-between layer " -#~ "instantiation and layer call. It is " -#~ "invoked automatically before the first " -#~ "execution of `call()`." +#~ msgid "dense matrix" #~ msgstr "" #~ msgid "" -#~ "This is typically used to create " -#~ "the weights of `Layer` subclasses (at" -#~ " the discretion of the subclass " -#~ "implementer)." +#~ "Concatenates a sequence of tensors ``a``" +#~ " along a new dimension ``axis``." #~ msgstr "" -#~ msgid "input_shape: Instance of `TensorShape`, or list of instances of" +#~ msgid "List of tensors in the same shape" #~ msgstr "" -#~ msgid "" -#~ "`TensorShape` if the layer expects a " -#~ "list of inputs (one instance per " -#~ "input)." +#~ msgid "the stack axis, defaults to 0" #~ msgstr "" -#~ msgid "This is where the layer's logic lives." +#~ msgid "stateful register for each package" #~ msgstr "" -#~ msgid "" -#~ "The `call()` method may not create " -#~ "state (except in its first invocation," -#~ " wrapping the creation of variables " -#~ "or other resources in `tf.init_scope()`). " -#~ "It is recommended to create state " -#~ "in `__init__()`, or the `build()` method" -#~ " that is called automatically before " -#~ "`call()` executes the first time." +#~ msgid "shape of output sampling tensor" #~ msgstr "" -#~ msgid "inputs: Input tensor, or dict/list/tuple of input tensors." +#~ msgid "only real data type is supported, \"32\" or \"64\", defaults to \"32\"" #~ msgstr "" -#~ msgid "" -#~ "The first positional `inputs` argument " -#~ "is subject to special rules: - " -#~ "`inputs` must be explicitly passed. A" -#~ " layer cannot have zero" +#~ msgid "Uniform random sampler from ``low`` to ``high``." #~ msgstr "" -#~ msgid "" -#~ "arguments, and `inputs` cannot be " -#~ "provided via the default value of " -#~ "a keyword argument." +#~ msgid "shape of output sampling tensor, defaults to 1" #~ msgstr "" -#~ msgid "NumPy array or Python scalar values in `inputs` get cast as tensors." +#~ msgid "Stop backpropagation from ``a``." #~ msgstr "" -#~ msgid "Keras mask metadata is only collected from `inputs`." +#~ msgid "``branches[index]()``" #~ msgstr "" -#~ msgid "" -#~ "Layers are built (`build(input_shape)` method)" -#~ " using shape info from `inputs` only." +#~ msgid "Constructs a tensor by tiling a given tensor." #~ msgstr "" -#~ msgid "`input_spec` compatibility is only checked against `inputs`." +#~ msgid "1d tensor with length the same as the rank of ``a``" #~ msgstr "" -#~ msgid "" -#~ "Mixed precision input casting is only" -#~ " applied to `inputs`. If a layer " -#~ "has tensor arguments in `*args` or " -#~ "`**kwargs`, their casting behavior in " -#~ "mixed precision should be handled " -#~ "manually." +#~ msgid "Convert a sparse matrix to dense tensor." #~ msgstr "" -#~ msgid "The SavedModel input specification is generated using `inputs` only." +#~ msgid "the resulted dense matrix" #~ msgstr "" #~ msgid "" -#~ "Integration with various ecosystem packages" -#~ " like TFMOT, TFLite, TF.js, etc is" -#~ " only supported for `inputs` and not" -#~ " for tensors in positional and " -#~ "keyword arguments." -#~ msgstr "" - -#~ msgid "*args: Additional positional arguments. May contain tensors, although" +#~ "Find the unique elements and their " +#~ "corresponding counts of the given tensor" +#~ " ``a``." #~ msgstr "" -#~ msgid "this is not recommended, for the reasons above." +#~ msgid "Unique elements, corresponding counts" #~ msgstr "" -#~ msgid "**kwargs: Additional keyword arguments. May contain tensors, although" +#~ msgid "Return the function which returns the value and grad of ``f``." #~ msgstr "" #~ msgid "" -#~ "this is not recommended, for the " -#~ "reasons above. The following optional " -#~ "keyword arguments are reserved: - " -#~ "`training`: Boolean scalar tensor of " -#~ "Python boolean indicating" +#~ "the value and grad function of " +#~ "``f`` with the same set of " +#~ "arguments as ``f``" #~ msgstr "" -#~ msgid "whether the `call` is meant for training or inference." +#~ msgid "" +#~ "Return the VVAG function of ``f``. " +#~ "The inputs for ``f`` is (args[0], " +#~ "args[1], args[2], ...), and the output" +#~ " of ``f`` is a scalar. Suppose " +#~ "VVAG(f) is a function with inputs " +#~ "in the form (vargs[0], args[1], args[2]," +#~ " ...), where vagrs[0] has one extra" +#~ " dimension than args[0] in the first" +#~ " axis and consistent with args[0] in" +#~ " shape for remaining dimensions, i.e. " +#~ "shape(vargs[0]) = [batch] + shape(args[0])." +#~ " (We only cover cases where " +#~ "``vectorized_argnums`` defaults to 0 here " +#~ "for demonstration). VVAG(f) returns a " +#~ "tuple as a value tensor with shape" +#~ " [batch, 1] and a gradient tuple " +#~ "with shape: ([batch]+shape(args[argnum]) for " +#~ "argnum in argnums). The gradient for " +#~ "argnums=k is defined as" #~ msgstr "" #~ msgid "" -#~ "`mask`: Boolean input mask. If the " -#~ "layer's `call()` method takes a `mask`" -#~ " argument, its default value will be" -#~ " set to the mask generated for " -#~ "`inputs` by the previous layer (if " -#~ "`input` did come from a layer that" -#~ " generated a corresponding mask, i.e. " -#~ "if it came from a Keras layer " -#~ "with masking support)." +#~ "g^k = \\frac{\\partial \\sum_{i\\in batch} " +#~ "f(vargs[0][i], args[1], ...)}{\\partial args[k]}" #~ msgstr "" -#~ msgid "A tensor or list/tuple of tensors." +#~ msgid "Therefore, if argnums=0, the gradient is reduced to" #~ msgstr "" -#~ msgid "Relevant classes for VQNHE" +#~ msgid "g^0_i = \\frac{\\partial f(vargs[0][i])}{\\partial vargs[0][i]}" #~ msgstr "" #~ msgid "" -#~ "Bases: " -#~ ":py:class:`keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule`" -#~ msgstr "" - -#~ msgid "Dense layer but with complex weights, used for building complex RBM" +#~ ", which is specifically suitable for " +#~ "batched VQE optimization, where args[0] " +#~ "is the circuit parameters." #~ msgstr "" -#~ msgid "VQNHE" +#~ msgid "And if argnums=1, the gradient is like" #~ msgstr "" -#~ msgid "[description]" +#~ msgid "" +#~ "g^1_i = \\frac{\\partial \\sum_j " +#~ "f(vargs[0][j], args[1])}{\\partial args[1][i]}\n" +#~ "\n" #~ msgstr "" -#~ msgid "VQE" +#~ msgid "" +#~ ", which is suitable for quantum " +#~ "machine learning scenarios, where ``f`` " +#~ "is the loss function, args[0] " +#~ "corresponds to the input data and " +#~ "args[1] corresponds to the weights in" +#~ " the QML model." #~ msgstr "" -#~ msgid "Backend register" +#~ msgid "" +#~ "the args to be vectorized, these " +#~ "arguments should share the same batch" +#~ " shape in the fist dimension" #~ msgstr "" -#~ msgid "Get the `tc.backend` object." +#~ msgid "" +#~ "Function that computes the dot product" +#~ " between a vector v and the " +#~ "Jacobian of the given function at " +#~ "the point given by the inputs. " +#~ "(reverse mode AD relevant) Strictly " +#~ "speaking, this function is value_and_vjp." #~ msgstr "" -#~ msgid "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\"" +#~ msgid "the function to carry out vjp calculation" #~ msgstr "" -#~ msgid "Raises" +#~ msgid "" +#~ "value vector or gradient from downstream" +#~ " in reverse mode AD the same " +#~ "shape as return of function ``f``" #~ msgstr "" -#~ msgid "Backend doesn't exist for `backend` argument." +#~ msgid "" +#~ "(``f(*inputs)``, vjp_tensor), where vjp_tensor " +#~ "is the same shape as inputs" #~ msgstr "" -#~ msgid "The `tc.backend` object that with all registered universal functions." +#~ msgid "" +#~ "Return the vectorized map or batched " +#~ "version of ``f`` on the first " +#~ "extra axis. The general interface " +#~ "supports ``f`` with multiple arguments " +#~ "and broadcast in the fist dimension." #~ msgstr "" -#~ msgid "Backend magic inherited from tensornetwork: jax backend" +#~ msgid "function to be broadcasted." #~ msgstr "" -#~ msgid "Bases: :py:class:`tensornetwork.backends.jax.jax_backend.JaxBackend`" +#~ msgid "vmap version of ``f``" #~ msgstr "" #~ msgid "" -#~ "See the original backend API at " -#~ "``jax backend``. " -#~ "`_" +#~ "Return a zeros-matrix of dimension " +#~ "`dim` Depending on specific backends, " +#~ "`dim` has to be either an int " +#~ "(numpy, torch, tensorflow) or a " +#~ "`ShapeType` object (for block-sparse " +#~ "backends)." #~ msgstr "" -#~ msgid "Returns the elementwise absolute value of tensor. Args:" +#~ msgid "Block-sparse behavior is currently not supported Args:" #~ msgstr "" -#~ msgid "tensor: An input tensor." +#~ msgid "Backend magic inherited from tensornetwork: numpy backend" #~ msgstr "" -#~ msgid "tensor: Its elementwise absolute value." +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.numpy.numpy_backend.NumPyBackend`" #~ msgstr "" -#~ msgid "Return the index of maximum of an array an axis." +#~ msgid "" +#~ "see the original backend API at " +#~ "`numpy backend " +#~ "`_" #~ msgstr "" -#~ msgid "[description], defaults to 0, different behavior from numpy defaults!" +#~ msgid "Backend magic inherited from tensornetwork: pytorch backend" #~ msgstr "" -#~ msgid "Return the index of minimum of an array an axis." +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend`" #~ msgstr "" -#~ msgid "Cast the tensor dtype of a ``a``." +#~ msgid "" +#~ "See the original backend API at " +#~ "``pytorch backend``. " +#~ "``_" #~ msgstr "" -#~ msgid "tensor" +#~ msgid "" +#~ "Note the functionality provided by " +#~ "pytorch backend is incomplete, it " +#~ "currenly lacks native efficicent jit and" +#~ " vmap support." #~ msgstr "" -#~ msgid "\"float32\", \"float64\", \"complex64\", \"complex128\"" +#~ msgid "Backend magic inherited from tensornetwork: tensorflow backend" #~ msgstr "" -#~ msgid "``a`` of new dtype" +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend`" #~ msgstr "" -#~ msgid "Join a sequence of arrays along an existing axis." +#~ msgid "" +#~ "See the original backend API at " +#~ "`'tensorflow backend''. " +#~ "`_" #~ msgstr "" -#~ msgid "[description], defaults to 0" +#~ msgid "Some common noise quantum channels." #~ msgstr "" #~ msgid "" -#~ "The native cond for XLA compiling, " -#~ "wrapper for ``tf.cond`` and limited " -#~ "functionality of ``jax.lax.cond``." +#~ "Return an amplitude damping channel. " +#~ "Notice: Amplitude damping corrspondings to " +#~ "p = 1." #~ msgstr "" -#~ msgid "Convert a np.array or a tensor to a tensor type for the backend." +#~ msgid "" +#~ "\\sqrt{p}\n" +#~ "\\begin{bmatrix}\n" +#~ " 1 & 0\\\\\n" +#~ " 0 & \\sqrt{1-\\gamma}\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{p}\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & \\sqrt{\\gamma}\\\\\n" +#~ " 0 & 0\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{1-p}\n" +#~ "\\begin{bmatrix}\n" +#~ " \\sqrt{1-\\gamma} & 0\\\\\n" +#~ " 0 & 1\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{1-p}\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & 0\\\\\n" +#~ " \\sqrt{\\gamma} & 0\\\\\n" +#~ "\\end{bmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "Generate the coo format sparse matrix" -#~ " from indices and values, which is" -#~ " the only sparse format supported in" -#~ " different ML backends." +#~ msgid "the damping parameter of amplitude (:math:`\\gamma`)" #~ msgstr "" -#~ msgid "shape [n, 2] for n non zero values in the returned matrix" +#~ msgid ":math:`p`" #~ msgstr "" -#~ msgid "shape [n]" +#~ msgid "An amplitude damping channel with given :math:`\\gamma` and :math:`p`" #~ msgstr "" -#~ msgid "Tuple[int, ...]" +#~ msgid "Return a Depolarizing Channel" #~ msgstr "" -#~ msgid "Return the expm of ``a``, matrix exponential." +#~ msgid "" +#~ "\\sqrt{1-p_x-p_y-p_z}\n" +#~ "\\begin{bmatrix}\n" +#~ " 1 & 0\\\\\n" +#~ " 0 & 1\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{p_x}\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & 1\\\\\n" +#~ " 1 & 0\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{p_y}\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & -1j\\\\\n" +#~ " 1j & 0\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\sqrt{p_z}\n" +#~ "\\begin{bmatrix}\n" +#~ " 1 & 0\\\\\n" +#~ " 0 & -1\\\\\n" +#~ "\\end{bmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "tensor in matrix form" +#~ msgid ":math:`p_x`" #~ msgstr "" -#~ msgid "matrix exponential of matrix ``a``" +#~ msgid ":math:`p_y`" #~ msgstr "" -#~ msgid "Return the cosine of a tensor ``a``." +#~ msgid ":math:`p_z`" #~ msgstr "" -#~ msgid "cosine of ``a``" +#~ msgid "Sequences of Gates" #~ msgstr "" -#~ msgid "Return the cumulative sum of the elements along a given axis." +#~ msgid "Convert Kraus operators to one Tensor (as one Super Gate)." #~ msgstr "" #~ msgid "" -#~ "The default behavior is the same " -#~ "as numpy, different from tf/torch as " -#~ "cumsum of the flatten 1D array, " -#~ "defaults to None" +#~ "\\sum_{k}^{} K_k \\otimes K_k^{\\dagger}\n" +#~ "\n" #~ msgstr "" -#~ msgid "Return the copy of tensor ''a''." +#~ msgid "A sequence of Gate" #~ msgstr "" -#~ msgid "Return an identity matrix of dimension `dim`" +#~ msgid "The corresponding Tensor of the list of Kraus operators" #~ msgstr "" -#~ msgid "" -#~ "Depending on specific backends, `dim` " -#~ "has to be either an int (numpy," -#~ " torch, tensorflow) or a `ShapeType` " -#~ "object (for block-sparse backends). " -#~ "Block-sparse behavior is currently not " -#~ "supported" +#~ msgid "Return a phase damping channel with given :math:`\\gamma`" #~ msgstr "" #~ msgid "" -#~ "N (int): The dimension of the " -#~ "returned matrix. dtype: The dtype of " -#~ "the returned matrix. M (int): The " -#~ "dimension of the returned matrix." +#~ "\\begin{bmatrix}\n" +#~ " 1 & 0\\\\\n" +#~ " 0 & \\sqrt{1-\\gamma}\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & 0\\\\\n" +#~ " 0 & \\sqrt{\\gamma}\\\\\n" +#~ "\\end{bmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "Return the function which is the grad function of input ``f``." +#~ msgid "The damping parameter of phase (:math:`\\gamma`)" #~ msgstr "" -#~ msgid "Example" +#~ msgid "A phase damping channel with given :math:`\\gamma`" #~ msgstr "" -#~ msgid "the function to be differentiated" +#~ msgid "Reset channel" #~ msgstr "" #~ msgid "" -#~ "the position of args in ``f`` that" -#~ " are to be differentiated, defaults " -#~ "to be 0" +#~ "\\begin{bmatrix}\n" +#~ " 1 & 0\\\\\n" +#~ " 0 & 0\\\\\n" +#~ "\\end{bmatrix}\\qquad\n" +#~ "\\begin{bmatrix}\n" +#~ " 0 & 1\\\\\n" +#~ " 0 & 0\\\\\n" +#~ "\\end{bmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "the grad function of ``f`` with the same set of arguments as ``f``" +#~ msgid "Check identity of a single qubit Kraus operators." #~ msgstr "" -#~ msgid "Return 1.j in as a tensor compatible with the backend." +#~ msgid "Examples:" #~ msgstr "" -#~ msgid "\"complex64\" or \"complex128\"" +#~ msgid "" +#~ "\\sum_{k}^{} K_k^{\\dagger} K_k = I\n" +#~ "\n" #~ msgstr "" -#~ msgid "1.j tensor" +#~ msgid "List of Kraus operators." #~ msgstr "" -#~ msgid "Return the elementwise imaginary value of a tensor ``a``." +#~ msgid "Quantum circuit: state simulator" #~ msgstr "" -#~ msgid "imaginary value of ``a``" +#~ msgid "``Circuit`` class. Simple usage demo below." #~ msgstr "" -#~ msgid "[summary]" +#~ msgid "Apply any gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The possible options" +#~ msgid "Qubit number than the gate applies on." #~ msgstr "" -#~ msgid "Sampling output shape" +#~ msgid "Parameters for the gate" #~ msgstr "" -#~ msgid "" -#~ "probability for each option in a, " -#~ "defaults to None, as equal probability" -#~ " distribution" +#~ msgid "Apply cnot gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Call the random normal function with " -#~ "the random state management behind the" -#~ " scene." -#~ msgstr "" - -#~ msgid "[description], defaults to 1" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 1.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "[description], defaults to \"32\"" +#~ msgid "Qubit number than the gate applies on. The matrix for the gate is" #~ msgstr "" -#~ msgid "Determine whether the type of input ``a`` is ``sparse``." +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" +#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j" +#~ " \\end{bmatrix}" #~ msgstr "" -#~ msgid "input matrix ``a``" +#~ msgid "Apply cr gate with parameters on the circuit." #~ msgstr "" -#~ msgid "a bool indicating whether the matrix ``a`` is sparse" +#~ msgid "Apply crx gate with parameters on the circuit." #~ msgstr "" -#~ msgid "Return a boolean on whether ``a`` is a tensor in backend package." +#~ msgid "Apply cry gate with parameters on the circuit." #~ msgstr "" -#~ msgid "a tensor to be determined" +#~ msgid "Apply crz gate with parameters on the circuit." #~ msgstr "" -#~ msgid "whether ``a`` is a tensor" +#~ msgid "Apply cy gate on the circuit." #~ msgstr "" -#~ msgid "Return the jitted version of function ``f``." +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.-1.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+1.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "function to be jitted" +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" +#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 0.-1.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+1.j & 0.+0.j" +#~ " \\end{bmatrix}" #~ msgstr "" -#~ msgid "" -#~ "index of args that doesn't regarded " -#~ "as tensor, only work for jax " -#~ "backend" +#~ msgid "Apply cz gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "whether open XLA compilation, only works" -#~ " for tensorflow backend, defaults False " -#~ "since several ops has no XLA " -#~ "correspondence" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & -1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "jitted version of ``f``" +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" +#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 0.+0.j & 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+0.j & -1.+0.j" +#~ " \\end{bmatrix}" #~ msgstr "" -#~ msgid "" -#~ "Function that computes a (forward-mode)" -#~ " Jacobian-vector product of ``f``. " -#~ "Strictly speaking, this function is " -#~ "value_and_jvp." +#~ msgid "Apply exp gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The function to compute jvp" +#~ msgid "Apply exp1 gate with parameters on the circuit." #~ msgstr "" -#~ msgid "input for ``f``" +#~ msgid "Apply h gate on the circuit." #~ msgstr "" -#~ msgid "tangents" +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} " +#~ "0.70710677+0.j & 0.70710677+0.j\\\\ " +#~ "0.70710677+0.j & -0.70710677+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "(``f(*inputs)``, jvp_tensor), where jvp_tensor " -#~ "is the same shape as the output" -#~ " of ``f``" +#~ "\\begin{bmatrix} 0.70710677+0.j & " +#~ "0.70710677+0.j\\\\ 0.70710677+0.j & " +#~ "-0.70710677+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Return the kronecker product of two matrices ``a`` and ``b``." +#~ msgid "Apply i gate on the circuit." #~ msgstr "" -#~ msgid "kronecker product of ``a`` and ``b``" +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "Return the maximum of an array or maximum along an axis." +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "[description], defaults to None" +#~ msgid "Apply iswap gate on the circuit." #~ msgstr "" -#~ msgid "Return the minimum of an array or minimum along an axis." +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+1.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+1.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Return the numpy array of a tensor" -#~ " ``a``, but may not work in a" -#~ " jitted function." +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j" +#~ " & 0.+1.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 0.+1.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 1.+0.j" +#~ " \\end{bmatrix}" #~ msgstr "" -#~ msgid "numpy array of ``a``" +#~ msgid "Apply r gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "One-hot encodes the given ``a``. " -#~ "Each index in the input ``a`` is" -#~ " encoded as a vector of zeros " -#~ "of length ``num`` with the element " -#~ "at index set to one:" +#~ msgid "Apply rx gate with parameters on the circuit." #~ msgstr "" -#~ msgid "input tensor" +#~ msgid "Apply ry gate with parameters on the circuit." #~ msgstr "" -#~ msgid "number of features in onehot dimension" +#~ msgid "Apply rz gate with parameters on the circuit." #~ msgstr "" -#~ msgid "onehot tensor with the last extra dimension" +#~ msgid "Apply s gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Return an ones-matrix of dimension " -#~ "`dim` Depending on specific backends, " -#~ "`dim` has to be either an int " -#~ "(numpy, torch, tensorflow) or a " -#~ "`ShapeType` object (for block-sparse " -#~ "backends). Block-sparse behavior is " -#~ "currently not supported Args:" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 0.+1.j " +#~ "\\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "shape (int): The dimension of the " -#~ "returned matrix. dtype: The dtype of " -#~ "the returned matrix." +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+1.j \\end{bmatrix}" +#~ msgstr "" + +#~ msgid "Apply sd gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "A jax like split API, but it " -#~ "doesn't split the key generator for " -#~ "other backends. It is just for a" -#~ " consistent interface of random code; " -#~ "make sure you know what the " -#~ "function actually does. This function is" -#~ " mainly a utility to write backend" -#~ " agnostic code instead of doing magic" -#~ " things." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 0.-1.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "Return the elementwise real value of a tensor ``a``." +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.-1.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "real value of ``a``" +#~ msgid "Apply swap gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Rectified linear unit activation function. " -#~ "Computes the element-wise function:" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "\\mathrm{relu}(x)=\\max(x,0)" +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j" +#~ " & 1.+0.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 1.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 1.+0.j" +#~ " \\end{bmatrix}" #~ msgstr "" -#~ msgid "Input tensor" +#~ msgid "Apply t gate on the circuit." #~ msgstr "" -#~ msgid "Tensor after relu" +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1. &" +#~ " +0.j & 0. & +0.j\\\\ 0. &" +#~ " +0.j & 0.70710677+0.70710677j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Roughly equivalent to operand[indices] = " -#~ "updates, indices only support shape with" -#~ " rank 2 for now." +#~ "\\begin{bmatrix} 1. & +0.j & 0. " +#~ "& +0.j\\\\ 0. & +0.j & " +#~ "0.70710677+0.70710677j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Set the random state attached to the backend." +#~ msgid "Apply td gate on the circuit." #~ msgstr "" -#~ msgid "the random seed, defaults to be None" +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1. &" +#~ " +0.j & 0. & +0.j\\\\ 0. &" +#~ " +0.j & 0.70710677-0.70710677j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "If set to be true, only get " -#~ "the random state in return instead " -#~ "of setting the state on the " -#~ "backend" +#~ "\\begin{bmatrix} 1. & +0.j & 0. " +#~ "& +0.j\\\\ 0. & +0.j & " +#~ "0.70710677-0.70710677j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Return the elementwise sine of a tensor ``a``." +#~ msgid "Apply toffoli gate on the circuit." #~ msgstr "" -#~ msgid "sine of ``a``" +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 1.+0.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "Return the total number of elements in ``a`` in tensor form." +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" +#~ " 1.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "the total number of elements in ``a``" +#~ msgid "Apply wroot gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Softmax function. Computes the function " -#~ "which rescales elements to the range " -#~ "[0,1] such that the elements along " -#~ "axis sum to 1." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} " +#~ "0.70710677+0.j & -0.5 & -0.5j\\\\ 0.5" +#~ " & -0.5j & 0.70710677+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "\\mathrm{softmax}(x) = \\frac{\\exp(x_i)}{\\sum_j \\exp(x_j)}" +#~ msgid "" +#~ "\\begin{bmatrix} 0.70710677+0.j & -0.5 &" +#~ " -0.5j\\\\ 0.5 & -0.5j & " +#~ "0.70710677+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Tensor" +#~ msgid "Apply x gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "A dimension along which Softmax will " -#~ "be computed , defaults to None for" -#~ " all axis sum." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 1.+0.j\\\\ 1.+0.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "concatenated tensor" +#~ msgid "" +#~ "\\begin{bmatrix} 0.+0.j & 1.+0.j\\\\ " +#~ "1.+0.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Solve the linear system Ax=b and return the solution x." +#~ msgid "Apply y gate on the circuit." #~ msgstr "" -#~ msgid "The multiplied matrix." +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 0.-1.j\\\\ 0.+1.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "The resulted matrix." +#~ msgid "" +#~ "\\begin{bmatrix} 0.+0.j & 0.-1.j\\\\ " +#~ "0.+1.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "The solution of the linear system." +#~ msgid "Apply z gate on the circuit." #~ msgstr "" -#~ msgid "A sparse matrix multiplies a dense matrix." +#~ msgid "" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & -1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "a sparse matrix" +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & -1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "a dense matrix" +#~ msgid "Circuit object based on state simulator." #~ msgstr "" -#~ msgid "dense matrix" +#~ msgid "The number of qubits in the circuit." #~ msgstr "" #~ msgid "" -#~ "Concatenates a sequence of tensors ``a``" -#~ " along a new dimension ``axis``." +#~ "If not None, the initial state of" +#~ " the circuit is taken as ``inputs``" +#~ " instead of :math:`\\vert 0\\rangle^n` " +#~ "qubits, defaults to None" #~ msgstr "" -#~ msgid "List of tensors in the same shape" +#~ msgid "(Nodes, dangling Edges) for a MPS like initial wavefunction" #~ msgstr "" -#~ msgid "the stack axis, defaults to 0" +#~ msgid "" +#~ "dict if two qubit gate is ready" +#~ " for split, including parameters for " +#~ "at least one of ``max_singular_values`` " +#~ "and ``max_truncation_err``." #~ msgstr "" -#~ msgid "stateful register for each package" +#~ msgid "" +#~ "Monte Carlo trajectory simulation of " +#~ "general Kraus channel whose Kraus " +#~ "operators cannot be amplified to unitary" +#~ " operators. For unitary operators composed" +#~ " Kraus channel, :py:meth:`unitary_kraus` is " +#~ "much faster." #~ msgstr "" -#~ msgid "shape of output sampling tensor" +#~ msgid "" +#~ "This function is jittable in theory. " +#~ "But only jax+GPU combination is " +#~ "recommended for jit since the graph " +#~ "building time is too long for " +#~ "other backend options; though the " +#~ "running time of the function is " +#~ "very fast for every case." #~ msgstr "" -#~ msgid "only real data type is supported, \"32\" or \"64\", defaults to \"32\"" +#~ msgid "list of ``tn.Node`` for Kraus operators" #~ msgstr "" -#~ msgid "Uniform random sampler from ``low`` to ``high``." +#~ msgid "the qubits index that Kraus channel is applied on" #~ msgstr "" -#~ msgid "shape of output sampling tensor, defaults to 1" +#~ msgid "" +#~ "random tensor between 0 or 1, " +#~ "defaults to be None, the random " +#~ "number will be generated automatically" #~ msgstr "" -#~ msgid "Stop backpropagation from ``a``." +#~ msgid "Compute the expectation of corresponding operators." #~ msgstr "" -#~ msgid "``branches[index]()``" +#~ msgid "" +#~ "operator and its position on the " +#~ "circuit, eg. ``(tc.gates.z(), [1, ]), " +#~ "(tc.gates.x(), [2, ])`` is for operator" +#~ " :math:`Z_1X_2`" #~ msgstr "" -#~ msgid "Constructs a tensor by tiling a given tensor." +#~ msgid "" +#~ "if True, then the wavefunction tensor" +#~ " is cached for further expectation " +#~ "evaluation, defaults to be true" #~ msgstr "" -#~ msgid "1d tensor with length the same as the rank of ``a``" +#~ msgid "Tensor with one element" #~ msgstr "" -#~ msgid "Convert a sparse matrix to dense tensor." +#~ msgid "[WIP], check whether the circuit is legal." #~ msgstr "" -#~ msgid "the resulted dense matrix" +#~ msgid "the bool indicating whether the circuit is legal" #~ msgstr "" -#~ msgid "" -#~ "Find the unique elements and their " -#~ "corresponding counts of the given tensor" -#~ " ``a``." +#~ msgid "Take measurement to the given quantum lines." #~ msgstr "" -#~ msgid "Unique elements, corresponding counts" +#~ msgid "measure on which quantum line" #~ msgstr "" -#~ msgid "Return the function which returns the value and grad of ``f``." +#~ msgid "if true, theoretical probability is also returned" #~ msgstr "" #~ msgid "" -#~ "the value and grad function of " -#~ "``f`` with the same set of " -#~ "arguments as ``f``" +#~ "Middle measurement in z-basis on the " +#~ "circuit, note the wavefunction output is" +#~ " not normalized with ``mid_measurement`` " +#~ "involved, one should normalize the state" +#~ " manually if needed." #~ msgstr "" -#~ msgid "" -#~ "Return the VVAG function of ``f``. " -#~ "The inputs for ``f`` is (args[0], " -#~ "args[1], args[2], ...), and the output" -#~ " of ``f`` is a scalar. Suppose " -#~ "VVAG(f) is a function with inputs " -#~ "in the form (vargs[0], args[1], args[2]," -#~ " ...), where vagrs[0] has one extra" -#~ " dimension than args[0] in the first" -#~ " axis and consistent with args[0] in" -#~ " shape for remaining dimensions, i.e. " -#~ "shape(vargs[0]) = [batch] + shape(args[0])." -#~ " (We only cover cases where " -#~ "``vectorized_argnums`` defaults to 0 here " -#~ "for demonstration). VVAG(f) returns a " -#~ "tuple as a value tensor with shape" -#~ " [batch, 1] and a gradient tuple " -#~ "with shape: ([batch]+shape(args[argnum]) for " -#~ "argnum in argnums). The gradient for " -#~ "argnums=k is defined as" +#~ msgid "the index of qubit that the Z direction postselection applied on" #~ msgstr "" -#~ msgid "" -#~ "g^k = \\frac{\\partial \\sum_{i\\in batch} " -#~ "f(vargs[0][i], args[1], ...)}{\\partial args[k]}" +#~ msgid "0 for spin up, 1 for spin down, defaults to be 0" #~ msgstr "" -#~ msgid "Therefore, if argnums=0, the gradient is reduced to" +#~ msgid "Reference: arXiv:1201.3974." #~ msgstr "" -#~ msgid "g^0_i = \\frac{\\partial f(vargs[0][i])}{\\partial vargs[0][i]}" +#~ msgid "sampled bit string and the corresponding theoretical probability" #~ msgstr "" -#~ msgid "" -#~ ", which is specifically suitable for " -#~ "batched VQE optimization, where args[0] " -#~ "is the circuit parameters." +#~ msgid "Replace the input state with the circuit structure unchanged." #~ msgstr "" -#~ msgid "And if argnums=1, the gradient is like" +#~ msgid "Input wavefunction." #~ msgstr "" #~ msgid "" -#~ "g^1_i = \\frac{\\partial \\sum_j " -#~ "f(vargs[0][j], args[1])}{\\partial args[1][i]}\n" -#~ "\n" +#~ "Replace the input state in MPS " +#~ "representation while keep the circuit " +#~ "structure unchanged." #~ msgstr "" -#~ msgid "" -#~ ", which is suitable for quantum " -#~ "machine learning scenarios, where ``f`` " -#~ "is the loss function, args[0] " -#~ "corresponds to the input data and " -#~ "args[1] corresponds to the weights in" -#~ " the QML model." +#~ msgid "Compute the output wavefunction from the circuit." #~ msgstr "" -#~ msgid "" -#~ "the args to be vectorized, these " -#~ "arguments should share the same batch" -#~ " shape in the fist dimension" +#~ msgid "the str indicating the form of the output wavefunction" #~ msgstr "" -#~ msgid "" -#~ "Function that computes the dot product" -#~ " between a vector v and the " -#~ "Jacobian of the given function at " -#~ "the point given by the inputs. " -#~ "(reverse mode AD relevant) Strictly " -#~ "speaking, this function is value_and_vjp." +#~ msgid "Tensor with the corresponding shape" #~ msgstr "" -#~ msgid "the function to carry out vjp calculation" +#~ msgid "Compute :math:`\\langle bra\\vert ops \\vert ket\\rangle`" #~ msgstr "" -#~ msgid "" -#~ "value vector or gradient from downstream" -#~ " in reverse mode AD the same " -#~ "shape as return of function ``f``" +#~ msgid "Example 1 (:math:`bra` is same as :math:`ket`)" #~ msgstr "" -#~ msgid "" -#~ "(``f(*inputs)``, vjp_tensor), where vjp_tensor " -#~ "is the same shape as inputs" +#~ msgid "Example 2 (:math:`bra` is different from :math:`ket`)" #~ msgstr "" -#~ msgid "" -#~ "Return the vectorized map or batched " -#~ "version of ``f`` on the first " -#~ "extra axis. The general interface " -#~ "supports ``f`` with multiple arguments " -#~ "and broadcast in the fist dimension." +#~ msgid "[description], defaults to None, which is the same as ``ket``" #~ msgstr "" -#~ msgid "function to be broadcasted." +#~ msgid "[description], defaults to True" #~ msgstr "" -#~ msgid "vmap version of ``f``" +#~ msgid "[description], defaults to False" #~ msgstr "" #~ msgid "" -#~ "Return a zeros-matrix of dimension " -#~ "`dim` Depending on specific backends, " -#~ "`dim` has to be either an int " -#~ "(numpy, torch, tensorflow) or a " -#~ "`ShapeType` object (for block-sparse " -#~ "backends)." -#~ msgstr "" - -#~ msgid "Block-sparse behavior is currently not supported Args:" -#~ msgstr "" - -#~ msgid "Backend magic inherited from tensornetwork: numpy backend" +#~ "Not an ideal visualization for quantum" +#~ " circuit, but reserve here as a " +#~ "general approch to show tensornetwork " +#~ "[Deperacted, use ``qir2tex instead``]" #~ msgstr "" -#~ msgid "" -#~ "Bases: " -#~ ":py:class:`tensornetwork.backends.numpy.numpy_backend.NumPyBackend`" +#~ msgid "Constants and setups" #~ msgstr "" #~ msgid "" -#~ "see the original backend API at " -#~ "`numpy backend " -#~ "`_" -#~ msgstr "" - -#~ msgid "Backend magic inherited from tensornetwork: pytorch backend" +#~ "To set runtime contractor of the " +#~ "tensornetwork for a better contraction " +#~ "path." #~ msgstr "" #~ msgid "" -#~ "Bases: " -#~ ":py:class:`tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend`" +#~ "\"auto\", \"greedy\", \"branch\", \"plain\", " +#~ "\"tng\", \"custom\", \"custom_stateful\". defaults" +#~ " to None (\"auto\")" #~ msgstr "" -#~ msgid "" -#~ "See the original backend API at " -#~ "``pytorch backend``. " -#~ "``_" +#~ msgid "Valid for \"custom\" or \"custom_stateful\" as method, defaults to None" #~ msgstr "" #~ msgid "" -#~ "Note the functionality provided by " -#~ "pytorch backend is incomplete, it " -#~ "currenly lacks native efficicent jit and" -#~ " vmap support." +#~ "It is not very useful, as " +#~ "``memory_limit`` leads to ``branch`` " +#~ "contraction instead of ``greedy`` which " +#~ "is rather slow, defaults to None" #~ msgstr "" -#~ msgid "Backend magic inherited from tensornetwork: tensorflow backend" +#~ msgid "Tensornetwork version is too low to support some of the contractors." #~ msgstr "" -#~ msgid "" -#~ "Bases: " -#~ ":py:class:`tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend`" +#~ msgid "Unknown method options." #~ msgstr "" -#~ msgid "" -#~ "See the original backend API at " -#~ "`'tensorflow backend''. " -#~ "`_" +#~ msgid "The new tensornetwork with its contractor set." #~ msgstr "" -#~ msgid "Some common noise quantum channels." +#~ msgid "To set the runtime numerical dtype of tensors." #~ msgstr "" #~ msgid "" -#~ "Return an amplitude damping channel. " -#~ "Notice: Amplitude damping corrspondings to " -#~ "p = 1." +#~ "\"complex64\" or \"complex128\", defaults to" +#~ " None, which is equivalent to " +#~ "\"complex64\"." #~ msgstr "" -#~ msgid "" -#~ "\\sqrt{p}\n" -#~ "\\begin{bmatrix}\n" -#~ " 1 & 0\\\\\n" -#~ " 0 & \\sqrt{1-\\gamma}\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{p}\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & \\sqrt{\\gamma}\\\\\n" -#~ " 0 & 0\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{1-p}\n" -#~ "\\begin{bmatrix}\n" -#~ " \\sqrt{1-\\gamma} & 0\\\\\n" -#~ " 0 & 1\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{1-p}\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & 0\\\\\n" -#~ " \\sqrt{\\gamma} & 0\\\\\n" -#~ "\\end{bmatrix}\n" -#~ "\n" +#~ msgid "The naive state-vector simulator contraction path." #~ msgstr "" -#~ msgid "the damping parameter of amplitude (:math:`\\gamma`)" +#~ msgid "The list of ``tn.Node``." #~ msgstr "" -#~ msgid ":math:`p`" +#~ msgid "The list of dangling node edges, defaults to be None." #~ msgstr "" -#~ msgid "An amplitude damping channel with given :math:`\\gamma` and :math:`p`" +#~ msgid "The ``tn.Node`` after contraction" #~ msgstr "" -#~ msgid "Return a Depolarizing Channel" +#~ msgid "To set the runtime backend of tensorcircuit." #~ msgstr "" #~ msgid "" -#~ "\\sqrt{1-p_x-p_y-p_z}\n" -#~ "\\begin{bmatrix}\n" -#~ " 1 & 0\\\\\n" -#~ " 0 & 1\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{p_x}\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & 1\\\\\n" -#~ " 1 & 0\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{p_y}\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & -1j\\\\\n" -#~ " 1j & 0\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\sqrt{p_z}\n" -#~ "\\begin{bmatrix}\n" -#~ " 1 & 0\\\\\n" -#~ " 0 & -1\\\\\n" -#~ "\\end{bmatrix}\n" -#~ "\n" +#~ "Note: ``tc.set_backend`` and " +#~ "``tc.cons.set_tensornetwork_backend`` are the same." #~ msgstr "" -#~ msgid ":math:`p_x`" +#~ msgid "" +#~ "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\". " +#~ "defaults to None, which gives the " +#~ "same behavior as " +#~ "``tensornetwork.backend_contextmanager.get_default_backend()``." #~ msgstr "" -#~ msgid ":math:`p_y`" +#~ msgid "Whether the object should be set as global." #~ msgstr "" -#~ msgid ":math:`p_z`" +#~ msgid "Quantum circuit class but with density matrix simulator" #~ msgstr "" -#~ msgid "Sequences of Gates" +#~ msgid "Quantum circuit class but with density matrix simulator: v2" #~ msgstr "" -#~ msgid "Convert Kraus operators to one Tensor (as one Super Gate)." +#~ msgid "Bases: :py:class:`tensorcircuit.densitymatrix.DMCircuit`" #~ msgstr "" -#~ msgid "" -#~ "\\sum_{k}^{} K_k \\otimes K_k^{\\dagger}\n" -#~ "\n" +#~ msgid "Experimental features" #~ msgstr "" -#~ msgid "A sequence of Gate" +#~ msgid "" +#~ "Declarations of single-qubit and two-" +#~ "qubit gates and their corresponding " +#~ "matrix." #~ msgstr "" -#~ msgid "The corresponding Tensor of the list of Kraus operators" +#~ msgid "Bases: :py:class:`tensornetwork.network_components.Node`" #~ msgstr "" -#~ msgid "Return a phase damping channel with given :math:`\\gamma`" +#~ msgid "Wrapper of tn.Node, quantum gate" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix}\n" -#~ " 1 & 0\\\\\n" -#~ " 0 & \\sqrt{1-\\gamma}\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & 0\\\\\n" -#~ " 0 & \\sqrt{\\gamma}\\\\\n" -#~ "\\end{bmatrix}\n" -#~ "\n" +#~ msgid "Bases: :py:class:`tensorcircuit.gates.GateF`" #~ msgstr "" -#~ msgid "The damping parameter of phase (:math:`\\gamma`)" +#~ msgid "Note one should provide the gate with properly reshaped." #~ msgstr "" -#~ msgid "A phase damping channel with given :math:`\\gamma`" +#~ msgid "corresponding gate" #~ msgstr "" -#~ msgid "Reset channel" +#~ msgid "The name of the gate." #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix}\n" -#~ " 1 & 0\\\\\n" -#~ " 0 & 0\\\\\n" -#~ "\\end{bmatrix}\\qquad\n" -#~ "\\begin{bmatrix}\n" -#~ " 0 & 1\\\\\n" -#~ " 0 & 0\\\\\n" -#~ "\\end{bmatrix}\n" -#~ "\n" +#~ msgid "the resulted gate" #~ msgstr "" -#~ msgid "Check identity of a single qubit Kraus operators." +#~ msgid "Convert the inputs to Tensor with specified dtype." #~ msgstr "" -#~ msgid "Examples:" +#~ msgid "inputs" #~ msgstr "" -#~ msgid "" -#~ "\\sum_{k}^{} K_k^{\\dagger} K_k = I\n" -#~ "\n" +#~ msgid "dtype of the output Tensors" #~ msgstr "" -#~ msgid "List of Kraus operators." +#~ msgid "List of Tensors" #~ msgstr "" -#~ msgid "Quantum circuit: state simulator" +#~ msgid "Returns a LaTeX bmatrix." #~ msgstr "" -#~ msgid "``Circuit`` class. Simple usage demo below." +#~ msgid "Formatted Display:" #~ msgstr "" -#~ msgid "Apply any gate with parameters on the circuit." +#~ msgid "" +#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j \\end{bmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "Qubit number than the gate applies on." +#~ msgid "2D numpy array" #~ msgstr "" -#~ msgid "Parameters for the gate" +#~ msgid "ValueError(\"bmatrix can at most display two dimensions\")" #~ msgstr "" -#~ msgid "Apply cnot gate on the circuit." +#~ msgid "latex str for bmatrix of array a" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 1.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" +#~ "Controlled rotation gate, when the " +#~ "control bit is 1, `rgate` is " +#~ "applied on the target gate." #~ msgstr "" -#~ msgid "Qubit number than the gate applies on. The matrix for the gate is" +#~ msgid "angle in radians" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" -#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j" -#~ " \\end{bmatrix}" +#~ msgid "CR Gate" #~ msgstr "" -#~ msgid "Apply cr gate with parameters on the circuit." +#~ msgid "" +#~ "Faster exponential gate, directly implemented" +#~ " based on RHS, only work when: " +#~ ":math:`U^2` is identity matrix." #~ msgstr "" -#~ msgid "Apply crx gate with parameters on the circuit." +#~ msgid "" +#~ "\\rm{exp}(U) &= e^{-i \\theta U} \\\\\n" +#~ " &= \\cos(\\theta) I - j \\sin(\\theta) U \\\\\n" +#~ "\n" #~ msgstr "" -#~ msgid "Apply cry gate with parameters on the circuit." +#~ msgid "input unitary (U)" #~ msgstr "" -#~ msgid "Apply crz gate with parameters on the circuit." +#~ msgid "suffix of Gate name" #~ msgstr "" -#~ msgid "Apply cy gate on the circuit." +#~ msgid "Exponential Gate" #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.-1.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+1.j & 0.+0.j \\end{bmatrix}" +#~ msgid "Exponential gate." #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" -#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 0.-1.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+1.j & 0.+0.j" -#~ " \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply cz gate on the circuit." +#~ "\\rm{exp}(U) = e^{-i \\theta U}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & -1.+0.j \\end{bmatrix}" +#~ msgid "iSwap gate." #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 1.+0.j" -#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 0.+0.j & 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+0.j & -1.+0.j" -#~ " \\end{bmatrix}" +#~ "iSwap(\\theta) =\n" +#~ "\\begin{pmatrix}\n" +#~ " 1 & 0 & 0 & 0\\\\\n" +#~ " 0 & \\cos(\\frac{\\pi}{2} \\theta )" +#~ " & j \\sin(\\frac{\\pi}{2} \\theta ) " +#~ "& 0\\\\\n" +#~ " 0 & j \\sin(\\frac{\\pi}{2} \\theta" +#~ " ) & \\cos(\\frac{\\pi}{2} \\theta ) " +#~ "& 0\\\\\n" +#~ " 0 & 0 & 0 & 1\\\\\n" +#~ "\\end{pmatrix}\n" +#~ "\n" #~ msgstr "" -#~ msgid "Apply exp gate with parameters on the circuit." +#~ msgid "iSwap Gate" #~ msgstr "" -#~ msgid "Apply exp1 gate with parameters on the circuit." +#~ msgid "Convert Gate to numpy array." #~ msgstr "" -#~ msgid "Apply h gate on the circuit." +#~ msgid "input Gate" #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} " -#~ "0.70710677+0.j & 0.70710677+0.j\\\\ " -#~ "0.70710677+0.j & -0.70710677+0.j \\end{bmatrix}" +#~ msgid "corresponding Tensor" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 0.70710677+0.j & " -#~ "0.70710677+0.j\\\\ 0.70710677+0.j & " -#~ "-0.70710677+0.j \\end{bmatrix}" +#~ "Inner helper function to generate gate" +#~ " functions, such as ``z()`` from " +#~ "``_z_matrix``" #~ msgstr "" -#~ msgid "Apply i gate on the circuit." +#~ msgid "General single qubit rotation gate" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 1.+0.j " -#~ "\\end{bmatrix}" +#~ "R(\\theta, \\phi, \\alpha) = i \\cos(\\theta) I\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply iswap gate on the circuit." +#~ "- i \\cos(\\phi) \\sin(\\alpha) \\sin(\\theta) X\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+1.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+1.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ "- i \\sin(\\phi) \\sin(\\alpha) \\sin(\\theta) Y\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j" -#~ " & 0.+1.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 0.+1.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 1.+0.j" -#~ " \\end{bmatrix}" +#~ "- i \\sin(\\theta) \\cos(\\alpha) Z\n" +#~ "\n" #~ msgstr "" -#~ msgid "Apply r gate with parameters on the circuit." +#~ msgid "R Gate" #~ msgstr "" -#~ msgid "Apply rx gate with parameters on the circuit." +#~ msgid "Random single qubit gate described in https://arxiv.org/abs/2002.07730." #~ msgstr "" -#~ msgid "Apply ry gate with parameters on the circuit." +#~ msgid "A random single qubit gate" #~ msgstr "" -#~ msgid "Apply rz gate with parameters on the circuit." +#~ msgid "Returns a random two-qubit gate." #~ msgstr "" -#~ msgid "Apply s gate on the circuit." +#~ msgid "a random two-qubit gate" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 0.+1.j " -#~ "\\end{bmatrix}" +#~ "Rotation gate, which is in matrix " +#~ "exponential form, shall give the same" +#~ " result as `rgate`." #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+1.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply sd gate on the circuit." +#~ "mx = \\sin(\\alpha) \\cos(\\phi) X\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 0.-1.j " -#~ "\\end{bmatrix}" +#~ "my = \\sin(\\alpha) \\sin(\\phi) Y\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.-1.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply swap gate on the circuit." +#~ "mz = \\cos(\\alpha) Z\n" +#~ "\n" #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ "R(\\theta, \\alpha, \\phi) = e^{-i\\theta (mx+my+mz)}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j\\\\ 0.+0.j & 0.+0.j" -#~ " & 1.+0.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 1.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 1.+0.j" -#~ " \\end{bmatrix}" +#~ msgid "Rotation Gate" #~ msgstr "" -#~ msgid "Apply t gate on the circuit." +#~ msgid "Rotation gate along X axis." #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1. &" -#~ " +0.j & 0. & +0.j\\\\ 0. &" -#~ " +0.j & 0.70710677+0.70710677j \\end{bmatrix}" +#~ "RX(\\theta) = e^{-i\\frac{\\theta}{2}X}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1. & +0.j & 0. " -#~ "& +0.j\\\\ 0. & +0.j & " -#~ "0.70710677+0.70710677j \\end{bmatrix}" +#~ msgid "RX Gate" #~ msgstr "" -#~ msgid "Apply td gate on the circuit." +#~ msgid "Rotation gate along Y axis." #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1. &" -#~ " +0.j & 0. & +0.j\\\\ 0. &" -#~ " +0.j & 0.70710677-0.70710677j \\end{bmatrix}" +#~ "RY(\\theta) = e^{-i\\frac{\\theta}{2}Y}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1. & +0.j & 0. " -#~ "& +0.j\\\\ 0. & +0.j & " -#~ "0.70710677-0.70710677j \\end{bmatrix}" +#~ msgid "RY Gate" #~ msgstr "" -#~ msgid "Apply toffoli gate on the circuit." +#~ msgid "Rotation gate along Z axis." #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 1.+0.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ "RZ(\\theta) = e^{-i\\frac{\\theta}{2}Z}\n" +#~ "\n" #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j\\\\ 0.+0.j &" -#~ " 1.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" +#~ msgid "RZ Gate" #~ msgstr "" -#~ msgid "Apply wroot gate on the circuit." +#~ msgid "Interfaces bridging different backends" #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} " -#~ "0.70710677+0.j & -0.5 & -0.5j\\\\ 0.5" -#~ " & -0.5j & 0.70710677+0.j \\end{bmatrix}" +#~ msgid "Keras layer for tc quantum function" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 0.70710677+0.j & -0.5 &" -#~ " -0.5j\\\\ 0.5 & -0.5j & " -#~ "0.70710677+0.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply x gate on the circuit." +#~ "`QuantumLayer` wraps the quantum function " +#~ "`f` as a `keras.Layer` so that " +#~ "tensorcircuit is better integrated with " +#~ "tensorflow." #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 1.+0.j\\\\ 1.+0.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "[description], defaults to \"glorot_uniform\"" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 0.+0.j & 1.+0.j\\\\ " -#~ "1.+0.j & 0.+0.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply y gate on the circuit." +#~ "Load function from the files in " +#~ "the ``tf.savedmodel`` format. We can " +#~ "load several functions at the same " +#~ "time, as they can be the same " +#~ "function of different input shapes." #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 0.-1.j\\\\ 0.+1.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ "The fallback function when all functions" +#~ " loaded are failed, defaults to None" #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 0.+0.j & 0.-1.j\\\\ " -#~ "0.+1.j & 0.+0.j \\end{bmatrix}" -#~ msgstr "" - -#~ msgid "Apply z gate on the circuit." +#~ "When there is not legal loaded " +#~ "function of the input shape and no" +#~ " fallback callable." #~ msgstr "" #~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & -1.+0.j " -#~ "\\end{bmatrix}" +#~ "A function that tries all loaded " +#~ "function against the input until the " +#~ "first success one." #~ msgstr "" #~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & -1.+0.j \\end{bmatrix}" +#~ "The keras loss function that directly" +#~ " taking the model output as the " +#~ "loss." #~ msgstr "" -#~ msgid "Circuit object based on state simulator." +#~ msgid "Save tf function in the file (``tf.savedmodel`` format)." #~ msgstr "" -#~ msgid "The number of qubits in the circuit." +#~ msgid "``tf.function`` ed function with graph building" #~ msgstr "" -#~ msgid "" -#~ "If not None, the initial state of" -#~ " the circuit is taken as ``inputs``" -#~ " instead of :math:`\\vert 0\\rangle^n` " -#~ "qubits, defaults to None" +#~ msgid "the dir path to save the function" #~ msgstr "" -#~ msgid "(Nodes, dangling Edges) for a MPS like initial wavefunction" +#~ msgid "FiniteMPS from tensornetwork with bug fixed" #~ msgstr "" #~ msgid "" -#~ "dict if two qubit gate is ready" -#~ " for split, including parameters for " -#~ "at least one of ``max_singular_values`` " -#~ "and ``max_truncation_err``." +#~ "Bases: " +#~ ":py:class:`tensornetwork.matrixproductstates.finite_mps.FiniteMPS`" #~ msgstr "" #~ msgid "" -#~ "Monte Carlo trajectory simulation of " -#~ "general Kraus channel whose Kraus " -#~ "operators cannot be amplified to unitary" -#~ " operators. For unitary operators composed" -#~ " Kraus channel, :py:meth:`unitary_kraus` is " -#~ "much faster." +#~ "Apply a two-site gate to an " +#~ "MPS. This routine will in general " +#~ "destroy any canonical form of the " +#~ "state. If a canonical form is " +#~ "needed, the user can restore it " +#~ "using `FiniteMPS.position`." #~ msgstr "" -#~ msgid "" -#~ "This function is jittable in theory. " -#~ "But only jax+GPU combination is " -#~ "recommended for jit since the graph " -#~ "building time is too long for " -#~ "other backend options; though the " -#~ "running time of the function is " -#~ "very fast for every case." +#~ msgid "A two-body gate." #~ msgstr "" -#~ msgid "list of ``tn.Node`` for Kraus operators" +#~ msgid "The first site where the gate acts." #~ msgstr "" -#~ msgid "the qubits index that Kraus channel is applied on" +#~ msgid "The second site where the gate acts." #~ msgstr "" -#~ msgid "" -#~ "random tensor between 0 or 1, " -#~ "defaults to be None, the random " -#~ "number will be generated automatically" +#~ msgid "The maximum number of singular values to keep." #~ msgstr "" -#~ msgid "Compute the expectation of corresponding operators." +#~ msgid "The maximum allowed truncation error." #~ msgstr "" #~ msgid "" -#~ "operator and its position on the " -#~ "circuit, eg. ``(tc.gates.z(), [1, ]), " -#~ "(tc.gates.x(), [2, ])`` is for operator" -#~ " :math:`Z_1X_2`" +#~ "An optional value to choose the " +#~ "MPS tensor at `center_position` to be" +#~ " isometric after the application of " +#~ "the gate. Defaults to `site1`. If " +#~ "the MPS is canonical " +#~ "(i.e.`BaseMPS.center_position != None`), and " +#~ "if the orthogonality center coincides " +#~ "with either `site1` or `site2`, the " +#~ "orthogonality center will be shifted to" +#~ " `center_position` (`site1` by default). If" +#~ " the orthogonality center does not " +#~ "coincide with `(site1, site2)` then " +#~ "`MPS.center_position` is set to `None`." #~ msgstr "" -#~ msgid "" -#~ "if True, then the wavefunction tensor" -#~ " is cached for further expectation " -#~ "evaluation, defaults to be true" +#~ msgid "Multiply `max_truncation_err` with the largest singular value." #~ msgstr "" -#~ msgid "Tensor with one element" +#~ msgid "" +#~ "\"rank of gate is {} but has " +#~ "to be 4\", \"site1 = {} is " +#~ "not between 0 <= site < N -" +#~ " 1 = {}\", \"site2 = {} is " +#~ "not between 1 <= site < N =" +#~ " {}\",\"Found site2 ={}, site1={}. Only " +#~ "nearest neighbor gates are currently " +#~ "supported\", \"f center_position = " +#~ "{center_position} not f in {(site1, " +#~ "site2)} \", or \"center_position = {}," +#~ " but gate is applied at sites " +#~ "{}, {}. Truncation should only be " +#~ "done if the gate is applied at " +#~ "the center position of the MPS.\"" #~ msgstr "" -#~ msgid "[WIP], check whether the circuit is legal." +#~ msgid "A scalar tensor containing the truncated weight of the truncation." #~ msgstr "" -#~ msgid "the bool indicating whether the circuit is legal" +#~ msgid "Measure the expectation value of local operators `ops` site `sites`." #~ msgstr "" -#~ msgid "Take measurement to the given quantum lines." +#~ msgid "A list Tensors of rank 2; the local operators to be measured." #~ msgstr "" -#~ msgid "measure on which quantum line" +#~ msgid "Sites where `ops` act." #~ msgstr "" -#~ msgid "if true, theoretical probability is also returned" +#~ msgid "measurements :math:`\\langle` `ops[n]`:math:`\\rangle` for n in `sites`" #~ msgstr "" #~ msgid "" -#~ "Middle measurement in z-basis on the " -#~ "circuit, note the wavefunction output is" -#~ " not normalized with ``mid_measurement`` " -#~ "involved, one should normalize the state" -#~ " manually if needed." +#~ "Compute the correlator :math:`\\langle` " +#~ "`op1[site1], op2[s]`:math:`\\rangle` between `site1`" +#~ " and all sites `s` in `sites2`. " +#~ "If `s == site1`, `op2[s]` will be" +#~ " applied first." #~ msgstr "" -#~ msgid "the index of qubit that the Z direction postselection applied on" +#~ msgid "Tensor of rank 2; the local operator at `site1`." #~ msgstr "" -#~ msgid "0 for spin up, 1 for spin down, defaults to be 0" +#~ msgid "Tensor of rank 2; the local operator at `sites2`." #~ msgstr "" -#~ msgid "Reference: arXiv:1201.3974." +#~ msgid "The site where `op1` acts" #~ msgstr "" -#~ msgid "sampled bit string and the corresponding theoretical probability" +#~ msgid "Sites where operator `op2` acts." #~ msgstr "" -#~ msgid "Replace the input state with the circuit structure unchanged." +#~ msgid "" +#~ "Correlator :math:`\\langle` `op1[site1], " +#~ "op2[s]`:math:`\\rangle` for `s` :math:`\\in` " +#~ "`sites2`." #~ msgstr "" -#~ msgid "Input wavefunction." +#~ msgid "Quantum circuit: MPS state simulator" #~ msgstr "" -#~ msgid "" -#~ "Replace the input state in MPS " -#~ "representation while keep the circuit " -#~ "structure unchanged." +#~ msgid "``MPSCircuit`` class. Simple usage demo below." #~ msgstr "" -#~ msgid "Compute the output wavefunction from the circuit." +#~ msgid "MPSCircuit object based on state simulator." #~ msgstr "" -#~ msgid "the str indicating the form of the output wavefunction" +#~ msgid "" +#~ "If not None, the initial state of" +#~ " the circuit is taken as ``tensors``" +#~ " instead of :math:`\\vert 0\\rangle^n` " +#~ "qubits, defaults to None" #~ msgstr "" -#~ msgid "Tensor with the corresponding shape" +#~ msgid "The center position of MPS, default to 0" #~ msgstr "" -#~ msgid "Compute :math:`\\langle bra\\vert ops \\vert ket\\rangle`" +#~ msgid "Apply a general qubit gate on MPS." #~ msgstr "" -#~ msgid "Example 1 (:math:`bra` is same as :math:`ket`)" +#~ msgid "The Gate to be applied" #~ msgstr "" -#~ msgid "Example 2 (:math:`bra` is different from :math:`ket`)" +#~ msgid "Qubit indices of the gate" #~ msgstr "" -#~ msgid "[description], defaults to None, which is the same as ``ket``" +#~ msgid "\"MPS does not support application of gate on > 2 qubits.\"" #~ msgstr "" -#~ msgid "[description], defaults to True" +#~ msgid "" +#~ "Apply a double qubit gate on " +#~ "adjacent qubits of Matrix Product States" +#~ " (MPS). Truncation rule is specified " +#~ "by `set_truncation_rule`." #~ msgstr "" -#~ msgid "[description], defaults to False" +#~ msgid "The first qubit index of the gate" #~ msgstr "" -#~ msgid "" -#~ "Not an ideal visualization for quantum" -#~ " circuit, but reserve here as a " -#~ "general approch to show tensornetwork " -#~ "[Deperacted, use ``qir2tex instead``]" +#~ msgid "The second qubit index of the gate" #~ msgstr "" -#~ msgid "Constants and setups" +#~ msgid "Center position of MPS, default is None" #~ msgstr "" #~ msgid "" -#~ "To set runtime contractor of the " -#~ "tensornetwork for a better contraction " -#~ "path." +#~ "Apply a double qubit gate on MPS." +#~ " Truncation rule is specified by " +#~ "`set_truncation_rule`." #~ msgstr "" #~ msgid "" -#~ "\"auto\", \"greedy\", \"branch\", \"plain\", " -#~ "\"tng\", \"custom\", \"custom_stateful\". defaults" -#~ " to None (\"auto\")" +#~ "Apply a single qubit gate on MPS," +#~ " and the gate must be unitary; " +#~ "no truncation is needed." #~ msgstr "" -#~ msgid "Valid for \"custom\" or \"custom_stateful\" as method, defaults to None" +#~ msgid "gate to be applied" #~ msgstr "" -#~ msgid "" -#~ "It is not very useful, as " -#~ "``memory_limit`` leads to ``branch`` " -#~ "contraction instead of ``greedy`` which " -#~ "is rather slow, defaults to None" +#~ msgid "Qubit index of the gate" #~ msgstr "" -#~ msgid "Tensornetwork version is too low to support some of the contractors." +#~ msgid "Compute the conjugate of the current MPS." #~ msgstr "" -#~ msgid "Unknown method options." +#~ msgid "The constructed MPS" #~ msgstr "" -#~ msgid "The new tensornetwork with its contractor set." +#~ msgid "Copy the current MPS." #~ msgstr "" -#~ msgid "To set the runtime numerical dtype of tensors." +#~ msgid "Copy the current MPS without the tensors." #~ msgstr "" -#~ msgid "" -#~ "\"complex64\" or \"complex128\", defaults to" -#~ " None, which is equivalent to " -#~ "\"complex64\"." +#~ msgid "Compute the expectation of the corresponding double qubit gate." #~ msgstr "" -#~ msgid "The naive state-vector simulator contraction path." +#~ msgid "qubit index of the gate" #~ msgstr "" -#~ msgid "The list of ``tn.Node``." +#~ msgid "" +#~ "Compute the expectation of the " +#~ "corresponding single qubit gate in the" +#~ " form of tensor." #~ msgstr "" -#~ msgid "The list of dangling node edges, defaults to be None." +#~ msgid "Gate to be applied" #~ msgstr "" -#~ msgid "The ``tn.Node`` after contraction" +#~ msgid "The expectation of the corresponding single qubit gate" #~ msgstr "" -#~ msgid "To set the runtime backend of tensorcircuit." +#~ msgid "" +#~ "Compute the expectation of the direct" +#~ " product of the corresponding two " +#~ "gates." #~ msgstr "" -#~ msgid "" -#~ "Note: ``tc.set_backend`` and " -#~ "``tc.cons.set_tensornetwork_backend`` are the same." +#~ msgid "First gate to be applied" #~ msgstr "" -#~ msgid "" -#~ "\"numpy\", \"tensorflow\", \"jax\", \"pytorch\". " -#~ "defaults to None, which gives the " -#~ "same behavior as " -#~ "``tensornetwork.backend_contextmanager.get_default_backend()``." +#~ msgid "Second gate to be applied" #~ msgstr "" -#~ msgid "Whether the object should be set as global." +#~ msgid "Qubit index of the first gate" #~ msgstr "" -#~ msgid "Quantum circuit class but with density matrix simulator" +#~ msgid "Qubit index of the second gate" #~ msgstr "" -#~ msgid "Quantum circuit class but with density matrix simulator: v2" +#~ msgid "The correlation of the corresponding two qubit gates" #~ msgstr "" -#~ msgid "Bases: :py:class:`tensorcircuit.densitymatrix.DMCircuit`" +#~ msgid "Construct the MPS from a given wavefunction." #~ msgstr "" -#~ msgid "Experimental features" +#~ msgid "The given wavefunction (any shape is OK)" #~ msgstr "" #~ msgid "" -#~ "Declarations of single-qubit and two-" -#~ "qubit gates and their corresponding " -#~ "matrix." +#~ "Compute the expectation of corresponding " +#~ "operators in the form of tensor." #~ msgstr "" -#~ msgid "Bases: :py:class:`tensornetwork.network_components.Node`" +#~ msgid "" +#~ "Operator and its position on the " +#~ "circuit, eg. ``(gates.Z(), [1]), (gates.X()," +#~ " [2])`` is for operator :math:`Z_1X_2`" #~ msgstr "" -#~ msgid "Wrapper of tn.Node, quantum gate" +#~ msgid "The expectation of corresponding operators" #~ msgstr "" -#~ msgid "Bases: :py:class:`tensorcircuit.gates.GateF`" +#~ msgid "Get the normalized Center Position." #~ msgstr "" -#~ msgid "Note one should provide the gate with properly reshaped." +#~ msgid "Normalized Center Position." #~ msgstr "" -#~ msgid "corresponding gate" +#~ msgid "Check whether the circuit is legal." #~ msgstr "" -#~ msgid "The name of the gate." +#~ msgid "Whether the circuit is legal." #~ msgstr "" -#~ msgid "the resulted gate" +#~ msgid "integer indicating the measure on which quantum line" +#~ msgstr "" + +#~ msgid "" +#~ "Middle measurement in the z-basis on " +#~ "the circuit, note the wavefunction " +#~ "output is not normalized with " +#~ "``mid_measurement`` involved, one should " +#~ "normalized the state manually if needed." #~ msgstr "" -#~ msgid "Convert the inputs to Tensor with specified dtype." +#~ msgid "The index of qubit that the Z direction postselection applied on" #~ msgstr "" -#~ msgid "inputs" +#~ msgid "0 for spin up, 1 for spin down, defaults to 0" #~ msgstr "" -#~ msgid "dtype of the output Tensors" +#~ msgid "Normalize MPS Circuit according to the center position." #~ msgstr "" -#~ msgid "List of Tensors" +#~ msgid "Wrapper of tn.FiniteMPS.position. Set orthogonality center." #~ msgstr "" -#~ msgid "Returns a LaTeX bmatrix." +#~ msgid "The orthogonality center" #~ msgstr "" -#~ msgid "Formatted Display:" +#~ msgid "Compute the projection between `other` as bra and `self` as ket." #~ msgstr "" -#~ msgid "" -#~ "\\begin{bmatrix} 1.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j \\end{bmatrix}\n" -#~ "\n" +#~ msgid "ket of the other MPS, which will be converted to bra automatically" #~ msgstr "" -#~ msgid "2D numpy array" +#~ msgid "The projection in form of tensor" #~ msgstr "" -#~ msgid "ValueError(\"bmatrix can at most display two dimensions\")" +#~ msgid "" +#~ "Set truncation rules when double qubit" +#~ " gates are applied. If nothing is " +#~ "specified, no truncation will take place" +#~ " and the bond dimension will keep " +#~ "growing. For more details, refer to " +#~ "`split_tensor`." #~ msgstr "" -#~ msgid "latex str for bmatrix of array a" +#~ msgid "Tensor with shape [1, -1]" #~ msgstr "" #~ msgid "" -#~ "Controlled rotation gate, when the " -#~ "control bit is 1, `rgate` is " -#~ "applied on the target gate." +#~ "Split the tensor by SVD or QR " +#~ "depends on whether a truncation is " +#~ "required." #~ msgstr "" -#~ msgid "angle in radians" +#~ msgid "The input tensor to split." #~ msgstr "" -#~ msgid "CR Gate" +#~ msgid "" +#~ "Determine the orthogonal center is on" +#~ " the left tensor or the right " +#~ "tensor." #~ msgstr "" -#~ msgid "" -#~ "Faster exponential gate, directly implemented" -#~ " based on RHS, only work when: " -#~ ":math:`U^2` is identity matrix." +#~ msgid "Two tensors after splitting" #~ msgstr "" -#~ msgid "" -#~ "\\rm{exp}(U) &= e^{-i \\theta U} \\\\\n" -#~ " &= \\cos(\\theta) I - j \\sin(\\theta) U \\\\\n" -#~ "\n" +#~ msgid "Quantum state and operator class backend by tensornetwork" #~ msgstr "" -#~ msgid "input unitary (U)" +#~ msgid "Bases: :py:class:`tensorcircuit.quantum.QuOperator`" #~ msgstr "" -#~ msgid "suffix of Gate name" +#~ msgid "Represents an adjoint (row) vector via a tensor network." #~ msgstr "" -#~ msgid "Exponential Gate" +#~ msgid "" +#~ "Constructs a new `QuAdjointVector` from " +#~ "a tensor network. This encapsulates an" +#~ " existing tensor network, interpreting it" +#~ " as an adjoint vector (row vector)." #~ msgstr "" -#~ msgid "Exponential gate." +#~ msgid "The edges of the network to be used as the input edges." #~ msgstr "" #~ msgid "" -#~ "\\rm{exp}(U) = e^{-i \\theta U}\n" -#~ "\n" +#~ "Nodes used to refer to parts of" +#~ " the tensor network that are not " +#~ "connected to any input or output " +#~ "edges (for example: a scalar factor)." #~ msgstr "" -#~ msgid "iSwap gate." +#~ msgid "" +#~ "Optional collection of edges to ignore" +#~ " when performing consistency checks." #~ msgstr "" #~ msgid "" -#~ "iSwap(\\theta) =\n" -#~ "\\begin{pmatrix}\n" -#~ " 1 & 0 & 0 & 0\\\\\n" -#~ " 0 & \\cos(\\frac{\\pi}{2} \\theta )" -#~ " & j \\sin(\\frac{\\pi}{2} \\theta ) " -#~ "& 0\\\\\n" -#~ " 0 & j \\sin(\\frac{\\pi}{2} \\theta" -#~ " ) & \\cos(\\frac{\\pi}{2} \\theta ) " -#~ "& 0\\\\\n" -#~ " 0 & 0 & 0 & 1\\\\\n" -#~ "\\end{pmatrix}\n" -#~ "\n" +#~ "Construct a `QuAdjointVector` directly from" +#~ " a single tensor. This first wraps" +#~ " the tensor in a `Node`, then " +#~ "constructs the `QuAdjointVector` from that " +#~ "`Node`." #~ msgstr "" -#~ msgid "iSwap Gate" +#~ msgid "The tensor for constructing an QuAdjointVector." #~ msgstr "" -#~ msgid "Convert Gate to numpy array." +#~ msgid "" +#~ "Sequence of integer indices specifying " +#~ "the order in which to interpret " +#~ "the axes as subsystems (input edges)." +#~ " If not specified, the axes are " +#~ "taken in ascending order." #~ msgstr "" -#~ msgid "input Gate" +#~ msgid "The new constructed QuAdjointVector give from the given tensor." #~ msgstr "" -#~ msgid "corresponding Tensor" +#~ msgid "" +#~ "Represents a linear operator via a " +#~ "tensor network. To interpret a tensor" +#~ " network as a linear operator, some" +#~ " of the dangling edges must be " +#~ "designated as `out_edges` (output edges) " +#~ "and the rest as `in_edges` (input " +#~ "edges). Considered as a matrix, the " +#~ "`out_edges` represent the row index and" +#~ " the `in_edges` represent the column " +#~ "index. The (right) action of the " +#~ "operator on another then consists of " +#~ "connecting the `in_edges` of the first" +#~ " operator to the `out_edges` of the" +#~ " second. Can be used to do " +#~ "simple linear algebra with tensor " +#~ "networks." #~ msgstr "" #~ msgid "" -#~ "Inner helper function to generate gate" -#~ " functions, such as ``z()`` from " -#~ "``_z_matrix``" +#~ "Creates a new `QuOperator` from a " +#~ "tensor network. This encapsulates an " +#~ "existing tensor network, interpreting it " +#~ "as a linear operator. The network " +#~ "is checked for consistency: All dangling" +#~ " edges must either be in `out_edges`," +#~ " `in_edges`, or `ignore_edges`." #~ msgstr "" -#~ msgid "General single qubit rotation gate" +#~ msgid "The edges of the network to be used as the output edges." #~ msgstr "" #~ msgid "" -#~ "R(\\theta, \\phi, \\alpha) = i \\cos(\\theta) I\n" -#~ "\n" +#~ "Optional collection of dangling edges to" +#~ " ignore when performing consistency checks." #~ msgstr "" #~ msgid "" -#~ "- i \\cos(\\phi) \\sin(\\alpha) \\sin(\\theta) X\n" -#~ "\n" +#~ "At least one reference node is " +#~ "required to specify a scalar. None " +#~ "provided!" #~ msgstr "" #~ msgid "" -#~ "- i \\sin(\\phi) \\sin(\\alpha) \\sin(\\theta) Y\n" -#~ "\n" +#~ "The adjoint of the operator. This " +#~ "creates a new `QuOperator` with " +#~ "complex-conjugate copies of all tensors " +#~ "in the network and with the input" +#~ " and output edges switched." #~ msgstr "" #~ msgid "" -#~ "- i \\sin(\\theta) \\cos(\\alpha) Z\n" -#~ "\n" -#~ msgstr "" - -#~ msgid "R Gate" -#~ msgstr "" - -#~ msgid "Random single qubit gate described in https://arxiv.org/abs/2002.07730." +#~ "Check that the network has the " +#~ "expected dimensionality. This checks that " +#~ "all input and output edges are " +#~ "dangling and that there are no " +#~ "other dangling edges (except any " +#~ "specified in `ignore_edges`). If not, an" +#~ " exception is raised." #~ msgstr "" -#~ msgid "A random single qubit gate" +#~ msgid "" +#~ "Contract the tensor network in place." +#~ " This modifies the tensor network " +#~ "representation of the operator (or " +#~ "vector, or scalar), reducing it to " +#~ "a single tensor, without changing the" +#~ " value." #~ msgstr "" -#~ msgid "Returns a random two-qubit gate." +#~ msgid "Manually specify the axis ordering of the final tensor." #~ msgstr "" -#~ msgid "a random two-qubit gate" +#~ msgid "The present object." #~ msgstr "" #~ msgid "" -#~ "Rotation gate, which is in matrix " -#~ "exponential form, shall give the same" -#~ " result as `rgate`." +#~ "Contracts the tensor network in place" +#~ " and returns the final tensor. Note" +#~ " that this modifies the tensor " +#~ "network representing the operator. The " +#~ "default ordering for the axes of " +#~ "the final tensor is: `*out_edges, " +#~ "*in_edges`. If there are any \"ignored\"" +#~ " edges, their axes come first: " +#~ "`*ignored_edges, *out_edges, *in_edges`." #~ msgstr "" #~ msgid "" -#~ "mx = \\sin(\\alpha) \\cos(\\phi) X\n" -#~ "\n" +#~ "Manually specify the axis ordering of" +#~ " the final tensor. The default " +#~ "ordering is determined by `out_edges` " +#~ "and `in_edges` (see above)." #~ msgstr "" -#~ msgid "" -#~ "my = \\sin(\\alpha) \\sin(\\phi) Y\n" -#~ "\n" +#~ msgid "Node count '{}' > 1 after contraction!" #~ msgstr "" -#~ msgid "" -#~ "mz = \\cos(\\alpha) Z\n" -#~ "\n" +#~ msgid "The final tensor representing the operator." #~ msgstr "" #~ msgid "" -#~ "R(\\theta, \\alpha, \\phi) = e^{-i\\theta (mx+my+mz)}\n" -#~ "\n" +#~ "Construct a `QuOperator` directly from a" +#~ " single tensor. This first wraps the" +#~ " tensor in a `Node`, then constructs" +#~ " the `QuOperator` from that `Node`." #~ msgstr "" -#~ msgid "Rotation Gate" +#~ msgid "The tensor." #~ msgstr "" -#~ msgid "Rotation gate along X axis." +#~ msgid "The axis indices of `tensor` to use as `out_edges`." #~ msgstr "" -#~ msgid "" -#~ "RX(\\theta) = e^{-i\\frac{\\theta}{2}X}\n" -#~ "\n" +#~ msgid "The axis indices of `tensor` to use as `in_edges`." #~ msgstr "" -#~ msgid "RX Gate" +#~ msgid "The new operator." #~ msgstr "" -#~ msgid "Rotation gate along Y axis." +#~ msgid "All tensor-network nodes involved in the operator." #~ msgstr "" #~ msgid "" -#~ "RY(\\theta) = e^{-i\\frac{\\theta}{2}Y}\n" -#~ "\n" -#~ msgstr "" - -#~ msgid "RY Gate" -#~ msgstr "" - -#~ msgid "Rotation gate along Z axis." +#~ "The norm of the operator. This is" +#~ " the 2-norm (also known as the " +#~ "Frobenius or Hilbert-Schmidt norm)." #~ msgstr "" #~ msgid "" -#~ "RZ(\\theta) = e^{-i\\frac{\\theta}{2}Z}\n" -#~ "\n" +#~ "The partial trace of the operator. " +#~ "Subsystems to trace out are supplied " +#~ "as indices, so that dangling edges " +#~ "are connected to each other as: " +#~ "`out_edges[i] ^ in_edges[i] for i in " +#~ "subsystems_to_trace_out` This does not modify" +#~ " the original network. The original " +#~ "ordering of the remaining subsystems is" +#~ " maintained." #~ msgstr "" -#~ msgid "RZ Gate" +#~ msgid "Indices of subsystems to trace out." #~ msgstr "" -#~ msgid "Interfaces bridging different backends" +#~ msgid "A new QuOperator or QuScalar representing the result." #~ msgstr "" -#~ msgid "Keras layer for tc quantum function" +#~ msgid "" +#~ "Tensor product with another operator. " +#~ "Given two operators `A` and `B`, " +#~ "produces a new operator `AB` " +#~ "representing `A` ⊗ `B`. The `out_edges`" +#~ " (`in_edges`) of `AB` is simply the" +#~ " concatenation of the `out_edges` " +#~ "(`in_edges`) of `A.copy()` with that of" +#~ " `B.copy()`: `new_out_edges = [*out_edges_A_copy," +#~ " *out_edges_B_copy]` `new_in_edges = " +#~ "[*in_edges_A_copy, *in_edges_B_copy]`" #~ msgstr "" -#~ msgid "" -#~ "`QuantumLayer` wraps the quantum function " -#~ "`f` as a `keras.Layer` so that " -#~ "tensorcircuit is better integrated with " -#~ "tensorflow." +#~ msgid "The other operator (`B`)." #~ msgstr "" -#~ msgid "[description], defaults to \"glorot_uniform\"" +#~ msgid "The result (`AB`)." #~ msgstr "" -#~ msgid "" -#~ "Load function from the files in " -#~ "the ``tf.savedmodel`` format. We can " -#~ "load several functions at the same " -#~ "time, as they can be the same " -#~ "function of different input shapes." +#~ msgid "The trace of the operator." #~ msgstr "" -#~ msgid "" -#~ "The fallback function when all functions" -#~ " loaded are failed, defaults to None" +#~ msgid "Represents a scalar via a tensor network." #~ msgstr "" #~ msgid "" -#~ "When there is not legal loaded " -#~ "function of the input shape and no" -#~ " fallback callable." +#~ "Constructs a new `QuScalar` from a " +#~ "tensor network. This encapsulates an " +#~ "existing tensor network, interpreting it " +#~ "as a scalar." #~ msgstr "" #~ msgid "" -#~ "A function that tries all loaded " -#~ "function against the input until the " -#~ "first success one." +#~ "Nodes used to refer to the tensor" +#~ " network (need not be exhaustive -" +#~ " one node from each disconnected " +#~ "subnetwork is sufficient)." #~ msgstr "" #~ msgid "" -#~ "The keras loss function that directly" -#~ " taking the model output as the " -#~ "loss." -#~ msgstr "" - -#~ msgid "Save tf function in the file (``tf.savedmodel`` format)." +#~ "Construct a `QuScalar` directly from a" +#~ " single tensor. This first wraps the" +#~ " tensor in a `Node`, then constructs" +#~ " the `QuScalar` from that `Node`." #~ msgstr "" -#~ msgid "``tf.function`` ed function with graph building" +#~ msgid "The tensor for constructing a new QuScalar." #~ msgstr "" -#~ msgid "the dir path to save the function" +#~ msgid "The new constructed QuScalar from the given tensor." #~ msgstr "" -#~ msgid "FiniteMPS from tensornetwork with bug fixed" +#~ msgid "Represents a (column) vector via a tensor network." #~ msgstr "" #~ msgid "" -#~ "Bases: " -#~ ":py:class:`tensornetwork.matrixproductstates.finite_mps.FiniteMPS`" +#~ "Constructs a new `QuVector` from a " +#~ "tensor network. This encapsulates an " +#~ "existing tensor network, interpreting it " +#~ "as a (column) vector." #~ msgstr "" #~ msgid "" -#~ "Apply a two-site gate to an " -#~ "MPS. This routine will in general " -#~ "destroy any canonical form of the " -#~ "state. If a canonical form is " -#~ "needed, the user can restore it " -#~ "using `FiniteMPS.position`." -#~ msgstr "" - -#~ msgid "A two-body gate." -#~ msgstr "" - -#~ msgid "The first site where the gate acts." +#~ "Construct a `QuVector` directly from a" +#~ " single tensor. This first wraps the" +#~ " tensor in a `Node`, then constructs" +#~ " the `QuVector` from that `Node`." #~ msgstr "" -#~ msgid "The second site where the gate acts." +#~ msgid "The tensor for constructing a \"QuVector\"." #~ msgstr "" -#~ msgid "The maximum number of singular values to keep." +#~ msgid "" +#~ "Sequence of integer indices specifying " +#~ "the order in which to interpret " +#~ "the axes as subsystems (output edges)." +#~ " If not specified, the axes are " +#~ "taken in ascending order." #~ msgstr "" -#~ msgid "The maximum allowed truncation error." +#~ msgid "The new constructed QuVector from the given tensor." #~ msgstr "" #~ msgid "" -#~ "An optional value to choose the " -#~ "MPS tensor at `center_position` to be" -#~ " isometric after the application of " -#~ "the gate. Defaults to `site1`. If " -#~ "the MPS is canonical " -#~ "(i.e.`BaseMPS.center_position != None`), and " -#~ "if the orthogonality center coincides " -#~ "with either `site1` or `site2`, the " -#~ "orthogonality center will be shifted to" -#~ " `center_position` (`site1` by default). If" -#~ " the orthogonality center does not " -#~ "coincide with `(site1, site2)` then " -#~ "`MPS.center_position` is set to `None`." +#~ "Check the vector spaces represented by" +#~ " two lists of edges are compatible." +#~ " The number of edges must be " +#~ "the same and the dimensions of " +#~ "each pair of edges must match. " +#~ "Otherwise, an exception is raised. " +#~ ":param edges_1: List of edges " +#~ "representing a many-body Hilbert space." +#~ " :type edges_1: Sequence[Edge] :param " +#~ "edges_2: List of edges representing a" +#~ " many-body Hilbert space. :type " +#~ "edges_2: Sequence[Edge]" #~ msgstr "" -#~ msgid "Multiply `max_truncation_err` with the largest singular value." +#~ msgid "" +#~ "Hilbert-space mismatch: \"Cannot connect " +#~ "{} subsystems with {} subsystems\", or" +#~ " \"Input dimension {} != output " +#~ "dimension {}.\"" #~ msgstr "" #~ msgid "" -#~ "\"rank of gate is {} but has " -#~ "to be 4\", \"site1 = {} is " -#~ "not between 0 <= site < N -" -#~ " 1 = {}\", \"site2 = {} is " -#~ "not between 1 <= site < N =" -#~ " {}\",\"Found site2 ={}, site1={}. Only " -#~ "nearest neighbor gates are currently " -#~ "supported\", \"f center_position = " -#~ "{center_position} not f in {(site1, " -#~ "site2)} \", or \"center_position = {}," -#~ " but gate is applied at sites " -#~ "{}, {}. Truncation should only be " -#~ "done if the gate is applied at " -#~ "the center position of the MPS.\"" +#~ "Eliminates any connected CopyNodes that " +#~ "are identity matrices. This will modify" +#~ " the network represented by `nodes`. " +#~ "Only identities that are connected to" +#~ " other nodes are eliminated." #~ msgstr "" -#~ msgid "A scalar tensor containing the truncated weight of the truncation." +#~ msgid "Collection of nodes to search." #~ msgstr "" -#~ msgid "Measure the expectation value of local operators `ops` site `sites`." +#~ msgid "" +#~ "The Dictionary mapping remaining Nodes " +#~ "to any replacements, Dictionary specifying " +#~ "all dangling-edge replacements." #~ msgstr "" -#~ msgid "A list Tensors of rank 2; the local operators to be measured." +#~ msgid "Compute the entropy from the given density matrix ``rho``." #~ msgstr "" -#~ msgid "Sites where `ops` act." +#~ msgid "[description], defaults to 1e-12" #~ msgstr "" -#~ msgid "measurements :math:`\\langle` `ops[n]`:math:`\\rangle` for n in `sites`" +#~ msgid "" +#~ "Note: further jit is recommended. For" +#~ " large Hilbert space, sparse Hamiltonian" +#~ " is recommended" #~ msgstr "" #~ msgid "" -#~ "Compute the correlator :math:`\\langle` " -#~ "`op1[site1], op2[s]`:math:`\\rangle` between `site1`" -#~ " and all sites `s` in `sites2`. " -#~ "If `s == site1`, `op2[s]` will be" -#~ " applied first." +#~ "Construct a 'QuOperator' representing the " +#~ "identity on a given space. Internally," +#~ " this is done by constructing " +#~ "'CopyNode's for each edge, with " +#~ "dimension according to 'space'." #~ msgstr "" -#~ msgid "Tensor of rank 2; the local operator at `site1`." +#~ msgid "" +#~ "A sequence of integers for the " +#~ "dimensions of the tensor product factors" +#~ " of the space (the edges in the" +#~ " tensor network)." #~ msgstr "" -#~ msgid "Tensor of rank 2; the local operator at `sites2`." +#~ msgid "The data type (for conversion to dense)." #~ msgstr "" -#~ msgid "The site where `op1` acts" +#~ msgid "The desired identity operator." #~ msgstr "" -#~ msgid "Sites where operator `op2` acts." +#~ msgid "" +#~ "Simulate the measuring of each qubit " +#~ "of ``p`` in the computational basis, " +#~ "thus producing output like that of " +#~ "``qiskit``." #~ msgstr "" #~ msgid "" -#~ "Correlator :math:`\\langle` `op1[site1], " -#~ "op2[s]`:math:`\\rangle` for `s` :math:`\\in` " -#~ "`sites2`." +#~ "The quantum state, assumed to be " +#~ "normalized, as either a ket or " +#~ "density operator." #~ msgstr "" -#~ msgid "Quantum circuit: MPS state simulator" +#~ msgid "The number of counts to perform." #~ msgstr "" -#~ msgid "``MPSCircuit`` class. Simple usage demo below." +#~ msgid "" +#~ "Defaults True. The bool indicating " +#~ "whether the return form is in the" +#~ " form of two array or one of" +#~ " the same length as the ``state`` " +#~ "(if ``sparse=False``)." #~ msgstr "" -#~ msgid "MPSCircuit object based on state simulator." +#~ msgid "The counts for each bit string measured." #~ msgstr "" #~ msgid "" -#~ "If not None, the initial state of" -#~ " the circuit is taken as ``tensors``" -#~ " instead of :math:`\\vert 0\\rangle^n` " -#~ "qubits, defaults to None" +#~ "Constructs an appropriately specialized " +#~ "QuOperator. If there are no edges, " +#~ "creates a QuScalar. If the are " +#~ "only output (input) edges, creates a " +#~ "QuVector (QuAdjointVector). Otherwise creates " +#~ "a QuOperator." #~ msgstr "" -#~ msgid "The center position of MPS, default to 0" +#~ msgid "" +#~ "op = qu.quantum_constructor([], [psi_node[0], " +#~ "psi_node[1]]) >>> show_attributes(op) op.is_scalar()" +#~ " -> False op.is_vector() -> " +#~ "False op.is_adjoint_vector() -> True " +#~ "len(op.out_edges) -> 0 len(op.in_edges)" +#~ " -> 2 >>> # psi_node[0] -> " +#~ "op.in_edges[0] >>> # psi_node[1] -> " +#~ "op.in_edges[1]" #~ msgstr "" -#~ msgid "Apply a general qubit gate on MPS." +#~ msgid "output edges." #~ msgstr "" -#~ msgid "The Gate to be applied" +#~ msgid "in edges." #~ msgstr "" -#~ msgid "Qubit indices of the gate" +#~ msgid "" +#~ "reference nodes for the tensor network" +#~ " (needed if there is a scalar " +#~ "component)." #~ msgstr "" -#~ msgid "\"MPS does not support application of gate on > 2 qubits.\"" +#~ msgid "edges to ignore when checking the dimensionality of the tensor network." #~ msgstr "" -#~ msgid "" -#~ "Apply a double qubit gate on " -#~ "adjacent qubits of Matrix Product States" -#~ " (MPS). Truncation rule is specified " -#~ "by `set_truncation_rule`." +#~ msgid "The new created QuOperator object." #~ msgstr "" -#~ msgid "The first qubit index of the gate" +#~ msgid "Compute the reduced density matrix from the quantum state ``state``." #~ msgstr "" -#~ msgid "The second qubit index of the gate" +#~ msgid "Compute the trace of several inputs ``o`` as tensor or ``QuOperator``." #~ msgstr "" -#~ msgid "Center position of MPS, default is None" +#~ msgid "\\mathrm{Tr}(\\prod_i O_i)" #~ msgstr "" -#~ msgid "" -#~ "Apply a double qubit gate on MPS." -#~ " Truncation rule is specified by " -#~ "`set_truncation_rule`." +#~ msgid "the trace of several inputs" #~ msgstr "" -#~ msgid "" -#~ "Apply a single qubit gate on MPS," -#~ " and the gate must be unitary; " -#~ "no truncation is needed." +#~ msgid "Tensornetwork Simplification" #~ msgstr "" -#~ msgid "gate to be applied" +#~ msgid "" +#~ "Get the new shape of two nodes," +#~ " also supporting to return original " +#~ "shapes of two nodes." #~ msgstr "" -#~ msgid "Qubit index of the gate" +#~ msgid "node one" #~ msgstr "" -#~ msgid "Compute the conjugate of the current MPS." +#~ msgid "node two" #~ msgstr "" -#~ msgid "The constructed MPS" +#~ msgid "Whether to include original shape of two nodes, default is True." #~ msgstr "" -#~ msgid "Copy the current MPS." +#~ msgid "The new shape of the two nodes." #~ msgstr "" -#~ msgid "Copy the current MPS without the tensors." +#~ msgid "" +#~ "Contract between Node ``a`` and ``b``," +#~ " with correct shape only and no " +#~ "calculation" #~ msgstr "" -#~ msgid "Compute the expectation of the corresponding double qubit gate." +#~ msgid "Shortcuts for measurement patterns on circuit" #~ msgstr "" -#~ msgid "qubit index of the gate" +#~ msgid "Some common graphs and lattices" #~ msgstr "" -#~ msgid "" -#~ "Compute the expectation of the " -#~ "corresponding single qubit gate in the" -#~ " form of tensor." +#~ msgid "1D chain with ``n`` sites" #~ msgstr "" -#~ msgid "Gate to be applied" +#~ msgid "" +#~ "This measurements pattern is specifically " +#~ "suitable for vmap. Parameterize the " +#~ "Pauli string to be measured." #~ msgstr "" -#~ msgid "The expectation of the corresponding single qubit gate" +#~ msgid "" +#~ "parameter tensors determines what Pauli " +#~ "string to be measured, shape is " +#~ "[nwires, 4] if onehot is False." #~ msgstr "" #~ msgid "" -#~ "Compute the expectation of the direct" -#~ " product of the corresponding two " -#~ "gates." +#~ "[description], defaults to False. If set" +#~ " to be True, structures will first" +#~ " go through onehot procedure." #~ msgstr "" -#~ msgid "First gate to be applied" +#~ msgid "COO_sparse_matrix" #~ msgstr "" -#~ msgid "Second gate to be applied" +#~ msgid "a real and scalar tensor of shape []" #~ msgstr "" -#~ msgid "Qubit index of the first gate" +#~ msgid "Helper functions" #~ msgstr "" -#~ msgid "Qubit index of the second gate" +#~ msgid "" +#~ "Return a callable function for output" +#~ " ith parts of the original output " +#~ "along the first axis. Original output" +#~ " supports List and Tensor." #~ msgstr "" -#~ msgid "The correlation of the corresponding two qubit gates" +#~ msgid "The function to be applied this method" #~ msgstr "" -#~ msgid "Construct the MPS from a given wavefunction." +#~ msgid "The ith parts of original output along the first axis (axis=0 or dim=0)" #~ msgstr "" -#~ msgid "The given wavefunction (any shape is OK)" +#~ msgid "The modified callable function" #~ msgstr "" -#~ msgid "" -#~ "Compute the expectation of corresponding " -#~ "operators in the form of tensor." +#~ msgid "Visualization on circuits" #~ msgstr "" -#~ msgid "" -#~ "Operator and its position on the " -#~ "circuit, eg. ``(gates.Z(), [1]), (gates.X()," -#~ " [2])`` is for operator :math:`Z_1X_2`" +#~ msgid "# TODO(@YHPeter): add examples" #~ msgstr "" -#~ msgid "The expectation of corresponding operators" +#~ msgid "" +#~ "Generate the PDF file with given " +#~ "latex string and filename. Latex command" +#~ " and file path can be specified. " +#~ "When notebook is True, convert the " +#~ "output PDF file to image and " +#~ "return a Image object." #~ msgstr "" -#~ msgid "Get the normalized Center Position." +#~ msgid "String of latex content" #~ msgstr "" -#~ msgid "Normalized Center Position." +#~ msgid "File name, defaults to random UUID `str(uuid4())`" #~ msgstr "" -#~ msgid "Check whether the circuit is legal." +#~ msgid "Executable Latex command, defaults to `pdflatex`" #~ msgstr "" -#~ msgid "Whether the circuit is legal." +#~ msgid "File path, defaults to current working place `os.getcwd()`" #~ msgstr "" -#~ msgid "integer indicating the measure on which quantum line" +#~ msgid "if notebook is True, return `Image` object; otherwise return `None`" #~ msgstr "" -#~ msgid "" -#~ "Middle measurement in the z-basis on " -#~ "the circuit, note the wavefunction " -#~ "output is not normalized with " -#~ "``mid_measurement`` involved, one should " -#~ "normalized the state manually if needed." +#~ msgid "_summary_" #~ msgstr "" -#~ msgid "The index of qubit that the Z direction postselection applied on" +#~ msgid "_description_" #~ msgstr "" -#~ msgid "0 for spin up, 1 for spin down, defaults to 0" +#~ msgid "[description], default is None." #~ msgstr "" -#~ msgid "Normalize MPS Circuit according to the center position." +#~ msgid "_description_, default is (1, -1)." #~ msgstr "" -#~ msgid "Wrapper of tn.FiniteMPS.position. Set orthogonality center." +#~ msgid "Apply fredkin gate on the circuit." #~ msgstr "" -#~ msgid "The orthogonality center" +#~ msgid "Apply orx gate with parameters on the circuit." #~ msgstr "" -#~ msgid "Compute the projection between `other` as bra and `self` as ket." +#~ msgid "Apply ory gate with parameters on the circuit." #~ msgstr "" -#~ msgid "ket of the other MPS, which will be converted to bra automatically" +#~ msgid "Apply orz gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The projection in form of tensor" +#~ msgid "Apply ox gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Set truncation rules when double qubit" -#~ " gates are applied. If nothing is " -#~ "specified, no truncation will take place" -#~ " and the bond dimension will keep " -#~ "growing. For more details, refer to " -#~ "`split_tensor`." +#~ msgid "Apply oy gate on the circuit." #~ msgstr "" -#~ msgid "Tensor with shape [1, -1]" +#~ msgid "Apply oz gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Split the tensor by SVD or QR " -#~ "depends on whether a truncation is " -#~ "required." +#~ "Random tensor between 0 or 1, " +#~ "defaults to be None, the random " +#~ "number will be generated automatically" #~ msgstr "" -#~ msgid "The input tensor to split." +#~ msgid "The str indicating the form of the output wavefunction." #~ msgstr "" #~ msgid "" -#~ "Determine the orthogonal center is on" -#~ " the left tensor or the right " -#~ "tensor." -#~ msgstr "" - -#~ msgid "Two tensors after splitting" +#~ "A collection of useful function snippets" +#~ " that irrelevant with the main " +#~ "modules or await for further refactor" #~ msgstr "" -#~ msgid "Quantum state and operator class backend by tensornetwork" +#~ msgid "VQNHE application" #~ msgstr "" -#~ msgid "Bases: :py:class:`tensorcircuit.quantum.QuOperator`" +#~ msgid "Apply **ANY** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "Represents an adjoint (row) vector via a tensor network." +#~ msgid "Apply **CR** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Constructs a new `QuAdjointVector` from " -#~ "a tensor network. This encapsulates an" -#~ " existing tensor network, interpreting it" -#~ " as an adjoint vector (row vector)." +#~ msgid "Apply **CRX** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The edges of the network to be used as the input edges." +#~ msgid "Apply **CRY** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Nodes used to refer to parts of" -#~ " the tensor network that are not " -#~ "connected to any input or output " -#~ "edges (for example: a scalar factor)." +#~ msgid "Apply **CRZ** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Optional collection of edges to ignore" -#~ " when performing consistency checks." +#~ msgid "Apply **EXP** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Construct a `QuAdjointVector` directly from" -#~ " a single tensor. This first wraps" -#~ " the tensor in a `Node`, then " -#~ "constructs the `QuAdjointVector` from that " -#~ "`Node`." +#~ msgid "Apply **EXP1** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The tensor for constructing an QuAdjointVector." +#~ msgid "Apply **FREDKIN** gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Sequence of integer indices specifying " -#~ "the order in which to interpret " -#~ "the axes as subsystems (input edges)." -#~ " If not specified, the axes are " -#~ "taken in ascending order." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 1.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "The new constructed QuAdjointVector give from the given tensor." +#~ msgid "Apply **ISWAP** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Represents a linear operator via a " -#~ "tensor network. To interpret a tensor" -#~ " network as a linear operator, some" -#~ " of the dangling edges must be " -#~ "designated as `out_edges` (output edges) " -#~ "and the rest as `in_edges` (input " -#~ "edges). Considered as a matrix, the " -#~ "`out_edges` represent the row index and" -#~ " the `in_edges` represent the column " -#~ "index. The (right) action of the " -#~ "operator on another then consists of " -#~ "connecting the `in_edges` of the first" -#~ " operator to the `out_edges` of the" -#~ " second. Can be used to do " -#~ "simple linear algebra with tensor " -#~ "networks." +#~ msgid "Apply **ORX** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Creates a new `QuOperator` from a " -#~ "tensor network. This encapsulates an " -#~ "existing tensor network, interpreting it " -#~ "as a linear operator. The network " -#~ "is checked for consistency: All dangling" -#~ " edges must either be in `out_edges`," -#~ " `in_edges`, or `ignore_edges`." +#~ msgid "Apply **ORY** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The edges of the network to be used as the output edges." +#~ msgid "Apply **ORZ** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Optional collection of dangling edges to" -#~ " ignore when performing consistency checks." +#~ msgid "Apply **OX** gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "At least one reference node is " -#~ "required to specify a scalar. None " -#~ "provided!" +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 1.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "1.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "" -#~ "The adjoint of the operator. This " -#~ "creates a new `QuOperator` with " -#~ "complex-conjugate copies of all tensors " -#~ "in the network and with the input" -#~ " and output edges switched." +#~ msgid "Apply **OY** gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Check that the network has the " -#~ "expected dimensionality. This checks that " -#~ "all input and output edges are " -#~ "dangling and that there are no " -#~ "other dangling edges (except any " -#~ "specified in `ignore_edges`). If not, an" -#~ " exception is raised." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 0.-1.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+1.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgstr "" + +#~ msgid "Apply **OZ** gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "Contract the tensor network in place." -#~ " This modifies the tensor network " -#~ "representation of the operator (or " -#~ "vector, or scalar), reducing it to " -#~ "a single tensor, without changing the" -#~ " value." +#~ "Qubit number than the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & -1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Manually specify the axis ordering of the final tensor." +#~ msgid "Apply **R** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "The present object." +#~ msgid "Apply **RX** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Contracts the tensor network in place" -#~ " and returns the final tensor. Note" -#~ " that this modifies the tensor " -#~ "network representing the operator. The " -#~ "default ordering for the axes of " -#~ "the final tensor is: `*out_edges, " -#~ "*in_edges`. If there are any \"ignored\"" -#~ " edges, their axes come first: " -#~ "`*ignored_edges, *out_edges, *in_edges`." +#~ msgid "Apply **RY** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Manually specify the axis ordering of" -#~ " the final tensor. The default " -#~ "ordering is determined by `out_edges` " -#~ "and `in_edges` (see above)." +#~ msgid "Apply **RZ** gate with parameters on the circuit." #~ msgstr "" -#~ msgid "Node count '{}' > 1 after contraction!" +#~ msgid "Apply **SD** gate on the circuit." #~ msgstr "" -#~ msgid "The final tensor representing the operator." +#~ msgid "Apply **TD** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Construct a `QuOperator` directly from a" -#~ " single tensor. This first wraps the" -#~ " tensor in a `Node`, then constructs" -#~ " the `QuOperator` from that `Node`." +#~ msgid "Apply **TOFFOLI** gate on the circuit." #~ msgstr "" -#~ msgid "The tensor." +#~ msgid "" +#~ "Apply unitary gates in ``kraus`` " +#~ "randomly based on corresponding ``prob``." #~ msgstr "" -#~ msgid "The axis indices of `tensor` to use as `out_edges`." +#~ msgid "Get the eigenvalues of matrix ``a``." #~ msgstr "" -#~ msgid "The axis indices of `tensor` to use as `in_edges`." +#~ msgid "eigenvalues of ``a``" #~ msgstr "" -#~ msgid "The new operator." +#~ msgid "" +#~ "Apply **ANY** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.any_gate`." #~ msgstr "" -#~ msgid "All tensor-network nodes involved in the operator." +#~ msgid "Qubit number that the gate applies on." #~ msgstr "" #~ msgid "" -#~ "The norm of the operator. This is" -#~ " the 2-norm (also known as the " -#~ "Frobenius or Hilbert-Schmidt norm)." +#~ "Apply **CNOT** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.cnot_gate`." #~ msgstr "" #~ msgid "" -#~ "The partial trace of the operator. " -#~ "Subsystems to trace out are supplied " -#~ "as indices, so that dangling edges " -#~ "are connected to each other as: " -#~ "`out_edges[i] ^ in_edges[i] for i in " -#~ "subsystems_to_trace_out` This does not modify" -#~ " the original network. The original " -#~ "ordering of the remaining subsystems is" -#~ " maintained." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 1.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Indices of subsystems to trace out." +#~ msgid "Qubit number that the gate applies on. The matrix for the gate is" #~ msgstr "" -#~ msgid "A new QuOperator or QuScalar representing the result." +#~ msgid "" +#~ "Apply **CR** gate with parameters on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.cr_gate`." #~ msgstr "" #~ msgid "" -#~ "Tensor product with another operator. " -#~ "Given two operators `A` and `B`, " -#~ "produces a new operator `AB` " -#~ "representing `A` ⊗ `B`. The `out_edges`" -#~ " (`in_edges`) of `AB` is simply the" -#~ " concatenation of the `out_edges` " -#~ "(`in_edges`) of `A.copy()` with that of" -#~ " `B.copy()`: `new_out_edges = [*out_edges_A_copy," -#~ " *out_edges_B_copy]` `new_in_edges = " -#~ "[*in_edges_A_copy, *in_edges_B_copy]`" +#~ "Apply **CRX** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.crx_gate`." #~ msgstr "" -#~ msgid "The other operator (`B`)." +#~ msgid "" +#~ "Apply **CRY** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.cry_gate`." #~ msgstr "" -#~ msgid "The result (`AB`)." +#~ msgid "" +#~ "Apply **CRZ** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.crz_gate`." #~ msgstr "" -#~ msgid "The trace of the operator." +#~ msgid "" +#~ "Apply **CY** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.cy_gate`." #~ msgstr "" -#~ msgid "Represents a scalar via a tensor network." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.-1.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+1.j & 0.+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Constructs a new `QuScalar` from a " -#~ "tensor network. This encapsulates an " -#~ "existing tensor network, interpreting it " -#~ "as a scalar." +#~ "Apply **CZ** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.cz_gate`." #~ msgstr "" #~ msgid "" -#~ "Nodes used to refer to the tensor" -#~ " network (need not be exhaustive -" -#~ " one node from each disconnected " -#~ "subnetwork is sufficient)." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & -1.+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Construct a `QuScalar` directly from a" -#~ " single tensor. This first wraps the" -#~ " tensor in a `Node`, then constructs" -#~ " the `QuScalar` from that `Node`." +#~ "Apply **EXP** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.exp_gate`." #~ msgstr "" -#~ msgid "The tensor for constructing a new QuScalar." +#~ msgid "" +#~ "Apply **EXP1** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.exp1_gate`." #~ msgstr "" -#~ msgid "The new constructed QuScalar from the given tensor." +#~ msgid "" +#~ "Apply **FREDKIN** gate on the circuit." +#~ " See :py:meth:`tensorcircuit.gates.fredkin_gate`." #~ msgstr "" -#~ msgid "Represents a (column) vector via a tensor network." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 1.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Constructs a new `QuVector` from a " -#~ "tensor network. This encapsulates an " -#~ "existing tensor network, interpreting it " -#~ "as a (column) vector." +#~ "Apply **H** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.h_gate`." #~ msgstr "" #~ msgid "" -#~ "Construct a `QuVector` directly from a" -#~ " single tensor. This first wraps the" -#~ " tensor in a `Node`, then constructs" -#~ " the `QuVector` from that `Node`." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} " +#~ "0.70710677+0.j & 0.70710677+0.j\\\\ " +#~ "0.70710677+0.j & -0.70710677+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "The tensor for constructing a \"QuVector\"." +#~ msgid "" +#~ "Apply **I** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.i_gate`." #~ msgstr "" #~ msgid "" -#~ "Sequence of integer indices specifying " -#~ "the order in which to interpret " -#~ "the axes as subsystems (output edges)." -#~ " If not specified, the axes are " -#~ "taken in ascending order." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "The new constructed QuVector from the given tensor." +#~ msgid "" +#~ "Apply **ISWAP** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.iswap_gate`." #~ msgstr "" #~ msgid "" -#~ "Check the vector spaces represented by" -#~ " two lists of edges are compatible." -#~ " The number of edges must be " -#~ "the same and the dimensions of " -#~ "each pair of edges must match. " -#~ "Otherwise, an exception is raised. " -#~ ":param edges_1: List of edges " -#~ "representing a many-body Hilbert space." -#~ " :type edges_1: Sequence[Edge] :param " -#~ "edges_2: List of edges representing a" -#~ " many-body Hilbert space. :type " -#~ "edges_2: Sequence[Edge]" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 0.+1.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+1.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Hilbert-space mismatch: \"Cannot connect " -#~ "{} subsystems with {} subsystems\", or" -#~ " \"Input dimension {} != output " -#~ "dimension {}.\"" +#~ "Apply **ORX** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.orx_gate`." #~ msgstr "" #~ msgid "" -#~ "Eliminates any connected CopyNodes that " -#~ "are identity matrices. This will modify" -#~ " the network represented by `nodes`. " -#~ "Only identities that are connected to" -#~ " other nodes are eliminated." +#~ "Apply **ORY** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.ory_gate`." #~ msgstr "" -#~ msgid "Collection of nodes to search." +#~ msgid "" +#~ "Apply **ORZ** gate with parameters on" +#~ " the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.orz_gate`." #~ msgstr "" #~ msgid "" -#~ "The Dictionary mapping remaining Nodes " -#~ "to any replacements, Dictionary specifying " -#~ "all dangling-edge replacements." +#~ "Apply **OX** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.ox_gate`." #~ msgstr "" -#~ msgid "Compute the entropy from the given density matrix ``rho``." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 1.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "1.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "[description], defaults to 1e-12" +#~ msgid "" +#~ "Apply **OY** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.oy_gate`." #~ msgstr "" #~ msgid "" -#~ "Note: further jit is recommended. For" -#~ " large Hilbert space, sparse Hamiltonian" -#~ " is recommended" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 0.-1.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+1.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Construct a 'QuOperator' representing the " -#~ "identity on a given space. Internally," -#~ " this is done by constructing " -#~ "'CopyNode's for each edge, with " -#~ "dimension according to 'space'." +#~ "Apply **OZ** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.oz_gate`." #~ msgstr "" #~ msgid "" -#~ "A sequence of integers for the " -#~ "dimensions of the tensor product factors" -#~ " of the space (the edges in the" -#~ " tensor network)." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & -1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "The data type (for conversion to dense)." +#~ msgid "" +#~ "Apply **R** gate with parameters on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.r_gate`." #~ msgstr "" -#~ msgid "The desired identity operator." +#~ msgid "" +#~ "Apply **RX** gate with parameters on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.rx_gate`." #~ msgstr "" #~ msgid "" -#~ "Simulate the measuring of each qubit " -#~ "of ``p`` in the computational basis, " -#~ "thus producing output like that of " -#~ "``qiskit``." +#~ "Apply **RY** gate with parameters on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.ry_gate`." #~ msgstr "" #~ msgid "" -#~ "The quantum state, assumed to be " -#~ "normalized, as either a ket or " -#~ "density operator." +#~ "Apply **RZ** gate with parameters on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.gates.rz_gate`." #~ msgstr "" -#~ msgid "The number of counts to perform." +#~ msgid "" +#~ "Apply **S** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.s_gate`." #~ msgstr "" #~ msgid "" -#~ "Defaults True. The bool indicating " -#~ "whether the return form is in the" -#~ " form of two array or one of" -#~ " the same length as the ``state`` " -#~ "(if ``sparse=False``)." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 0.+1.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "The counts for each bit string measured." +#~ msgid "" +#~ "Apply **SD** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.sd_gate`." #~ msgstr "" #~ msgid "" -#~ "Constructs an appropriately specialized " -#~ "QuOperator. If there are no edges, " -#~ "creates a QuScalar. If the are " -#~ "only output (input) edges, creates a " -#~ "QuVector (QuAdjointVector). Otherwise creates " -#~ "a QuOperator." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & 0.-1.j " +#~ "\\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "op = qu.quantum_constructor([], [psi_node[0], " -#~ "psi_node[1]]) >>> show_attributes(op) op.is_scalar()" -#~ " -> False op.is_vector() -> " -#~ "False op.is_adjoint_vector() -> True " -#~ "len(op.out_edges) -> 0 len(op.in_edges)" -#~ " -> 2 >>> # psi_node[0] -> " -#~ "op.in_edges[0] >>> # psi_node[1] -> " -#~ "op.in_edges[1]" +#~ "Apply **SWAP** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.swap_gate`." #~ msgstr "" -#~ msgid "output edges." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " +#~ "0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "in edges." +#~ msgid "" +#~ "Apply **T** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.t_gate`." #~ msgstr "" #~ msgid "" -#~ "reference nodes for the tensor network" -#~ " (needed if there is a scalar " -#~ "component)." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1. &" +#~ " +0.j & 0. & +0.j\\\\ 0. &" +#~ " +0.j & 0.70710677+0.70710677j \\end{bmatrix}" #~ msgstr "" -#~ msgid "edges to ignore when checking the dimensionality of the tensor network." +#~ msgid "" +#~ "Apply **TD** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.td_gate`." #~ msgstr "" -#~ msgid "The new created QuOperator object." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1. &" +#~ " +0.j & 0. & +0.j\\\\ 0. &" +#~ " +0.j & 0.70710677-0.70710677j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Compute the reduced density matrix from the quantum state ``state``." +#~ msgid "" +#~ "Apply **TOFFOLI** gate on the circuit." +#~ " See :py:meth:`tensorcircuit.gates.toffoli_gate`." #~ msgstr "" -#~ msgid "Compute the trace of several inputs ``o`` as tensor or ``QuOperator``." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" +#~ " 0.+0.j & 0.+0.j & 0.+0.j & " +#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 0.+0.j & 1.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j & 0.+0.j & " +#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" +#~ " 0.+0.j & 1.+0.j\\\\ 0.+0.j & " +#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" +#~ " & 0.+0.j & 1.+0.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "\\mathrm{Tr}(\\prod_i O_i)" +#~ msgid "" +#~ "Apply **WROOT** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.wroot_gate`." #~ msgstr "" -#~ msgid "the trace of several inputs" +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} " +#~ "0.70710677+0.j & -0.5 & -0.5j\\\\ 0.5" +#~ " & -0.5j & 0.70710677+0.j \\end{bmatrix}" #~ msgstr "" -#~ msgid "Tensornetwork Simplification" +#~ msgid "" +#~ "Apply **X** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.x_gate`." #~ msgstr "" #~ msgid "" -#~ "Get the new shape of two nodes," -#~ " also supporting to return original " -#~ "shapes of two nodes." +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 1.+0.j\\\\ 1.+0.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "node one" +#~ msgid "" +#~ "Apply **Y** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.y_gate`." #~ msgstr "" -#~ msgid "node two" +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 0.+0.j " +#~ "& 0.-1.j\\\\ 0.+1.j & 0.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" -#~ msgid "Whether to include original shape of two nodes, default is True." +#~ msgid "" +#~ "Apply **Z** gate on the circuit. " +#~ "See :py:meth:`tensorcircuit.gates.z_gate`." #~ msgstr "" -#~ msgid "The new shape of the two nodes." +#~ msgid "" +#~ "Qubit number that the gate applies " +#~ "on. The matrix for the gate is" +#~ " .. math:: \\begin{bmatrix} 1.+0.j " +#~ "& 0.+0.j\\\\ 0.+0.j & -1.+0.j " +#~ "\\end{bmatrix}" #~ msgstr "" #~ msgid "" -#~ "Contract between Node ``a`` and ``b``," -#~ " with correct shape only and no " -#~ "calculation" +#~ "Apply unitary gates in ``kraus`` " +#~ "randomly based on corresponding ``prob``. " +#~ "If ``prob`` is ``None``, this is " +#~ "reduced to kraus channel language." #~ msgstr "" -#~ msgid "Shortcuts for measurement patterns on circuit" +#~ msgid "The density matrix simulator based on tensornetwork engine." #~ msgstr "" -#~ msgid "Some common graphs and lattices" +#~ msgid "Number of qubits" #~ msgstr "" -#~ msgid "1D chain with ``n`` sites" +#~ msgid "if True, nothing initialized, only for internal use, defaults to False" #~ msgstr "" -#~ msgid "" -#~ "This measurements pattern is specifically " -#~ "suitable for vmap. Parameterize the " -#~ "Pauli string to be measured." +#~ msgid "the state input for the circuit, defaults to None" #~ msgstr "" -#~ msgid "" -#~ "parameter tensors determines what Pauli " -#~ "string to be measured, shape is " -#~ "[nwires, 4] if onehot is False." +#~ msgid "the density matrix input for the circuit, defaults to None" #~ msgstr "" #~ msgid "" -#~ "[description], defaults to False. If set" -#~ " to be True, structures will first" -#~ " go through onehot procedure." -#~ msgstr "" - -#~ msgid "COO_sparse_matrix" +#~ "Apply amplitudedamping quantum channel on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.channels.amplitudedampingchannel`" #~ msgstr "" -#~ msgid "a real and scalar tensor of shape []" +#~ msgid "Parameters for the channel." #~ msgstr "" -#~ msgid "Helper functions" +#~ msgid "Return the output density matrix of the circuit." #~ msgstr "" #~ msgid "" -#~ "Return a callable function for output" -#~ " ith parts of the original output " -#~ "along the first axis. Original output" -#~ " supports List and Tensor." -#~ msgstr "" - -#~ msgid "The function to be applied this method" +#~ "check whether the final return is " +#~ "a legal density matrix, defaults to " +#~ "False" #~ msgstr "" -#~ msgid "The ith parts of original output along the first axis (axis=0 or dim=0)" +#~ msgid "whether to reuse previous results, defaults to True" #~ msgstr "" -#~ msgid "The modified callable function" +#~ msgid "The output densitymatrix in 2D shape tensor form" #~ msgstr "" -#~ msgid "Visualization on circuits" +#~ msgid "" +#~ "Apply depolarizing quantum channel on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.channels.depolarizingchannel`" #~ msgstr "" -#~ msgid "# TODO(@YHPeter): add examples" +#~ msgid "" +#~ "Apply phasedamping quantum channel on " +#~ "the circuit. See " +#~ ":py:meth:`tensorcircuit.channels.phasedampingchannel`" #~ msgstr "" #~ msgid "" -#~ "Generate the PDF file with given " -#~ "latex string and filename. Latex command" -#~ " and file path can be specified. " -#~ "When notebook is True, convert the " -#~ "output PDF file to image and " -#~ "return a Image object." +#~ "Apply reset quantum channel on the " +#~ "circuit. See " +#~ ":py:meth:`tensorcircuit.channels.resetchannel`" #~ msgstr "" -#~ msgid "String of latex content" +#~ msgid "Generate tensorflow sparse matrix from Pauli string sum" #~ msgstr "" -#~ msgid "File name, defaults to random UUID `str(uuid4())`" +#~ msgid "" +#~ "1D Tensor representing for a Pauli " +#~ "string, e.g. [1, 0, 0, 3, 2] " +#~ "is for :math:`X_0Z_3Y_4`" #~ msgstr "" -#~ msgid "Executable Latex command, defaults to `pdflatex`" +#~ msgid "" +#~ "the weight for the Pauli string " +#~ "defaults to None (all Pauli strings " +#~ "weight 1.0)" #~ msgstr "" -#~ msgid "File path, defaults to current working place `os.getcwd()`" +#~ msgid "the tensorflow sparse matrix" #~ msgstr "" -#~ msgid "if notebook is True, return `Image` object; otherwise return `None`" +#~ msgid "" +#~ "2D Tensor, each row is for a " +#~ "Pauli string, e.g. [1, 0, 0, 3," +#~ " 2] is for :math:`X_0Z_3Y_4`" #~ msgstr "" -#~ msgid "_summary_" +#~ msgid "" +#~ "1D Tensor, each element corresponds the" +#~ " weight for each Pauli string " +#~ "defaults to None (all Pauli strings " +#~ "weight 1.0)" #~ msgstr "" -#~ msgid "_description_" +#~ msgid "the tensorflow coo sparse matrix" #~ msgstr "" -#~ msgid "[description], default is None." +#~ msgid "Generate scipy sparse matrix from Pauli string sum" #~ msgstr "" -#~ msgid "_description_, default is (1, -1)." +#~ msgid "the scipy coo sparse matrix" #~ msgstr "" -#~ msgid "Apply fredkin gate on the circuit." +#~ msgid "Generate tensorflow dense matrix from Pauli string sum" #~ msgstr "" -#~ msgid "Apply orx gate with parameters on the circuit." +#~ msgid "the tensorflow dense matrix" #~ msgstr "" -#~ msgid "Apply ory gate with parameters on the circuit." +#~ msgid "" +#~ "The projector of the operator. The " +#~ "operator, as a linear operator, on " +#~ "the adjoint of the operator." #~ msgstr "" -#~ msgid "Apply orz gate with parameters on the circuit." +#~ msgid "" +#~ "Set :math:`A` is the operator in " +#~ "matrix form, then the projector of " +#~ "operator is defined as: :math:`A^\\dagger " +#~ "A`" #~ msgstr "" -#~ msgid "Apply ox gate on the circuit." +#~ msgid "The projector of the operator." #~ msgstr "" -#~ msgid "Apply oy gate on the circuit." +#~ msgid "The reduced density of the operator." #~ msgstr "" -#~ msgid "Apply oz gate on the circuit." +#~ msgid "" +#~ "Set :math:`A` is the matrix of the" +#~ " operator, then the reduced density " +#~ "is defined as:" #~ msgstr "" -#~ msgid "" -#~ "Random tensor between 0 or 1, " -#~ "defaults to be None, the random " -#~ "number will be generated automatically" +#~ msgid "\\mathrm{Tr}_{subsystems}(A^\\dagger A)" #~ msgstr "" -#~ msgid "The str indicating the form of the output wavefunction." +#~ msgid "" +#~ "Firstly, take the projector of the " +#~ "operator, then trace out the subsystems" +#~ " to trace out are supplied as " +#~ "indices, so that dangling edges are " +#~ "connected to each other as: " +#~ "`out_edges[i] ^ in_edges[i] for i in " +#~ "subsystems_to_trace_out` This does not modify" +#~ " the original network. The original " +#~ "ordering of the remaining subsystems is" +#~ " maintained." #~ msgstr "" #~ msgid "" -#~ "A collection of useful function snippets" -#~ " that irrelevant with the main " -#~ "modules or await for further refactor" +#~ "The QuOperator of the reduced density" +#~ " of the operator with given " +#~ "subsystems." #~ msgstr "" -#~ msgid "VQNHE application" +#~ msgid "" +#~ "Contracts the tensor network in place" +#~ " and returns the final tensor in " +#~ "two dimentional matrix. The default " +#~ "ordering for the axes of the final" +#~ " tensor is: (:math:`\\prod` dimension of" +#~ " out_edges, :math:`\\prod` dimension of " +#~ "in_edges)" #~ msgstr "" -#~ msgid "Apply **ANY** gate with parameters on the circuit." +#~ msgid "The two-dimentional tensor representing the operator." #~ msgstr "" -#~ msgid "Apply **CR** gate with parameters on the circuit." +#~ msgid "" +#~ "Returns a bool indicating if QuOperator" +#~ " is an adjoint vector. Examples can" +#~ " be found in the `QuOperator.from_tensor`." #~ msgstr "" -#~ msgid "Apply **CRX** gate with parameters on the circuit." +#~ msgid "" +#~ "Returns a bool indicating if QuOperator" +#~ " is a scalar. Examples can be " +#~ "found in the `QuOperator.from_tensor`." #~ msgstr "" -#~ msgid "Apply **CRY** gate with parameters on the circuit." +#~ msgid "" +#~ "Returns a bool indicating if QuOperator" +#~ " is a vector. Examples can be " +#~ "found in the `QuOperator.from_tensor`." #~ msgstr "" -#~ msgid "Apply **CRZ** gate with parameters on the circuit." +#~ msgid "" +#~ "Tensor product with another operator. " +#~ "Given two operators `A` and `B`, " +#~ "produces a new operator `AB` " +#~ "representing :math:`A ⊗ B`. The " +#~ "`out_edges` (`in_edges`) of `AB` is " +#~ "simply the concatenation of the " +#~ "`out_edges` (`in_edges`) of `A.copy()` with" +#~ " that of `B.copy()`: `new_out_edges = " +#~ "[*out_edges_A_copy, *out_edges_B_copy]` `new_in_edges " +#~ "= [*in_edges_A_copy, *in_edges_B_copy]`" #~ msgstr "" -#~ msgid "Apply **EXP** gate with parameters on the circuit." +#~ msgid "" +#~ "Set :math:`A` is the operator in " +#~ "matrix form, then the projector of " +#~ "operator is defined as: :math:`A " +#~ "A^\\dagger`" #~ msgstr "" -#~ msgid "Apply **EXP1** gate with parameters on the circuit." +#~ msgid "\\mathrm{Tr}_{subsystems}(A A^\\dagger)" #~ msgstr "" -#~ msgid "Apply **FREDKIN** gate on the circuit." +#~ msgid "Compute the double state of the given Hamiltonian operator ``h``." #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 1.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 1.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "Hamiltonian operator in form of Tensor." #~ msgstr "" -#~ msgid "Apply **ISWAP** gate on the circuit." +#~ msgid "The double state of ``h`` with the given ``beta``." #~ msgstr "" -#~ msgid "Apply **ORX** gate with parameters on the circuit." +#~ msgid "Return fidelity scalar between two states rho and rho0." #~ msgstr "" -#~ msgid "Apply **ORY** gate with parameters on the circuit." +#~ msgid "\\operatorname{Tr}(\\sqrt{\\sqrt{rho} rho_0 \\sqrt{rho}})" #~ msgstr "" -#~ msgid "Apply **ORZ** gate with parameters on the circuit." +#~ msgid "The density matrix in form of Tensor." #~ msgstr "" -#~ msgid "Apply **OX** gate on the circuit." +#~ msgid "The sqrtm of a Hermitian matrix ``a``." #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 1.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "1.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "Compute the Gibbs state of the given Hamiltonian operator ``h``." #~ msgstr "" -#~ msgid "Apply **OY** gate on the circuit." +#~ msgid "The Gibbs state of ``h`` with the given ``beta``." #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 0.-1.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+1.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "Mutual information between AB subsystem described by ``cut``." #~ msgstr "" -#~ msgid "Apply **OZ** gate on the circuit." +#~ msgid "The AB subsystem." #~ msgstr "" -#~ msgid "" -#~ "Qubit number than the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & -1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "The mutual information between AB subsystem described by ``cut``." #~ msgstr "" -#~ msgid "Apply **R** gate with parameters on the circuit." +#~ msgid "Taylor expansion of :math:`ln(x+1)`." #~ msgstr "" -#~ msgid "Apply **RX** gate with parameters on the circuit." +#~ msgid "The :math:`k` th order, default is 2." #~ msgstr "" -#~ msgid "Apply **RY** gate with parameters on the circuit." +#~ msgid "The :math:`k` th order of Taylor expansion of :math:`ln(x+1)`." #~ msgstr "" -#~ msgid "Apply **RZ** gate with parameters on the circuit." +#~ msgid "" +#~ "Compute the trace distance between two" +#~ " density matrix ``rho`` and ``rho2``." #~ msgstr "" -#~ msgid "Apply **SD** gate on the circuit." +#~ msgid "Epsilon, defaults to 1e-12" #~ msgstr "" -#~ msgid "Apply **TD** gate on the circuit." +#~ msgid "The trace distance between two density matrix ``rho`` and ``rho2``." #~ msgstr "" -#~ msgid "Apply **TOFFOLI** gate on the circuit." +#~ msgid "\\operatorname{Tr}(\\prod_i O_i)" #~ msgstr "" #~ msgid "" -#~ "Apply unitary gates in ``kraus`` " -#~ "randomly based on corresponding ``prob``." +#~ "Compute the truncated free energy from" +#~ " the given density matrix ``rho``." #~ msgstr "" -#~ msgid "Get the eigenvalues of matrix ``a``." +#~ msgid "The :math:`k` th order, defaults to 2" #~ msgstr "" -#~ msgid "eigenvalues of ``a``" +#~ msgid "The :math:`k` th order of the truncated free energy." #~ msgstr "" #~ msgid "" -#~ "Apply **ANY** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.any_gate`." +#~ "The circuit ansatz is firstly one " +#~ "layer of Hadamard gates and then " +#~ "we have ``nlayers`` blocks of " +#~ ":math:`e^{i\\theta Z_iZ_{i+1}}` two-qubit gate" +#~ " in ladder layout, following rx gate." #~ msgstr "" -#~ msgid "Qubit number that the gate applies on." +#~ msgid "The circuit" #~ msgstr "" -#~ msgid "" -#~ "Apply **CNOT** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.cnot_gate`." +#~ msgid "paramter tensor with 2*nlayer*n elements" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 1.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 1.+0.j & 0.+0.j \\end{bmatrix}" +#~ msgid "number of ZZ+RX blocks, defaults to 2" #~ msgstr "" -#~ msgid "Qubit number that the gate applies on. The matrix for the gate is" +#~ msgid "" +#~ "whether use SVD split to reduce ZZ" +#~ " gate bond dimension, defaults to " +#~ "False" #~ msgstr "" -#~ msgid "" -#~ "Apply **CR** gate with parameters on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.cr_gate`." +#~ msgid "The circuit with example ansatz attached" #~ msgstr "" #~ msgid "" -#~ "Apply **CRX** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.crx_gate`." +#~ "Function decorator wraps the function " +#~ "with the first input and output in" +#~ " the format of circuit, the wrapped" +#~ " function has the first input and " +#~ "the output as the state tensor." #~ msgstr "" -#~ msgid "" -#~ "Apply **CRY** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.cry_gate`." +#~ msgid "Function with the fist input and the output as ``Circuit`` object." #~ msgstr "" #~ msgid "" -#~ "Apply **CRZ** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.crz_gate`." +#~ "Wrapped function with the first input" +#~ " and the output as the state " +#~ "tensor correspondingly." #~ msgstr "" -#~ msgid "" -#~ "Apply **CY** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.cy_gate`." +#~ msgid "Two-dimensional grid lattice" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.-1.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+1.j & 0.+0.j \\end{bmatrix}" +#~ msgid "number of rows" #~ msgstr "" -#~ msgid "" -#~ "Apply **CZ** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.cz_gate`." +#~ msgid "number of cols" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & -1.+0.j \\end{bmatrix}" +#~ msgid "return all col edge with 1d index encoding" #~ msgstr "" #~ msgid "" -#~ "Apply **EXP** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.exp_gate`." +#~ "whether to include pbc edges (periodic" +#~ " boundary condition), defaults to False" #~ msgstr "" -#~ msgid "" -#~ "Apply **EXP1** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.exp1_gate`." +#~ msgid "list of col edge" #~ msgstr "" -#~ msgid "" -#~ "Apply **FREDKIN** gate on the circuit." -#~ " See :py:meth:`tensorcircuit.gates.fredkin_gate`." +#~ msgid "return all row edge with 1d index encoding" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 1.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 1.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "list of row edge" #~ msgstr "" -#~ msgid "" -#~ "Apply **H** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.h_gate`." +#~ msgid "Get the 2D grid lattice in ``nx.Graph`` format" #~ msgstr "" #~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} " -#~ "0.70710677+0.j & 0.70710677+0.j\\\\ " -#~ "0.70710677+0.j & -0.70710677+0.j \\end{bmatrix}" +#~ "whether to include pbc edges (periodic" +#~ " boundary condition), defaults to True" #~ msgstr "" #~ msgid "" -#~ "Apply **I** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.i_gate`." +#~ "Generate a permutation matrix P. Due " +#~ "to the different convention or qubits'" +#~ " order in qiskit and tensorcircuit, " +#~ "the unitary represented by the same " +#~ "circuit is different. They are related" +#~ " by this permutation matrix P: P " +#~ "@ U_qiskit @ P = U_tc" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 1.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "# of qubits" #~ msgstr "" -#~ msgid "" -#~ "Apply **ISWAP** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.iswap_gate`." +#~ msgid "The permutation matrix P" #~ msgstr "" #~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 0.+1.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+1.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ "Generate a qiskit quantum circuit using" +#~ " the quantum intermediate representation " +#~ "(qir) in tensorcircuit." #~ msgstr "" -#~ msgid "" -#~ "Apply **ORX** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.orx_gate`." +#~ msgid "qiskit QuantumCircuit object" #~ msgstr "" #~ msgid "" -#~ "Apply **ORY** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.ory_gate`." +#~ "Generate a tensorcircuit circuit using " +#~ "the quantum circuit data in qiskit." #~ msgstr "" -#~ msgid "" -#~ "Apply **ORZ** gate with parameters on" -#~ " the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.orz_gate`." +#~ msgid "Quantum circuit data from qiskit." #~ msgstr "" -#~ msgid "" -#~ "Apply **OX** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.ox_gate`." +#~ msgid "Input state of the circuit. Default is None." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 1.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "1.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "A quantum circuit in tensorcircuit" #~ msgstr "" #~ msgid "" -#~ "Apply **OY** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.oy_gate`." +#~ "Translating from the gate name to " +#~ "gate information including the number of" +#~ " control qubits and the reduced gate" +#~ " name." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 0.-1.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+1.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "String of gate name" #~ msgstr "" -#~ msgid "" -#~ "Apply **OZ** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.oz_gate`." +#~ msgid "# of control qubits, reduced gate name" #~ msgstr "" #~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & -1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 1.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ "Generate Tex code from 'qir' string " +#~ "to illustrate the circuit structure. " +#~ "This visualization is based on quantikz" +#~ " package." #~ msgstr "" -#~ msgid "" -#~ "Apply **R** gate with parameters on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.r_gate`." +#~ msgid "The quantum intermediate representation of a circuit in tensorcircuit." #~ msgstr "" -#~ msgid "" -#~ "Apply **RX** gate with parameters on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.rx_gate`." +#~ msgid "Initial state, default is an all zero state '000...000'." #~ msgstr "" -#~ msgid "" -#~ "Apply **RY** gate with parameters on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.ry_gate`." +#~ msgid "Measurement Basis, default is None which means no" #~ msgstr "" #~ msgid "" -#~ "Apply **RZ** gate with parameters on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.gates.rz_gate`." +#~ "measurement in the end of the " +#~ "circuit. :type measure: Optional[List[str]] " +#~ ":param rcompress: If true, a right " +#~ "compression of the circuit will be " +#~ "conducted. A right compression means we" +#~ " will try to shift gates from " +#~ "right to left if possible. Default " +#~ "is false. :type rcompress: bool :param" +#~ " lcompress: If true, a left " +#~ "compression of the circuit will be " +#~ "conducted. A left compression means we" +#~ " will try to shift gates from " +#~ "left to right if possible. Default " +#~ "is false. :type lcompress: bool :param" +#~ " standalone: If true, the tex code" +#~ " will be designed to generate a " +#~ "standalone document. Default is false " +#~ "which means the generated tex code " +#~ "is just a quantikz code block. " +#~ ":type standalone: bool :param " +#~ "return_string_table: If true, a string " +#~ "table of tex code will also be " +#~ "returned. Default is false. :type " +#~ "return_string_table: bool :return: Tex code" +#~ " of circuit visualization based on " +#~ "quantikz package. If return_string_table is" +#~ " true, a string table of tex " +#~ "code will also be returned. :rtype: " +#~ "Union[str, Tuple[str, List[List[str]]]]" #~ msgstr "" -#~ msgid "" -#~ "Apply **S** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.s_gate`." +#~ msgid ":math:`ket`." #~ msgstr "" #~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 0.+1.j " -#~ "\\end{bmatrix}" +#~ "Get Pauli string array and weights " +#~ "array for a qubit Hamiltonian as a" +#~ " sum of Pauli strings defined in " +#~ "openfermion QubitOperator." #~ msgstr "" -#~ msgid "" -#~ "Apply **SD** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.sd_gate`." +#~ msgid "Apply mpo gate in MPO format on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & 0.-1.j " -#~ "\\end{bmatrix}" +#~ msgid "Apply multicontrol gate in MPO format on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Apply **SWAP** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.swap_gate`." +#~ msgid "Returns the amplitude of the circuit given the bitstring l." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j\\\\ " -#~ "0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j \\end{bmatrix}" +#~ msgid "Apply the gate to two bits with given indexes." #~ msgstr "" -#~ msgid "" -#~ "Apply **T** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.t_gate`." +#~ msgid "The Gate applied on bits." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1. &" -#~ " +0.j & 0. & +0.j\\\\ 0. &" -#~ " +0.j & 0.70710677+0.70710677j \\end{bmatrix}" +#~ msgid "The index of the bit to apply the Gate." #~ msgstr "" -#~ msgid "" -#~ "Apply **TD** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.td_gate`." +#~ msgid "Apply the gate to the bit with the given index." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1. &" -#~ " +0.j & 0. & +0.j\\\\ 0. &" -#~ " +0.j & 0.70710677-0.70710677j \\end{bmatrix}" +#~ msgid "The Gate applied on the bit." #~ msgstr "" #~ msgid "" -#~ "Apply **TOFFOLI** gate on the circuit." -#~ " See :py:meth:`tensorcircuit.gates.toffoli_gate`." +#~ "Return the list of nodes that " +#~ "consititues the expectation value just " +#~ "before the contraction." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 1.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 1.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j\\\\" -#~ " 0.+0.j & 0.+0.j & 0.+0.j & " -#~ "1.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j\\\\ 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 0.+0.j & 1.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j\\\\ 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j & 0.+0.j & " -#~ "0.+0.j\\\\ 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 0.+0.j & 0.+0.j &" -#~ " 0.+0.j & 1.+0.j\\\\ 0.+0.j & " -#~ "0.+0.j & 0.+0.j & 0.+0.j & 0.+0.j" -#~ " & 0.+0.j & 1.+0.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "whether contract the output state firstly, defaults to True" #~ msgstr "" -#~ msgid "" -#~ "Apply **WROOT** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.wroot_gate`." +#~ msgid "The tensor network for the expectation" #~ msgstr "" #~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} " -#~ "0.70710677+0.j & -0.5 & -0.5j\\\\ 0.5" -#~ " & -0.5j & 0.70710677+0.j \\end{bmatrix}" +#~ "if true, we sample from the final" +#~ " state if memory allsows, True is " +#~ "prefered, defaults to False" #~ msgstr "" #~ msgid "" -#~ "Apply **X** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.x_gate`." +#~ "List (if batch) of tuple (binary " +#~ "configuration tensor and correponding " +#~ "probability)" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 1.+0.j\\\\ 1.+0.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "Sampling bistrings from the circuit output based on quantum amplitudes." #~ msgstr "" -#~ msgid "" -#~ "Apply **Y** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.y_gate`." +#~ msgid "tensorcircuit.densitymatrix2" #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 0.+0.j " -#~ "& 0.-1.j\\\\ 0.+1.j & 0.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "Apply **CNOT** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Apply **Z** gate on the circuit. " -#~ "See :py:meth:`tensorcircuit.gates.z_gate`." +#~ msgid "Apply **CY** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Qubit number that the gate applies " -#~ "on. The matrix for the gate is" -#~ " .. math:: \\begin{bmatrix} 1.+0.j " -#~ "& 0.+0.j\\\\ 0.+0.j & -1.+0.j " -#~ "\\end{bmatrix}" +#~ msgid "Apply **CZ** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Apply unitary gates in ``kraus`` " -#~ "randomly based on corresponding ``prob``. " -#~ "If ``prob`` is ``None``, this is " -#~ "reduced to kraus channel language." +#~ msgid "Apply **H** gate on the circuit." #~ msgstr "" -#~ msgid "The density matrix simulator based on tensornetwork engine." +#~ msgid "Apply **I** gate on the circuit." #~ msgstr "" -#~ msgid "Number of qubits" +#~ msgid "Apply **S** gate on the circuit." #~ msgstr "" -#~ msgid "if True, nothing initialized, only for internal use, defaults to False" +#~ msgid "Apply **SWAP** gate on the circuit." #~ msgstr "" -#~ msgid "the state input for the circuit, defaults to None" +#~ msgid "Apply **T** gate on the circuit." #~ msgstr "" -#~ msgid "the density matrix input for the circuit, defaults to None" +#~ msgid "Apply **WROOT** gate on the circuit." #~ msgstr "" -#~ msgid "" -#~ "Apply amplitudedamping quantum channel on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.channels.amplitudedampingchannel`" +#~ msgid "Apply **X** gate on the circuit." #~ msgstr "" -#~ msgid "Parameters for the channel." +#~ msgid "Apply **Y** gate on the circuit." #~ msgstr "" -#~ msgid "Return the output density matrix of the circuit." +#~ msgid "Apply **Z** gate on the circuit." #~ msgstr "" #~ msgid "" -#~ "check whether the final return is " -#~ "a legal density matrix, defaults to " -#~ "False" +#~ "Compute :math:`\\prod_{i\\in \\text{index}} s_i`," +#~ " where the probability for each " +#~ "bitstring is given as a vector " +#~ "``results``." #~ msgstr "" -#~ msgid "whether to reuse previous results, defaults to True" +#~ msgid "Generate sparse tensor from Pauli string sum" #~ msgstr "" -#~ msgid "The output densitymatrix in 2D shape tensor form" +#~ msgid "Generate dense matrix from Pauli string sum" #~ msgstr "" -#~ msgid "" -#~ "Apply depolarizing quantum channel on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.channels.depolarizingchannel`" +#~ msgid "Generate Heisenberg Hamiltonian with possible external fields." #~ msgstr "" -#~ msgid "" -#~ "Apply phasedamping quantum channel on " -#~ "the circuit. See " -#~ ":py:meth:`tensorcircuit.channels.phasedampingchannel`" +#~ msgid "calibration qubit list" #~ msgstr "" -#~ msgid "" -#~ "Apply reset quantum channel on the " -#~ "circuit. See " -#~ ":py:meth:`tensorcircuit.channels.resetchannel`" +#~ msgid "tensorcircuit.cloud" #~ msgstr "" -#~ msgid "Generate tensorflow sparse matrix from Pauli string sum" +#~ msgid "tensorcircuit.cloud.config" #~ msgstr "" -#~ msgid "" -#~ "1D Tensor representing for a Pauli " -#~ "string, e.g. [1, 0, 0, 3, 2] " -#~ "is for :math:`X_0Z_3Y_4`" +#~ msgid "gate name list to be counted, defaults to None (counting all gates)" #~ msgstr "" #~ msgid "" -#~ "the weight for the Pauli string " -#~ "defaults to None (all Pauli strings " -#~ "weight 1.0)" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.jax.jax_backend.JaxBackend`, " +#~ ":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" #~ msgstr "" -#~ msgid "the tensorflow sparse matrix" +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.numpy.numpy_backend.NumPyBackend`," +#~ " " +#~ ":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" #~ msgstr "" #~ msgid "" -#~ "2D Tensor, each row is for a " -#~ "Pauli string, e.g. [1, 0, 0, 3," -#~ " 2] is for :math:`X_0Z_3Y_4`" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.pytorch.pytorch_backend.PyTorchBackend`," +#~ " " +#~ ":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" #~ msgstr "" #~ msgid "" -#~ "1D Tensor, each element corresponds the" -#~ " weight for each Pauli string " -#~ "defaults to None (all Pauli strings " -#~ "weight 1.0)" +#~ "Bases: " +#~ ":py:class:`tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend`," +#~ " " +#~ ":py:class:`tensorcircuit.backends.abstract_backend.ExtendedBackend`" #~ msgstr "" -#~ msgid "the tensorflow coo sparse matrix" +#~ msgid "Bases: :py:class:`tensorcircuit.abstractcircuit.AbstractCircuit`" #~ msgstr "" -#~ msgid "Generate scipy sparse matrix from Pauli string sum" +#~ msgid "Return a Depolarizing Channel for 1 qubit or 2 qubits" #~ msgstr "" -#~ msgid "the scipy coo sparse matrix" +#~ msgid "number of qubits, 1 and 2 are avaliable, defaults 1" #~ msgstr "" -#~ msgid "Generate tensorflow dense matrix from Pauli string sum" +#~ msgid "Bases: :py:class:`tensorcircuit.basecircuit.BaseCircuit`" #~ msgstr "" -#~ msgid "the tensorflow dense matrix" +#~ msgid "Bases: :py:class:`torch.nn.modules.module.Module`" #~ msgstr "" #~ msgid "" -#~ "The projector of the operator. The " -#~ "operator, as a linear operator, on " -#~ "the adjoint of the operator." +#~ "This allows better BC support for " +#~ ":meth:`load_state_dict`. In :meth:`state_dict`, the" +#~ " version number will be saved as " +#~ "in the attribute `_metadata` of the " +#~ "returned state dict, and thus pickled." +#~ " `_metadata` is a dictionary with " +#~ "keys that follow the naming convention" +#~ " of state dict. See " +#~ "``_load_from_state_dict`` on how to use " +#~ "this information in loading." #~ msgstr "" #~ msgid "" -#~ "Set :math:`A` is the operator in " -#~ "matrix form, then the projector of " -#~ "operator is defined as: :math:`A^\\dagger " -#~ "A`" +#~ "If new parameters/buffers are added/removed" +#~ " from a module, this number shall " +#~ "be bumped, and the module's " +#~ "`_load_from_state_dict` method can compare the" +#~ " version number and do appropriate " +#~ "changes if the state dict is from" +#~ " before the change." #~ msgstr "" -#~ msgid "The projector of the operator." +#~ msgid "" +#~ "Note that extra state should be " +#~ "pickleable to ensure working serialization " +#~ "of the state_dict. We only provide " +#~ "provide backwards compatibility guarantees for" +#~ " serializing Tensors; other objects may " +#~ "break backwards compatibility if their " +#~ "serialized pickled form changes." #~ msgstr "" -#~ msgid "The reduced density of the operator." +#~ msgid "*(string, torch.Tensor)* -- Tuple containing the name and buffer" #~ msgstr "" -#~ msgid "" -#~ "Set :math:`A` is the matrix of the" -#~ " operator, then the reduced density " -#~ "is defined as:" +#~ msgid "*(string, Module)* -- Tuple containing a name and child module" #~ msgstr "" -#~ msgid "\\mathrm{Tr}_{subsystems}(A^\\dagger A)" +#~ msgid "*(string, Module)* -- Tuple of name and module" #~ msgstr "" - -#~ msgid "" -#~ "Firstly, take the projector of the " -#~ "operator, then trace out the subsystems" -#~ " to trace out are supplied as " -#~ "indices, so that dangling edges are " -#~ "connected to each other as: " -#~ "`out_edges[i] ^ in_edges[i] for i in " -#~ "subsystems_to_trace_out` This does not modify" -#~ " the original network. The original " -#~ "ordering of the remaining subsystems is" -#~ " maintained." + +#~ msgid "*(string, Parameter)* -- Tuple containing the name and parameter" #~ msgstr "" #~ msgid "" -#~ "The QuOperator of the reduced density" -#~ " of the operator with given " -#~ "subsystems." +#~ "The hook will be called every time" +#~ " after :func:`forward` has computed an " +#~ "output. It should have the following " +#~ "signature::" #~ msgstr "" #~ msgid "" -#~ "Contracts the tensor network in place" -#~ " and returns the final tensor in " -#~ "two dimentional matrix. The default " -#~ "ordering for the axes of the final" -#~ " tensor is: (:math:`\\prod` dimension of" -#~ " out_edges, :math:`\\prod` dimension of " -#~ "in_edges)" +#~ "The input contains only the positional" +#~ " arguments given to the module. " +#~ "Keyword arguments won't be passed to " +#~ "the hooks and only to the " +#~ "``forward``. The hook can modify the " +#~ "output. It can modify the input " +#~ "inplace but it will not have " +#~ "effect on forward since this is " +#~ "called after :func:`forward` is called." #~ msgstr "" -#~ msgid "The two-dimentional tensor representing the operator." +#~ msgid "" +#~ "The hook will be called every time" +#~ " before :func:`forward` is invoked. It " +#~ "should have the following signature::" #~ msgstr "" #~ msgid "" -#~ "Returns a bool indicating if QuOperator" -#~ " is an adjoint vector. Examples can" -#~ " be found in the `QuOperator.from_tensor`." +#~ "The input contains only the positional" +#~ " arguments given to the module. " +#~ "Keyword arguments won't be passed to " +#~ "the hooks and only to the " +#~ "``forward``. The hook can modify the " +#~ "input. User can either return a " +#~ "tuple or a single modified value " +#~ "in the hook. We will wrap the " +#~ "value into a tuple if a single " +#~ "value is returned(unless that value is" +#~ " already a tuple)." #~ msgstr "" #~ msgid "" -#~ "Returns a bool indicating if QuOperator" -#~ " is a scalar. Examples can be " -#~ "found in the `QuOperator.from_tensor`." +#~ "The hook will be called every time" +#~ " the gradients with respect to module" +#~ " inputs are computed. The hook should" +#~ " have the following signature::" #~ msgstr "" -#~ msgid "" -#~ "Returns a bool indicating if QuOperator" -#~ " is a vector. Examples can be " -#~ "found in the `QuOperator.from_tensor`." +#~ msgid "Returns a dictionary containing a whole state of the module." #~ msgstr "" #~ msgid "" -#~ "Tensor product with another operator. " -#~ "Given two operators `A` and `B`, " -#~ "produces a new operator `AB` " -#~ "representing :math:`A ⊗ B`. The " -#~ "`out_edges` (`in_edges`) of `AB` is " -#~ "simply the concatenation of the " -#~ "`out_edges` (`in_edges`) of `A.copy()` with" -#~ " that of `B.copy()`: `new_out_edges = " -#~ "[*out_edges_A_copy, *out_edges_B_copy]` `new_in_edges " -#~ "= [*in_edges_A_copy, *in_edges_B_copy]`" +#~ "Visualise the circuit. This method " +#~ "recevies the keywords as same as " +#~ "qiskit.circuit.QuantumCircuit.draw. More details can" +#~ " be found here: " +#~ "https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.draw.html." +#~ msgstr "" + +#~ msgid "the corresponding qubit" +#~ msgstr "" + +#~ msgid "Bases: :py:class:`~keras.engine.training.Model`" #~ msgstr "" #~ msgid "" -#~ "Set :math:`A` is the operator in " -#~ "matrix form, then the projector of " -#~ "operator is defined as: :math:`A " -#~ "A^\\dagger`" +#~ "This method can also be called " +#~ "directly on a Functional Model during" +#~ " construction. In this case, any loss" +#~ " Tensors passed to this Model must" +#~ " be symbolic and be able to be" +#~ " traced back to the model's `Input`s." +#~ " These losses become part of the " +#~ "model's topology and are tracked in " +#~ "`get_config`." #~ msgstr "" -#~ msgid "\\mathrm{Tr}_{subsystems}(A A^\\dagger)" +#~ msgid "" +#~ "Additional keyword arguments for backward " +#~ "compatibility. Accepted values: inputs - " +#~ "Deprecated, will be automatically inferred." #~ msgstr "" -#~ msgid "Compute the double state of the given Hamiltonian operator ``h``." +#~ msgid "" +#~ "Additional keyword arguments for backward " +#~ "compatibility. Accepted values:" #~ msgstr "" -#~ msgid "Hamiltonian operator in form of Tensor." +#~ msgid "inputs - Deprecated, will be automatically inferred." #~ msgstr "" -#~ msgid "The double state of ``h`` with the given ``beta``." +#~ msgid "Deprecated, will be automatically inferred." #~ msgstr "" -#~ msgid "Return fidelity scalar between two states rho and rho0." +#~ msgid "Whether to use `ResourceVariable`." #~ msgstr "" -#~ msgid "\\operatorname{Tr}(\\sqrt{\\sqrt{rho} rho_0 \\sqrt{rho}})" +#~ msgid "" +#~ "When giving unsupported dtype and no " +#~ "initializer or when trainable has " +#~ "been set to True with synchronization" +#~ " set as `ON_READ`." #~ msgstr "" -#~ msgid "The density matrix in form of Tensor." +#~ msgid "This is an alias of `self.__call__`." #~ msgstr "" -#~ msgid "The sqrtm of a Hermitian matrix ``a``." +#~ msgid "Input tensor(s)." #~ msgstr "" -#~ msgid "Compute the Gibbs state of the given Hamiltonian operator ``h``." +#~ msgid "additional positional arguments to be passed to `self.call`." #~ msgstr "" -#~ msgid "The Gibbs state of ``h`` with the given ``beta``." +#~ msgid "additional keyword arguments to be passed to `self.call`." #~ msgstr "" -#~ msgid "Mutual information between AB subsystem described by ``cut``." +#~ msgid "Output tensor(s)." #~ msgstr "" -#~ msgid "The AB subsystem." +#~ msgid "" +#~ "1. In case of invalid user-" +#~ "provided data (not of type tuple," +#~ " list, `TensorShape`, or dict). " +#~ "2. If the model requires call " +#~ "arguments that are agnostic to " +#~ "the input shapes (positional or keyword" +#~ " arg in call signature). 3. If" +#~ " not all layers were properly built." +#~ " 4. If float type inputs are " +#~ "not supported within the layers." #~ msgstr "" -#~ msgid "The mutual information between AB subsystem described by ``cut``." +#~ msgid "" +#~ "In case of invalid user-provided " +#~ "data (not of type tuple, list," +#~ " `TensorShape`, or dict). 2. If " +#~ "the model requires call arguments that" +#~ " are agnostic to the input " +#~ "shapes (positional or keyword arg in " +#~ "call signature). 3. If not all " +#~ "layers were properly built. 4. If" +#~ " float type inputs are not supported" +#~ " within the layers." #~ msgstr "" -#~ msgid "Taylor expansion of :math:`ln(x+1)`." +#~ msgid "" +#~ "A mask or list of masks. A " +#~ "mask can be either a boolean " +#~ "tensor or None (no mask). For more" +#~ " details, check the guide " +#~ "[here](https://www.tensorflow.org/guide/keras/masking_and_padding)." #~ msgstr "" -#~ msgid "The :math:`k` th order, default is 2." +#~ msgid "" +#~ "A mask or list of masks. A " +#~ "mask can be either a boolean " +#~ "tensor or None (no mask). For more" +#~ " details, check the guide" #~ msgstr "" -#~ msgid "The :math:`k` th order of Taylor expansion of :math:`ln(x+1)`." +#~ msgid "" +#~ "Loss function. Maybe be a string " +#~ "(name of loss function), or a " +#~ "`tf.keras.losses.Loss` instance. See " +#~ "`tf.keras.losses`. A loss function is " +#~ "any callable with the signature `loss" +#~ " = fn(y_true, y_pred)`, where `y_true` " +#~ "are the ground truth values, and " +#~ "`y_pred` are the model's predictions. " +#~ "`y_true` should have shape `(batch_size, " +#~ "d0, .. dN)` (except in the case" +#~ " of sparse loss functions such as " +#~ "sparse categorical crossentropy which expects" +#~ " integer arrays of shape `(batch_size, " +#~ "d0, .. dN-1)`). `y_pred` should have " +#~ "shape `(batch_size, d0, .. dN)`. The " +#~ "loss function should return a float " +#~ "tensor. If a custom `Loss` instance " +#~ "is used and reduction is set to" +#~ " `None`, return value has shape " +#~ "`(batch_size, d0, .. dN-1)` i.e. per-" +#~ "sample or per-timestep loss values; " +#~ "otherwise, it is a scalar. If the" +#~ " model has multiple outputs, you can" +#~ " use a different loss on each " +#~ "output by passing a dictionary or " +#~ "a list of losses. The loss value" +#~ " that will be minimized by the " +#~ "model will then be the sum of " +#~ "all individual losses, unless `loss_weights`" +#~ " is specified." #~ msgstr "" #~ msgid "" -#~ "Compute the trace distance between two" -#~ " density matrix ``rho`` and ``rho2``." +#~ "List of metrics to be evaluated by" +#~ " the model during training and " +#~ "testing. Each of this can be a " +#~ "string (name of a built-in " +#~ "function), function or a " +#~ "`tf.keras.metrics.Metric` instance. See " +#~ "`tf.keras.metrics`. Typically you will use " +#~ "`metrics=['accuracy']`. A function is any " +#~ "callable with the signature `result =" +#~ " fn(y_true, y_pred)`. To specify different" +#~ " metrics for different outputs of a" +#~ " multi-output model, you could also" +#~ " pass a dictionary, such as " +#~ "`metrics={'output_a': 'accuracy', 'output_b': " +#~ "['accuracy', 'mse']}`. You can also pass" +#~ " a list to specify a metric or" +#~ " a list of metrics for each " +#~ "output, such as `metrics=[['accuracy'], " +#~ "['accuracy', 'mse']]` or `metrics=['accuracy', " +#~ "['accuracy', 'mse']]`. When you pass the" +#~ " strings 'accuracy' or 'acc', we " +#~ "convert this to one of " +#~ "`tf.keras.metrics.BinaryAccuracy`, " +#~ "`tf.keras.metrics.CategoricalAccuracy`, " +#~ "`tf.keras.metrics.SparseCategoricalAccuracy` based on " +#~ "the loss function used and the " +#~ "model output shape. We do a " +#~ "similar conversion for the strings " +#~ "'crossentropy' and 'ce' as well." +#~ msgstr "" + +#~ msgid "" +#~ "Optional list or dictionary specifying " +#~ "scalar coefficients (Python floats) to " +#~ "weight the loss contributions of " +#~ "different model outputs. The loss value" +#~ " that will be minimized by the " +#~ "model will then be the *weighted " +#~ "sum* of all individual losses, weighted" +#~ " by the `loss_weights` coefficients. If" +#~ " a list, it is expected to have" +#~ " a 1:1 mapping to the model's " +#~ "outputs. If a dict, it is expected" +#~ " to map output names (strings) to" +#~ " scalar coefficients." +#~ msgstr "" + +#~ msgid "" +#~ "Optional list or dictionary specifying " +#~ "scalar coefficients (Python floats) to " +#~ "weight the loss contributions of " +#~ "different model outputs. The loss value" +#~ " that will be minimized by the " +#~ "model will then be the *weighted " +#~ "sum* of all individual losses, weighted" +#~ " by the `loss_weights` coefficients." +#~ msgstr "" + +#~ msgid "If a list, it is expected to have a 1:1 mapping to the model's" +#~ msgstr "" + +#~ msgid "" +#~ "outputs. If a dict, it is expected" +#~ " to map output names (strings) to " +#~ "scalar coefficients." +#~ msgstr "" + +#~ msgid "" +#~ "Bool. Defaults to `False`. If `True`," +#~ " this `Model`'s logic will not be " +#~ "wrapped in a `tf.function`. Recommended " +#~ "to leave this as `None` unless " +#~ "your `Model` cannot be run inside " +#~ "a `tf.function`. `run_eagerly=True` is not " +#~ "supported when using " +#~ "`tf.distribute.experimental.ParameterServerStrategy`." +#~ msgstr "" + +#~ msgid "" +#~ "Int. Defaults to 1. The number of" +#~ " batches to run during each " +#~ "`tf.function` call. Running multiple batches" +#~ " inside a single `tf.function` call " +#~ "can greatly improve performance on TPUs" +#~ " or small models with a large " +#~ "Python overhead. At most, one full " +#~ "epoch will be run each execution. " +#~ "If a number larger than the size" +#~ " of the epoch is passed, the " +#~ "execution will be truncated to the " +#~ "size of the epoch. Note that if" +#~ " `steps_per_execution` is set to `N`, " +#~ "`Callback.on_batch_begin` and `Callback.on_batch_end` " +#~ "methods will only be called every " +#~ "`N` batches (i.e. before/after each " +#~ "`tf.function` execution)." #~ msgstr "" -#~ msgid "Epsilon, defaults to 1e-12" +#~ msgid "" +#~ "If the layer has not been built," +#~ " this method will call `build` on " +#~ "the layer. This assumes that the " +#~ "layer will later be used with " +#~ "inputs that match the input shape " +#~ "provided here." #~ msgstr "" -#~ msgid "The trace distance between two density matrix ``rho`` and ``rho2``." +#~ msgid "" +#~ "Shape tuple (tuple of integers) or " +#~ "list of shape tuples (one per " +#~ "output tensor of the layer). Shape " +#~ "tuples can include None for free " +#~ "dimensions, instead of an integer." #~ msgstr "" -#~ msgid "\\operatorname{Tr}(\\prod_i O_i)" +#~ msgid "An input shape tuple." #~ msgstr "" #~ msgid "" -#~ "Compute the truncated free energy from" -#~ " the given density matrix ``rho``." +#~ "Single TensorSpec or nested structure of" +#~ " TensorSpec objects, describing how the" +#~ " layer would transform the provided " +#~ "input." #~ msgstr "" -#~ msgid "The :math:`k` th order, defaults to 2" +#~ msgid "Single TensorSpec or nested structure of TensorSpec objects, describing" #~ msgstr "" -#~ msgid "The :math:`k` th order of the truncated free energy." +#~ msgid "how the layer would transform the provided input." #~ msgstr "" #~ msgid "" -#~ "The circuit ansatz is firstly one " -#~ "layer of Hadamard gates and then " -#~ "we have ``nlayers`` blocks of " -#~ ":math:`e^{i\\theta Z_iZ_{i+1}}` two-qubit gate" -#~ " in ladder layout, following rx gate." +#~ "Input data. It could be: - A " +#~ "Numpy array (or array-like), or a" +#~ " list of arrays (in case the " +#~ "model has multiple inputs). - A " +#~ "TensorFlow tensor, or a list of " +#~ "tensors (in case the model has " +#~ "multiple inputs). - A dict mapping " +#~ "input names to the corresponding " +#~ "array/tensors, if the model has named" +#~ " inputs. - A `tf.data` dataset. " +#~ "Should return a tuple of either " +#~ "`(inputs, targets)` or `(inputs, targets," +#~ " sample_weights)`. - A generator or " +#~ "`keras.utils.Sequence` returning `(inputs, targets)`" +#~ " or `(inputs, targets, sample_weights)`. " +#~ "A more detailed description of unpacking" +#~ " behavior for iterator types (Dataset, " +#~ "generator, Sequence) is given in the " +#~ "`Unpacking behavior for iterator-like " +#~ "inputs` section of `Model.fit`." #~ msgstr "" -#~ msgid "The circuit" +#~ msgid "0 or 1. Verbosity mode. 0 = silent, 1 = progress bar." #~ msgstr "" -#~ msgid "paramter tensor with 2*nlayer*n elements" +#~ msgid "" +#~ "Optional Numpy array of weights for " +#~ "the test samples, used for weighting " +#~ "the loss function. You can either " +#~ "pass a flat (1D) Numpy array with" +#~ " the same length as the input " +#~ "samples (1:1 mapping between weights " +#~ "and samples), or in the case of" +#~ " temporal data, you can pass a" +#~ " 2D array with shape `(samples, " +#~ "sequence_length)`, to apply a different " +#~ "weight to every timestep of every" +#~ " sample. This argument is not " +#~ "supported when `x` is a dataset, " +#~ "instead pass sample weights as the " +#~ "third element of `x`." #~ msgstr "" -#~ msgid "number of ZZ+RX blocks, defaults to 2" -#~ msgstr "" +#~ msgid "" +#~ "List of `keras.callbacks.Callback` instances. " +#~ "List of callbacks to apply during " +#~ "evaluation. See " +#~ "[callbacks](/api_docs/python/tf/keras/callbacks)." +#~ msgstr "" + +#~ msgid "" +#~ "`Model.evaluate` is not yet supported " +#~ "with `tf.distribute.experimental.ParameterServerStrategy`." +#~ msgstr "" #~ msgid "" -#~ "whether use SVD split to reduce ZZ" -#~ " gate bond dimension, defaults to " -#~ "False" +#~ "Trains the model for a fixed " +#~ "number of epochs (iterations on a " +#~ "dataset)." #~ msgstr "" -#~ msgid "The circuit with example ansatz attached" +#~ msgid "" +#~ "Input data. It could be: - A " +#~ "Numpy array (or array-like), or a" +#~ " list of arrays (in case the " +#~ "model has multiple inputs). - A " +#~ "TensorFlow tensor, or a list of " +#~ "tensors (in case the model has " +#~ "multiple inputs). - A dict mapping " +#~ "input names to the corresponding " +#~ "array/tensors, if the model has named" +#~ " inputs. - A `tf.data` dataset. " +#~ "Should return a tuple of either " +#~ "`(inputs, targets)` or `(inputs, targets," +#~ " sample_weights)`. - A generator or " +#~ "`keras.utils.Sequence` returning `(inputs, targets)`" +#~ " or `(inputs, targets, sample_weights)`. " +#~ "- A `tf.keras.utils.experimental.DatasetCreator`, " +#~ "which wraps a callable that takes " +#~ "a single argument of type " +#~ "`tf.distribute.InputContext`, and returns a " +#~ "`tf.data.Dataset`. `DatasetCreator` should be " +#~ "used when users prefer to specify " +#~ "the per-replica batching and sharding" +#~ " logic for the `Dataset`. See " +#~ "`tf.keras.utils.experimental.DatasetCreator` doc for " +#~ "more information. A more detailed " +#~ "description of unpacking behavior for " +#~ "iterator types (Dataset, generator, Sequence)" +#~ " is given below. If using " +#~ "`tf.distribute.experimental.ParameterServerStrategy`, only " +#~ "`DatasetCreator` type is supported for " +#~ "`x`." +#~ msgstr "" + +#~ msgid "" +#~ "A more detailed description of unpacking" +#~ " behavior for iterator types (Dataset, " +#~ "generator, Sequence) is given below. If" +#~ " using `tf.distribute.experimental.ParameterServerStrategy`," +#~ " only `DatasetCreator` type is supported" +#~ " for `x`." +#~ msgstr "" + +#~ msgid "" +#~ "'auto', 0, 1, or 2. Verbosity " +#~ "mode. 0 = silent, 1 = progress " +#~ "bar, 2 = one line per epoch. " +#~ "'auto' defaults to 1 for most " +#~ "cases, but 2 when used with " +#~ "`ParameterServerStrategy`. Note that the " +#~ "progress bar is not particularly useful" +#~ " when logged to a file, so " +#~ "verbose=2 is recommended when not " +#~ "running interactively (eg, in a " +#~ "production environment)." +#~ msgstr "" + +#~ msgid "" +#~ "Float between 0 and 1. Fraction " +#~ "of the training data to be used" +#~ " as validation data. The model will" +#~ " set apart this fraction of the " +#~ "training data, will not train on " +#~ "it, and will evaluate the loss " +#~ "and any model metrics on this " +#~ "data at the end of each epoch." +#~ " The validation data is selected " +#~ "from the last samples in the `x`" +#~ " and `y` data provided, before " +#~ "shuffling. This argument is not " +#~ "supported when `x` is a dataset, " +#~ "generator or `keras.utils.Sequence` instance. " +#~ "`validation_split` is not yet supported " +#~ "with `tf.distribute.experimental.ParameterServerStrategy`." +#~ msgstr "" + +#~ msgid "Float between 0 and 1." +#~ msgstr "" + +#~ msgid "" +#~ "Fraction of the training data to " +#~ "be used as validation data. The " +#~ "model will set apart this fraction " +#~ "of the training data, will not " +#~ "train on it, and will evaluate the" +#~ " loss and any model metrics on " +#~ "this data at the end of each " +#~ "epoch. The validation data is selected" +#~ " from the last samples in the " +#~ "`x` and `y` data provided, before " +#~ "shuffling. This argument is not " +#~ "supported when `x` is a dataset, " +#~ "generator or" +#~ msgstr "" + +#~ msgid "`keras.utils.Sequence` instance." +#~ msgstr "" + +#~ msgid "" +#~ "`validation_split` is not yet supported " +#~ "with `tf.distribute.experimental.ParameterServerStrategy`." +#~ msgstr "" + +#~ msgid "" +#~ "Data on which to evaluate the loss" +#~ " and any model metrics at the " +#~ "end of each epoch. The model will" +#~ " not be trained on this data. " +#~ "Thus, note the fact that the " +#~ "validation loss of data provided using" +#~ " `validation_split` or `validation_data` is " +#~ "not affected by regularization layers " +#~ "like noise and dropout. `validation_data` " +#~ "will override `validation_split`. `validation_data`" +#~ " could be: - A tuple `(x_val, " +#~ "y_val)` of Numpy arrays or tensors." +#~ " - A tuple `(x_val, y_val, " +#~ "val_sample_weights)` of NumPy arrays. - " +#~ "A `tf.data.Dataset`. - A Python " +#~ "generator or `keras.utils.Sequence` returning " +#~ "`(inputs, targets)` or `(inputs, targets, " +#~ "sample_weights)`. `validation_data` is not yet" +#~ " supported with " +#~ "`tf.distribute.experimental.ParameterServerStrategy`." +#~ msgstr "" + +#~ msgid "" +#~ "Optional dictionary mapping class indices " +#~ "(integers) to a weight (float) value," +#~ " used for weighting the loss function" +#~ " (during training only). This can be" +#~ " useful to tell the model to " +#~ "\"pay more attention\" to samples from" +#~ " an under-represented class." +#~ msgstr "" + +#~ msgid "" +#~ "Optional Numpy array of weights for " +#~ "the training samples, used for weighting" +#~ " the loss function (during training " +#~ "only). You can either pass a flat" +#~ " (1D) Numpy array with the same " +#~ "length as the input samples (1:1 " +#~ "mapping between weights and samples), " +#~ "or in the case of temporal data," +#~ " you can pass a 2D array with" +#~ " shape `(samples, sequence_length)`, to " +#~ "apply a different weight to every " +#~ "timestep of every sample. This argument" +#~ " is not supported when `x` is a" +#~ " dataset, generator, or `keras.utils.Sequence`" +#~ " instance, instead provide the " +#~ "sample_weights as the third element of" +#~ " `x`." +#~ msgstr "" + +#~ msgid "Optional Numpy array of weights for" +#~ msgstr "" + +#~ msgid "" +#~ "the training samples, used for weighting" +#~ " the loss function (during training " +#~ "only). You can either pass a flat" +#~ " (1D) Numpy array with the same " +#~ "length as the input samples (1:1 " +#~ "mapping between weights and samples), or" +#~ " in the case of temporal data, " +#~ "you can pass a 2D array with " +#~ "shape `(samples, sequence_length)`, to apply" +#~ " a different weight to every timestep" +#~ " of every sample. This argument is" +#~ " not supported when `x` is a " +#~ "dataset, generator, or" +#~ msgstr "" + +#~ msgid "`keras.utils.Sequence` instance, instead provide the sample_weights" +#~ msgstr "" + +#~ msgid "as the third element of `x`." +#~ msgstr "" + +#~ msgid "" +#~ "Integer or `None`. Total number of " +#~ "steps (batches of samples) before " +#~ "declaring one epoch finished and " +#~ "starting the next epoch. When training" +#~ " with input tensors such as " +#~ "TensorFlow data tensors, the default " +#~ "`None` is equal to the number of" +#~ " samples in your dataset divided by" +#~ " the batch size, or 1 if that" +#~ " cannot be determined. If x is " +#~ "a `tf.data` dataset, and 'steps_per_epoch' " +#~ "is None, the epoch will run until" +#~ " the input dataset is exhausted. When" +#~ " passing an infinitely repeating dataset," +#~ " you must specify the `steps_per_epoch` " +#~ "argument. If `steps_per_epoch=-1` the training" +#~ " will run indefinitely with an " +#~ "infinitely repeating dataset. This argument" +#~ " is not supported with array inputs." +#~ " When using " +#~ "`tf.distribute.experimental.ParameterServerStrategy`: * " +#~ "`steps_per_epoch=None` is not supported." #~ msgstr "" #~ msgid "" -#~ "Function decorator wraps the function " -#~ "with the first input and output in" -#~ " the format of circuit, the wrapped" -#~ " function has the first input and " -#~ "the output as the state tensor." +#~ "Integer or `None`. Total number of " +#~ "steps (batches of samples) before " +#~ "declaring one epoch finished and " +#~ "starting the next epoch. When training" +#~ " with input tensors such as " +#~ "TensorFlow data tensors, the default " +#~ "`None` is equal to the number of" +#~ " samples in your dataset divided by" +#~ " the batch size, or 1 if that" +#~ " cannot be determined. If x is " +#~ "a `tf.data` dataset, and 'steps_per_epoch' " +#~ "is None, the epoch will run until" +#~ " the input dataset is exhausted. When" +#~ " passing an infinitely repeating dataset," +#~ " you must specify the `steps_per_epoch` " +#~ "argument. If `steps_per_epoch=-1` the training" +#~ " will run indefinitely with an " +#~ "infinitely repeating dataset. This argument" +#~ " is not supported with array inputs." +#~ " When using " +#~ "`tf.distribute.experimental.ParameterServerStrategy`:" #~ msgstr "" -#~ msgid "Function with the fist input and the output as ``Circuit`` object." +#~ msgid "" +#~ "Only relevant if validation data is " +#~ "provided. Integer or `collections.abc.Container` " +#~ "instance (e.g. list, tuple, etc.). If" +#~ " an integer, specifies how many " +#~ "training epochs to run before a " +#~ "new validation run is performed, e.g." +#~ " `validation_freq=2` runs validation every " +#~ "2 epochs. If a Container, specifies " +#~ "the epochs on which to run " +#~ "validation, e.g. `validation_freq=[1, 2, 10]`" +#~ " runs validation at the end of " +#~ "the 1st, 2nd, and 10th epochs." #~ msgstr "" #~ msgid "" -#~ "Wrapped function with the first input" -#~ " and the output as the state " -#~ "tensor correspondingly." +#~ "tf.keras.utils.Sequence to the `x` argument" +#~ " of fit, which will in fact " +#~ "yield not only features (x) but " +#~ "optionally targets (y) and sample " +#~ "weights. Keras requires that the output" +#~ " of such iterator-likes be " +#~ "unambiguous. The iterator should return " +#~ "a tuple of length 1, 2, or " +#~ "3, where the optional second and " +#~ "third elements will be used for y" +#~ " and sample_weight respectively. Any other" +#~ " type provided will be wrapped in " +#~ "a length one tuple, effectively treating" +#~ " everything as 'x'. When yielding " +#~ "dicts, they should still adhere to " +#~ "the top-level tuple structure. e.g. " +#~ "`({\"x0\": x0, \"x1\": x1}, y)`. Keras" +#~ " will not attempt to separate " +#~ "features, targets, and weights from the" +#~ " keys of a single dict." #~ msgstr "" -#~ msgid "Two-dimensional grid lattice" +#~ msgid "A notable unsupported data type is the namedtuple. The reason is that" #~ msgstr "" -#~ msgid "number of rows" +#~ msgid "" +#~ "it behaves like both an ordered " +#~ "datatype (tuple) and a mapping datatype" +#~ " (dict). So given a namedtuple of " +#~ "the form:" #~ msgstr "" -#~ msgid "number of cols" +#~ msgid "Retrieves losses relevant to a specific set of inputs." #~ msgstr "" -#~ msgid "return all col edge with 1d index encoding" +#~ msgid "Input tensor or list/tuple of input tensors." #~ msgstr "" -#~ msgid "" -#~ "whether to include pbc edges (periodic" -#~ " boundary condition), defaults to False" +#~ msgid "List of loss tensors of the layer that depend on `inputs`." #~ msgstr "" -#~ msgid "list of col edge" +#~ msgid "Retrieves updates relevant to a specific set of inputs." #~ msgstr "" -#~ msgid "return all row edge with 1d index encoding" +#~ msgid "List of update ops of the layer that depend on `inputs`." #~ msgstr "" -#~ msgid "list of row edge" +#~ msgid "Deprecated, do NOT use! Only for compatibility with external Keras." #~ msgstr "" -#~ msgid "Get the 2D grid lattice in ``nx.Graph`` format" +#~ msgid "" +#~ "Loads all layer weights, either from " +#~ "a TensorFlow or an HDF5 weight " +#~ "file." #~ msgstr "" #~ msgid "" -#~ "whether to include pbc edges (periodic" -#~ " boundary condition), defaults to True" +#~ "If `by_name` is False weights are " +#~ "loaded based on the network's topology." +#~ " This means the architecture should " +#~ "be the same as when the weights" +#~ " were saved. Note that layers that" +#~ " don't have weights are not taken " +#~ "into account in the topological " +#~ "ordering, so adding or removing layers" +#~ " is fine as long as they don't" +#~ " have weights." #~ msgstr "" #~ msgid "" -#~ "Generate a permutation matrix P. Due " -#~ "to the different convention or qubits'" -#~ " order in qiskit and tensorcircuit, " -#~ "the unitary represented by the same " -#~ "circuit is different. They are related" -#~ " by this permutation matrix P: P " -#~ "@ U_qiskit @ P = U_tc" +#~ "If `by_name` is True, weights are " +#~ "loaded into layers only if they " +#~ "share the same name. This is " +#~ "useful for fine-tuning or transfer-" +#~ "learning models where some of the " +#~ "layers have changed." #~ msgstr "" -#~ msgid "# of qubits" +#~ msgid "" +#~ "Only topological loading (`by_name=False`) is" +#~ " supported when loading weights from " +#~ "the TensorFlow format. Note that " +#~ "topological loading differs slightly between" +#~ " TensorFlow and HDF5 formats for " +#~ "user-defined classes inheriting from " +#~ "`tf.keras.Model`: HDF5 loads based on a" +#~ " flattened list of weights, while the" +#~ " TensorFlow format loads based on the" +#~ " object-local names of attributes to" +#~ " which layers are assigned in the " +#~ "`Model`'s constructor." #~ msgstr "" -#~ msgid "The permutation matrix P" +#~ msgid "" +#~ "String, path to the weights file " +#~ "to load. For weight files in " +#~ "TensorFlow format, this is the file " +#~ "prefix (the same as was passed to" +#~ " `save_weights`). This can also be a" +#~ " path to a SavedModel saved from " +#~ "`model.save`." #~ msgstr "" #~ msgid "" -#~ "Generate a qiskit quantum circuit using" -#~ " the quantum intermediate representation " -#~ "(qir) in tensorcircuit." +#~ "Boolean, whether to load weights by " +#~ "name or by topological order. Only " +#~ "topological loading is supported for " +#~ "weight files in TensorFlow format." #~ msgstr "" -#~ msgid "qiskit QuantumCircuit object" +#~ msgid "" +#~ "Boolean, whether to skip loading of " +#~ "layers where there is a mismatch " +#~ "in the number of weights, or a " +#~ "mismatch in the shape of the " +#~ "weight (only valid when `by_name=True`)." #~ msgstr "" #~ msgid "" -#~ "Generate a tensorcircuit circuit using " -#~ "the quantum circuit data in qiskit." +#~ "Optional `tf.train.CheckpointOptions` object that" +#~ " specifies options for loading weights." #~ msgstr "" -#~ msgid "Quantum circuit data from qiskit." +#~ msgid "" +#~ "When loading a weight file in " +#~ "TensorFlow format, returns the same " +#~ "status object as `tf.train.Checkpoint.restore`. " +#~ "When graph building, restore ops are " +#~ "run automatically as soon as the " +#~ "network is built (on first call " +#~ "for user-defined classes inheriting from" +#~ " `Model`, immediately if it is " +#~ "already built). When loading weights in" +#~ " HDF5 format, returns `None`." #~ msgstr "" -#~ msgid "Input state of the circuit. Default is None." +#~ msgid "" +#~ "When loading a weight file in " +#~ "TensorFlow format, returns the same " +#~ "status object as `tf.train.Checkpoint.restore`. " +#~ "When graph building, restore ops are " +#~ "run automatically as soon as the " +#~ "network is built (on first call " +#~ "for user-defined classes inheriting from" +#~ " `Model`, immediately if it is " +#~ "already built)." #~ msgstr "" -#~ msgid "A quantum circuit in tensorcircuit" +#~ msgid "When loading weights in HDF5 format, returns `None`." #~ msgstr "" -#~ msgid "" -#~ "Translating from the gate name to " -#~ "gate information including the number of" -#~ " control qubits and the reduced gate" -#~ " name." +#~ msgid "If `h5py` is not available and the weight file is in HDF5 format." #~ msgstr "" -#~ msgid "String of gate name" +#~ msgid "If `skip_mismatch` is set to `True` when `by_name` is `False`." #~ msgstr "" -#~ msgid "# of control qubits, reduced gate name" +#~ msgid "" +#~ "Returns the model's metrics added using" +#~ " `compile()`, `add_metric()` APIs." #~ msgstr "" #~ msgid "" -#~ "Generate Tex code from 'qir' string " -#~ "to illustrate the circuit structure. " -#~ "This visualization is based on quantikz" -#~ " package." +#~ "Computation is done in batches. This " +#~ "method is designed for performance in" +#~ " large scale inputs. For small amount" +#~ " of inputs that fit in one " +#~ "batch, directly using `__call__()` is " +#~ "recommended for faster execution, e.g., " +#~ "`model(x)`, or `model(x, training=False)` if" +#~ " you have layers such as " +#~ "`tf.keras.layers.BatchNormalization` that behaves " +#~ "differently during inference. Also, note " +#~ "the fact that test loss is not " +#~ "affected by regularization layers like " +#~ "noise and dropout." #~ msgstr "" -#~ msgid "The quantum intermediate representation of a circuit in tensorcircuit." +#~ msgid "Verbosity mode, 0 or 1." #~ msgstr "" -#~ msgid "Initial state, default is an all zero state '000...000'." +#~ msgid "" +#~ "List of `keras.callbacks.Callback` instances. " +#~ "List of callbacks to apply during " +#~ "prediction. See " +#~ "[callbacks](/api_docs/python/tf/keras/callbacks)." #~ msgstr "" -#~ msgid "Measurement Basis, default is None which means no" +#~ msgid "If `model.predict_on_batch` is wrapped in a `tf.function`." #~ msgstr "" #~ msgid "" -#~ "measurement in the end of the " -#~ "circuit. :type measure: Optional[List[str]] " -#~ ":param rcompress: If true, a right " -#~ "compression of the circuit will be " -#~ "conducted. A right compression means we" -#~ " will try to shift gates from " -#~ "right to left if possible. Default " -#~ "is false. :type rcompress: bool :param" -#~ " lcompress: If true, a left " -#~ "compression of the circuit will be " -#~ "conducted. A left compression means we" -#~ " will try to shift gates from " -#~ "left to right if possible. Default " -#~ "is false. :type lcompress: bool :param" -#~ " standalone: If true, the tex code" -#~ " will be designed to generate a " -#~ "standalone document. Default is false " -#~ "which means the generated tex code " -#~ "is just a quantikz code block. " -#~ ":type standalone: bool :param " -#~ "return_string_table: If true, a string " -#~ "table of tex code will also be " -#~ "returned. Default is false. :type " -#~ "return_string_table: bool :return: Tex code" -#~ " of circuit visualization based on " -#~ "quantikz package. If return_string_table is" -#~ " true, a string table of tex " -#~ "code will also be returned. :rtype: " -#~ "Union[str, Tuple[str, List[List[str]]]]" +#~ "This method should contain the " +#~ "mathematical logic for one step of " +#~ "inference. This typically includes the " +#~ "forward pass." #~ msgstr "" -#~ msgid ":math:`ket`." +#~ msgid "Saves the model to Tensorflow SavedModel or a single HDF5 file." #~ msgstr "" #~ msgid "" -#~ "Get Pauli string array and weights " -#~ "array for a qubit Hamiltonian as a" -#~ " sum of Pauli strings defined in " -#~ "openfermion QubitOperator." +#~ "Please see `tf.keras.models.save_model` or the" +#~ " [Serialization and Saving " +#~ "guide](https://keras.io/guides/serialization_and_saving/) for" +#~ " details." #~ msgstr "" -#~ msgid "Apply mpo gate in MPO format on the circuit." +#~ msgid "String, PathLike, path to SavedModel or H5 file to save the model." #~ msgstr "" -#~ msgid "Apply multicontrol gate in MPO format on the circuit." +#~ msgid "If True, save optimizer's state together." #~ msgstr "" -#~ msgid "Returns the amplitude of the circuit given the bitstring l." +#~ msgid "" +#~ "Either `'tf'` or `'h5'`, indicating " +#~ "whether to save the model to " +#~ "Tensorflow SavedModel or HDF5. Defaults " +#~ "to 'tf' in TF 2.X, and 'h5' " +#~ "in TF 1.X." #~ msgstr "" -#~ msgid "Apply the gate to two bits with given indexes." +#~ msgid "" +#~ "Signatures to save with the SavedModel." +#~ " Applicable to the 'tf' format only." +#~ " Please see the `signatures` argument " +#~ "in `tf.saved_model.save` for details." #~ msgstr "" -#~ msgid "The Gate applied on bits." +#~ msgid "" +#~ "(only applies to SavedModel format) " +#~ "`tf.saved_model.SaveOptions` object that specifies" +#~ " options for saving to SavedModel." #~ msgstr "" -#~ msgid "The index of the bit to apply the Gate." +#~ msgid "" +#~ "(only applies to SavedModel format) When" +#~ " enabled, the SavedModel will store " +#~ "the function traces for each layer. " +#~ "This can be disabled, so that only" +#~ " the configs of each layer are " +#~ "stored. Defaults to `True`. Disabling " +#~ "this will decrease serialization time " +#~ "and reduce file size, but it " +#~ "requires that all custom layers/models " +#~ "implement a `get_config()` method." #~ msgstr "" -#~ msgid "Apply the gate to the bit with the given index." +#~ msgid "```python from keras.models import load_model" #~ msgstr "" -#~ msgid "The Gate applied on the bit." +#~ msgid "" +#~ "model.save('my_model.h5') # creates a HDF5" +#~ " file 'my_model.h5' del model # " +#~ "deletes the existing model" #~ msgstr "" #~ msgid "" -#~ "Return the list of nodes that " -#~ "consititues the expectation value just " -#~ "before the contraction." +#~ "# returns a compiled model # " +#~ "identical to the previous one model " +#~ "= load_model('my_model.h5') ```" #~ msgstr "" -#~ msgid "whether contract the output state firstly, defaults to True" +#~ msgid "Returns the `tf.TensorSpec` of call inputs as a tuple `(args, kwargs)`." #~ msgstr "" -#~ msgid "The tensor network for the expectation" +#~ msgid "" +#~ "# arg_specs is `[tf.TensorSpec(...), ...]`." +#~ " kwarg_specs, in this example, is #" +#~ " an empty dict since functional " +#~ "models do not use keyword arguments. " +#~ "arg_specs, kwarg_specs = model.save_spec()" #~ msgstr "" #~ msgid "" -#~ "if true, we sample from the final" -#~ " state if memory allsows, True is " -#~ "prefered, defaults to False" +#~ "'serving_default': serve.get_concrete_function(*arg_specs, " +#~ "**kwarg_specs)" #~ msgstr "" #~ msgid "" -#~ "List (if batch) of tuple (binary " -#~ "configuration tensor and correponding " -#~ "probability)" +#~ "The TensorFlow format matches objects " +#~ "and variables by starting at a " +#~ "root object, `self` for `save_weights`, " +#~ "and greedily matching attribute names. " +#~ "For `Model.save` this is the `Model`," +#~ " and for `Checkpoint.save` this is " +#~ "the `Checkpoint` even if the " +#~ "`Checkpoint` has a model attached. This" +#~ " means saving a `tf.keras.Model` using " +#~ "`save_weights` and loading into a " +#~ "`tf.train.Checkpoint` with a `Model` attached" +#~ " (or vice versa) will not match " +#~ "the `Model`'s variables. See the [guide" +#~ " to training " +#~ "checkpoints](https://www.tensorflow.org/guide/checkpoint) for" +#~ " details on the TensorFlow format." #~ msgstr "" -#~ msgid "Sampling bistrings from the circuit output based on quantum amplitudes." +#~ msgid "" +#~ "Either 'tf' or 'h5'. A `filepath` " +#~ "ending in '.h5' or '.keras' will " +#~ "default to HDF5 if `save_format` is " +#~ "`None`. Otherwise `None` defaults to " +#~ "'tf'." #~ msgstr "" -#~ msgid "tensorcircuit.densitymatrix2" +#~ msgid "If `h5py` is not available when attempting to save in HDF5 format." #~ msgstr "" -#~ msgid "Apply **CNOT** gate on the circuit." +#~ msgid "" +#~ "Relative or absolute positions of log" +#~ " elements in each line. If not " +#~ "provided, defaults to `[.33, .55, .67," +#~ " 1.]`." #~ msgstr "" -#~ msgid "Apply **CY** gate on the circuit." +#~ msgid "" +#~ "Print function to use. Defaults to " +#~ "`print`. It will be called on each" +#~ " line of the summary. You can " +#~ "set it to a custom function in " +#~ "order to capture the string summary." #~ msgstr "" -#~ msgid "Apply **CZ** gate on the circuit." +#~ msgid "" +#~ "Whether to expand the nested models. " +#~ "If not provided, defaults to `False`." #~ msgstr "" -#~ msgid "Apply **H** gate on the circuit." +#~ msgid "" +#~ "Input data. It could be: - A " +#~ "Numpy array (or array-like), or a" +#~ " list of arrays (in case the " +#~ "model has multiple inputs). - A " +#~ "TensorFlow tensor, or a list of " +#~ "tensors (in case the model has " +#~ "multiple inputs). - A dict mapping " +#~ "input names to the corresponding " +#~ "array/tensors, if the model has " +#~ "named inputs." #~ msgstr "" -#~ msgid "Apply **I** gate on the circuit." +#~ msgid "A dict mapping input names to the corresponding array/tensors, if" #~ msgstr "" -#~ msgid "Apply **S** gate on the circuit." +#~ msgid "the model has named inputs." #~ msgstr "" -#~ msgid "Apply **SWAP** gate on the circuit." +#~ msgid "If `model.test_on_batch` is wrapped in a `tf.function`." #~ msgstr "" -#~ msgid "Apply **T** gate on the circuit." +#~ msgid "Additional keyword arguments to be passed to `json.dumps()`." #~ msgstr "" -#~ msgid "Apply **WROOT** gate on the circuit." +#~ msgid "" +#~ "Optional dictionary mapping class indices " +#~ "(integers) to a weight (float) to " +#~ "apply to the model's loss for the" +#~ " samples from this class during " +#~ "training. This can be useful to " +#~ "tell the model to \"pay more " +#~ "attention\" to samples from an under-" +#~ "represented class." #~ msgstr "" -#~ msgid "Apply **X** gate on the circuit." +#~ msgid "" +#~ "This method can be overridden to " +#~ "support custom training logic. For " +#~ "concrete examples of how to override " +#~ "this method see [Customizing what " +#~ "happends in " +#~ "fit](https://www.tensorflow.org/guide/keras/customizing_what_happens_in_fit)." +#~ " This method is called by " +#~ "`Model.make_train_function`." #~ msgstr "" -#~ msgid "Apply **Y** gate on the circuit." +#~ msgid "" +#~ "This method should contain the " +#~ "mathematical logic for one step of " +#~ "training. This typically includes the " +#~ "forward pass, loss calculation, " +#~ "backpropagation, and metric updates." #~ msgstr "" -#~ msgid "Apply **Z** gate on the circuit." +#~ msgid "Bases: :py:class:`~keras.engine.base_layer.Layer`" #~ msgstr "" #~ msgid "" -#~ "Compute :math:`\\prod_{i\\in \\text{index}} s_i`," -#~ " where the probability for each " -#~ "bitstring is given as a vector " -#~ "``results``." +#~ "Input tensor, or dict/list/tuple of " +#~ "input tensors. The first positional " +#~ "`inputs` argument is subject to special" +#~ " rules: - `inputs` must be explicitly" +#~ " passed. A layer cannot have zero" +#~ " arguments, and `inputs` cannot be " +#~ "provided via the default value of " +#~ "a keyword argument. - NumPy array " +#~ "or Python scalar values in `inputs` " +#~ "get cast as tensors. - Keras mask" +#~ " metadata is only collected from " +#~ "`inputs`. - Layers are built " +#~ "(`build(input_shape)` method) using shape " +#~ "info from `inputs` only. - `input_spec`" +#~ " compatibility is only checked against " +#~ "`inputs`. - Mixed precision input " +#~ "casting is only applied to `inputs`." +#~ " If a layer has tensor arguments" +#~ " in `*args` or `**kwargs`, their " +#~ "casting behavior in mixed precision " +#~ "should be handled manually. - The " +#~ "SavedModel input specification is generated" +#~ " using `inputs` only. - Integration " +#~ "with various ecosystem packages like " +#~ "TFMOT, TFLite, TF.js, etc is only " +#~ "supported for `inputs` and not for " +#~ "tensors in positional and keyword " +#~ "arguments." #~ msgstr "" -#~ msgid "Generate sparse tensor from Pauli string sum" +#~ msgid "" +#~ "Additional keyword arguments. May contain " +#~ "tensors, although this is not " +#~ "recommended, for the reasons above. The" +#~ " following optional keyword arguments are" +#~ " reserved: - `training`: Boolean scalar " +#~ "tensor of Python boolean indicating " +#~ "whether the `call` is meant for " +#~ "training or inference. - `mask`: Boolean" +#~ " input mask. If the layer's `call()`" +#~ " method takes a `mask` argument, " +#~ "its default value will be set to" +#~ " the mask generated for `inputs` by" +#~ " the previous layer (if `input` did" +#~ " come from a layer that generated" +#~ " a corresponding mask, i.e. if it " +#~ "came from a Keras layer with " +#~ "masking support)." #~ msgstr "" -#~ msgid "Generate dense matrix from Pauli string sum" +#~ msgid "" +#~ "Bases: " +#~ ":py:class:`~keras.optimizer_v2.learning_rate_schedule.LearningRateSchedule`" #~ msgstr "" -#~ msgid "Generate Heisenberg Hamiltonian with possible external fields." +#~ msgid "" +#~ "Get Pauli string array and weights " +#~ "array for a qubit Hamiltonian as a" +#~ " sum of Pauli strings defined in " +#~ "openfermion ``QubitOperator``." #~ msgstr "" -#~ msgid "calibration qubit list" +#~ msgid "``openfermion.ops.operators.qubit_operator.QubitOperator``" #~ msgstr "" -#~ msgid "tensorcircuit.cloud" +#~ msgid "The number of qubits" #~ msgstr "" -#~ msgid "tensorcircuit.cloud.config" +#~ msgid "Pauli String array and weights array" #~ msgstr "" diff --git a/docs/source/locale/zh/LC_MESSAGES/contribs.po b/docs/source/locale/zh/LC_MESSAGES/contribs.po index cb11a0fd..004ca724 100644 --- a/docs/source/locale/zh/LC_MESSAGES/contribs.po +++ b/docs/source/locale/zh/LC_MESSAGES/contribs.po @@ -9,142 +9,222 @@ msgid "" msgstr "" "Project-Id-Version: tensorcircuit \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-02 14:19+0800\n" +"POT-Creation-Date: 2023-07-14 15:43+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.9.1\n" +"Generated-By: Babel 2.12.1\n" +#: ../../source/contribs/development_Mac.md:1 #: ../../source/contribs/development_MacARM.md:1 +#: ../../source/contribs/development_MacM2.md:1 msgid "Tensorcircuit Installation Guide on MacOS" msgstr "" -#: ../../source/contribs/development_MacARM.md:3 -msgid "Contributed by Mark (Zixuan) Song" +#: ../../source/contribs/development_Mac.md:3 +msgid "Contributed by [_Mark (Zixuan) Song_](https://marksong.tech)" msgstr "" -#: ../../source/contribs/development_MacARM.md:5 +#: ../../source/contribs/development_Mac.md:5 +msgid "" +"Apple has updated Tensorflow (for MacOS) so that installation on M-series" +" (until M2) and Intel-series Mac can follow the exact same procedure." +msgstr "" + +#: ../../source/contribs/development_Mac.md:7 +#: ../../source/contribs/development_MacARM.md:8 +#: ../../source/contribs/development_MacM2.md:10 msgid "Starting From Scratch" msgstr "" -#: ../../source/contribs/development_MacARM.md:7 -msgid "For completely new macos or macos without xcode and brew" +#: ../../source/contribs/development_Mac.md:9 +msgid "For completely new Macos or Macos without Xcode and Homebrew installed." msgstr "" -#: ../../source/contribs/development_MacARM.md:9 +#: ../../source/contribs/development_Mac.md:11 +#: ../../source/contribs/development_MacARM.md:12 +#: ../../source/contribs/development_MacM2.md:12 msgid "Install Xcode Command Line Tools" msgstr "" -#: ../../source/contribs/development_MacARM.md:11 +#: ../../source/contribs/development_Mac.md:13 +#: ../../source/contribs/development_MacARM.md:14 +#: ../../source/contribs/development_MacM2.md:14 msgid "Need graphical access to the machine." msgstr "" -#: ../../source/contribs/development_MacARM.md:13 +#: ../../source/contribs/development_Mac.md:15 +#: ../../source/contribs/development_MacARM.md:16 +#: ../../source/contribs/development_MacM2.md:16 msgid "Run `xcode-select --install` to install if on optimal internet." msgstr "" -#: ../../source/contribs/development_MacARM.md:15 +#: ../../source/contribs/development_Mac.md:17 msgid "" -"Or Download from [Apple](https://developer.apple.com/download/more/) " -"Command Line Tools installation image then install if internet connection" -" is weak." +"Or Download it from [Apple](https://developer.apple.com/download/more/) " +"Command Line Tools installation image then install it if the internet " +"connection is weak." msgstr "" -#: ../../source/contribs/development_MacARM.md:17 +#: ../../source/contribs/development_Mac.md:19 +#: ../../source/contribs/development_MacARM.md:20 +#: ../../source/contribs/development_MacM2.md:20 msgid "Install Miniconda" msgstr "" -#: ../../source/contribs/development_MacARM.md:19 +#: ../../source/contribs/development_Mac.md:21 msgid "" -"Due to the limitation of MacOS and packages, the lastest version of " -"python does not always function as desired, thus miniconda installation " -"is advised to solve the issues." +"Due to the limitation of MacOS and packages, the latest version of Python" +" does not always function as desired, thus miniconda installation is " +"advised to solve the issues." msgstr "" -#: ../../source/contribs/development_MacARM.md:28 -msgid "Install TC Prerequisites" -msgstr "" - -#: ../../source/contribs/development_MacARM.md:34 +#: ../../source/contribs/development_Mac.md:30 +#: ../../source/contribs/development_MacARM.md:37 msgid "Install TC Backends" msgstr "" -#: ../../source/contribs/development_MacARM.md:36 -msgid "There are four backends to choose from, Numpy, Tensorflow, Jax, Torch." +#: ../../source/contribs/development_Mac.md:32 +msgid "There are four backends to choose from, Numpy, Tensorflow, Jax, and Torch." msgstr "" -#: ../../source/contribs/development_MacARM.md:38 +#: ../../source/contribs/development_Mac.md:34 +#: ../../source/contribs/development_MacARM.md:41 msgid "Install Jax, Pytorch, Qiskit, Cirq (Optional)" msgstr "" -#: ../../source/contribs/development_MacARM.md:44 +#: ../../source/contribs/development_Mac.md:40 +#: ../../source/contribs/development_MacARM.md:47 msgid "Install Tensorflow (Optional)" msgstr "" -#: ../../source/contribs/development_MacARM.md:46 -msgid "Install Tensorflow (Recommended Approach)" +#: ../../source/contribs/development_Mac.md:42 +msgid "Installation" +msgstr "" + +#: ../../source/contribs/development_Mac.md:44 +msgid "For Tensorflow version 2.13 or later:" msgstr "" -#: ../../source/contribs/development_MacARM.md:48 +#: ../../source/contribs/development_Mac.md:50 +msgid "For Tensorflow version 2.12 or earlier:" +msgstr "" + +#: ../../source/contribs/development_Mac.md:56 +#: ../../source/contribs/development_MacARM.md:57 +#: ../../source/contribs/development_MacARM.md:89 +msgid "Verify Tensorflow Installation" +msgstr "" + +#: ../../source/contribs/development_Mac.md:74 +#: ../../source/contribs/development_MacARM.md:107 +msgid "Install Tensorcircuit" +msgstr "" + +#: ../../source/contribs/development_Mac.md:80 msgid "" -"❗️ Tensorflow with MacOS optimization would not function correctly in " -"version 2.11.0 and before. Do not use this version of tensorflow if you " -"intented to train any machine learning model." +"Until July 2023, this has been tested on Intel Macs running Ventura, M1 " +"Macs running Ventura, M2 Macs running Ventura, and M2 Macs running Sonoma" +" beta." +msgstr "" + +#: ../../source/contribs/development_MacARM.md:3 +msgid "Contributed by Mark (Zixuan) Song" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:5 +#: ../../source/contribs/development_MacM2.md:5 +msgid "" +".. warning:: This page is deprecated. Please visit `the update " +"tutorial `_ for the latest information." +msgstr "" + +#: ../../source/contribs/development_MacARM.md:10 +msgid "For completely new macos or macos without xcode and brew" msgstr "" -#: ../../source/contribs/development_MacARM.md:50 +#: ../../source/contribs/development_MacARM.md:18 +#: ../../source/contribs/development_MacM2.md:18 msgid "" -"FYI: Error can occur when machine learning training or gpu related code " -"is involved." +"Or Download from [Apple](https://developer.apple.com/download/more/) " +"Command Line Tools installation image then install if internet connection" +" is weak." msgstr "" -#: ../../source/contribs/development_MacARM.md:52 +#: ../../source/contribs/development_MacARM.md:22 msgid "" -"⚠️ Tensorflow without macos optimization does not support Metal API and " -"utilizing GPU (both intel chips and M-series chips) until at least " -"tensorflow 2.11. Tensorflow-macos would fail when running " -"`tc.backend.to_dense()`" +"Due to the limitation of MacOS and packages, the lastest version of " +"python does not always function as desired, thus miniconda installation " +"is advised to solve the issues." msgstr "" -#: ../../source/contribs/development_MacARM.md:60 -msgid "Verify Tensorflow Installation" +#: ../../source/contribs/development_MacARM.md:31 +msgid "Install TC Prerequisites" msgstr "" -#: ../../source/contribs/development_MacARM.md:78 -msgid "Install Tensorcircuit" +#: ../../source/contribs/development_MacARM.md:39 +msgid "There are four backends to choose from, Numpy, Tensorflow, Jax, Torch." +msgstr "" + +#: ../../source/contribs/development_MacARM.md:49 +msgid "Install Tensorflow without MacOS optimization" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:75 +msgid "Install Tensorflow with MacOS optimization (Recommended)" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:77 +msgid "For tensorflow version 2.13 or later:" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:83 +msgid "For tensorflow version 2.12 or earlier:" msgstr "" -#: ../../source/contribs/development_MacARM.md:84 -msgid "Testing Platform (Tested Feb 2023)" +#: ../../source/contribs/development_MacARM.md:113 +msgid "Testing Platform (Tested Jun 2023)" msgstr "" -#: ../../source/contribs/development_MacARM.md:86 +#: ../../source/contribs/development_MacARM.md:115 msgid "Platform 1:" msgstr "" -#: ../../source/contribs/development_MacARM.md:87 +#: ../../source/contribs/development_MacARM.md:116 msgid "MacOS Ventura 13.1 (Build version 22C65)" msgstr "" -#: ../../source/contribs/development_MacARM.md:88 +#: ../../source/contribs/development_MacARM.md:117 msgid "M1 Ultra" msgstr "" -#: ../../source/contribs/development_MacARM.md:89 +#: ../../source/contribs/development_MacARM.md:118 msgid "Platform 2:" msgstr "" -#: ../../source/contribs/development_MacARM.md:90 +#: ../../source/contribs/development_MacARM.md:119 msgid "MacOS Ventura 13.2 (Build version 22D49)" msgstr "" -#: ../../source/contribs/development_MacARM.md:91 +#: ../../source/contribs/development_MacARM.md:120 msgid "M1 Ultra (Virtual)" msgstr "" +#: ../../source/contribs/development_MacARM.md:121 +msgid "Platform 4:" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:122 +msgid "MacOS Sonoma 14.0 Beta 2 (Build version 23A5276g)" +msgstr "" + +#: ../../source/contribs/development_MacARM.md:123 +msgid "M2 Max" +msgstr "" + #: ../../source/contribs/development_MacM1.rst:2 msgid "Run TensorCircuit on TensorlowBackend with Apple M1" msgstr "" @@ -156,7 +236,7 @@ msgstr "" #: ../../source/contribs/development_MacM1.rst:7 msgid "" "This page is deprecated. Please visit `the update tutorial " -"`_ for latest information." +"`_ for the latest information." msgstr "" #: ../../source/contribs/development_MacM1.rst:11 @@ -256,6 +336,146 @@ msgstr "" msgid "Then unpackage it, and cd into the folder with \"setup.py\". Conducting" msgstr "" +#: ../../source/contribs/development_MacM2.md:3 +msgid "Contributed by [Hong-Ye Hu](https://github.com/hongyehu)" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:8 +msgid "" +"The key issue addressed in this document is **how to install both " +"TensorFlow and Jax on a M2 chip MacOS without conflict**." +msgstr "" + +#: ../../source/contribs/development_MacM2.md:22 +msgid "" +"Due to the limitation of MacOS and packages, the lastest version of " +"python does not always function as desired, thus miniconda installation " +"is advised to solve the issues. And use anaconda virtual environment is " +"always a good habit." +msgstr "" + +#: ../../source/contribs/development_MacM2.md:30 +msgid "Install Packages" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:31 +msgid "" +"First, create a virtual environment, and make sure the python version is " +"3.8.5 by" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:36 +msgid "" +"Then, install the TensorFlow from `.whl` file (file can be downloaded " +"from this " +"[URL](https://drive.google.com/drive/folders/1oSipZLnoeQB0Awz8U68KYeCPsULy_dQ7))." +" This will install TensorFlow version 2.4.1" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:40 +msgid "Next, one need to install **Jax** and **Optax** by" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:45 +msgid "" +"Now, hopefully, you should be able to use both Jax and TensorFlow in this" +" environment. But sometimes, it may give you an error \"ERROR: package " +"Chardet not found.\". If that is the case, you can install it by `conda " +"install chardet`. Lastly, install tensorcircuit" +msgstr "" + +#: ../../source/contribs/development_MacM2.md:51 +msgid "" +"This is the solution that seems to work for M2-chip MacOS. Please let me " +"know if there is a better solution!" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:1 +msgid "MacOS Tensorcircuit 安装教程" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:3 +msgid "[_Mark (Zixuan) Song_](https://marksong.tech) 撰写" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:5 +msgid "由于苹果更新了Tensorflow,因此M系列(直到M2)和英特尔系列Mac上的安装可以遵循完全相同的过程。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:7 +msgid "从头开始" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:9 +msgid "对于全新的Macos或未安装Xcode和Homebrew的Macos。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:11 +msgid "安装Xcode命令行工具" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:13 +msgid "需要对机器的图形访问。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:15 +msgid "如果网络良好,请运行`xcode-select --install`进行安装。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:17 +msgid "或者,如果网络连接较弱,请从[苹果](https://developer.apple.com/download/more/)下载命令行工具安装映像,然后进行安装。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:19 +msgid "安装Miniconda" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:21 +msgid "由于MacOS和软件包的限制,因此建议安装miniconda以解决问题。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:30 +msgid "安装TC后端" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:32 +msgid "有四个后端可供选择,Numpy,Tensorflow,Jax和Torch。" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:34 +msgid "安装Jax,Pytorch,Qiskit,Cirq(可选)" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:40 +msgid "安装Tensorflow(可选)" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:42 +msgid "安装步骤" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:44 +msgid "Tensorflow版本2.13或之后:" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:50 +msgid "Tensorflow版本2.12或之前:" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:56 +msgid "验证Tensorflow安装" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:74 +msgid "安装Tensorcircuit" +msgstr "" + +#: ../../source/contribs/development_Mac_cn.md:80 +msgid "" +"直到2023年7月,这已在运行Ventura的英特尔i9 Mac、运行Ventura的M1 Mac、运行Ventura的M2 " +"Mac、运行Sonoma测试版的M2 Mac上进行了测试。" +msgstr "" + #: ../../source/contribs/development_windows.rst:2 msgid "Run TensorCircuit on Windows Machine with Docker" msgstr "" @@ -666,3 +886,39 @@ msgstr "" #~ msgid "Testing Platform" #~ msgstr "" +#~ msgid "Install Tensorflow (Recommended Approach)" +#~ msgstr "" + +#~ msgid "" +#~ "❗️ Tensorflow with MacOS optimization " +#~ "would not function correctly in version" +#~ " 2.11.0 and before. Do not use " +#~ "this version of tensorflow if you " +#~ "intented to train any machine learning" +#~ " model." +#~ msgstr "" + +#~ msgid "" +#~ "FYI: Error can occur when machine " +#~ "learning training or gpu related code" +#~ " is involved." +#~ msgstr "" + +#~ msgid "" +#~ "⚠️ Tensorflow without macos optimization " +#~ "does not support Metal API and " +#~ "utilizing GPU (both intel chips and " +#~ "M-series chips) until at least " +#~ "tensorflow 2.11. Tensorflow-macos would " +#~ "fail when running `tc.backend.to_dense()`" +#~ msgstr "" + +#~ msgid "Testing Platform (Tested Feb 2023)" +#~ msgstr "" + +#~ msgid "" +#~ "This page is deprecated. Please visit" +#~ " `the update tutorial `_" +#~ " for latest information." +#~ msgstr "" + diff --git a/docs/source/locale/zh/LC_MESSAGES/index.po b/docs/source/locale/zh/LC_MESSAGES/index.po index 1ee54686..20ed436d 100644 --- a/docs/source/locale/zh/LC_MESSAGES/index.po +++ b/docs/source/locale/zh/LC_MESSAGES/index.po @@ -6,165 +6,354 @@ # msgid "" msgstr "" -"Project-Id-Version: tensorcircuit\n" +"Project-Id-Version: tensorcircuit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-02 13:41+0800\n" -"PO-Revision-Date: 2022-04-16 22:37+0800\n" +"POT-Creation-Date: 2023-05-28 14:36+0800\n" +"PO-Revision-Date: 2023-05-28 14:39+0800\n" "Last-Translator: Xinghan Yang\n" -"Language: cn\n" "Language-Team: \n" +"Language: cn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.1\n" +"X-Generator: Poedit 3.2.2\n" #: ../../source/index.rst:2 -msgid "Guide to TensorCircuit" -msgstr "TensorCircuit 指南" +msgid "TensorCircuit Documentation" +msgstr "参考文档" + +#: ../../source/index.rst:8 +msgid "**Welcome and congratulations! You have found TensorCircuit.** 👏" +msgstr "**祝贺你发现了 TensorCircuit!** 👏" + +#: ../../source/index.rst:11 +msgid "Introduction" +msgstr "介绍" -#: ../../source/index.rst:7 +#: ../../source/index.rst:13 msgid "" -"TensorCircuit is an open source quantum circuit and algorithm simulation " -"framework." -msgstr "TensorCircuit 是开源的量子线路和量子算法模拟软件框架。" +"TensorCircuit is an open-source high-performance quantum computing software " +"framework in Python." +msgstr "TensorCircuit 是基于 Python 的开源高性能量子计算软件框架。" -#: ../../source/index.rst:9 -msgid "It is built for human beings. 👽" +#: ../../source/index.rst:15 +msgid "It is built for humans. 👽" msgstr "适合人类。👽" -#: ../../source/index.rst:11 +#: ../../source/index.rst:17 msgid "It is designed for speed, flexibility and elegance. 🚀" msgstr "速度,灵活,优雅。🚀" -#: ../../source/index.rst:13 +#: ../../source/index.rst:19 msgid "It is empowered by advanced tensor network simulator engine. 🔋" msgstr "先进张量网络引擎赋能。🔋" -#: ../../source/index.rst:15 +#: ../../source/index.rst:21 +msgid "" +"It is ready for quantum hardware access with CPU/GPU/QPU (local/cloud) hybrid " +"solutions. 🖥" +msgstr "量子硬件支持,优雅 CPU/GPU/QPU 混合部署方案。 🖥" + +#: ../../source/index.rst:23 msgid "" "It is implemented with industry-standard machine learning frameworks: " "TensorFlow, JAX, and PyTorch. 🤖" msgstr "业界标准机器学习框架 TensorFlow,JAX,PyTorch 实现。🤖" -#: ../../source/index.rst:17 +#: ../../source/index.rst:25 msgid "" "It is compatible with machine learning engineering paradigms: automatic " -"differentiation, just-in-time compilation, vectorized parallelism and GPU" -" acceleration. 🛠" +"differentiation, just-in-time compilation, vectorized parallelism and GPU " +"acceleration. 🛠" msgstr "与机器学习工程实践兼容:自动微分,即时编译,向量并行化和 GPU 加速。🛠" -#: ../../source/index.rst:20 -msgid "Links" -msgstr "重要链接" +#: ../../source/index.rst:27 +msgid "" +"With the help of TensorCircuit, now get ready to efficiently and elegantly " +"solve interesting and challenging quantum computing problems: from academic " +"research prototype to industry application deployment." +msgstr "" +"有了 TensorCircuit,你现在可以高效优雅地解决量子计算中的各种问题:从学术研究的原" +"型开发到工业应用的部署。" + +#: ../../source/index.rst:33 +msgid "Relevant Links" +msgstr "相关链接" + +#: ../../source/index.rst:35 +msgid "" +"TensorCircuit is created and maintained by `Shi-Xin Zhang `_ and this version is released by `Tencent Quantum Lab `_." +msgstr "" +"TensorCircuit 由 `Shi-Xin Zhang `_ 创建和维" +"护;此版本由 `腾讯量子实验室 `_ 发布。" + +#: ../../source/index.rst:37 +msgid "" +"The current core authors of TensorCircuit are `Shi-Xin Zhang `_ and `Yu-Qin Chen `_. We also " +"thank `contributions `_ from the lab and the open source community." +msgstr "" +"TensorCircuit 当前主要作者为 `Shi-Xin Zhang `_,`Yu-Qin Chen `_。同时感谢来自实验室和开源社" +"区的 `贡献 `_。" -#: ../../source/index.rst:22 +#: ../../source/index.rst:40 msgid "" -"TensorCircuit is created and maintained by `Shi-Xin Zhang " -"`_ and this version of the software is" -" released by `Tencent Quantum Lab `_. The " -"current core authors of TensorCircuit are `Shi-Xin Zhang " -"`_ and `Yu-Qin Chen " -"`_. We also thank `contributions " -"`_ from the lab and the open source" -" community." -msgstr "" - -#: ../../source/index.rst:26 -msgid "Source code: https://github.com/tencent-quantum-lab/tensorcircuit" -msgstr "源代码: https://github.com/tencent-quantum-lab/tensorcircuit" - -#: ../../source/index.rst:28 -#, fuzzy -msgid "Software Whitepaper: https://arxiv.org/abs/2205.10091" -msgstr "白皮书文章: https://arxiv.org/abs/2205.10091" - -#: ../../source/index.rst:30 -msgid "Documentation: https://tensorcircuit.readthedocs.io" -msgstr "文档: https://tensorcircuit.readthedocs.io" - -#: ../../source/index.rst:32 -msgid "Issue Tracker: https://github.com/tencent-quantum-lab/tensorcircuit/issues" -msgstr "问题跟踪: https://github.com/tencent-quantum-lab/tensorcircuit/issues" - -#: ../../source/index.rst:34 -msgid "Forum: https://github.com/tencent-quantum-lab/tensorcircuit/discussions" -msgstr "论坛社区: https://github.com/tencent-quantum-lab/tensorcircuit/discussions" - -#: ../../source/index.rst:36 -msgid "PyPI page: https://pypi.org/project/tensorcircuit" -msgstr "PyPI 页面: https://pypi.org/project/tensorcircuit" - -#: ../../source/index.rst:38 +"If you have any further questions or collaboration ideas, please use the issue " +"tracker or forum below, or send email to shixinzhang#tencent.com." +msgstr "" +"如果关于 TensorCircuit 有任何问题咨询或合作意向,请在 issue 或 discussion 提问," +"或发送邮件到 shixinzhang#tencent.com。" + +#: ../../source/index.rst:45 +msgid "Source code" +msgstr "源代码" + +#: ../../source/index.rst:49 +msgid "GitHub" +msgstr "" + +#: ../../source/index.rst:52 +msgid "Documentation" +msgstr "参考文档" + +#: ../../source/index.rst:56 +msgid "Readthedocs" +msgstr "" + +#: ../../source/index.rst:59 +msgid "Whitepaper" +msgstr "白皮书" + +#: ../../source/index.rst:63 +msgid "*Quantum* journal" +msgstr "Quantum 期刊" + +#: ../../source/index.rst:66 +msgid "Issue Tracker" +msgstr "问题跟踪" + +#: ../../source/index.rst:70 +msgid "GitHub Issues" +msgstr "" + +#: ../../source/index.rst:73 +msgid "Forum" +msgstr "论坛" + +#: ../../source/index.rst:77 +msgid "GitHub Discussions" +msgstr "" + +#: ../../source/index.rst:80 +msgid "PyPI" +msgstr "" + +#: ../../source/index.rst:84 +msgid "``pip install``" +msgstr "" + +#: ../../source/index.rst:87 +msgid "DockerHub" +msgstr "" + +#: ../../source/index.rst:91 +msgid "``docker pull``" +msgstr "" + +#: ../../source/index.rst:94 +msgid "Application" +msgstr "应用" + +#: ../../source/index.rst:98 +msgid "Research using TC" +msgstr "研究项目" + +#: ../../source/index.rst:101 +msgid "Cloud" +msgstr "量子云" + +#: ../../source/index.rst:104 +msgid "Tencent Quantum Cloud" +msgstr "腾讯量子云平台" + +#: ../../source/index.rst:131 +msgid "Unified Quantum Programming" +msgstr "统一量子编程" + +#: ../../source/index.rst:133 msgid "" -"DockerHub page: " -"https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit" +"TensorCircuit is unifying infrastructures and interfaces for quantum computing." +msgstr "TensorCircuit 尝试统一量子计算的基础设施和编程界面。" + +#: ../../source/index.rst:140 +msgid "Unified Backends" +msgstr "统一后端" + +#: ../../source/index.rst:144 +msgid "Jax/TensorFlow/PyTorch/Numpy/Cupy" +msgstr "" + +#: ../../source/index.rst:146 +msgid "Unified Devices" +msgstr "统一设备" + +#: ../../source/index.rst:150 +msgid "CPU/GPU/TPU" msgstr "" -"DockerHub 页面: " -"https://hub.docker.com/repository/docker/tensorcircuit/tensorcircuit" -#: ../../source/index.rst:43 +#: ../../source/index.rst:152 +msgid "Unified Providers" +msgstr "统一平台" + +#: ../../source/index.rst:156 +msgid "QPUs from different vendors" +msgstr "不同供应商的 QPU" + +#: ../../source/index.rst:158 +msgid "Unified Resources" +msgstr "统一资源" + +#: ../../source/index.rst:162 +msgid "local/cloud/HPC" +msgstr "本地/云/集群" + +#: ../../source/index.rst:170 +msgid "Unified Interfaces" +msgstr "统一接口" + +#: ../../source/index.rst:174 +msgid "numerical sim/hardware exp" +msgstr "数值模拟/硬件实验" + +#: ../../source/index.rst:176 +msgid "Unified Engines" +msgstr "统一引擎" + +#: ../../source/index.rst:180 +msgid "ideal/noisy/approximate simulation" +msgstr "理想/含噪/近似模拟" + +#: ../../source/index.rst:182 +msgid "Unified Representations" +msgstr "统一表示" + +#: ../../source/index.rst:186 +msgid "from/to_IR/qiskit/openqasm/json" +msgstr "" + +#: ../../source/index.rst:188 +msgid "Unified Pipelines" +msgstr "统一流程" + +#: ../../source/index.rst:192 +msgid "stateless functional programming/stateful ML models" +msgstr "函数式编程/面向对象模型" + +#: ../../source/index.rst:198 msgid "Reference Documentation" msgstr "参考文档" -#: ../../source/index.rst:45 +#: ../../source/index.rst:200 msgid "" -"The following documentation sections briefly introduce TensorCircuit to " -"the users and developpers." +"The following documentation sections briefly introduce TensorCircuit to the " +"users and developpers." msgstr "以下文档向用户和开发者简要介绍了 TensorCircuit 软件。" -#: ../../source/index.rst:58 +#: ../../source/index.rst:213 msgid "Tutorials" msgstr "教程" -#: ../../source/index.rst:60 +#: ../../source/index.rst:215 msgid "" -"The following documentation sections include integrated examples in the " -"form of Jupyter Notebook." -msgstr "以下 Jupyter Notebook 格式的文档包括了一系列使用 TensorCircuit 的集成案例。" +"The following documentation sections include integrated examples in the form of " +"Jupyter Notebook." +msgstr "" +"以下 Jupyter Notebook 格式的文档包括了一系列使用 TensorCircuit 的集成案例。" -#: ../../source/index.rst:74 +#: ../../source/index.rst:229 msgid "API References" msgstr "API 参考" -#: ../../source/index.rst:83 +#: ../../source/index.rst:238 msgid "Indices and Tables" msgstr "索引和表格" -#: ../../source/index.rst:85 +#: ../../source/index.rst:240 msgid ":ref:`genindex`" msgstr ":ref:`genindex`" -#: ../../source/index.rst:86 +#: ../../source/index.rst:241 msgid ":ref:`modindex`" msgstr ":ref:`modindex`" -#: ../../source/index.rst:87 +#: ../../source/index.rst:242 msgid ":ref:`search`" msgstr ":ref:`search`" #~ msgid "" -#~ "Binder online: https://mybinder.org/v2/gh/refraction-" -#~ "ray/tc-env/master?urlpath=git-pull?repo=https://github.com" -#~ "/tencent-quantum-" -#~ "lab/tensorcircuit&urlpath=lab/tree/tensorcircuit/&branch=master" +#~ "Binder online: https://mybinder.org/v2/gh/refraction-ray/tc-env/master?" +#~ "urlpath=git-pull?repo=https://github.com/tencent-quantum-lab/" +#~ "tensorcircuit&urlpath=lab/tree/tensorcircuit/&branch=master" #~ msgstr "" -#~ "在线 Binder Jupyter: https://mybinder.org/v2/gh" -#~ "/refraction-ray/tc-env/master?urlpath=git-" -#~ "pull?repo=https://github.com/tencent-quantum-" -#~ "lab/tensorcircuit&urlpath=lab/tree/tensorcircuit/&branch=master" +#~ "在线 Binder Jupyter: https://mybinder.org/v2/gh/refraction-ray/tc-env/master?" +#~ "urlpath=git-pull?repo=https://github.com/tencent-quantum-lab/" +#~ "tensorcircuit&urlpath=lab/tree/tensorcircuit/&branch=master" + +#~ msgid "Software Whitepaper: https://arxiv.org/abs/2205.10091" +#~ msgstr "白皮书文章: https://arxiv.org/abs/2205.10091" + +#~ msgid "Guide to TensorCircuit" +#~ msgstr "TensorCircuit 指南" + +#~ msgid "Links" +#~ msgstr "重要链接" + +#~ msgid "Source code: https://github.com/tencent-quantum-lab/tensorcircuit" +#~ msgstr "源代码: https://github.com/tencent-quantum-lab/tensorcircuit" + +#~ msgid "Documentation: https://tensorcircuit.readthedocs.io" +#~ msgstr "文档: https://tensorcircuit.readthedocs.io" #~ msgid "" -#~ "This project is released by `Tencent " -#~ "Quantum Lab `_ and " -#~ "is created and maintained by `Shi-" -#~ "Xin Zhang `_ " -#~ "The current core authors are `Shi-" -#~ "Xin Zhang `_ " -#~ "and `Yu-Qin Chen " -#~ "`_. We also thank " -#~ "`contributions `_ from the " -#~ "lab and the open source community." +#~ "Software Whitepaper (published in Quantum): https://quantum-journal.org/" +#~ "papers/q-2023-02-02-912/" #~ msgstr "" +#~ "软件白皮书 (发表于 Quantum): https://quantum-journal.org/papers/" +#~ "q-2023-02-02-912/" + +#~ msgid "" +#~ "Issue Tracker: https://github.com/tencent-quantum-lab/tensorcircuit/issues" +#~ msgstr "问题跟踪: https://github.com/tencent-quantum-lab/tensorcircuit/issues" + +#~ msgid "Forum: https://github.com/tencent-quantum-lab/tensorcircuit/discussions" +#~ msgstr "" +#~ "论坛社区: https://github.com/tencent-quantum-lab/tensorcircuit/discussions" + +#~ msgid "PyPI page: https://pypi.org/project/tensorcircuit" +#~ msgstr "PyPI 页面: https://pypi.org/project/tensorcircuit" + +#~ msgid "" +#~ "DockerHub page: https://hub.docker.com/repository/docker/tensorcircuit/" +#~ "tensorcircuit" +#~ msgstr "" +#~ "DockerHub 页面: https://hub.docker.com/repository/docker/tensorcircuit/" +#~ "tensorcircuit" + +#~ msgid "" +#~ "Research and projects based on TensorCircuit: https://github.com/tencent-" +#~ "quantum-lab/tensorcircuit#research-and-applications" +#~ msgstr "" +#~ "基于 TensorCircuit 的研究和项目: https://github.com/tencent-quantum-lab/" +#~ "tensorcircuit#research-and-applications" + +#~ msgid "Tencent Quantum Cloud Service: https://quantum.tencent.com/cloud/" +#~ msgstr "腾讯量子云服务: https://quantum.tencent.com/cloud/" +#~ msgid "Research based on TC" +#~ msgstr "基于 TC 的研究项目" diff --git a/docs/source/locale/zh/LC_MESSAGES/infras.po b/docs/source/locale/zh/LC_MESSAGES/infras.po index 6a2077b5..b285ed77 100644 --- a/docs/source/locale/zh/LC_MESSAGES/infras.po +++ b/docs/source/locale/zh/LC_MESSAGES/infras.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: tensorcircuit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-13 11:04+0800\n" +"POT-Creation-Date: 2023-05-27 18:52+0800\n" "PO-Revision-Date: 2022-04-18 20:44+0800\n" "Last-Translator: Xinghan Yang\n" "Language: cn\n" @@ -120,10 +120,11 @@ msgid "**ML Interfaces Related Modules:**" msgstr "**机器学习接口相关模块:**" #: ../../source/infras.rst:35 +#, fuzzy msgid "" ":py:mod:`tensorcircuit.interfaces`: Provide interfaces when quantum " "simulation backend is different from neural libraries. Currently include " -"PyTorch and scipy optimizer interfaces." +"PyTorch, TensorFlow, NumPy and SciPy optimizer interfaces." msgstr "" ":py:mod:`tensorcircuit.interfaces`: 当量子模拟后端与神经库不同时提供接口。 目前包括 PyTorch 和 " "scipy 优化器接口。" @@ -216,30 +217,46 @@ msgstr "" #: ../../source/infras.rst:65 msgid "" ":py:mod:`tensorcircuit.results`: Provide tools to process count dict and " -"to apply error mitigation" +"to apply error mitigation." msgstr "" #: ../../source/infras.rst:67 +msgid "**Cloud quantum hardware access module:**" +msgstr "" + +#: ../../source/infras.rst:69 +msgid "" +":py:mod:`tensorcircuit.cloud`: Provide quantum cloud SDK that can access " +"and program the real quantum hardware." +msgstr "" + +#: ../../source/infras.rst:71 +msgid "" +":py:mod:`tensorcircuit.compiler`: Provide compiler chains to compile and " +"transform quantum circuits." +msgstr "" + +#: ../../source/infras.rst:73 msgid "**Shortcuts and Templates for Circuit Manipulation:**" msgstr "**电路操作的快捷方式和模板:**" -#: ../../source/infras.rst:69 +#: ../../source/infras.rst:75 msgid "" ":py:mod:`tensorcircuit.templates`: provide handy shortcuts functions for " "expectation or circuit building patterns." msgstr ":py:mod:`tensorcircuit.templates`: 为期望或电路构建模式提供方便的快捷函数。" -#: ../../source/infras.rst:71 +#: ../../source/infras.rst:77 msgid "**Applications:**" msgstr "**应用:**" -#: ../../source/infras.rst:73 +#: ../../source/infras.rst:79 msgid "" ":py:mod:`tensorcircuit.applications`: most code here is not maintained " "and deprecated, use at your own risk." msgstr ":py:mod:`tensorcircuit.applications`: 这里的大多数代码都没有维护并且被弃用了,使用风险自负。" -#: ../../source/infras.rst:77 +#: ../../source/infras.rst:83 msgid "" "Recommend reading order -- only read the part of code you care about for " "your purpose. If you want to get an overview of the codebase, please read" @@ -248,11 +265,11 @@ msgstr "" "推荐阅读顺序——只阅读你关心的部分代码。如果您想了解代码库的概述,之后可以阅读 ``tc.circuit`` 后面的 ``tc.cons`` 和 " "``tc.gates``。" -#: ../../source/infras.rst:82 +#: ../../source/infras.rst:88 msgid "Relation between TensorCircuit and TensorNetwork" msgstr "TensorCircuit 和 TensorNetwork 之间的关系" -#: ../../source/infras.rst:84 +#: ../../source/infras.rst:90 msgid "" "TensorCircuit has a strong connection with the `TensorNetwork package " "`_ released by Google. Since the" @@ -266,7 +283,7 @@ msgstr "" "包的文档和教程很差,大多数时候,我们需要深入研究 TensorNetwork 的代码库来弄清楚发生了什么。换句话说,要阅读 " "TensorCircuit 代码库,可能需要经常参考 TensorNetwork 代码库。" -#: ../../source/infras.rst:86 +#: ../../source/infras.rst:92 msgid "" "Inside TensorCircuit, we heavily utilize TensorNetwork-related APIs from " "the TensorNetwork package and highly customized several modules from " @@ -275,7 +292,7 @@ msgstr "" "在 TensorCircuit 内部,我们大量使用了 TensorNetwork 包中与 TensorNetwork 相关的 " "API,并通过继承和重写从 TensorNetwork 中高度定制了几个模块:" -#: ../../source/infras.rst:88 +#: ../../source/infras.rst:94 msgid "" "We implement our own /backends from TensorNetwork's /backends by adding " "much more APIs and fixing lots of bugs in TensorNetwork's implementations" @@ -285,7 +302,7 @@ msgstr "" "我们从 TensorNetwork 的后端实现我们自己的后端,方法是添加更多 API,并通过猴子补丁修复 TensorNetwork " "在某些后端的实现中的许多错误。(上游是不活跃的,反馈不够灵敏)" -#: ../../source/infras.rst:90 +#: ../../source/infras.rst:96 msgid "" "We borrow TensorNetwork's code in /quantum to our ``tc.quantum`` module, " "since TensorNetwork has no ``__init__.py`` file to export these MPO and " @@ -296,7 +313,7 @@ msgstr "" "TensorNetwork 没有 ``__init__.py`` 文件来导出这些 MPO 和 MPS " "相关对象。当然,从那时起,我们已经取得了实质性的代码改进。" -#: ../../source/infras.rst:92 +#: ../../source/infras.rst:98 msgid "" "We borrow the TensorNetwork's code in /matrixproductstates as " "``tc.mps_base`` for bug fixing and jit/AD compatibility, so that we have " @@ -305,15 +322,15 @@ msgstr "" "我们借用 /matrixproductstates 中 TensorNetwork 的代码作为 ``tc.mps_base`` " "用于错误修复和即时编译/自动微分兼容性,以便我们更好地支持基于 MPS 的量子电路模拟器。" -#: ../../source/infras.rst:96 +#: ../../source/infras.rst:102 msgid "Relations of Circuit-like classes" msgstr "" -#: ../../source/infras.rst:108 +#: ../../source/infras.rst:114 msgid "QuOperator/QuVector and MPO/MPS" msgstr "QuOperator/QuVector 和 MPO/MPS" -#: ../../source/infras.rst:110 +#: ../../source/infras.rst:116 msgid "" ":py:class:`tensorcircuit.quantum.QuOperator`, " ":py:class:`tensorcircuit.quantum.QuVector` and " @@ -327,19 +344,19 @@ msgstr "" ":py:class:`tensorcircuit.quantum.QuAdjointVector` 是从 TensorNetwork " "包中采用的类。它们的行为类似于与其他成分交互时的矩阵/向量(列或行),而内部结构由张量网络维护以提高效率和紧凑性。" -#: ../../source/infras.rst:113 +#: ../../source/infras.rst:119 msgid "" "We use code examples and associated tensor diagrams to illustrate these " "object abstractions." msgstr "我们使用代码示例和相关的张量图来说明这些对象抽象。" -#: ../../source/infras.rst:117 +#: ../../source/infras.rst:123 msgid "" "``QuOperator`` can express MPOs and ``QuVector`` can express MPSs, but " "they can express more than these fixed structured tensor networks." msgstr "``QuOperator`` 可以表达 MPO,``QuVector`` 可以表达 MPS,但它们可以表达的不仅仅是这些固定的结构化张量网络。" -#: ../../source/infras.rst:145 +#: ../../source/infras.rst:151 msgid "" "Note how in this example, ``matrix`` is not a typical MPO but still can " "be expressed as ``QuOperator``. Indeed, any tensor network with two sets " @@ -351,7 +368,7 @@ msgstr "" "``QuOperator``。事实上,任何具有两组相同维度的悬边的张量网络都可以被视为 `` QuOperator``。``QuVector`` " "更加灵活,因为我们可以将所有悬空边视为向量维度。" -#: ../../source/infras.rst:147 +#: ../../source/infras.rst:153 msgid "" "Also, note how ``^`` is overloaded as ``tn.connect`` to connect edges " "between different nodes in TensorNetwork. And indexing the node gives the" @@ -360,7 +377,7 @@ msgstr "" "还要注意 ``^`` 是如何被重载为 ``tn.connect`` 以连接 TensorNetwork " "中不同节点之间的边。索引节点给出了节点的边,例如 ``n1[0]`` 意味着 ``节点 n1`` 的第一条边。" -#: ../../source/infras.rst:149 +#: ../../source/infras.rst:155 msgid "" "The convention to define the ``QuOperator`` is firstly giving " "``out_edges`` (left index or row index of the matrix) and then giving " @@ -370,7 +387,7 @@ msgstr "" "定义 ``QuOperator`` 的惯例是首先给出 ``out_edges``(矩阵的左索引或行索引),然后给出 " "``in_edges``(矩阵的右索引或列索引)。边列表包含来自 TensorNetwork 库的边对象。" -#: ../../source/infras.rst:151 +#: ../../source/infras.rst:157 msgid "" "Such QuOperator/QuVector abstraction support various calculations only " "possible on matrix/vectors, such as matmul (``@``), adjoint " @@ -386,6 +403,62 @@ msgstr "" "(``*``)、张量乘积(``|``)和偏迹(``.partial_trace(subsystems_to_trace_out)``)。要提取这些对象的矩阵信息,我们可以使用" " ``.eval()`` 或 ``.eval_matrix() ``,前者保留了张量网络的形状信息,而后者给出了形状秩为2的矩阵表示。" +#: ../../source/infras.rst:162 +msgid "Quantum Cloud SDK: Layerwise API design" +msgstr "" + +#: ../../source/infras.rst:164 +msgid "From lower level to higher level, a view of API layers invoking QPU calls" +msgstr "" + +#: ../../source/infras.rst:166 +msgid "" +"Vendor specific implementation of functional API in, e.g., " +":py:mod:`tensorcircuit.cloud.tencent`" +msgstr "" + +#: ../../source/infras.rst:168 +msgid "" +"Provider agnostic functional lower level API for task/device management " +"in :py:mod:`tensorcircuit.cloud.apis`" +msgstr "" + +#: ../../source/infras.rst:170 +msgid "" +"Object oriented abstraction for Provider/Device/Task in " +":py:mod:`tensorcircuit.cloud.abstraction`" +msgstr "" + +#: ../../source/infras.rst:172 +msgid "" +"Unified batch submission interface as standarized in " +":py:meth:`tensorcircuit.cloud.wrapper.batch_submit_template`" +msgstr "" + +#: ../../source/infras.rst:174 +msgid "" +"Numerical and experimental unified all-in-one interface as " +":py:meth:`tensorcircuit.cloud.wrapper.batch_expectation_ps`" +msgstr "" + +#: ../../source/infras.rst:176 +msgid "" +"Application level code with QPU calls built directly on " +"``batch_expectation_ps`` or more fancy algorithms can be built on " +"``batch_submit_func`` so that these algorithms can be reused as long as " +"one function ``batch_submit_func`` is defined for a given vendor (cheaper" +" than defining a new provider from lower level)." +msgstr "" + +#: ../../source/infras.rst:181 +msgid "" +"For compiler, error mitigation and results post-processing parts, they " +"can be carefully designed to decouple with the QPU calls, so they are " +"separately implemented in :py:mod:`tensorcircuit.compiler` and " +":py:mod:`tensorcircuit.results`, and they can be independently useful " +"even without tc's cloud access." +msgstr "" + #~ msgid "" #~ ":py:mod:`tensorcircuit.densitymatrix2`: Highly efficient" #~ " implementation of " @@ -397,3 +470,9 @@ msgstr "" #~ ":py:obj:`tensorcircuit.densitymatrix2.DMCircuit2` " #~ "类的高效实现,总是比参考的实现更适用。" +#~ msgid "" +#~ ":py:mod:`tensorcircuit.results`: Provide tools to" +#~ " process count dict and to apply " +#~ "error mitigation" +#~ msgstr "" + diff --git a/docs/source/locale/zh/LC_MESSAGES/quickstart.po b/docs/source/locale/zh/LC_MESSAGES/quickstart.po index fb97d394..b4275455 100644 --- a/docs/source/locale/zh/LC_MESSAGES/quickstart.po +++ b/docs/source/locale/zh/LC_MESSAGES/quickstart.po @@ -8,15 +8,15 @@ msgid "" msgstr "" "Project-Id-Version: tensorcircuit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-02 14:19+0800\n" -"PO-Revision-Date: 2022-04-11 08:23+0800\n" +"POT-Creation-Date: 2023-07-14 15:43+0800\n" +"PO-Revision-Date: 2023-05-07 11:01+0800\n" "Last-Translator: Xinghan Yang\n" "Language: cn\n" "Language-Team: Xinghan Yang\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.9.1\n" +"Generated-By: Babel 2.12.1\n" #: ../../source/quickstart.rst:3 msgid "Quick Start" @@ -24,15 +24,15 @@ msgstr "快速上手" #: ../../source/quickstart.rst:6 msgid "Installation" -msgstr "" +msgstr "安装" #: ../../source/quickstart.rst:8 -msgid "For x86 Linux or Mac," -msgstr "" +msgid "For x86 Linux," +msgstr "x64 Linux" #: ../../source/quickstart.rst:10 msgid "``pip install tensorcircuit``" -msgstr "" +msgstr "``pip install tensorcircuit``" #: ../../source/quickstart.rst:12 msgid "" @@ -71,19 +71,24 @@ msgstr "" #: ../../source/quickstart.rst:28 msgid "" -"For Windows, due to the lack of support for Jax, we recommend to use " -"docker or WSL, please refer to `TC via windows docker " -"`_ or `TC via WSL " -"`_." +"For more details on docker setup, please refer to `docker readme " +"`_." msgstr "" #: ../../source/quickstart.rst:30 msgid "" -"For Mac with M series chips (arm architecture), please refer to `TC on " -"Mac M series `_." +"For Windows, due to the lack of support for Jax, we recommend to use " +"docker or WSL, please refer to `TC via windows docker " +"`_ or `TC via WSL " +"`_." msgstr "" #: ../../source/quickstart.rst:32 +msgid "For MacOS, please refer to `TC on Mac `_." +msgstr "For MacOS, please refer to `在Mac上安装TC `_." + +#: ../../source/quickstart.rst:34 msgid "" "Overall, the installation of TensorCircuit is simple, since it is purely " "in Python and hence very portable. As long as the users can take care of " @@ -91,30 +96,36 @@ msgid "" "TensorCircuit will work as expected." msgstr "" -#: ../../source/quickstart.rst:36 +#: ../../source/quickstart.rst:37 +msgid "" +"To debug the installation issue or report bugs, please check the " +"environment information by ``tc.about()``." +msgstr "" + +#: ../../source/quickstart.rst:40 msgid "" "We also provide a nightly build of tensorcircuit via PyPI which can be " "accessed by ``pip uninstall tensorcircuit``, then ``pip install " "tensorcircuit-nightly``" msgstr "" -#: ../../source/quickstart.rst:42 +#: ../../source/quickstart.rst:46 msgid "Circuit Object" msgstr "电路对象" -#: ../../source/quickstart.rst:44 +#: ../../source/quickstart.rst:48 msgid "The basic object for TensorCircuit is ``tc.Circuit``." msgstr "TensorCircuit的基本对象是 ``tc.Circuit``。" -#: ../../source/quickstart.rst:46 +#: ../../source/quickstart.rst:50 msgid "Initialize the circuit with the number of qubits ``c=tc.Circuit(n)``." msgstr "用量子比特数(n) ``c=tc.Circuit(n)`` 来初始化电路。" -#: ../../source/quickstart.rst:48 +#: ../../source/quickstart.rst:52 msgid "**Input States:**" msgstr "**输入状态:**" -#: ../../source/quickstart.rst:50 +#: ../../source/quickstart.rst:54 msgid "" "The default input function for the circuit is :math:`\\vert 0^n " "\\rangle`. One can change this to other wavefunctions by directly feeding" @@ -123,17 +134,17 @@ msgstr "" "电路的默认输入函数是 :math:`\\vert 0^n \\rangle` 。可以通过直接输入输入状态向量 w 将其更改为其他波函数: " "``c=tc.Circuit(n, inputs=w)``。" -#: ../../source/quickstart.rst:52 +#: ../../source/quickstart.rst:56 msgid "" "One can also feed matrix product states as input states for the circuit, " "but we leave MPS/MPO usage for future sections." msgstr "也可以将矩阵乘积状态作为电路的输入状态,但我们将矩阵乘积状态/矩阵乘积算子的使用留待后续讲解。" -#: ../../source/quickstart.rst:54 +#: ../../source/quickstart.rst:58 msgid "**Quantum Gates:**" msgstr "**量子门:**" -#: ../../source/quickstart.rst:56 +#: ../../source/quickstart.rst:60 msgid "" "We can apply gates on circuit objects. For example, using ``c.H(1)`` or " "``c.rx(2, theta=0.2)``, we can apply Hadamard gate on qubit 1 (0-based) " @@ -142,15 +153,15 @@ msgstr "" "我们可以将门应用于电路对象。 例如,使用 ``c.H(1)`` 或 ``c.rx(2, theta=0.2)``,我们可以将 Hadamard " "门应用于量子比特1 (基于0)或将 Rx 门应用于量子比特2 :math:`e^{-i\\theta/2 X}`。" -#: ../../source/quickstart.rst:58 +#: ../../source/quickstart.rst:62 msgid "The same rule also applies to multi-qubit gates, such as ``c.cnot(0, 1)``." msgstr "同样的规则亦适用于多量子比特门,例如 ``c.cnot(0, 1)`` 。" -#: ../../source/quickstart.rst:60 +#: ../../source/quickstart.rst:64 msgid "There are also highly customizable gates, two instances are:" msgstr "这些量子门也是高度可定制的,下面是两个例子" -#: ../../source/quickstart.rst:62 +#: ../../source/quickstart.rst:66 msgid "" "``c.exp1(0, 1, unitary=m, theta=0.2)`` which is for the exponential gate " ":math:`e^{i\\theta m}` of any matrix m as long as :math:`m^2=1`." @@ -158,33 +169,33 @@ msgstr "" "``c.exp1(0, 1, unitary=m, theta=0.2)`` 用于任何矩阵 m 的指数门 :math:`e^{i\\theta " "m}`,只要 m 满足 :math:`m^2=1`。" -#: ../../source/quickstart.rst:64 +#: ../../source/quickstart.rst:68 msgid "" "``c.any(0, 1, unitary=m)`` which is for applying the unitary gate m on " "the circuit." msgstr "``c.any(0, 1, unitary=m)`` 在电路上作用任意的幺正量子门。" -#: ../../source/quickstart.rst:66 +#: ../../source/quickstart.rst:70 msgid "These two examples are flexible and support gates on any number of qubits." msgstr "这两个例子很灵活,支持任意数量的量子比特上的门。" -#: ../../source/quickstart.rst:68 +#: ../../source/quickstart.rst:72 msgid "**Measurements and Expectations:**" msgstr "**测量与期望**" -#: ../../source/quickstart.rst:70 +#: ../../source/quickstart.rst:74 msgid "" "The most straightforward way to get the output from the circuit object is" " by getting the output wavefunction in vector form as ``c.state()``." msgstr "从电路对象中获取输出的最直接的方法是通过 ``c.state()`` 以向量形式获取输出波函数。" -#: ../../source/quickstart.rst:72 +#: ../../source/quickstart.rst:76 msgid "" "For bitstring sampling, we have ``c.perfect_sampling()`` which returns " "the bitstring and the corresponding probability amplitude." msgstr "对于位串采样,我们有 ``c.perfect_sampling()``,它返回位串和相应的概率幅度。" -#: ../../source/quickstart.rst:74 +#: ../../source/quickstart.rst:78 msgid "" "To measure part of the qubits, we can use ``c.measure(0, 1)``, if we want" " to know the corresponding probability of the measurement output, try " @@ -195,18 +206,18 @@ msgstr "" "``c.measure(0, 1, with_prob=True)``。 测量 API 在默认情况下是不可即时编译的 " ",但我们也有一个可即时编译的版本,如 ``c.measure_jit(0, 1)``。" -#: ../../source/quickstart.rst:76 +#: ../../source/quickstart.rst:80 msgid "" "The measurement and sampling utilize advanced algorithms based on " "tensornetwork and thus require no knowledge or space for the full " "wavefunction." msgstr "测量和采样使用了基于张量网络的高级算法,因此不需要任何相关知识或者空间来获取全波函数。" -#: ../../source/quickstart.rst:78 +#: ../../source/quickstart.rst:82 msgid "See the example below:" msgstr "请看下面的例子:" -#: ../../source/quickstart.rst:96 +#: ../../source/quickstart.rst:100 msgid "" "To compute expectation values for local observables, we have " "``c.expectation([tc.gates.z(), [0]], [tc.gates.z(), [1]])`` for " @@ -218,35 +229,35 @@ msgstr "" "``c.expectation([tc.gates.x(), [0]])`` 对应的期望为 :math:`\\langle X_0 " "\\rangle`时." -#: ../../source/quickstart.rst:98 +#: ../../source/quickstart.rst:102 msgid "" "This expectation API is rather flexible, as one can measure an m on " "several qubits as ``c.expectation([m, [0, 1, 2]])``." msgstr "因为可以在几个量子比特上测量一个 m,这种计算期望值的 API 相当灵活:``c.expectation([m, [0, 1, 2]])``。" -#: ../../source/quickstart.rst:100 +#: ../../source/quickstart.rst:104 msgid "" "We can also extract the unitary matrix underlying the whole circuit as " "follows:" msgstr "我们还可以提取整个电路下面的幺正矩阵,如下所示:" -#: ../../source/quickstart.rst:113 +#: ../../source/quickstart.rst:117 msgid "**Circuit Transformations:**" msgstr "**电路可视化**" -#: ../../source/quickstart.rst:115 +#: ../../source/quickstart.rst:119 msgid "" "We currently support transform ``tc.Circuit`` from and to Qiskit " "``QuantumCircuit`` object." msgstr "我们目前支持 ``tc.Circuit`` 与 Qiskit ``QuantumCircuit`` 对象之间的互相转换。" -#: ../../source/quickstart.rst:117 +#: ../../source/quickstart.rst:121 msgid "" "Export to Qiskit (possible for further hardware experiment, compiling, " "and visualization): ``c.to_qiskit()``." msgstr "导出到 Qiskit(可能用于进一步的硬件实验、编译和可视化):``c.to_qiskit()``。" -#: ../../source/quickstart.rst:119 +#: ../../source/quickstart.rst:123 msgid "" "Import from Qiskit: ``c = tc.Circuit.from_qiskit(QuantumCircuit, n)``. " "Parameterized Qiskit circuit is supported by passing the parameters to " @@ -254,11 +265,11 @@ msgid "" "similar to the ``assign_parameters`` function in Qiskit." msgstr "" -#: ../../source/quickstart.rst:123 +#: ../../source/quickstart.rst:127 msgid "**Circuit Visualization:**" msgstr "**电路可视化**" -#: ../../source/quickstart.rst:125 +#: ../../source/quickstart.rst:129 msgid "" "``c.vis_tex()`` can generate tex code for circuit visualization based on " "LaTeX `quantikz `__ package." @@ -266,14 +277,14 @@ msgstr "" "``c.vis_tex()`` 可以基于 `quantikz `__ " "package 生成用于电路可视化的 tex 代码。" -#: ../../source/quickstart.rst:127 +#: ../../source/quickstart.rst:131 msgid "" "There are also some automatic pipeline helper functions to directly " "generate figures from tex code, but they require extra installations in " "the environment." msgstr "还有一些自动辅助函数可以直接从 tex 代码生成图形,但它们需要在环境中进行额外安装。" -#: ../../source/quickstart.rst:129 +#: ../../source/quickstart.rst:133 msgid "" "``render_pdf(tex)`` function requires full installation of LaTeX locally." " And in the Jupyter environment, we may prefer ``render_pdf(tex, " @@ -285,7 +296,7 @@ msgstr "" "``render_pdf(tex, notebook=True)`` 来返回 jpg 图形,这需要安装 wand magicwand 库,请参阅 " "`这里 `__ 。" -#: ../../source/quickstart.rst:131 +#: ../../source/quickstart.rst:135 msgid "" "Or since we can transform ``tc.Circuit`` into QuantumCircuit easily, we " "have a simple pipeline to first transform ``tc.Circuit`` into Qiskit and " @@ -296,18 +307,18 @@ msgstr "" "或者因为我们可以轻松地将 ``tc.Circuit`` 转换为 QuantumCircuit,我们有一个简单的管道来首先转换 " "``tc.Circuit`` 为 Qiskit,然后调用 Qiskit 中内置的可视化。 也就是说,我们有 ``c.draw()`` API。" -#: ../../source/quickstart.rst:133 +#: ../../source/quickstart.rst:137 msgid "**Circuit Intermediate Representation:**" msgstr "**电路中间表示:**" -#: ../../source/quickstart.rst:135 +#: ../../source/quickstart.rst:139 msgid "" "TensorCircuit provides its own circuit IR as a python list of dicts. This" " IR can be further utilized to run compiling, generate serialization " "qasm, or render circuit figures." msgstr "TensorCircuit 提供自己的中间表示是元素是字典的列表。此中间表示可进一步用于运行编译、生成序列化 qasm 或渲染电路图。" -#: ../../source/quickstart.rst:137 +#: ../../source/quickstart.rst:141 msgid "" "The IR is given as a list, each element is a dict containing information " "on one gate that is applied to the circuit. Note gate attr in the dict is" @@ -316,18 +327,18 @@ msgstr "" "中间表示以列表形式给出,每个元素都是一个字典,其中包含应用于电路的一个量子门的信息。 注意字典中的 gate atrr " "实际上是一个返回此量子门的节点的 python 函数。" -#: ../../source/quickstart.rst:149 +#: ../../source/quickstart.rst:153 msgid "Programming Paradigm" msgstr "编程范式" -#: ../../source/quickstart.rst:151 +#: ../../source/quickstart.rst:155 msgid "" "The most common case and the most typical programming paradigm for " "TensorCircuit are to evaluate the circuit output and the corresponding " "quantum gradients, which is common in variational quantum algorithms." msgstr "TensorCircuit 最常见的情况和最典型的编程范式是评估电路的输出以及相应的量子梯度,这在变分量子算法中很常见。" -#: ../../source/quickstart.rst:178 +#: ../../source/quickstart.rst:182 #, fuzzy msgid "" "Also for a non-quantum example (linear regression) demonstrating the " @@ -344,7 +355,7 @@ msgstr "" "dev/blob/master/examples/universal_lr.py>`_ 。 " "这个例子可能对机器学习的用户更友好,因为它纯粹是经典的,同时也展示了 TensorCircuit 的主要特征和范式。" -#: ../../source/quickstart.rst:181 +#: ../../source/quickstart.rst:185 msgid "" "If the user has no intention to maintain the application code in a " "backend agnostic fashion, the API for ML frameworks can be more handily " @@ -353,11 +364,11 @@ msgstr "" "如果用户无意以与后端无关的方式维护应用程序代码,则可以更方便地使用用于机器学习框架的 API 并将其与 TensorCircuit API " "交替使用。" -#: ../../source/quickstart.rst:216 +#: ../../source/quickstart.rst:220 msgid "Automatic Differentiation, JIT, and Vectorized Parallelism" msgstr "自动微分、即时编译和矢量化并行 " -#: ../../source/quickstart.rst:218 +#: ../../source/quickstart.rst:222 msgid "" "For concepts of AD, JIT and VMAP, please refer to `Jax documentation " "`__ ." @@ -365,7 +376,7 @@ msgstr "" "关于自动微分、即时编译和向量并行化,请参考 `Jax 文档 " "`__ 。" -#: ../../source/quickstart.rst:220 +#: ../../source/quickstart.rst:224 msgid "" "The related API design in TensorCircuit closely follows the functional " "programming design pattern in Jax with some slight differences. So we " @@ -375,21 +386,21 @@ msgstr "" "TensorCircuit 中的相关 API 设计与 Jax 中的函数式编程的设计模式密切相关,但是略有不同。因此,我们强烈建议用户学习一些有关 " "Jax 的基础知识,无论他们打算使用哪种机器学习后端。" -#: ../../source/quickstart.rst:222 +#: ../../source/quickstart.rst:226 msgid "**AD Support:**" msgstr "**自动微分支持**" -#: ../../source/quickstart.rst:224 +#: ../../source/quickstart.rst:228 msgid "" "Gradients, vjps, jvps, natural gradients, Jacobians, and Hessians. AD is " "the base for all modern machine learning libraries." msgstr "梯度、矢量雅可比乘积、自然梯度、 Jacobian 矩阵和 Hessian 矩阵。自动微分是所有现代机器学习库的基础。" -#: ../../source/quickstart.rst:228 +#: ../../source/quickstart.rst:232 msgid "**JIT Support:**" msgstr "**自动微分支持**" -#: ../../source/quickstart.rst:230 +#: ../../source/quickstart.rst:234 msgid "" "Parameterized quantum circuits can run in a blink. Always use jit if the " "circuit will get evaluations multiple times, it can greatly boost the " @@ -404,11 +415,11 @@ msgstr "" " 即时编译,否则,即时编译的函数可能会返回意外结果或每次在点击时都重新编译(浪费大量时间)。要了解更多关于即时编译机制的信息,可以参考关于 " "``tf.function`` 或 ``jax.jit`` 的文档或博客,即使这两者仍然存在细微差别。" -#: ../../source/quickstart.rst:234 +#: ../../source/quickstart.rst:238 msgid "**VMAP Support:**" msgstr "**自动微分支持**" -#: ../../source/quickstart.rst:236 +#: ../../source/quickstart.rst:240 msgid "" "Inputs, parameters, measurements, circuit structures, and Monte Carlo " "noise can all be evaluated in parallel. To learn more about vmap " @@ -418,11 +429,11 @@ msgstr "" "输入、参数、测量、电路结构、蒙特卡洛噪声都可以并行测算。 要了解有关矢量并行化机制的更多信息,可以参考 ``tf.vectorized_map``" " 或 ``jax.vmap`` 上的文档或博客。" -#: ../../source/quickstart.rst:241 +#: ../../source/quickstart.rst:245 msgid "Backend Agnosticism" msgstr "后端无关特性" -#: ../../source/quickstart.rst:243 +#: ../../source/quickstart.rst:247 msgid "" "TensorCircuit supports TensorFlow, Jax, and PyTorch backends. We " "recommend using TensorFlow or Jax backend since PyTorch lacks advanced " @@ -431,7 +442,7 @@ msgstr "" "TensorCircuit 支持 TensorFlow、Jax 和 PyTorch 后端。 我们建议使用 TensorFlow 或 Jax " "后端,因为 PyTorch 缺乏高级 jit 和 vmap 功能。" -#: ../../source/quickstart.rst:245 +#: ../../source/quickstart.rst:249 msgid "" "The backend can be set as ``K=tc.set_backend(\"jax\")`` and ``K`` is the " "backend with a full set of APIs as a conventional ML framework, which can" @@ -440,7 +451,7 @@ msgstr "" "后端可以设置为 ``K=tc.set_backend(\"jax\")`` ,``K``作为常规机器学习框架的全套API的后端,也可以通过``tc" " .backend`` 被访问。" -#: ../../source/quickstart.rst:268 +#: ../../source/quickstart.rst:272 #, fuzzy msgid "" "The supported APIs in the backend come from two sources, one part is " @@ -455,11 +466,15 @@ msgstr "" " 另一个来自 `TensorCircuit package `__。" -#: ../../source/quickstart.rst:422 +#: ../../source/quickstart.rst:427 +msgid "​" +msgstr "" + +#: ../../source/quickstart.rst:430 msgid "Switch the Dtype" msgstr "转换 dtype" -#: ../../source/quickstart.rst:424 +#: ../../source/quickstart.rst:432 msgid "" "TensorCircuit supports simulation using 32/64 bit precession. The default" " dtype is 32-bit as \"complex64\". Change this by " @@ -469,24 +484,24 @@ msgstr "" "\"complex64\"。可以通过 ``tc.set_dtype(\"complex128\")`` 把 dtype 改为 \"complex" " 128\" 。" -#: ../../source/quickstart.rst:427 +#: ../../source/quickstart.rst:435 msgid "" "``tc.dtypestr`` always returns the current dtype string: either " "\"complex64\" or \"complex128\"." msgstr "``tc.dtypestr`` 总会返回当前的 dtype 字符串: 不是 \"complex64\" 就是 \"complex128\"." -#: ../../source/quickstart.rst:431 +#: ../../source/quickstart.rst:439 msgid "Setup the Contractor" msgstr "设置 contractor" -#: ../../source/quickstart.rst:433 +#: ../../source/quickstart.rst:441 msgid "" "TensorCircuit is a tensornetwork contraction-based quantum circuit " "simulator. A contractor is for searching for the optimal contraction path" " of the circuit tensornetwork." msgstr "TensorCircuit 是一个基于张量网络收缩的量子电路模拟器。 contractor 用于搜索电路张量网络的最佳收缩路径。" -#: ../../source/quickstart.rst:435 +#: ../../source/quickstart.rst:443 msgid "" "There are various advanced contractors provided by third-party packages, " "such as `opt-einsum `__ and " @@ -496,7 +511,7 @@ msgstr "" "`__ 和 `cotengra " "`__ 。" -#: ../../source/quickstart.rst:437 +#: ../../source/quickstart.rst:445 msgid "" "`opt-einsum` is shipped with TensorNetwork package. To use cotengra, one " "needs to pip install it; kahypar is also recommended to install with " @@ -505,11 +520,11 @@ msgstr "" "`opt-einsum` 随 TensorNetwork 软件包一起。如要使用 cotengra,则需要 pip 安装它; 还建议安装 " "cotengra 随 kahypar 一起使用。" -#: ../../source/quickstart.rst:439 +#: ../../source/quickstart.rst:447 msgid "Some setup cases:" msgstr "一些设置案例:" -#: ../../source/quickstart.rst:465 +#: ../../source/quickstart.rst:473 #, fuzzy msgid "" "For advanced configurations on cotengra contractors, please refer to " @@ -524,25 +539,25 @@ msgstr "" "`contractor 教程 `__." -#: ../../source/quickstart.rst:467 +#: ../../source/quickstart.rst:475 msgid "**Setup in Function or Context Level**" msgstr "**函数和上下文级别的设置**" -#: ../../source/quickstart.rst:469 +#: ../../source/quickstart.rst:477 msgid "" "Beside global level setup, we can also setup the backend, the dtype, and " "the contractor at the function level or context manager level:" msgstr "除了全局级别设置,我们还可以在函数级别或上下文管理器级别设置后端、dtype 和contractor:" -#: ../../source/quickstart.rst:487 +#: ../../source/quickstart.rst:495 msgid "Noisy Circuit Simulation" msgstr "噪声电路模拟" -#: ../../source/quickstart.rst:489 +#: ../../source/quickstart.rst:497 msgid "**Monte Carlo State Simulator:**" msgstr "**蒙特卡洛态模拟器**" -#: ../../source/quickstart.rst:491 +#: ../../source/quickstart.rst:499 msgid "" "For the Monte Carlo trajectory noise simulator, the unitary Kraus channel" " can be handled easily. TensorCircuit also supports fully jittable and " @@ -551,40 +566,40 @@ msgstr "" "对于蒙特卡洛轨迹噪声模拟器,可以轻松处理幺正的 Kraus 通道。 不过,TensorCircuit 还支持完全可即时编译和可微分的通用 " "Kraus 通道蒙特卡罗模拟。" -#: ../../source/quickstart.rst:518 +#: ../../source/quickstart.rst:526 msgid "**Density Matrix Simulator:**" msgstr "**密度矩阵模拟器**" -#: ../../source/quickstart.rst:520 +#: ../../source/quickstart.rst:528 msgid "" "Density matrix simulator ``tc.DMCircuit`` simulates the noise in a full " "form, but takes twice qubits to do noiseless simulation. The API is the " "same as ``tc.Circuit``." msgstr "密度矩阵模拟器``tc.DMCircuit`` 以完整形式模拟噪声,但需要两倍的量子比特。API 与 ``tc.Circuit`` 基本相同。" -#: ../../source/quickstart.rst:539 +#: ../../source/quickstart.rst:547 msgid "**Experiment with quantum errors:**" msgstr "" -#: ../../source/quickstart.rst:541 +#: ../../source/quickstart.rst:549 msgid "Multiple quantum errors can be added on circuit." msgstr "" -#: ../../source/quickstart.rst:557 +#: ../../source/quickstart.rst:565 msgid "**Experiment with readout error:**" msgstr "" -#: ../../source/quickstart.rst:559 +#: ../../source/quickstart.rst:567 msgid "" "Readout error can be added in experiments for sampling and expectation " "value calculation." msgstr "" -#: ../../source/quickstart.rst:585 +#: ../../source/quickstart.rst:593 msgid "MPS and MPO" msgstr "矩阵乘积状态和矩阵乘积算子" -#: ../../source/quickstart.rst:587 +#: ../../source/quickstart.rst:595 msgid "" "TensorCircuit has its class for MPS and MPO originally defined in " "TensorNetwork as ``tc.QuVector``, ``tc.QuOperator``." @@ -592,7 +607,7 @@ msgstr "" "TensorCircuit 有自己的 MPS 和 MPO 类,起初在 TensorNetwork 中定义为“tc.QuVector” 和 " "“tc.QuOperator”。" -#: ../../source/quickstart.rst:589 +#: ../../source/quickstart.rst:597 msgid "" "``tc.QuVector`` can be extracted from ``tc.Circuit`` as the tensor " "network form for the output state (uncontracted) by ``c.quvector()``." @@ -600,7 +615,7 @@ msgstr "" "作为``c.quvector()`` 的输出状态(未收缩)的张量网络形式,``tc.QuVector`` 可以从``tc.Circuit`` " "中提取。" -#: ../../source/quickstart.rst:591 +#: ../../source/quickstart.rst:599 msgid "" "The QuVector forms a wavefunction w, which can also be fed into Circuit " "as the inputs state as ``c=tc.Circuit(n, mps_inputs=w)``." @@ -608,61 +623,61 @@ msgstr "" "QuVector 形成一个波函数 w,它也可以作为 ``c=tc.Circuit(n, mps_inputs=w)`` 的输入状态输入到 " "Circuit 中。" -#: ../../source/quickstart.rst:593 +#: ../../source/quickstart.rst:601 msgid "MPS as input state for circuit" msgstr "MPS 作为电路的输入状态" -#: ../../source/quickstart.rst:595 +#: ../../source/quickstart.rst:603 msgid "" "The MPS/QuVector representation of the input state has a more efficient " "and compact form." msgstr "输入状态的 MPS/QuVector 表示具有更高效和紧凑的形式。" -#: ../../source/quickstart.rst:607 +#: ../../source/quickstart.rst:615 msgid "MPS as (uncomputed) output state for circuit" msgstr "MPS 作为电路的(未计算的)输出状态" -#: ../../source/quickstart.rst:609 +#: ../../source/quickstart.rst:617 msgid "" "For example, a quick way to calculate the wavefunction overlap without " "explicitly computing the state amplitude is given as below:" msgstr "例如,在不显式计算状态幅度的情况下,计算波函数重叠的快速方法如下:" -#: ../../source/quickstart.rst:626 +#: ../../source/quickstart.rst:634 msgid "MPO as the gate on the circuit" msgstr "MPO 作为电路上的门" -#: ../../source/quickstart.rst:628 +#: ../../source/quickstart.rst:636 msgid "" "Instead of a common quantum gate in matrix/node format, we can directly " "apply a gate in MPO/QuOperator format." msgstr "代替矩阵/节点格式的普通量子门,我们可以直接应用 MPO/QuOperator 格式的门。" -#: ../../source/quickstart.rst:639 +#: ../../source/quickstart.rst:647 msgid "" "The representative gate defined in MPO format is the ``multicontrol`` " "gate." msgstr "以 MPO 格式定义的代表门是 ``multicontrol`` 门。" -#: ../../source/quickstart.rst:641 +#: ../../source/quickstart.rst:649 msgid "MPO as the operator for expectation evaluation on a circuit" msgstr "MPO作为电路期望估测算子" -#: ../../source/quickstart.rst:643 +#: ../../source/quickstart.rst:651 msgid "" "We can also measure operator expectation on the circuit output state " "where the operator is in MPO/QuOperator format." msgstr "我们还可以测量运算符对 MPO/QuOperator 格式的电路输出状态的期望。" -#: ../../source/quickstart.rst:655 +#: ../../source/quickstart.rst:663 msgid "Interfaces" msgstr "接口" -#: ../../source/quickstart.rst:657 +#: ../../source/quickstart.rst:665 msgid "**PyTorch Interface to Hybrid with PyTorch Modules:**" msgstr "**与 PyTorch 模块混合的 PyTorch 接口:**" -#: ../../source/quickstart.rst:659 +#: ../../source/quickstart.rst:667 msgid "" "As we have mentioned in the backend section, the PyTorch backend may lack" " advanced features. This doesn't mean we cannot hybrid the advanced " @@ -673,7 +688,7 @@ msgstr "" "正如我们在后端部分提到的,PyTorch 后端可能缺少高级功能。 这并不意味着我们不能将高级量子电路模块与 PyTorch 神经模块混合。 " "我们可以在 TensorFlow 或 Jax 后端运行量子函数,同时使用 Torch 接口包装它。 " -#: ../../source/quickstart.rst:686 +#: ../../source/quickstart.rst:694 msgid "" "For a GPU/CPU, torch/tensorflow, quantum/classical hybrid machine " "learning pipeline enabled by tensorcircuit, see `example script " @@ -681,96 +696,102 @@ msgid "" "lab/tensorcircuit/blob/master/examples/hybrid_gpu_pipeline.py>`__." msgstr "" -#: ../../source/quickstart.rst:688 +#: ../../source/quickstart.rst:696 +msgid "" +"There is also a more flexible torch interface that support static non-" +"tensor inputs as keyword arguments, which can be utilized as below:" +msgstr "" + +#: ../../source/quickstart.rst:710 msgid "" "We also provider wrapper of quantum function for torch module as " ":py:meth:`tensorcircuit.TorchLayer` alias to " ":py:meth:`tensorcircuit.torchnn.QuantumNet`." msgstr "" -#: ../../source/quickstart.rst:690 +#: ../../source/quickstart.rst:712 msgid "" "For ``TorchLayer``, ``use_interface=True`` is by default, which natively " "allow the quantum function defined on other tensorcircuit backends, such " "as jax or tf for speed consideration." msgstr "" -#: ../../source/quickstart.rst:692 +#: ../../source/quickstart.rst:714 msgid "" "``TorchLayer`` can process multiple input arguments as multiple function " "inputs, following torch practice." msgstr "" -#: ../../source/quickstart.rst:720 +#: ../../source/quickstart.rst:742 msgid "**TensorFlow interfaces:**" msgstr "" -#: ../../source/quickstart.rst:722 +#: ../../source/quickstart.rst:744 msgid "" "Similar rules apply similar as torch interface. The interface can even be" " used within jit environment outside. See " ":py:meth:`tensorcircuit.interfaces.tensorflow.tensorflow_interface`." msgstr "" -#: ../../source/quickstart.rst:725 +#: ../../source/quickstart.rst:747 msgid "" "We also provider ``enable_dlpack=True`` option in torch and tf " "interfaces, which allow the tensor transformation happen without memory " "transfer via dlpack, higher version of tf or torch package required." msgstr "" -#: ../../source/quickstart.rst:728 +#: ../../source/quickstart.rst:750 msgid "" "We also provider wrapper of quantum function for keras layer as " ":py:meth:`tensorcircuit.KerasLayer` alias to " ":py:meth:`tensorcircuit.keras.KerasLayer`." msgstr "" -#: ../../source/quickstart.rst:730 +#: ../../source/quickstart.rst:752 msgid "" "``KerasLayer`` can process multiple input arguments with the input as a " "dict, following the common keras practice, see example below." msgstr "" -#: ../../source/quickstart.rst:752 +#: ../../source/quickstart.rst:774 msgid "**Scipy Interface to Utilize Scipy Optimizers:**" msgstr "**使用 scipy接口使用scipy优化器:**" -#: ../../source/quickstart.rst:754 +#: ../../source/quickstart.rst:776 msgid "" "Automatically transform quantum functions as scipy-compatible values and " "grad functions as provided for scipy interface with ``jac=True``." msgstr "为带有 jac=True 的 scipy 接口自动将量子函数转换为与 scipy 兼容的 value 和 grad 函数。" -#: ../../source/quickstart.rst:780 +#: ../../source/quickstart.rst:802 msgid "Templates as Shortcuts" msgstr "捷径模板" -#: ../../source/quickstart.rst:782 +#: ../../source/quickstart.rst:804 msgid "**Measurements:**" msgstr "**测量**" -#: ../../source/quickstart.rst:784 +#: ../../source/quickstart.rst:806 msgid "Ising type Hamiltonian defined on a general graph" msgstr "在一般图上定义的伊辛型哈密顿量" -#: ../../source/quickstart.rst:786 +#: ../../source/quickstart.rst:808 msgid "" "See " ":py:meth:`tensorcircuit.templates.measurements.spin_glass_measurements`" msgstr "参考 :py:meth:`tensorcircuit.templates.measurements.spin_glass_measurements`" -#: ../../source/quickstart.rst:788 +#: ../../source/quickstart.rst:810 msgid "Heisenberg Hamiltonian on a general graph with possible external fields" msgstr "具有可能存在的外场的一般图上的海森堡哈密顿量" -#: ../../source/quickstart.rst:790 +#: ../../source/quickstart.rst:812 msgid "" "See " ":py:meth:`tensorcircuit.templates.measurements.heisenberg_measurements`" msgstr "参考 :py:meth:`tensorcircuit.templates.measurements.heisenberg_measurements`" -#: ../../source/quickstart.rst:792 +#: ../../source/quickstart.rst:814 msgid "**Circuit Blocks:**" msgstr "**电路块**" @@ -842,3 +863,13 @@ msgstr "**电路块**" #~ msgid "Import from Qiskit: ``c = tc.Circuit.from_qiskit(QuantumCircuit, n)``" #~ msgstr "从 Qiskit 导入:``c = tc.Circuit.from_qiskit(QuantumCircuit, n)``" +#~ msgid "For x86 Linux or Mac," +#~ msgstr "" + +#~ msgid "" +#~ "For Mac with M series chips (arm" +#~ " architecture), please refer to `TC " +#~ "on Mac M series " +#~ "`_." +#~ msgstr "" + diff --git a/docs/source/locale/zh/LC_MESSAGES/sharpbits.po b/docs/source/locale/zh/LC_MESSAGES/sharpbits.po index 95459bb9..5b2bfadc 100644 --- a/docs/source/locale/zh/LC_MESSAGES/sharpbits.po +++ b/docs/source/locale/zh/LC_MESSAGES/sharpbits.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: tensorcircuit \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-06-27 20:10+0800\n" +"POT-Creation-Date: 2023-05-07 10:47+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,9 +27,7 @@ msgid "" "Be fast is never for free, though much cheaper in TensorCircuit, but you " "have to be cautious especially in terms of AD, JIT compatibility. We will" " go through the main sharp edges 🔪 in this note." -msgstr "" -"虽然在TensorCircuit中速度很快,但是你必须小心,尤其是在AD和JIT兼容性" -"方面。" +msgstr "虽然在TensorCircuit中速度很快,但是你必须小心,尤其是在AD和JIT兼容性方面。" #: ../../source/sharpbits.rst:9 msgid "Jit Compatibility" @@ -45,10 +43,7 @@ msgid "" " otherwise the recompilation is incurred which is time-consuming. " "Therefore, if there are input args that are non-tensor or varying shape " "tensors and frequently change, jit is not recommend." -msgstr "" -"输入必须是张量形式,且输入张量的形状必须固定,否则会重新编译,这是非常耗" -"时的。因此,如果有输入参数是非张量或者变化形状的张量,且经常变化,不建议" -"使用jit。" +msgstr "输入必须是张量形式,且输入张量的形状必须固定,否则会重新编译,这是非常耗时的。因此,如果有输入参数是非张量或者变化形状的张量,且经常变化,不建议使用jit。" #: ../../source/sharpbits.rst:38 msgid "Mix use of numpy and ML backend APIs" @@ -63,17 +58,14 @@ msgid "" "For numpy ops, they will be only called in jit staging time (the first " "run)." msgstr "" -"为了使函数可jit和可AD,函数中的每个操作都应该通过ML后端(``tc.backend`` API" -"或者直接调用后端API ``tf`` 或者 ``jax``)。这是因为ML后端必须创建计算" -"图来"进行AD和JIT转换。对于numpy操作,它们只会在jit编译阶段被调用(第一" -"次运行)。" +"为了使函数可jit和可AD,函数中的每个操作都应该通过ML后端(``tc.backend`` API或者直接调用后端API ``tf`` 或者 " +"``jax``)。这是因为ML后端必须创建计算图来\"进行AD和JIT转换。对于numpy操作,它们只会在jit编译阶段被调用(第一次运行)。" #: ../../source/sharpbits.rst:54 msgid "" "Numpy call inside jitted function can be helpful if you are sure of the " "behavior is what you expect." -msgstr "" -"如果你确定numpy调用的行为是你期望的,那么在jit函数中调用numpy是有帮助的。" +msgstr "如果你确定numpy调用的行为是你期望的,那么在jit函数中调用numpy是有帮助的。" #: ../../source/sharpbits.rst:83 msgid "list append under if" @@ -84,37 +76,77 @@ msgid "" "Append something to a Python list within if whose condition is based on " "tensor values will lead to wrong results. Actually values of both branch " "will be attached to the list. See example below." -msgstr "" -"在if条件基于张量值的情况下,将内容附加到Python列表中会导致错误的结果。实际" -"上,两个分支的值都会被附加到列表中。参见下面的例子。" +msgstr "在if条件基于张量值的情况下,将内容附加到Python列表中会导致错误的结果。实际上,两个分支的值都会被附加到列表中。参见下面的例子。" #: ../../source/sharpbits.rst:108 msgid "" "The above code raise ``ConcretizationTypeError`` exception directly for " "Jax backend since Jax jit doesn't support tensor value if condition." -msgstr "" -"上面的代码直接为Jax后端引发了``ConcretizationTypeError``异常,因为Jax " -"jit不支持张量值if条件。" +msgstr "上面的代码直接为Jax后端引发了``ConcretizationTypeError``异常,因为Jax jit不支持张量值if条件。" #: ../../source/sharpbits.rst:110 msgid "Similarly, conditional gate application must be takend carefully." msgstr "类似地,必须小心地应用条件门。" #: ../../source/sharpbits.rst:145 +msgid "Tensor variables consistency" +msgstr "" + +#: ../../source/sharpbits.rst:148 +msgid "" +"All tensor variables' backend (tf vs jax vs ..), dtype (float vs " +"complex), shape and device (cpu vs gpu) must be compatible/consistent." +msgstr "" + +#: ../../source/sharpbits.rst:150 +msgid "Inspect the backend, dtype, shape and device using the following codes." +msgstr "" + +#: ../../source/sharpbits.rst:162 +msgid "" +"If the backend is inconsistent, one can convert the tensor backend via " +":py:meth:`tensorcircuit.interfaces.tensortrans.general_args_to_backend`." +msgstr "" + +#: ../../source/sharpbits.rst:173 +msgid "" +"If the dtype is inconsistent, one can convert the tensor dtype using " +"``tc.backend.cast``." +msgstr "" + +#: ../../source/sharpbits.rst:184 +msgid "" +"Also note the jax issue on float64/complex128, see `jax gotcha " +"`_." +msgstr "" + +#: ../../source/sharpbits.rst:186 +msgid "" +"If the shape is not consistent, one can convert the shape by " +"``tc.backend.reshape``." +msgstr "" + +#: ../../source/sharpbits.rst:188 +msgid "" +"If the device is not consistent, one can move the tensor between devices " +"by ``tc.backend.device_move``." +msgstr "" + +#: ../../source/sharpbits.rst:192 msgid "AD Consistency" msgstr "AD一致性" -#: ../../source/sharpbits.rst:147 +#: ../../source/sharpbits.rst:194 msgid "" "TF and JAX backend manage the differentiation rules differently for " "complex-valued function (actually up to a complex conjuagte). See issue " "discussion `tensorflow issue " "`_." msgstr "" -"TF和JAX后端对复值函数的微分规则的管理方式不同(实际上是复共轭)。参见讨论 " -"`tensorflow issue `_。" +"TF和JAX后端对复值函数的微分规则的管理方式不同(实际上是复共轭)。参见讨论 `tensorflow issue " +"`_。" -#: ../../source/sharpbits.rst:149 +#: ../../source/sharpbits.rst:196 msgid "" "In TensorCircuit, currently we make the difference in AD transparent, " "namely, when switching the backend, the AD behavior and result for " @@ -124,18 +156,18 @@ msgid "" "careful when dealing with AD on complex valued function in a backend " "agnostic way in TensorCircuit." msgstr "" -"在TensorCircuit中,我们目前使AD的差异透明,即在切换后端时,复值函数的AD行为" -"和结果可能不同,并由相应后端框架的本质行为决定。所有与AD相关的操作,如 " -"``grad`` 或者 ``jacrev`` 都可能受到影响。因此,用户在TensorCircuit中以后端" -"无关的方式处理复值函数的AD时必须小心。" +"在TensorCircuit中,我们目前使AD的差异透明,即在切换后端时,复值函数的AD行为和结果可能不同,并由相应后端框架的本质行为决定。所有与AD相关的操作,如" +" ``grad`` 或者 ``jacrev`` " +"都可能受到影响。因此,用户在TensorCircuit中以后端无关的方式处理复值函数的AD时必须小心。" -#: ../../source/sharpbits.rst:152 +#: ../../source/sharpbits.rst:199 msgid "" "See example script on computing Jacobian with different modes on " "different backends: `jacobian_cal.py `_. Also see the " "code below for a reference:" msgstr "" -"参考不同后端的不同模式下计算Jacobian的示例脚本:`jacobian_cal.py `_。" -"另外请参考下面的代码:" +"参考不同后端的不同模式下计算Jacobian的示例脚本:`jacobian_cal.py `_。另外请参考下面的代码:" + diff --git a/docs/source/modules.rst b/docs/source/modules.rst index fb5b3091..0144a199 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -1,5 +1,5 @@ tensorcircuit -================================================== +================================================================================ .. toctree:: ./api/about.rst ./api/abstractcircuit.rst @@ -8,10 +8,12 @@ tensorcircuit ./api/basecircuit.rst ./api/channels.rst ./api/circuit.rst + ./api/cloud.rst ./api/compiler.rst ./api/cons.rst ./api/densitymatrix.rst ./api/experimental.rst + ./api/fgs.rst ./api/gates.rst ./api/interfaces.rst ./api/keras.rst @@ -20,6 +22,7 @@ tensorcircuit ./api/noisemodel.rst ./api/quantum.rst ./api/results.rst + ./api/shadows.rst ./api/simplify.rst ./api/templates.rst ./api/torchnn.rst diff --git a/docs/source/modules.rst.backup b/docs/source/modules.rst.backup index 28261e24..280c7584 100644 --- a/docs/source/modules.rst.backup +++ b/docs/source/modules.rst.backup @@ -1,200 +1,29 @@ -tensorcircuit API -===================== - +tensorcircuit +================================================== .. toctree:: - :maxdepth: 4 - - -tensorcircuit.backends module ------------------------------------- - -.. automodule:: tensorcircuit.backends - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.backends.backend_factory module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.backends.backend_factory - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.backends.jax_backend module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.backends.jax_backend - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.backends.numpy_backend module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.backends.numpy_backend - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.backends.pytorch_backend module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.backends.pytorch_backend - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.backends.tensorflow_backend module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.backends.tensorflow_backend - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.channels module -------------------------------------- - -.. automodule:: tensorcircuit.channels - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.circuit module -------------------------------------- - -.. automodule:: tensorcircuit.circuit - :members: - :undoc-members: - :show-inheritance: - - -tensorcircuit.cons module -------------------------------------- - -.. automodule:: tensorcircuit.cons - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.densitymatrix module -------------------------------------- - -.. automodule:: tensorcircuit.densitymatrix - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.densitymatrix2 module -------------------------------------- - -.. automodule:: tensorcircuit.densitymatrix2 - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.experimental module -------------------------------------- - -.. automodule:: tensorcircuit.experimental - :members: - :undoc-members: - :show-inheritance: - - -tensorcircuit.gates module ---------------------------------- - -.. automodule:: tensorcircuit.gates - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.interfaces module ---------------------------------- - -.. automodule:: tensorcircuit.interfaces - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.keras module ---------------------------------- - -.. automodule:: tensorcircuit.keras - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.mpscircuit module ---------------------------------- - -.. automodule:: tensorcircuit.mpscircuit - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.quantum module ---------------------------------- - -.. automodule:: tensorcircuit.quantum - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.simplify module ---------------------------------- - -.. automodule:: tensorcircuit.simplify - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.templates module ------------------------------------- - -.. automodule:: tensorcircuit.templates - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.templates.blocks module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.templates.blocks - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.templates.graphs module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.templates.graphs - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.templates.measurements module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: tensorcircuit.templates.measurements - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.utils module ---------------------------------- - -.. automodule:: tensorcircuit.utils - :members: - :undoc-members: - :show-inheritance: - -tensorcircuit.vis module ---------------------------------- - -.. automodule:: tensorcircuit.vis - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file + ./api/about.rst + ./api/abstractcircuit.rst + ./api/applications.rst + ./api/backends.rst + ./api/basecircuit.rst + ./api/channels.rst + ./api/circuit.rst + ./api/cloud.rst + ./api/compiler.rst + ./api/cons.rst + ./api/densitymatrix.rst + ./api/experimental.rst + ./api/gates.rst + ./api/interfaces.rst + ./api/keras.rst + ./api/mps_base.rst + ./api/mpscircuit.rst + ./api/noisemodel.rst + ./api/quantum.rst + ./api/results.rst + ./api/simplify.rst + ./api/templates.rst + ./api/torchnn.rst + ./api/translation.rst + ./api/utils.rst + ./api/vis.rst \ No newline at end of file diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 32d54342..647066b6 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -5,7 +5,7 @@ Quick Start Installation -------------- -- For x86 Linux or Mac, +- For x86 Linux, ``pip install tensorcircuit`` @@ -25,9 +25,11 @@ Docker is also recommended (especially Linux + Nvidia GPU setup): ``sudo docker run -it --network host --gpus all tensorcircuit/tensorcircuit``. +For more details on docker setup, please refer to `docker readme `_. + - For Windows, due to the lack of support for Jax, we recommend to use docker or WSL, please refer to `TC via windows docker `_ or `TC via WSL `_. -- For Mac with M series chips (arm architecture), please refer to `TC on Mac M series `_. +- For MacOS, please refer to `TC on Mac `_. Overall, the installation of TensorCircuit is simple, since it is purely in Python and hence very portable. As long as the users can take care of the installation of ML frameworks on the corresponding system, TensorCircuit will work as expected. @@ -146,6 +148,8 @@ The IR is given as a list, each element is a dict containing information on one >>> c.to_qir() [{'gate': cnot, 'index': (0, 1), 'name': 'cnot', 'split': None}, {'gate': crx, 'index': (1, 0), 'name': 'crx', 'split': None, 'parameters': {'theta': 0.2}}] +We can also create new copied circuit via ``c.copy()`` which internally utilize the ``qir``. + Programming Paradigm ------------------------- diff --git a/docs/source/statics/landscape.jpg b/docs/source/statics/landscape.jpg new file mode 100644 index 00000000..3ffd7902 Binary files /dev/null and b/docs/source/statics/landscape.jpg differ diff --git a/docs/source/statics/qd_alg.jpg b/docs/source/statics/qd_alg.jpg new file mode 100644 index 00000000..3300f074 Binary files /dev/null and b/docs/source/statics/qd_alg.jpg differ diff --git a/docs/source/statics/tianxuan_s1.png b/docs/source/statics/tianxuan_s1.png new file mode 100644 index 00000000..983ac187 Binary files /dev/null and b/docs/source/statics/tianxuan_s1.png differ diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst index 2596f072..e5697960 100644 --- a/docs/source/tutorial.rst +++ b/docs/source/tutorial.rst @@ -6,6 +6,9 @@ Jupyter Tutorials tutorials/circuit_basics.ipynb tutorials/qaoa.ipynb + tutorials/qaoa_bo.ipynb + tutorials/qaoa_nae3sat.ipynb + tutorials/qaoa_quantum_dropout.ipynb tutorials/tfim_vqe.ipynb tutorials/mnist_qml.ipynb tutorials/torch_qml.ipynb @@ -20,4 +23,9 @@ Jupyter Tutorials tutorials/vqex_mbl.ipynb tutorials/dqas.ipynb tutorials/barren_plateaus.ipynb - tutorials/qaoa_portfolio_optimization.ipynb \ No newline at end of file + tutorials/qubo_problem.ipynb + tutorials/portfolio_optimization.ipynb + tutorials/imag_time_evo.ipynb + tutorials/classical_shadows.ipynb + tutorials/sklearn_svc.ipynb + tutorials/qcloud_sdk_demo.ipynb \ No newline at end of file diff --git a/docs/source/tutorial_cn.rst b/docs/source/tutorial_cn.rst index a6f4d03f..956d03b6 100644 --- a/docs/source/tutorial_cn.rst +++ b/docs/source/tutorial_cn.rst @@ -19,4 +19,5 @@ tutorials/optimization_and_expressibility_cn.ipynb tutorials/vqex_mbl_cn.ipynb tutorials/dqas_cn.ipynb - tutorials/barren_plateaus_cn.ipynb \ No newline at end of file + tutorials/barren_plateaus_cn.ipynb + tutorials/sklearn_svc_cn.ipynb \ No newline at end of file diff --git a/docs/source/tutorials/barren_plateaus_cn.ipynb b/docs/source/tutorials/barren_plateaus_cn.ipynb index 4288475f..6f5a8a49 100644 --- a/docs/source/tutorials/barren_plateaus_cn.ipynb +++ b/docs/source/tutorials/barren_plateaus_cn.ipynb @@ -158,7 +158,9 @@ " dtype=\"float32\",\n", ")\n", "\n", - "e, grad = op_expectation_vmap_vvag(params, seed, n, nlayers) # 不同随机电路的 ZZ 可观测量和梯度的期望\n", + "e, grad = op_expectation_vmap_vvag(\n", + " params, seed, n, nlayers\n", + ") # 不同随机电路的 ZZ 可观测量和梯度的期望\n", "\n", "grad_var = tf.math.reduce_std(tf.math.reduce_std(grad, axis=0), axis=0)[\n", " 0, 0\n", diff --git a/docs/source/tutorials/benchmark_circuits.ipynb b/docs/source/tutorials/benchmark_circuits.ipynb new file mode 100644 index 00000000..e2e5eb1d --- /dev/null +++ b/docs/source/tutorials/benchmark_circuits.ipynb @@ -0,0 +1,211 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Benchmark Chips" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Benchmark chips using mirror circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "from tensorcircuit.results import qem\n", + "from tensorcircuit.results.qem import benchmark_circuits\n", + "import random\n", + "import numpy as np\n", + "\n", + "from tensorcircuit.cloud import apis\n", + "from tensorcircuit.results import counts\n", + "from tensorcircuit.compiler.qiskit_compiler import qiskit_compile\n", + "from matplotlib import cm\n", + "\n", + "%matplotlib inline\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0, 1], [6, 2], [4, 0], [0, 4], [8, 4], [1, 5], [3, 7], [0, 3], [2, 0], [5, 1], [3, 0], [7, 3], [0, 2], [2, 6], [4, 8], [1, 0]]\n" + ] + } + ], + "source": [ + "d = apis.get_device(\"tianxuan_s1\")\n", + "couple_list = d.topology()\n", + "print(couple_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "nq: [0, 1] depth: 1 success 4.1484000000000005\n", + "nq: [0, 1] depth: 2 success 3.7722999999999995\n", + "nq: [0, 1, 2] depth: 1 success 3.2711\n", + "nq: [0, 1, 2] depth: 2 success 3.2814\n", + "nq: [0, 1, 2, 3] depth: 1 success 3.1682000000000006\n", + "nq: [0, 1, 2, 3] depth: 2 success 2.5158\n", + "nq: [0, 1, 2, 3, 4] depth: 1 success 2.1039999999999996\n", + "nq: [0, 1, 2, 3, 4] depth: 2 success 1.4552999999999998\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "result_list = []\n", + "\n", + "\n", + "for nq in range(2, 6):\n", + " qlis = list(range(nq))\n", + " graph = []\n", + " for i in range(len(couple_list)):\n", + " if couple_list[i][0] in qlis and couple_list[i][1] in qlis:\n", + " graph.append(couple_list[i])\n", + "\n", + " G = nx.Graph()\n", + " G.add_edges_from(graph)\n", + " nx.draw(G, with_labels=True)\n", + "\n", + " for depth in range(1, 3):\n", + " A = 0\n", + " for numc in range(5):\n", + " c, ideal = benchmark_circuits.mirror_circuit(\n", + " depth=depth,\n", + " two_qubit_gate_prob=1,\n", + " connectivity_graph=G,\n", + " seed=random.randint(0, 100),\n", + " ) # includes np.sqrt(X)^{\\dagger} gate,identity gate\n", + "\n", + " c1, info = qiskit_compile(\n", + " c,\n", + " compiled_options={\n", + " \"basis_gates\": [\"h\", \"rz\", \"x\", \"y\", \"z\", \"cz\"],\n", + " \"optimization_level\": 2,\n", + " # \"coupling_map\": d.topology(),\n", + " },\n", + " )\n", + "\n", + " t = apis.submit_task(\n", + " circuit=c1,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + " )\n", + " raw_count = t.results(blocked=True) # position_counts=logical_counts\n", + " # print(\"raw\",raw_count[list(ideal.keys())[0]]/10000)\n", + "\n", + " A += raw_count[list(ideal.keys())[0]] / 10000\n", + " print(\"nq:\", qlis, \"depth:\", depth, \"success\", A)\n", + " result_list.append(A)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "result_list1 = [i / 5 for i in result_list]\n", + "result_list2 = np.reshape(result_list1, [4, 2])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Depth')" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots()\n", + "Z = np.transpose(result_list2)\n", + "X = list(range(2, 6))\n", + "Y = list(range(1, 3))\n", + "p = ax.pcolor(X, Y, Z, vmin=Z.min(), vmax=Z.max(), cmap=\"rainbow\")\n", + "cb = fig.colorbar(p, ax=ax)\n", + "plt.xlabel(\"Nqubit\")\n", + "plt.ylabel(\"Depth\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.13 ('tf')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "4d2770c334f3778740193ba4b3686745ae5c2e3ee10c8c0d673798cf1c2fcefe" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/tutorials/classical_shadows.ipynb b/docs/source/tutorials/classical_shadows.ipynb new file mode 100644 index 00000000..e6776482 --- /dev/null +++ b/docs/source/tutorials/classical_shadows.ipynb @@ -0,0 +1,795 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Classical Shadows in Pauli Basis" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Overview" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "[Classical shadows](https://www.nature.com/articles/s41567-020-0932-7) formalism is an efficient method to estimate multiple observables. In this tutorial, we will show how to use the ``shadows`` module in ``TensorCircuit`` to implement classic shadows in Pauli basis." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Let's first briefly review the classical shadows in Pauli basis. For an $n$-qubit quantum state $\\rho$, we randomly perform Pauli projection measurement on each qubit and obtain a snapshot like $\\{1,-1,-1,1,\\cdots,1,-1\\}$. This process is equivalent to apply a random unitary $U_i$ to $\\rho$ and measure in computational basis to obtain $|b_i\\rangle=|s_{i1}\\cdots s_{in}\\rangle,\\ s_{ij}\\in\\{0,1\\}$:\n", + "$$\n", + "\\rho\\rightarrow U_i\\rho U_i^{\\dagger}\\xrightarrow{measure}|b_i\\rangle\\langle b_i|,\n", + "$$\n", + "where $U_i=\\bigotimes_{j=1}^{n}u_{ij}$, $u_{ij}\\in\\{H, HS^{\\dagger}, \\mathbb{I}\\}$ correspond to the projection measurements of Pauli $X$, $Y$, $Z$ respectively. Then we reverse the operation to get the equivalent measurement result on $\\rho$:\n", + "$$\n", + "\\rho\\xrightarrow{measure}U_i^{\\dagger}|b_i\\rangle\\langle b_i| U_i.\n", + "$$\n", + "Moreover, we perform $N$ random measurements and view their average as a quantum channel:\n", + "$$\n", + "\\mathbb{E}\\left[U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i\\right]=\\mathcal{M}(\\rho),\n", + "$$\n", + "we can invert the channel to get the approximation of $\\rho$:\n", + "$$\n", + "\\rho=\\mathbb{E}\\left[\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)\\right].\n", + "$$\n", + "We call each $\\rho_i=\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)$ a shadow snapshot state and their ensemble $S(\\rho;N)=\\{\\rho_i|i=1,\\cdots,N\\}$ classical shadows." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "In Pauli basis, we have a simple expression of $\\mathcal{M}^{-1}$:\n", + "$$\n", + "\\begin{split}\n", + " \\rho_i&=\\mathcal{M}^{-1}(U_i^{\\dagger}|b_i\\rangle\\langle b_i|U_i)=\\bigotimes_{j=1}^{n}\\left(3u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}|u_{ij}-\\mathbb{I}\\right),\\\\\n", + " \\rho&=\\frac{1}{N}\\sum_{i=1}^{N}\\rho_i\\ .\n", + "\\end{split}\n", + "$$\n", + "For an observable Pauli string $O=\\bigotimes_{j=1}^{n}P_j,\\ P_j\\in\\{\\mathbb{I}, X, Y, Z\\}$, we can directly use $\\rho$ to calculate $\\langle O\\rangle=\\text{Tr}(O\\rho)$. In practice, we will divide the classical shadows into $K$ parts to calculate the expectation values independently and take the median to avoid the influence of outliers:\n", + "$$\n", + "\\langle O\\rangle=\\text{median}\\{\\langle O_{(1)}\\rangle,\\cdots,\\langle O_{(K)}\\rangle\\},\n", + "$$\n", + "where\n", + "$$\n", + "\\begin{split}\n", + " \\langle O_{(k)}\\rangle&=\\frac{1}{\\lceil N/K\\rceil}\\sum_{i=(k-1)\\lceil N/K\\rceil+1}^{k\\lceil N/K\\rceil}\\text{Tr}\\left[\\bigotimes_{j=1}^{n}P_j(3u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}|u_{ij}-\\mathbb{I})\\right]\\\\\n", + " &=\\frac{1}{\\lceil N/K\\rceil}\\sum_{i=(k-1)\\lceil N/K\\rceil+1}^{k\\lceil N/K\\rceil}\\prod_{j=1}^n\\text{Tr}\\left[3P_j u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}|u_{ij}\\right].\n", + "\\end{split}\n", + "$$" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Setup" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 13, + "outputs": [ + { + "data": { + "text/plain": "('complex128', 'float64')" + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import tensorcircuit as tc\n", + "from tensorcircuit import shadows\n", + "import numpy as np\n", + "from functools import partial\n", + "import time\n", + "import matplotlib.pyplot as plt\n", + "\n", + "tc.set_backend(\"jax\")\n", + "tc.set_dtype(\"complex128\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:21.649753Z", + "start_time": "2023-08-09T04:51:21.598273400Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## Construct the Classical Shadow Snapshots" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We first set the number of qubits $n$ and the number of repeated measurements $r$ on each Pauli string. Then from the target observable Pauli strings $\\{O_i|i=1,\\cdots,M\\}$ (0, 1, 2, and 3 correspond to $\\mathbb{I}$, $X$, $Y$, and $Z$, respectively), the error $\\epsilon$ and the rate of failure $\\delta$, we can use ``shadow_bound`` function to get the total number of snapshots $N$ and the number of equal parts $K$ to split the shadow snapshot states to compute the median of means:\n", + "$$\n", + "\\begin{split}\n", + " K&=2\\log(2M/\\delta),\\\\\n", + " N&=K\\frac{34}{\\epsilon^2}\\max_{1\\le i\\le M}\\left\\|O_i-\\frac{\\text{Tr}(O_i)}{2^n}\\mathbb{I}\\right\\|^2_{\\text{shadow}}=K\\frac{34}{\\epsilon^2}3^{\\max_{1\\le i\\le M}k_i},\n", + "\\end{split}\n", + "$$\n", + "where $k_i$ is the number of nontrivial Pauli matrices in $O_i$. Please refer to the Theorem S1 and Lemma S3 in [Huang, Kueng and Preskill (2020)](https://www.nature.com/articles/s41567-020-0932-7) for the details of proof. It should be noted that ``shadow_bound`` has a certain degree of overestimation of $N$, and so many measurements are not really needed in practice. Moreover, ``shadow_bound`` is not jitable and no need to jit." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 14, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N: 489600\tK: 16\tnumber of Pauli strings: 97920\n" + ] + } + ], + "source": [ + "n, r = 8, 5\n", + "ps = [\n", + " [1, 0, 0, 0, 0, 0, 0, 2],\n", + " [0, 3, 0, 0, 0, 0, 1, 0],\n", + " [0, 0, 2, 0, 0, 3, 0, 0],\n", + " [0, 0, 0, 1, 2, 0, 0, 0],\n", + " [0, 0, 0, 3, 1, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 3, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 2, 0],\n", + " [3, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 2, 0, 0, 0, 0, 3, 0],\n", + " [0, 0, 1, 0, 0, 2, 0, 0],\n", + "]\n", + "\n", + "epsilon, delta = 0.1, 0.01\n", + "N, K = shadows.shadow_bound(ps, epsilon, delta)\n", + "nps = N // r # number of random selected Pauli strings\n", + "print(f\"N: {N}\\tK: {K}\\tnumber of Pauli strings: {nps}\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:21.707924900Z", + "start_time": "2023-08-09T04:51:21.604342400Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then we use random quantum circuit to generate an entangled state." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 15, + "outputs": [], + "source": [ + "nlayers = 10\n", + "thetas = 2 * np.random.rand(nlayers, n) - 1\n", + "\n", + "c = tc.Circuit(n)\n", + "for i in range(n):\n", + " c.H(i)\n", + "for i in range(nlayers):\n", + " for j in range(n):\n", + " c.cnot(j, (j + 1) % n)\n", + " for j in range(n):\n", + " c.rz(j, theta=thetas[i, j] * np.pi)\n", + "\n", + "psi = c.state()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:21.814604700Z", + "start_time": "2023-08-09T04:51:21.615066400Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "We randomly generate Pauli strings. Since the function after just-in-time (jit) compilation does not support random sampling, we need to generate all random states in advance, that is, variable ``status``." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 16, + "outputs": [], + "source": [ + "pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(nps, n)))\n", + "status = tc.backend.convert_to_tensor(np.random.rand(nps, r))" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:21.815119500Z", + "start_time": "2023-08-09T04:51:21.813574500Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "If ``measurement_only=True`` (default ``False``), the outputs of ``shadow_snapshots`` are snapshot bit strings $\\{b_i=s_{i1}\\cdots s_{in}\\ |i=1,\\cdots,N,\\ s_{ij}\\in\\{0,1\\}\\}$, otherwise the outputs are snapshot states $\\{u_{ij}^{\\dagger}|s_{ij}\\rangle\\langle s_{ij}| u_{ij}\\ |i=1,\\cdots,N,\\ j=1,\\cdots,n\\}$. If you only need to generate one batch of snapshots or generate multiple batches of snapshots with different ``nps`` or ``r``, jit cannot provide speedup. Jit will only accelerate when the same shape of snapshots are generated multiple times." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 17, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "shape of snapshot states: (97920, 5, 8, 2, 2)\n" + ] + } + ], + "source": [ + "@partial(tc.backend.jit, static_argnums=(3,))\n", + "def shadow_ss(psi, pauli_strings, status, measurement_only=False):\n", + " return shadows.shadow_snapshots(\n", + " psi, pauli_strings, status, measurement_only=measurement_only\n", + " )\n", + "\n", + "\n", + "ss_states = shadow_ss(psi, pauli_strings, status) # jit is not necessary here\n", + "print(\"shape of snapshot states:\", ss_states.shape)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:24.715816800Z", + "start_time": "2023-08-09T04:51:21.883673400Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## Estimate the Expectation Values of Observables" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Since the operation of taking the median is not jitable, the outputs of ``expectation_ps_shadows`` have $K$ values, and we need to take the median of them." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 18, + "outputs": [], + "source": [ + "def shadow_expec(snapshots_states, ob):\n", + " return shadows.expectation_ps_shadow(snapshots_states, ps=ob, k=K)\n", + "\n", + "\n", + "sejit = tc.backend.jit(shadow_expec)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:51:25.082792700Z", + "start_time": "2023-08-09T04:51:24.750909500Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "It can be seen from the running time that every time the number of Pauli strings changes, ``shadow_expec`` will be recompiled, but for the same number of Pauli strings but different observables, ``shadow_expec`` will only be compiled once. In the end, the absolute errors given by classical shadows are much smaller than the $\\epsilon=0.1$ we set, so ``shadow_bound`` gives a very loose upper bound." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 19, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "observable: No.0\tnumber of Pauli strings: 1000\ttime: 0.9454922676086426\n", + "observable: No.1\tnumber of Pauli strings: 1000\ttime: 0.001840353012084961\n", + "observable: No.2\tnumber of Pauli strings: 1000\ttime: 0.0014374256134033203\n", + "observable: No.3\tnumber of Pauli strings: 1000\ttime: 0.0013763904571533203\n", + "observable: No.4\tnumber of Pauli strings: 1000\ttime: 0.0013554096221923828\n", + "observable: No.5\tnumber of Pauli strings: 1000\ttime: 0.0013613700866699219\n", + "observable: No.6\tnumber of Pauli strings: 1000\ttime: 0.0013325214385986328\n", + "observable: No.7\tnumber of Pauli strings: 1000\ttime: 0.0013136863708496094\n", + "observable: No.8\tnumber of Pauli strings: 1000\ttime: 0.0013325214385986328\n", + "observable: No.9\tnumber of Pauli strings: 1000\ttime: 0.0013117790222167969\n", + "observable: No.0\tnumber of Pauli strings: 10000\ttime: 0.9969091415405273\n", + "observable: No.1\tnumber of Pauli strings: 10000\ttime: 0.012966394424438477\n", + "observable: No.2\tnumber of Pauli strings: 10000\ttime: 0.012765884399414062\n", + "observable: No.3\tnumber of Pauli strings: 10000\ttime: 0.012974739074707031\n", + "observable: No.4\tnumber of Pauli strings: 10000\ttime: 0.012665033340454102\n", + "observable: No.5\tnumber of Pauli strings: 10000\ttime: 0.012889623641967773\n", + "observable: No.6\tnumber of Pauli strings: 10000\ttime: 0.013180255889892578\n", + "observable: No.7\tnumber of Pauli strings: 10000\ttime: 0.012682914733886719\n", + "observable: No.8\tnumber of Pauli strings: 10000\ttime: 0.012678146362304688\n", + "observable: No.9\tnumber of Pauli strings: 10000\ttime: 0.012636423110961914\n", + "observable: No.0\tnumber of Pauli strings: 20000\ttime: 1.015674352645874\n", + "observable: No.1\tnumber of Pauli strings: 20000\ttime: 0.025749921798706055\n", + "observable: No.2\tnumber of Pauli strings: 20000\ttime: 0.02578139305114746\n", + "observable: No.3\tnumber of Pauli strings: 20000\ttime: 0.02524733543395996\n", + "observable: No.4\tnumber of Pauli strings: 20000\ttime: 0.025956153869628906\n", + "observable: No.5\tnumber of Pauli strings: 20000\ttime: 0.02669525146484375\n", + "observable: No.6\tnumber of Pauli strings: 20000\ttime: 0.026634931564331055\n", + "observable: No.7\tnumber of Pauli strings: 20000\ttime: 0.026463985443115234\n", + "observable: No.8\tnumber of Pauli strings: 20000\ttime: 0.0273745059967041\n", + "observable: No.9\tnumber of Pauli strings: 20000\ttime: 0.026821374893188477\n", + "observable: No.0\tnumber of Pauli strings: 30000\ttime: 1.0086262226104736\n", + "observable: No.1\tnumber of Pauli strings: 30000\ttime: 0.03922295570373535\n", + "observable: No.2\tnumber of Pauli strings: 30000\ttime: 0.038678884506225586\n", + "observable: No.3\tnumber of Pauli strings: 30000\ttime: 0.03868269920349121\n", + "observable: No.4\tnumber of Pauli strings: 30000\ttime: 0.04024958610534668\n", + "observable: No.5\tnumber of Pauli strings: 30000\ttime: 0.03927755355834961\n", + "observable: No.6\tnumber of Pauli strings: 30000\ttime: 0.039815664291381836\n", + "observable: No.7\tnumber of Pauli strings: 30000\ttime: 0.04002213478088379\n", + "observable: No.8\tnumber of Pauli strings: 30000\ttime: 0.03934764862060547\n", + "observable: No.9\tnumber of Pauli strings: 30000\ttime: 0.04060721397399902\n", + "observable: No.0\tnumber of Pauli strings: 40000\ttime: 1.2912404537200928\n", + "observable: No.1\tnumber of Pauli strings: 40000\ttime: 0.05326724052429199\n", + "observable: No.2\tnumber of Pauli strings: 40000\ttime: 0.05272030830383301\n", + "observable: No.3\tnumber of Pauli strings: 40000\ttime: 0.054486989974975586\n", + "observable: No.4\tnumber of Pauli strings: 40000\ttime: 0.0538792610168457\n", + "observable: No.5\tnumber of Pauli strings: 40000\ttime: 0.05555129051208496\n", + "observable: No.6\tnumber of Pauli strings: 40000\ttime: 0.05361533164978027\n", + "observable: No.7\tnumber of Pauli strings: 40000\ttime: 0.05325675010681152\n", + "observable: No.8\tnumber of Pauli strings: 40000\ttime: 0.05487465858459473\n", + "observable: No.9\tnumber of Pauli strings: 40000\ttime: 0.05441641807556152\n", + "observable: No.0\tnumber of Pauli strings: 50000\ttime: 0.999931812286377\n", + "observable: No.1\tnumber of Pauli strings: 50000\ttime: 0.06137228012084961\n", + "observable: No.2\tnumber of Pauli strings: 50000\ttime: 0.06159329414367676\n", + "observable: No.3\tnumber of Pauli strings: 50000\ttime: 0.06138134002685547\n", + "observable: No.4\tnumber of Pauli strings: 50000\ttime: 0.060491085052490234\n", + "observable: No.5\tnumber of Pauli strings: 50000\ttime: 0.06045842170715332\n", + "observable: No.6\tnumber of Pauli strings: 50000\ttime: 0.0629739761352539\n", + "observable: No.7\tnumber of Pauli strings: 50000\ttime: 0.06146860122680664\n", + "observable: No.8\tnumber of Pauli strings: 50000\ttime: 0.061437129974365234\n", + "observable: No.9\tnumber of Pauli strings: 50000\ttime: 0.061475515365600586\n", + "observable: No.0\tnumber of Pauli strings: 60000\ttime: 1.03033447265625\n", + "observable: No.1\tnumber of Pauli strings: 60000\ttime: 0.06811189651489258\n", + "observable: No.2\tnumber of Pauli strings: 60000\ttime: 0.06913161277770996\n", + "observable: No.3\tnumber of Pauli strings: 60000\ttime: 0.06945395469665527\n", + "observable: No.4\tnumber of Pauli strings: 60000\ttime: 0.06843304634094238\n", + "observable: No.5\tnumber of Pauli strings: 60000\ttime: 0.06950116157531738\n", + "observable: No.6\tnumber of Pauli strings: 60000\ttime: 0.07009696960449219\n", + "observable: No.7\tnumber of Pauli strings: 60000\ttime: 0.06856656074523926\n", + "observable: No.8\tnumber of Pauli strings: 60000\ttime: 0.06969141960144043\n", + "observable: No.9\tnumber of Pauli strings: 60000\ttime: 0.0678703784942627\n", + "observable: No.0\tnumber of Pauli strings: 70000\ttime: 1.0191996097564697\n", + "observable: No.1\tnumber of Pauli strings: 70000\ttime: 0.07705307006835938\n", + "observable: No.2\tnumber of Pauli strings: 70000\ttime: 0.07620859146118164\n", + "observable: No.3\tnumber of Pauli strings: 70000\ttime: 0.07670450210571289\n", + "observable: No.4\tnumber of Pauli strings: 70000\ttime: 0.0766746997833252\n", + "observable: No.5\tnumber of Pauli strings: 70000\ttime: 0.07552027702331543\n", + "observable: No.6\tnumber of Pauli strings: 70000\ttime: 0.07716488838195801\n", + "observable: No.7\tnumber of Pauli strings: 70000\ttime: 0.07647228240966797\n", + "observable: No.8\tnumber of Pauli strings: 70000\ttime: 0.07623863220214844\n", + "observable: No.9\tnumber of Pauli strings: 70000\ttime: 0.07545590400695801\n", + "observable: No.0\tnumber of Pauli strings: 80000\ttime: 1.0341267585754395\n", + "observable: No.1\tnumber of Pauli strings: 80000\ttime: 0.08658909797668457\n", + "observable: No.2\tnumber of Pauli strings: 80000\ttime: 0.08614206314086914\n", + "observable: No.3\tnumber of Pauli strings: 80000\ttime: 0.0857245922088623\n", + "observable: No.4\tnumber of Pauli strings: 80000\ttime: 0.08441877365112305\n", + "observable: No.5\tnumber of Pauli strings: 80000\ttime: 0.08495783805847168\n", + "observable: No.6\tnumber of Pauli strings: 80000\ttime: 0.08582544326782227\n", + "observable: No.7\tnumber of Pauli strings: 80000\ttime: 0.0861966609954834\n", + "observable: No.8\tnumber of Pauli strings: 80000\ttime: 0.08437252044677734\n", + "observable: No.9\tnumber of Pauli strings: 80000\ttime: 0.0852508544921875\n", + "observable: No.0\tnumber of Pauli strings: 90000\ttime: 1.031904697418213\n", + "observable: No.1\tnumber of Pauli strings: 90000\ttime: 0.09243512153625488\n", + "observable: No.2\tnumber of Pauli strings: 90000\ttime: 0.09180665016174316\n", + "observable: No.3\tnumber of Pauli strings: 90000\ttime: 0.09398865699768066\n", + "observable: No.4\tnumber of Pauli strings: 90000\ttime: 0.09126615524291992\n", + "observable: No.5\tnumber of Pauli strings: 90000\ttime: 0.09299516677856445\n", + "observable: No.6\tnumber of Pauli strings: 90000\ttime: 0.09152960777282715\n", + "observable: No.7\tnumber of Pauli strings: 90000\ttime: 0.09381914138793945\n", + "observable: No.8\tnumber of Pauli strings: 90000\ttime: 0.09076142311096191\n", + "observable: No.9\tnumber of Pauli strings: 90000\ttime: 0.08988714218139648\n", + "observable: No.0\tnumber of Pauli strings: 97920\ttime: 1.050750494003296\n", + "observable: No.1\tnumber of Pauli strings: 97920\ttime: 0.09993815422058105\n", + "observable: No.2\tnumber of Pauli strings: 97920\ttime: 0.10038924217224121\n", + "observable: No.3\tnumber of Pauli strings: 97920\ttime: 0.09895133972167969\n", + "observable: No.4\tnumber of Pauli strings: 97920\ttime: 0.09973955154418945\n", + "observable: No.5\tnumber of Pauli strings: 97920\ttime: 0.10170507431030273\n", + "observable: No.6\tnumber of Pauli strings: 97920\ttime: 0.09864187240600586\n", + "observable: No.7\tnumber of Pauli strings: 97920\ttime: 0.09945058822631836\n", + "observable: No.8\tnumber of Pauli strings: 97920\ttime: 0.09991574287414551\n", + "observable: No.9\tnumber of Pauli strings: 97920\ttime: 0.09802794456481934\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "bz = 1000\n", + "\n", + "exact = []\n", + "for ob in ps:\n", + " exact.append(tc.backend.real(c.expectation_ps(ps=ob)))\n", + "exact = np.asarray(exact)[:, None]\n", + "\n", + "bzs, res = [], []\n", + "for i in range(bz, nps + bz, bz):\n", + " res.append([])\n", + " ss_states_batch = ss_states[:i]\n", + " bzs.append(ss_states_batch.shape[0])\n", + " t0 = time.time()\n", + " for j, ob in enumerate(ps):\n", + " expcs = sejit(ss_states_batch, ob)\n", + " res[-1].append(np.median(expcs))\n", + " t = time.time()\n", + " if i == bz or i % (bz * 10) == 0 or i >= nps:\n", + " print(\n", + " f\"observable: No.{j}\\tnumber of Pauli strings: {bzs[-1]}\\ttime: {t - t0}\"\n", + " )\n", + " t0 = t\n", + "res = np.asarray(res).T\n", + "bzs = np.asarray(bzs) * r\n", + "\n", + "error = np.abs(res - exact)\n", + "plt.figure()\n", + "plt.xlabel(\"N\")\n", + "plt.ylabel(\"Error\")\n", + "for i, y in enumerate(error):\n", + " plt.plot(bzs, y, label=f\"No.{i}\")\n", + "plt.legend()\n", + "plt.show()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:53:57.091936Z", + "start_time": "2023-08-09T04:51:25.071809100Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## Estimate the Entanglement Entropy" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We can also use classical shadows to calculate entanglement entropy. ``entropy_shadow`` first reconstructs the reduced density matrix, then solves the eigenvalues and finally calculates the entanglement entropy from non-negative eigenvalues. Since the time and space complexity of reconstructing the density matrix is exponential with respect to the system size, this method is only efficient when the reduced system size is constant. ``entropy_shadow`` is jitable, but it will only accelerate when the reduced sub systems have the same shape." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 20, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sub: [1, 4]\ttime: 0.1788625717163086\texact: 1.3222456063743848\tshadow entropy: 1.323659494989336\n", + "sub: [2, 7]\ttime: 0.03922629356384277\texact: 1.313932933107046\tshadow entropy: 1.315937416629094\n", + "sub: [3, 6]\ttime: 0.03881263732910156\texact: 1.342032043092265\tshadow entropy: 1.3427963599754822\n", + "sub: [0, 5]\ttime: 0.03893852233886719\texact: 1.3458706554536102\tshadow entropy: 1.346507278883028\n", + "sub: [7, 0]\ttime: 0.039243221282958984\texact: 1.3496695271830874\tshadow entropy: 1.3504498597279848\n", + "sub: [1, 4, 7]\ttime: 0.2567908763885498\texact: 1.8741003653918944\tshadow entropy: 1.8777698830270055\n", + "sub: [0, 3, 6]\ttime: 0.11173439025878906\texact: 1.8633273061204374\tshadow entropy: 1.8638162138941512\n", + "sub: [5, 4, 2]\ttime: 0.11144137382507324\texact: 1.908653965480665\tshadow entropy: 1.9084333256925539\n", + "sub: [7, 2, 5]\ttime: 0.1119997501373291\texact: 1.8916979397866593\tshadow entropy: 1.88828077605345\n", + "sub: [0, 1, 2]\ttime: 0.11184382438659668\texact: 1.8717789129825904\tshadow entropy: 1.8724197548909916\n" + ] + } + ], + "source": [ + "subs = [\n", + " [1, 4],\n", + " [2, 7],\n", + " [3, 6],\n", + " [0, 5],\n", + " [7, 0],\n", + " [1, 4, 7],\n", + " [0, 3, 6],\n", + " [5, 4, 2],\n", + " [7, 2, 5],\n", + " [0, 1, 2],\n", + "]\n", + "\n", + "\n", + "@tc.backend.jit\n", + "def shadow_ent(snapshots_states, sub, alpha=2):\n", + " return shadows.entropy_shadow(snapshots_states, sub=sub, alpha=alpha)\n", + "\n", + "\n", + "for sub in subs:\n", + " exact_rdm = tc.quantum.reduced_density_matrix(\n", + " psi, cut=[i for i in range(n) if i not in sub]\n", + " )\n", + " exact_ent = tc.quantum.renyi_entropy(exact_rdm, k=2)\n", + "\n", + " t0 = time.time()\n", + " ent = shadow_ent(ss_states, sub)\n", + " t = time.time()\n", + " print(f\"sub: {sub}\\ttime: {t - t0}\\texact: {exact_ent}\\tshadow entropy: {ent}\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:53:58.139584Z", + "start_time": "2023-08-09T04:53:57.091936Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "On the other hand, for the second order Renyi entropy, we have another method to calculate it in polynomial time by random measurements:\n", + "$$\n", + "\\begin{split}\n", + " R_A^2&=-\\log\\left(\\text{Tr}(\\rho_A^2)\\right),\\\\\n", + " \\text{Tr}(\\rho_A^2)&=2^k\\sum_{b,b'\\in\\{0,1\\}^k}(-2)^{-H(b,b')}\\overline{P(b)P(b')},\n", + "\\end{split}\n", + "$$\n", + "where $A$ is the $k$-d reduced system, $H(b,b')$ is the Hamming distance between $b$ and $b'$, $P(b)$ is the probability for measuring $\\rho_A$ and obtaining the outcomes $b$ thus we need a larger $r$ to obtain a good enough priori probability, and the overline means the average on all random selected Pauli strings. Please refer to [Brydges, et al. (2019)](https://www.science.org/doi/full/10.1126/science.aau4963) for more details. We can use ``renyi_entropy_2`` to implement this method, but it is not jitable because we need to build the dictionary based on the bit strings obtained by measurements, which is a dynamical process. Compared with ``entropy_shadow``, it cannot filter out non-negative eigenvalues, so the accuracy is slightly worse." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 21, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sub: [1, 4]\ttime: 3.794407606124878\tshadow entropy 2: 1.2866729353788704\n", + "sub: [2, 7]\ttime: 3.796651840209961\tshadow entropy 2: 1.2875279355654872\n", + "sub: [3, 6]\ttime: 3.760688066482544\tshadow entropy 2: 1.314993963087972\n", + "sub: [0, 5]\ttime: 3.765700101852417\tshadow entropy 2: 1.317198599992926\n", + "sub: [7, 0]\ttime: 3.784120559692383\tshadow entropy 2: 1.3218300427352758\n", + "sub: [1, 4, 7]\ttime: 3.859661817550659\tshadow entropy 2: 1.7701671972428563\n", + "sub: [0, 3, 6]\ttime: 3.874009132385254\tshadow entropy 2: 1.7684695179560657\n", + "sub: [5, 4, 2]\ttime: 3.831859827041626\tshadow entropy 2: 1.8037352454314826\n", + "sub: [7, 2, 5]\ttime: 3.824885368347168\tshadow entropy 2: 1.8006117836020135\n", + "sub: [0, 1, 2]\ttime: 3.8377578258514404\tshadow entropy 2: 1.782393800345501\n" + ] + } + ], + "source": [ + "nps, r = 1000, 500\n", + "\n", + "pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(nps, n)))\n", + "status = tc.backend.convert_to_tensor(np.random.rand(nps, r))\n", + "\n", + "snapshots = shadows.shadow_snapshots(psi, pauli_strings, status, measurement_only=True)\n", + "\n", + "t0 = time.time()\n", + "for sub in subs:\n", + " ent2 = shadows.renyi_entropy_2(snapshots, sub)\n", + "\n", + " t = time.time()\n", + " print(f\"sub: {sub}\\ttime: {t - t0}\\tshadow entropy 2: {ent2}\")\n", + " t0 = t" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:54:36.511330700Z", + "start_time": "2023-08-09T04:53:58.139683500Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## Reconstruct the Density Matrix" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We can use ``global_shadow_state``, ``global_shadow_state1`` or ``global_shadow_state2`` to reconstruct the density matrix. These three functions use different methods, but the results are exactly the same. All functions are jitable, but since we only use each of them once here, they are not wrapped. In terms of implementation details, ``global_shadow_state`` uses ``kron`` and is recommended, the other two use ``einsum``." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 22, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "exact:\n", + " [[0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]\n", + " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", + " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", + " [0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]]\n", + "\n", + "shadow state: error: 0.02441655995426051\n", + " [[ 0.49141+0.j 0.00159+0.00219j 0.00378+0.00306j 0.5004 +0.0081j ]\n", + " [ 0.00159-0.00219j 0.0019 +0.j -0.00855+0.00297j -0.00567-0.00126j]\n", + " [ 0.00378-0.00306j -0.00855-0.00297j 0.00805+0.j -0.00273-0.00249j]\n", + " [ 0.5004 -0.0081j -0.00567+0.00126j -0.00273+0.00249j 0.49864+0.j ]]\n", + "\n", + "shadow state 1: error: 0.02441655995426051\n", + " [[ 0.49141+0.j 0.00159+0.00219j 0.00378+0.00306j 0.5004 +0.0081j ]\n", + " [ 0.00159-0.00219j 0.0019 +0.j -0.00855+0.00297j -0.00567-0.00126j]\n", + " [ 0.00378-0.00306j -0.00855-0.00297j 0.00805+0.j -0.00273-0.00249j]\n", + " [ 0.5004 -0.0081j -0.00567+0.00126j -0.00273+0.00249j 0.49864+0.j ]]\n", + "\n", + "shadow state 2: error: 0.02441655995426051\n", + " [[ 0.49141+0.j 0.00159+0.00219j 0.00378+0.00306j 0.5004 +0.0081j ]\n", + " [ 0.00159-0.00219j 0.0019 +0.j -0.00855+0.00297j -0.00567-0.00126j]\n", + " [ 0.00378-0.00306j -0.00855-0.00297j 0.00805+0.j -0.00273-0.00249j]\n", + " [ 0.5004 -0.0081j -0.00567+0.00126j -0.00273+0.00249j 0.49864+0.j ]]\n" + ] + } + ], + "source": [ + "n, nps, r = 2, 10000, 5\n", + "\n", + "c = tc.Circuit(n)\n", + "c.H(0)\n", + "c.cnot(0, 1)\n", + "\n", + "psi = c.state()\n", + "bell_state = psi[:, None] @ psi[None, :]\n", + "\n", + "pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(nps, n)))\n", + "status = tc.backend.convert_to_tensor(np.random.rand(nps, r))\n", + "lss_states = shadows.shadow_snapshots(psi, pauli_strings, status)\n", + "sdw_state = shadows.global_shadow_state(lss_states)\n", + "sdw_state1 = shadows.global_shadow_state1(lss_states)\n", + "sdw_state2 = shadows.global_shadow_state2(lss_states)\n", + "\n", + "print(\"exact:\\n\", bell_state)\n", + "print(f\"\\nshadow state: error: {np.linalg.norm(bell_state - sdw_state)}\\n\", sdw_state)\n", + "print(\n", + " f\"\\nshadow state 1: error: {np.linalg.norm(bell_state - sdw_state)}\\n\", sdw_state1\n", + ")\n", + "print(\n", + " f\"\\nshadow state 2: error: {np.linalg.norm(bell_state - sdw_state)}\\n\", sdw_state2\n", + ")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:54:36.634162200Z", + "start_time": "2023-08-09T04:54:36.517005400Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 23, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", + "Python version: 3.10.11\n", + "Numpy version: 1.23.5\n", + "Scipy version: 1.11.0\n", + "Pandas version: 2.0.2\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra version: 0.2.1.dev15+g120379e\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: []\n", + "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", + "Jax version: 0.4.13\n", + "Jax installation doesn't support GPU\n", + "JaxLib version: 0.4.13\n", + "PyTorch version: 2.0.1\n", + "PyTorch GPU support: False\n", + "PyTorch GPUs: []\n", + "Cupy is not installed\n", + "Qiskit version: 0.24.1\n", + "Cirq version: 1.1.0\n", + "TensorCircuit version 0.10.0\n" + ] + } + ], + "source": [ + "tc.about()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-09T04:54:36.638744200Z", + "start_time": "2023-08-09T04:54:36.634714500Z" + } + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/source/tutorials/error_mitigation.ipynb b/docs/source/tutorials/error_mitigation.ipynb new file mode 100644 index 00000000..abb35992 --- /dev/null +++ b/docs/source/tutorials/error_mitigation.ipynb @@ -0,0 +1,613 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# QEM Applications" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "from tensorcircuit.results import qem\n", + "from tensorcircuit.results.qem import qem_methods, benchmark_circuits\n", + "from tensorcircuit.results.qem import (\n", + " zne_option,\n", + " apply_zne,\n", + " dd_option,\n", + " apply_dd,\n", + " apply_rc,\n", + ")\n", + "\n", + "from tensorcircuit.cloud import apis\n", + "from tensorcircuit.results import counts\n", + "from tensorcircuit.results.readout_mitigation import ReadoutMit\n", + "from tensorcircuit.compiler.qiskit_compiler import qiskit_compile\n", + "\n", + "from functools import partial\n", + "import numpy as np\n", + "import networkx as nx" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ZNE" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0, 1], [6, 2], [4, 0], [0, 4], [8, 4], [1, 5], [3, 7], [0, 3], [2, 0], [5, 1], [3, 0], [7, 3], [0, 2], [2, 6], [4, 8], [1, 0]]\n" + ] + } + ], + "source": [ + "d = apis.get_device(\"tianxuan_s1\")\n", + "couple_list = d.topology()\n", + "print(couple_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "mit = tc.results.rem.ReadoutMit(\n", + " \"tianxuan_s1?o=0\"\n", + ") # set ?o=0 for readout mitigation initialization\n", + "mit.cals_from_system(qubits=9, shots=4096)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "graph = [(2, 0), (3, 7), (0, 3), (1, 5), (2, 6)]\n", + "weight = [1] * len(graph)\n", + "params = np.array([[1, 1], [1, 1]])\n", + "optimization_level = 2\n", + "\n", + "\n", + "c = benchmark_circuits.QAOA_circuit(graph, weight, params)\n", + "c.to_qiskit().draw(\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "c1, info = qiskit_compile(\n", + " c,\n", + " compiled_options={\n", + " \"basis_gates\": [\"h\", \"rz\", \"x\", \"y\", \"z\", \"cz\"],\n", + " \"optimization_level\": optimization_level,\n", + " # \"coupling_map\": d.topology(),\n", + " },\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ideal 0.9400000000000001\n", + "raw 0.37379999999999997\n", + "read 0.4909275773352902\n" + ] + } + ], + "source": [ + "t = apis.submit_task(circuit=c, shots=10000, device=\"simulator:aer\")\n", + "raw_count = t.results(blocked=True)\n", + "ideal = sum(\n", + " [\n", + " -counts.expectation(raw_count, z=[graph[e][0], graph[e][1]]) * weight[e]\n", + " for e in range(len(graph))\n", + " ]\n", + ")\n", + "print(\"ideal\", ideal)\n", + "\n", + "t = apis.submit_task(\n", + " circuit=c1,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + ")\n", + "raw_count = t.results(blocked=True)\n", + "raw = sum(\n", + " [\n", + " -counts.expectation(raw_count, z=[graph[e][0], graph[e][1]]) * weight[e]\n", + " for e in range(len(graph))\n", + " ]\n", + ")\n", + "print(\"raw\", raw)\n", + "read = sum(\n", + " [\n", + " -mit.expectation(raw_count, z=[graph[e][0], graph[e][1]], **info) * weight[e]\n", + " for e in range(len(graph))\n", + " ]\n", + ")\n", + "print(\"read\", read)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "zne 0.6603988839789069\n" + ] + }, + { + "data": { + "image/png": "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nDkTWlrvTtyOiYlBs2bNMHPmTN6AmoiIVApLHNF/aGtrY/r06bh69SpsbW0BAHl5eQgICICjoyPu3r0rcEIiIqJ3WOKICmFvb4+rV69i2rRp0NTUBPDuYtJGRkYCJyMiInqHJY7oI3R0dDBr1ixcvnwZ1tbWCAoKkt0dhIiISGgscUSf0bRpU0RFRWHAgAFy469evcLSpUuRl5cnUDIiIirLWOKIikBbWxsikUhuzNvbG7/88gtatWqFmzdvCpSMiIjKKpY4oi8QFxeHPXv2AACuXLmCxo0bY9GiRcjPzxc4GRERlRUscURfwNraGhcuXED9+vUBADk5OZgwYQLatGmD27dvC5yOiIjKApY4oi/UokULXL9+Hb/88ovso9aIiAjY29tj2bJlXJUjIqJixRJH9BX09fWxePFi/P3336hbty4A4O3bt/D19UW7du14XTkiIio2LHFEStCqVStER0fj559/lq3KXbhwARcuXBA4GRERlVYscURKYmBggGXLluHcuXOoXbs2evTogeHDhwsdi4iISiktoQMQlTZt27ZFTEwM3rx5U+CyJKdPn0bHjh2hocG/n4iI6OvwvyRExaBcuXIwNTWVGzt69ChcXFzg7OyMR48eCROMiIhKDZY4ohLw9u1b/PDDDwCAs2fPwsbGBuvWrYNUKhU4GRERqSuWOKISoKenh61bt6JmzZoAgMzMTPz444/o3Lkznjx5InA6IiJSRyxxRCWkU6dOiI2NxahRo2Rjp0+fhrW1NTZu3MhVOSIiUghLHFEJMjIywrp163Dy5EnUqFEDAJCRkQEvLy907doV//77r8AJiYhIXbDEEQmgc+fOiIuLw/fffy8bO3nyJHx8fARMRURE6oQljkggxsbG2LRpE44fP45q1arB0NAQy5YtEzoWERGpCV4njkhgXbt2RVxcHG7cuCE78eG9xMREmJmZFbjeHBEREVfiiFRAxYoV0b59e7mx9PR0ODo6olevXkhISBAmGBERqSyWOCIV5efnhydPnuDIkSOwsrLC77//zjNYiYhIhiWOSEV169YNVapUAQC8fv0aQ4cOxXfffYekpCSBkxERkSpgiSNSUb1790Z8fDwGDhwoGzt48CCsrKywa9cursoREZVxLHFEKszU1BQ7d+7Evn37ULlyZQDAq1evMGjQIPTv3x/JyckCJyQiIqGwxBGpgb59+yI+Ph79+/eXjf3xxx9o3rw5cnNzBUxGRERCYYkjUhOVK1fGnj17sHv3blSqVAnAu5MfdHR0BE5GRERCYIkjUjMDBgxAfHw8ZsyYgTFjxsg9l5+fL1AqIiIqaV9U4vLy8nD69GmsW7cOGRkZAIDnz58jMzNTqeGIqHBmZmYICAiAhob8j/D48eMxePBgvHr1SqBkRERUUhQucY8fP4aNjQ169eqFsWPH4sWLFwCABQsWwM/PT+kBPxQUFARLS0vo6enB0dERV65cKdJ+u3btgkgkQu/evYs3IJFAwsPDsWrVKuzcuRNWVlY4fPiw0JGIiKgYKVzifHx84ODggNevX0NfX1823qdPH4SFhSk13Id2794NX19fzJgxA1FRUbCzs4Orq+tnz9B79OgR/Pz80KZNm2LNRySk169fo0KFCgCApKQk9OrVC+7u7nj9+rWwwYiIqFgoXOL+/vtvTJ06tcDB1JaWlnj27JnSghVm6dKl8PLygqenJxo1aoS1a9fCwMAAmzdv/ug++fn5GDJkCGbOnInatWsXaz4iIb2/rlz37t1lY9u2bYOVlRWOHTsmYDIiIioOWoruIJFICj14+t9//4WhoaFSQhUmNzcXkZGR8Pf3l41paGjA2dkZERERH91v1qxZqFKlCkaMGIG///77s98nJycHOTk5ssfp6ekAALFYDLFY/BXvgIrD+znh3LxTuXJl7N+/H9u2bcMvv/yCtLQ0JCQkoEePHnB3d8fixYtlq3UlhXOk2jg/qo3zo/qUPUeKvI7CJa5z585Yvnw51q9fDwAQiUTIzMzEjBkz0K1bN0VfrshevnyJ/Px8mJmZyY2bmZnh1q1bhe5z/vx5bNq0CdHR0UX+PoGBgZg5c2aB8bNnz8LAwEChzFRyQkNDhY6gUkxNTbFkyRL89ttviIqKAgBs3boVx44dw5w5c1C1atUSz8Q5Um2cH9XG+VF9ypqj7OzsIm+rcIlbsmQJXF1d0ahRI7x9+xaDBw/G3bt3ZVeWVxUZGRkYNmwYNmzYAFNT0yLv5+/vD19fX9nj9PR0WFhYoEOHDrJrc5HqEIvFCA0NhYuLC7S1tYWOo3KGDRuG4OBg+Pn5ISMjA3Xr1oWHhwc0NTVLLAPnSLVxflQb50f1KXuO3n8CWBQKl7gaNWrgxo0b2LVrF2JiYpCZmYkRI0ZgyJAhcic6KJupqSk0NTUL3Pw7KSkJ5ubmBba/f/8+Hj16hJ49e8rGJBIJAEBLSwu3b99GnTp1Cuynq6sLXV3dAuPa2tr8AVJhnJ+PGzVqFLp06QJvb28sXrwYenp6guTgHKk2zo9q4/yoPmXNkSKvoXCJA96VoKFDh37Jrl9MR0cHTZs2RVhYmOwyIRKJBGFhYfD29i6wfYMGDRAbGys3NnXqVGRkZGDFihWwsLAoidhEKqFmzZqFXnIkIiICW7duxcKFC4v1mFYiIlI+hUvc1q1bP/m8u7v7F4f5HF9fXwwfPhwODg5o3rw5li9fjqysLHh6esq+d/Xq1REYGAg9PT1YW1vL7f/+gO4Px4nKojdv3sDDwwN37tzBn3/+ic2bN6Njx45CxyIioiJSuMT5+PjIPRaLxcjOzoaOjg4MDAyKtcS5ubnhxYsXmD59OhITE2Fvb48TJ07ITnZ48uRJgSvYE1HhoqKiZJcFevz4MTp16oSxY8di/vz5KF++vMDpiIjocxRuPK9fv5b7yszMxO3bt9G6desSObHB29sbjx8/Rk5ODi5fvgxHR0fZc+fOnUNwcPBH9w0ODsbBgweLPSOROmjVqhViYmLQrl072VhQUBBsbW0RHh4uYDIiIioKpSxb1a1bF/Pnzy+wSkdEqq127do4c+YMVq5cKTsx6eHDh2jfvj18fHyQlZUlcEIiIvoYpX32qKWlhefPnyvr5YiohGhoaOCnn35CTEwMWrduLRtfuXIl7OzscPXqVQHTERHRxyh8TNyHZ7hJpVIkJCRg9erVaNWqldKCEVHJ+vbbb3Hu3DmsWrUK/v7+ePv2LZ4+fVqslw4iIqIvp3CJe395j/dEIhEqV66Mjh07YsmSJcrKRUQC0NTUxM8//4xu3brBw8MDPXv25NncREQq6ovunUpEpVu9evXw999/QyqVyo3n5ORg5cqV8Pb25godEZHAeD0OIiqUpqYmtLTk/86bPXs2JkyYgCZNmuDy5csCJSMiIqCIK3H/vZfo5yxduvSLwxCR6nr58iWWLVsGALh16xZatmyJCRMmICAgoNBb1RERUfEqUom7fv16kV5MJBJ9VRgiUl2mpqa4cuUKPDw8cO3aNUgkEsyfPx+HDx9GSEgIHBwchI5IRFSmFKnEnT17trhzEJEasLKyQkREBBYuXIiAgACIxWL8888/aNGiBSZNmoRp06ZxVY6IqITwmDgiUoiWlhYmT56MyMhINGnSBACQn5+PuXPnwsHBAVFRUQInJCIqGxQ+OxUArl27hj179uDJkyfIzc2Ve27//v1KCUZEqs3GxgaXLl3C/PnzMWvWLOTl5SEuLg4HDx6UlTsiIio+Cq/E7dq1Cy1btsTNmzdx4MABiMVixMfH48yZMzA2Ni6OjESkorS1tTFt2jRcvXoVdnZ2sLW1xdSpU4WORURUJii8Ejdv3jwsW7YMY8eOhaGhIVasWIFvvvkGP/zwA6pWrVocGYlIxdnb2+PKlStITk6Gjo6O3HPnz59HXl6eQMmIiEovhVfi7t+/j+7duwMAdHR0kJWVBZFIhPHjx2P9+vVKD0hE6kFHRwc1atSQG4uJiYGrqysmTJiA2NhYgZIREZVOCpe4ihUrIiMjAwBQvXp1xMXFAQBSU1ORnZ2t3HREpLakUilGjhwJsViMBw8eoEWLFpg3bx5X5YiIlEThEte2bVuEhoYCAPr37w8fHx94eXlh0KBB6NSpk9IDEpF6EolE+O2339CwYUMAgFgsxpQpU+Dk5IR//vlH4HREROpP4RK3evVqDBw4EAAwZcoU+Pr6IikpCX379sWmTZuUHpCI1JeDgwMuX76Mvn37QkPj3a+ba9euoXHjxliwYAFX5YiIvoLCJc7ExATVqlV7t7OGBiZNmoTDhw9jyZIlqFixotIDEpF609PTw7Bhw/DXX3+hQYMGAIDc3FxMmjQJrVu3xq1btwROSESknhQucc7OzggODkZ6enpx5CGiUqp58+aIioqCn5+f7BZ9ly9fxuDBgyGVSgVOR0SkfhQucVZWVvD394e5uTn69++PQ4cOQSwWF0c2Iipl9PX1sWjRIpw/fx5169aFhoYG1q5dy/suExF9AYVL3IoVK/Ds2TMcPHgQ5cqVg7u7O8zMzDBq1CiEh4cXR0YiKmVatmyJ6OhoHD58GM2bN5d77sWLF5BIJAIlIyJSH19071QNDQ107twZwcHBSEpKwrp163DlyhV07NhR2fmIqJQyMDCQXXPyvby8PPTo0QPt27fHvXv3BEpGRKQevqjEvZeYmIi1a9diwYIFiImJQbNmzZSVi4jKoCVLluDKlSv4+++/YWdnh1WrVnFVjojoIxQucenp6diyZQtcXFxgYWGBNWvW4H//+x/u3r2LS5cuFUdGIiojWrRogW+++QYAkJ2djXHjxqFjx4548OCBwMmIiFSPwiXOzMwMU6ZMgbW1NSIiInD79m1Mnz4dderUKY58RFSGtGvXDjExMRgzZoxsLDw8HLa2tlizZg1X5YiI/kPhEnf48GH8+++/WLZsGRwcHIojExGVYeXLl0dQUBDCwsJQq1YtAEBWVhbGjBkDFxcXPHr0SNiAREQqQuES5+LiIrvyOhFRcenYsSNiY2Pxww8/yMbOnDkDOzs7vHz5UsBkRESqgW2MiFSWoaEh1q5di5MnT8LCwgIA8P3338PU1FTgZEREwmOJIyKV17lzZ8TGxsLf3x9z586Ve04ikfCOD0RUJrHEEZFaMDY2xrx582BgYCA3vmrVKnTr1g3//vuvQMmIiITBEkdEauvOnTvw9/fHiRMnYG1tjZCQEK7KEVGZofUlO4WFhSEsLAzJyckFTvnfvHmzUoIREX1OcnIyKlasiDdv3iAtLQ0eHh7Yu3cv1q9fj2rVqgkdj4ioWCm8Ejdz5kx07twZYWFhePnyJV6/fi33RURUUlq3bo24uDi4u7vLxo4dOwYrKyts27aNq3JEVKopvBK3du1aBAcHY9iwYcWRh4hIIRUrVkRISAj69euHUaNGITExEampqXB3d8e+ffuwbt06mJubCx2TiEjpFF6Jy83NRcuWLYsjS5EEBQXB0tISenp6cHR0xJUrVz667f79++Hg4IAKFSqgXLlysLe3x7Zt20owLRGVlJ49eyI+Ph5DhgyRjR0+fBhWVla4fPmygMmIiIqHwiVu5MiR2LFjR3Fk+azdu3fD19cXM2bMQFRUFOzs7ODq6ork5ORCtzcxMcGUKVMQERGBmJgYeHp6wtPTEydPnizh5ERUEkxMTLB9+3bs378fVapUAQAYGRmhUaNGAicjIlI+hT9Offv2LdavX4/Tp0/D1tYW2tracs8vXbpUaeE+tHTpUnh5ecHT0xPAu492jx07hs2bN2PSpEkFtm/fvr3cYx8fH4SEhOD8+fNwdXUttpxEJKw+ffqgTZs2+OmnnzBq1CgYGhoKHYmISOkULnExMTGwt7cHAMTFxck9JxKJlBKqMLm5uYiMjIS/v79sTENDA87OzoiIiPjs/lKpFGfOnMHt27exYMGCj26Xk5ODnJwc2eP09HQAgFgshlgs/op3QMXh/ZxwblSXUHNkbGyMrVu3Fvjejx49wqxZs7BgwQJUrly5RDOpIv4MqTbOj+pT9hwp8joKl7izZ88quotSvHz5Evn5+TAzM5MbNzMzw61btz66X1paGqpXr46cnBxoamrit99+g4uLy0e3DwwMxMyZMwuMnz17tsBFRkl1hIaGCh2BPkMV5kgikWDGjBmIjY3FkSNH8OOPP8LJyUnoWCpBFeaHPo7zo/qUNUfZ2dlF3vaLrhP33vsrpNeoUeNrXqZYGRoaIjo6GpmZmQgLC4Ovry9q165d4KPW9/z9/eHr6yt7nJ6eDgsLC3To0AGVKlUqodRUVGKxGKGhoXBxcSnw0T6pBlWao3v37uH58+cA3v2Bt2DBAri5uWH58uVl9udbleaHCuL8qD5lz9H7TwCLQuESJ5FIMGfOHCxZsgSZmZkA3hWlX375BVOmTIGGRvHcBMLU1BSamppISkqSG09KSvrk5QM0NDTw7bffAgDs7e1x8+ZNBAYGfrTE6erqQldXt8C4trY2f4BUGOdH9anCHDVs2BDx8fH48ccfcfDgQQDvTpg6d+4c1q1bh169egmaT0iqMD/0cZwf1aesOVLkNRRuXFOmTMHq1asxf/58XL9+HdevX8e8efOwatUqTJs2TdGXKzIdHR00bdoUYWFhsjGJRIKwsDCFPg6RSCRyx7wRUdliZmaG/fv3Y/v27ahYsSKAd38M9u7dG8OGDUNKSorACYmIikbhEhcSEoKNGzdi9OjRsLW1ha2tLcaMGYMNGzYgODi4GCL+H19fX2zYsAEhISG4efMmRo8ejaysLNnZqu7u7nInPgQGBiI0NBQPHjzAzZs3sWTJEmzbtg1Dhw4t1pxEpNpEIhGGDBmC+Ph49OzZUza+fft2WFtb49SpUwKmIyIqGoU/Tk1JSUGDBg0KjDdo0KDY/4J1c3PDixcvMH36dCQmJsLe3h4nTpyQnezw5MkTuY9zs7KyMGbMGPz777/Q19dHgwYNsH37dri5uRVrTiJSD1WrVsWhQ4ewbds2jBs3DmlpaUhISEB+fr7Q0YiIPkvhEmdnZ4fVq1dj5cqVcuOrV6+GnZ2d0oJ9jLe3N7y9vQt97ty5c3KP58yZgzlz5hR7JiJSXyKRCO7u7ujUqRNGjRqFqlWromvXrkLHIiL6LIVL3MKFC9G9e3ecPn1adixaREQEnj59iuPHjys9IBFRSahevTqOHj2K3NxcuXGpVIqVK1fCw8MDxsbGAqUjIipI4WPi2rVrhzt37qBPnz5ITU1FamoqvvvuO9y+fRtt2rQpjoxERCVCJBIVODt9y5Yt+Pnnn2FjY8NrdRGRSvmi68RVq1YNc+fOVXYWIiKVkpubixkzZgAAnj59is6dO2PUqFFYvHgxb+VFRIIrUomLiYmBtbU1NDQ0EBMT88ltbW1tlRKMiEhoOjo6OH/+PEaMGCG7vNH69etx8uRJbNq0CZ06dRI4IRGVZUUqcfb29khMTESVKlVgb28PkUgEqVRaYDuRSMSzuoioVKlVqxZCQ0Oxbt06+Pn5ISsrC48fP4azszNGjx6NhQsXonz58kLHJKIyqEjHxD18+FB2o+iHDx/iwYMHePjwYYGvBw8eFGtYIiIhiEQi/Pjjj4iNjUWHDh1k42vWrIGtrW2BM+OJiEpCkUpcrVq1IBKJAACPHz9G9erVUatWLbmv6tWr4/Hjx8UalohISN988w1Onz6N1atXw8DAAMC7P2w3btwocDIiKosUPju1Q4cOhV7UNy0tTe4vVCKi0khDQwNjx45FTEwM2rZtC3Nz8wLXzSQiKgkKlzipVCpblfuvV69eoVy5ckoJRUSk6urUqYOzZ8/iwoULMDExkXvu2rVryM7OFigZEZUVRb7EyHfffQfg3bEhHh4ectdSys/PR0xMDFq2bKn8hEREKkpDQwO1a9eWG0tISEDnzp1hamqK4OBg/l4komJT5BL3/krlUqkUhoaG0NfXlz2no6ODFi1awMvLS/kJiYjUiI+PD16/fo3Xr1+jdevW8PX1xezZs+V+ZxIRKUORS9yWLVsAAJaWlvDz8+NHp0REhZg9ezaePn2KS5cuQSqVYsmSJTh69CiCg4PRokULoeMRUSmi8DFxM2bMYIEjIvqI+vXr4/z581i4cKHssJPbt2+jVatWmDhxIt6+fStwQiIqLRQucQCwb98+DBgwAC1atECTJk3kvoiIyjpNTU38+uuvuH79Opo1awYAkEgkWLhwIZo0aYKrV68KnJCISgOFS9zKlSvh6ekJMzMzXL9+Hc2bN0elSpXw4MEDdO3atTgyEhGppYYNG+LixYuYN28edHR0AAA3b97E//73P67IEdFXU7jE/fbbb1i/fj1WrVoFHR0dTJgwAaGhoRg3bhzS0tKKIyMRkdrS0tKCv78/IiMj0bRpUwDv/hjW09MTOBkRqTuFS9yTJ09kp8zr6+sjIyMDADBs2DDs3LlTuemIiEoJa2trREREYO/evejfv7/cc+np6cjNzRUoGRGpK4VLnLm5ueyODTVr1sSlS5cAvLv1jFQqVW46IqJSRFtbG/369SswPmrUKDRr1gzR0dElH4qI1JbCJa5jx444fPgwAMDT0xPjx4+Hi4sL3Nzc0KdPH6UHJCIqzfbu3Yvdu3cjJiYGzZo1w8yZMyEWi4WORURqoMjXiXtv/fr1kEgkAICxY8eiUqVKuHjxIv73v//hhx9+UHpAIqLSrG7durC1tUVMTAzy8vIQEBCAQ4cOITg4GLa2tkLHIyIVpvBK3L///gtNTU3Z44EDB2LlypXw9vZGYmKiUsMREZV29vb2uHr1KqZNmyb73Xr9+nU4ODhg7ty5yMvLEzghEakqhUvcN998gxcvXhQYT0lJwTfffKOUUEREZYmOjg5mzZqFy5cvw8rKCgAgFosxdepUtGjRAnFxcQInJCJVpHCJk0qlEIlEBcYzMzN5yjwR0Vdo2rQpIiMjMXnyZGhovPv1/P7SJPHx8QKnIyJVU+Rj4nx9fQEAIpEI06ZNg4GBgey5/Px8XL58Gfb29koPSERUlujq6mLu3Lno1asXPDw8cPPmTbi6uqJRo0ZCRyMiFVPkEnf9+nUA71biYmNjZVcfB959FGBnZwc/Pz/lJyQiKoOaN2+OqKgozJ07F2PGjCnwCYhEIpGt1hFR2VTkEnf27FkA7y4rsmLFChgZGRVbKCIiAvT09DB79uwC40ePHsW8efOwZcsW1K9fX4BkRKQKFP4zbvny5YWeLZWSkoL09HSlhCIiosKlpKTAy8sLERERsLe3x7Jly5Cfny90LCISgMIlbuDAgdi1a1eB8T179mDgwIFKCUVERIVLSEiAoaEhAODt27fw9fVF+/btce/ePYGTEVFJU7jEXb58GR06dCgw3r59e1y+fFkpoYiIqHBWVlaIjo7Gzz//LDtO7vz587C1tcXKlStlF2MnotJP4RKXk5NT6MepYrEYb968UUooIiL6OAMDAyxbtgznzp1D7dq1AQBv3ryBj48POnTogAcPHgickIhKgsIlrnnz5li/fn2B8bVr16Jp06ZKCUVERJ/Xtm1bxMTEwNvbWzb2119/wdbWFkeOHBEwGRGVBIXvnTpnzhw4Ozvjxo0b6NSpEwAgLCwMV69exalTp5QekIiIPq5cuXJYtWoVvvvuO3z//fd49OgRNDU1ed1OojJA4ZW4Vq1aISIiAjVq1MCePXtw5MgRfPvtt4iJiUGbNm2KIyMREX1Ghw4dEBsbi9GjR2PZsmWwsLAQOhIRFTOFV+KAdzds3rFjh7KzEBHRVyhfvjx+++23AuNpaWnw9vbGnDlzUKtWLQGSEVFx+KLLfd+/fx9Tp07F4MGDkZycDAD4888/eW8/IiIV9Msvv2D79u2wsbHBhg0bIJVKhY5EREqgcIkLDw+HjY0NLl++jD/++AOZmZkAgBs3bmDGjBlKD/ihoKAgWFpaQk9PD46Ojrhy5cpHt92wYQPatGmDihUromLFinB2dv7k9kREpU1qaqrseOWMjAyMGjUKXbt2xdOnTwVORkRfS+ESN2nSJMyZMwehoaFy90/t2LEjLl26pNRwH9q9ezd8fX0xY8YMREVFwc7ODq6urrLVwA+dO3cOgwYNwtmzZxEREQELCwt07twZz549K9acRESqokKFCoiNjcX3338vGzt58iSsra2xefNmrsoRqTGFS1xsbCz69OlTYLxKlSp4+fKlUkJ9zNKlS+Hl5QVPT080atQIa9euhYGBATZv3lzo9r///jvGjBkDe3t7NGjQABs3boREIkFYWFix5iQiUiXGxsbYtGkTjh8/jmrVqgEA0tPTMWLECPTq1QuvXr0SOCERfQmFT2yoUKECEhIS8M0338iNX79+HdWrV1dasA/l5uYiMjIS/v7+sjENDQ04OzsjIiKiSK+RnZ0NsVgMExOTj26Tk5ODnJwc2eP394MVi8UQi8VfmJ6Ky/s54dyoLs6R6nB2dsb169fh5+eHbdu2AQBOnDiBv/76CyKRCEOHDhU4IX2IPz+qT9lzpMjrKFziBg4ciIkTJ2Lv3r0QiUSQSCS4cOEC/Pz84O7urujLFdnLly+Rn58PMzMzuXEzMzPcunWrSK8xceJEVKtWDc7Ozh/dJjAwEDNnziwwfvbsWRgYGCgWmkpMaGio0BHoMzhHqqNv376oWbMmfvvtN7x+/RrZ2dm4dOnSJ//AJWHx50f1KWuOsrOzi7ytSKrgARG5ubkYO3YsgoODkZ+fDy0tLeTn52Pw4MEIDg6GpqamwoGL4vnz56hevTouXrwIJycn2fiECRMQHh7+2fu2zp8/HwsXLsS5c+dga2v70e0KW4mzsLBAQkICKlWq9PVvhJRKLBYjNDQULi4u0NbWFjoOFYJzpLpSUlLw888/Iz4+HhcvXoSurq7QkegD/PlRfcqeo/T0dJiamiItLQ1GRkaf3FbhlTgdHR1s2LAB06ZNQ1xcHDIzM9G4cWPUrVv3iwMXhampKTQ1NZGUlCQ3npSUBHNz80/uu3jxYsyfPx+nT5/+ZIEDAF1d3UJ/kWlra/MHSIVxflQf50j1mJmZYevWrThw4AB0dXXl5mfz5s3o3r17gU8/SBj8+VF9ypojRV7ji64TBwA1a9ZE165d0b9//2IvcMC78ti0aVO5kxLen6Tw35W5Dy1cuBCzZ8/GiRMn4ODgUOw5iYjUzYd/uJ49exYjRoyAlZUVdu3axTNYiVTUF5W4TZs2wdraGnp6etDT04O1tTU2btyo7GwF+Pr6YsOGDQgJCcHNmzcxevRoZGVlwdPTEwDg7u4ud+LDggULMG3aNGzevBmWlpZITExEYmKi7Np2REQkTyqVyn6Pvnr1CoMGDUL//v0/eiknIhKOwiVu+vTp8PHxQc+ePbF3717s3bsXPXv2xPjx4zF9+vTiyCjj5uaGxYsXY/r06bC3t0d0dDROnDghW+5/8uQJEhISZNuvWbMGubm56NevH6pWrSr7Wrx4cbHmJCJSVyKRCEeOHEH//v1lY3/88QesrKywd+9eAZMR0YcUPiZuzZo12LBhAwYNGiQb+9///gdbW1v89NNPmDVrllIDfsjb2xve3t6FPnfu3Dm5x48ePSrWLEREpVHlypWxZ88e7NmzB2PGjMGrV6/w8uVLDBgwAAMGDEBQUBBMTU2FjklU5im8EicWiws9tqxp06bIy8tTSigiIhLegAEDEB8fL3eB9z179sDKygoHDhwQMBkRAV9Q4oYNG4Y1a9YUGF+/fj2GDBmilFBERKQazMzM8Mcff2DHjh2y68glJydj8eLFkEgkAqcjKtsU/jgVeHdiw6lTp9CiRQsAwOXLl/HkyRO4u7vD19dXtt3SpUuVk5KIiAQjEokwaNAgdOjQAT/88ANOnTqFLVu2QEPjiy9wQERKoHCJi4uLQ5MmTQAA9+/fB/DuGm6mpqaIi4uTbScSiZQUkYiIVIG5uTkOHjyIO3fuoF69enLP/fPPP6hatSoqVqwoUDqiskfhEnf27NniyEFERGpAJBKhfv36cmPZ2dno3bs3MjMzsWHDBnTv3l2gdERli8Jr4S9evPjoc7GxsV8VhoiI1M+sWbNw9+5dJCQkoEePHvD09ERqaqrQsYhKPYVLnI2NDY4dO1ZgfPHixWjevLlSQhERkfrw9vZGly5dZI+Dg4NhbW2NEydOCJiKqPRTuMT5+vqib9++GD16NN68eYNnz56hU6dOWLhwIXbs2FEcGYmISIXVqFEDx48fx8aNG2FoaAgAePbsGbp27QovLy+kp6cLnJCodFK4xE2YMAERERH4+++/YWtrC1tbW+jq6iImJkbuWkJERFR2iEQijBgxAnFxcXB2dpaNb9y4EdbW1ggNDRUwHVHp9EXnh3/77bewtrbGo0ePkJ6eDjc3N5ibmys7GxERqZmaNWvi1KlTWLduHcqXLw8AePr0KXr27InExESB0xGVLgqXuAsXLsDW1hZ3795FTEwM1qxZg59++glubm54/fp1cWQkIiI1IhKJMGrUKMTGxqJjx44AgICAAP6xT6RkCpe4jh07ws3NDZcuXULDhg0xcuRIXL9+HU+ePIGNjU1xZCQiIjVkaWmJ0NBQ7Ny5E35+fnLP5eTkIDMzU6BkRKWDwiXu1KlTmD9/PrS1tWVjderUwYULF/DDDz8oNRwREak3DQ0NDBw4EFpa8pclnTlzJmxtbREeHi5QMiL1p3CJa9euXeEvpKGBadOmfXUgIiIq3a5cuYIFCxbg4cOHaN++PXx8fJCVlSV0LCK1U+QS161bN6Slpckez58/X+5ijq9evUKjRo2UGo6IiEqfSpUqoWXLlrLHK1euhL29Pc6fPy9gKiL1U+QSd/LkSeTk5Mgez5s3DykpKbLHeXl5uH37tnLTERFRqVOnTh2cO3cOy5Ytg56eHgDg3r17aNu2LXx9fZGdnS1wQiL1UOQSJ5VKP/mYiIioqDQ1NfHzzz/jxo0bcHJyAvDuvyvLli1D48aNERERIXBCItX3RdeJIyIiUoZ69erh77//xqJFi6CrqwsAuHPnDlq3bo1Tp04JnI5ItRW5xIlEIohEogJjREREX0NTUxN+fn6Ijo6W3YPbxsYG7du3FzYYkYrT+vwm70ilUnh4eMj+Unr79i1+/PFHlCtXDgDkjpcjIiJSVIMGDXDhwgUsWbIEXbp0gY6OjtzzUqmUiwdE/1HkEjd8+HC5x0OHDi2wjbu7+9cnIiKiMktLSwsTJ04sMB4dHQ1PT09s2LABDg4OAiQjUj1FLnFbtmwpzhxERESFys3NhYeHB27cuIEWLVpg0qRJmDZtmuyTIaKyiic2EBGRSnvx4gU0NTUBAPn5+Zg7dy6aNWuGqKgogZMRCYsljoiIVFr16tVx6dIlzJo1S3b7rtjYWDg6OmLGjBnIzc0VOCGRMFjiiIhI5Wlra2PatGm4du0a7OzsALy7yPysWbPQvHlz3LhxQ+CERCWPJY6IiNSGnZ0drly5ghkzZshW5W7cuAEHBwds2LBB4HREJYsljoiI1IqOjg4CAgJw+fJl2NjYAHh3+RF7e3thgxGVsCKfnUpERKRKmjRpgqtXr2L27NnQ0NBAs2bNhI5EVKJY4oiISG3p6upizpw5Bcbz8vIwZswY+Pj4wMrKSoBkRMWPH6cSEVGps3jxYmzYsAFNmjTBggULkJeXJ3QkIqVjiSMiolIlLy8Pu3btAvDuQsGTJk1C69atcevWLYGTESkXSxwREZUqWlpaiIiIgJ+fn+xeq5cvX4a9vT2WLFmC/Px8gRMSKQdLHBERlTr6+vpYtGgRzp8/j7p16wIAcnJy4Ofnh7Zt2+LOnTsCJyT6eixxRERUarVs2RLR0dEYP368bFXu4sWLsLOzw8qVKwVOR/R11K7EBQUFwdLSEnp6enB0dMSVK1c+um18fDz69u0LS0tLiEQiLF++vOSCEhGRSjAwMMDSpUsRHh6OOnXqAADevn2Lx48fC5yM6OuoVYnbvXs3fH19MWPGDERFRcHOzg6urq5ITk4udPvs7GzUrl0b8+fPh7m5eQmnJSIiVdKmTRvcuHEDP/30Exo0aFDopUmI1IlalbilS5fCy8sLnp6eaNSoEdauXQsDAwNs3ry50O2bNWuGRYsWYeDAgdDV1S3htEREpGrKlSuHlStXIjIyEvr6+nLP7d+/Hw8ePBAoGZHi1KbE5ebmIjIyEs7OzrIxDQ0NODs7IyIiQsBkRESkbgwMDOQe37lzB0OGDIGtrS3WrFkDiUQiUDKiolObOza8fPkS+fn5MDMzkxs3MzNT6rV/cnJykJOTI3ucnp4OABCLxRCLxUr7PqQc7+eEc6O6OEeqjfPzztSpU/H27VsAwJgxY7Bv3z6sW7cOtWrVEjQX50f1KXuOFHkdtSlxJSUwMBAzZ84sMH727NkCf7mR6ggNDRU6An0G50i1lfX5+e6775CRkYETJ04AAM6cOQMbGxt4enqic+fOsjNbhVLW50cdKGuOsrOzi7yt2pQ4U1NTaGpqIikpSW48KSlJqSct+Pv7w9fXV/Y4PT0dFhYW6NChAypVqqS070PKIRaLERoaChcXF2hrawsdhwrBOVJtnJ//07dvX5w+fRo//PADnj59irdv32LNmjW4e/cu1q5di5o1a5Z4Js6P6lP2HL3/BLAo1KbE6ejooGnTpggLC0Pv3r0BABKJBGFhYfD29lba99HV1S30JAhtbW3+AKkwzo/q4xypNs7PO127dkVcXBx++eUXbNy4EQBw+vRpNG7cGMuWLcP3338vyKoc50f1KWuOFHkNtTmxAQB8fX2xYcMGhISE4ObNmxg9ejSysrLg6ekJAHB3d4e/v79s+9zcXERHRyM6Ohq5ubl49uwZoqOjce/ePaHeAhERqTgjIyNs2LABf/75J6pXrw4AyMjIwJw5cxT6qIuouKnNShwAuLm54cWLF5g+fToSExNhb2+PEydOyE52ePLkCTQ0/q+XPn/+HI0bN5Y9Xrx4MRYvXox27drh3LlzJR2fiIjUSJcuXRAXFwdfX18EBwdjy5YtKFeunNCxiGTUqsQBgLe390c/Pv2wmFlaWkIqlZZAKiIiKo0qVKiAzZs3w8/PD40aNZJ77unTp9DU1ES1atUESkdlnVp9nEpERCSEDwucRCLB8OHDYWVlhe3bt3PBgATBEkdERKSgjRs34uzZs0hNTcWwYcPQp08fJCYmCh2LyhiWOCIiIgX169cPQ4YMkT0+dOgQrKyssHPnTq7KUYlhiSMiIlKQiYkJtm/fjv3796NKlSoAgJSUFAwePBj9+vVDcnKywAmpLGCJIyIi+kJ9+vRBfHw8Bg4cKBvbv38/rKyssGfPHgGTUVnAEkdERPQVTE1NsXPnTuzduxempqYA3t3v283NDVFRUQKno9KMJY6IiEgJ+vXrh/j4ePTt2xcAMHLkSDRp0kTgVFSaqd114oiIiFRVlSpVsHfvXuzfvx8uLi5yz0mlUqSlpaFChQrChKNShytxRERllFQqRWpqKlJSUpCamsqzKpVEJBKhb9++MDIykhvfvHkzGjRogEOHDgmUjEobljgiojImIyMDO3fuRM/e36FVe2dMmTkXrdo7o2fv77Bz505kZGQIHbHUefLkCcaPH4+kpCT07t0bQ4cORUpKitCxSM2xxBERlSERERHo1LkrJgQE4s5bQ5i090AV1zEwae+BO28NMSEgEJ06d0VERITQUUsVHR0dtG/fXvb4999/h5WVFY4ePSpcKFJ7LHFERGVEREQERo72Rop+NTTyDET9HqNgWt8BhjXqwbS+A+r3GIVGnoFI0a+GkaO9WeSUyNzcHIcOHUJISAiMjY0BAImJiejZsyc8PDyQmpoqbEBSSyxxRERlQEZGBnx8f0WOSR006DUWOuWMC91Op5wxGvQaixyTOvDx/ZUfrSqRSCSCu7s74uPj0a1bN9l4SEgIrKyscPz4cQHTkTpiiSMiKgOOHj2KhJR01Ok8HCINzU9uK9LQRB0XdySkpOPYsWMllLDsqF69Oo4ePYrNmzfLTn54/vw5unfvjk2bNgmcjtQJSxwRUSknlUrx+6490K9l99EVuA/plK8AvVp22L5zN89aLQYikQienp6Ii4tD586dAQBVq1ZFnz59BE5G6oTXiSMiKuXS0tJw5/4DmLT3VGi/SnWb4G54MNLT02XHcZFyWVhY4MSJE9i4cSNq1KgBExMTuedZoOlTuBJHRFTKZWdnQyIFtPQMFNpPS88AEimQlZVVTMkIeLcq5+Xlha5du8qNJyQkwNHRETdu3BAoGak6rsQREZVyBgYG0BABeW+zFdov7202NERAuXLliikZfYxUKsUPP/yA6OhoREdHIyEhAYsWLUL58uWFjkYqhCtxRESlnLGxMerVqY2Uu4rdjP3V3SjUrVO7wJ0HqPhlZmYiMzNT9njt2rWwtbXFuXPnhAtFKocljoiolBOJRBgycADePIpGblZakfbJzUzF28c3MHSQG0QiUTEnpA8ZGhri9OnTWLFiBXR1dQEADx8+RIcOHTBu3Dh+xE0AWOKIiMqEHj16oKqJEe6fCoFUkv/JbaWSfNwP3YqqJkbo3r17CSWkD2loaGD06NFYvnw52rRpIxtftWoV7Ozs8PfffwuYjlQBSxwRURlgaGiIFUsXQTflPm4dCkJuZmqh2+VmpuLWoSDoptzHymWLYWhoWLJBqYCqVasiNDQUK1asgL6+PgDg/v37aNeuHWbNmiVwOhISSxwRURnh5OSEjWtWw+TNc/wTPBm3jqzDi1tXkfH0Nl7cuopbR9bhn+DJMHnzHJvWBqFFixZCR6b/T0NDA+PGjcONGzfQqlUrAO9OfmjUqJHAyUhIPDuViKgMcXJyQtipP3Hs2DFs37kbd8JDkJmVhfLlyqH+t7UxdOZk9OjRg2dBqqi6desiPDwcK1asQGxsLPr16yd0JBIQSxwRURljaGiIgQMHws3NDa9evcKRI0fQs2dPVKpUiScxqAFNTU34+voW+tzEiRPRp08frqKWEfw4lYiojBKJRDA2NoaJiQmMjY1Z4NTcnj17sHDhQrRq1QoTJ07E27dvhY5ExYwljoiIqBTYunUrAEAikWDhwoVo0qQJrl69KnAqKk4scURERKXAwYMHERgYCB0dHQDAzZs34eTkhClTpiAnJ0fgdFQcWOKIiIhKAS0tLUyaNAmRkZFo2rQpACA/Px/z5s2Dg4MDIiMjBU5IysYSR0REVIpYW1sjIiICc+bMgba2NgAgLi4Ojo6OmD59OvLzP32xZ1IfLHFERESljLa2NqZMmYJr167B3t4ewLtVuRs3bkBDg//pLy04k0RERKWUra0trly5gpkzZ8LMzAzr1q3jWcilCEscERFRKaatrY3p06fj3r17MDc3l3vu7NmziImJESgZfS2WOCIiojLgw7twvHr1CoMHD4aDgwPmzp2LvLw8gZLRl2KJIyIiKoMWLVqExMREiMViTJ06FS1atEBcXJzQsUgBalfigoKCYGlpCT09PTg6OuLKlSuf3H7v3r1o0KAB9PT0YGNjg+PHj5dQUiIiItU1c+ZM+Pv7y050eH9pksDAQK7KqQm1KnG7d++Gr68vZsyYgaioKNjZ2cHV1RXJycmFbn/x4kUMGjQII0aMwPXr19G7d2/07t2bf2kQEVGZp6uri3nz5iEiIgINGzYEAOTm5mLy5Mlo2bIl/vnnH4ET0ueoVYlbunQpvLy84OnpiUaNGmHt2rUwMDDA5s2bC91+xYoV6NKlC3799Vc0bNgQs2fPRpMmTbB69eoSTk5ERKSamjdvjqioKEyYMEG2Knf16lU0adIECxcu5HXlVJiW0AGKKjc3F5GRkfD395eNaWhowNnZGREREYXuExERAV9fX7kxV1dXHDx48KPfJycnR+72JOnp6QAAsVgMsVj8Fe+AisP7OeHcqC7OkWrj/Ki2kpofTU1NzJkzBz169MCIESNw9+5d5OTkYO7cuRgwYACqV69erN9fnSl7jhR5HbUpcS9fvkR+fj7MzMzkxs3MzHDr1q1C90lMTCx0+8TExI9+n8DAQMycObPA+NmzZ2FgYPAFyakkhIaGCh2BPoNzpNo4P6qtJOdnzpw52LFjBw4fPozhw4fjxo0buHHjRol9f3WlrDnKzs4u8rZqU+JKir+/v9zqXXp6OiwsLNChQwdUqlRJwGRUGLFYjNDQULi4uMhuL0OqhXOk2jg/qk2o+enTpw9iY2NhbW0td3HgtLQ0JCcno27duiWWRdUpe47efwJYFGpT4kxNTaGpqYmkpCS58aSkpAIXL3zP3Nxcoe2Bdwd66urqFhjX1tbmLzgVxvlRfZwj1cb5UW1CzE+TJk0KjE2cOBE7d+5EYGAgfvrpJ97C6z+UNUeKvIba/Ovr6OigadOmCAsLk41JJBKEhYXBycmp0H2cnJzktgfeLXd+bHsiIiIqXGhoKDZv3ow3b97g559/RocOHXD//n2hY5VpalPiAMDX1xcbNmxASEgIbt68idGjRyMrKwuenp4AAHd3d7kTH3x8fHDixAksWbIEt27dQkBAAK5duwZvb2+h3gIREZFaatmypdx/P//66y/Y2toiKCgIEolEwGRll1qVODc3NyxevBjTp0+Hvb09oqOjceLECdnJC0+ePEFCQoJs+5YtW2LHjh1Yv3497OzssG/fPhw8eBDW1tZCvQUiIiK1VK5cOaxatQpnzpyBpaUlgHcH4Xt7e6NTp054+PChsAHLILUqcQDg7e2Nx48fIycnB5cvX4ajo6PsuXPnziE4OFhu+/79++P27dvIyclBXFwcunXrVsKJiYiISo8OHTogNjYWo0ePlo2dO3cONjY2WLt2LaRSqYDpyha1K3FEREQkrPLly+O3335DaGgoatasCQDIysrC6NGjP3ktVlIuljgiIiL6Is7OzoiNjcWoUaMAAJ06dUKvXr0ETlVypFIpUlNTkZKSgtTU1BJfhVSbS4wQERGR6jEyMsK6devw3XffoX79+gUuO5KWlgZjY2OB0hWPjIwMHD16FL/v2oM79x4gMysLgYuXo963tTFk4AD06NEDhoaGxZ6DK3FERET01VxdXWUnPLx35swZ1KpVC1u2bCk1x8pFRESgU+eumBAQiDtvDWHS3gNVXMfApL0H7rw1xISAQHTq3PWjtwRVJpY4IiIiUrqMjAx8//33SEtLw/fff48ePXrg2bNnQsf6KhERERg52hsp+tXQyDMQ9XuMgml9BxjWqAfT+g6o32MUGnkGIkW/GkaO9i72IscSR0REREonkUjQvn172ePjx4/DysoKW7duVctVuYyMDPj4/oockzpo0GssdMoV/hGxTjljNOg1FjkmdeDj+ysyMjKKLRNLHBERESmdsbExgoODcfjwYdntLtPS0jB8+HD06tVL7rqu6uDo0aNISElHnc7DIdLQ/OS2Ig1N1HFxR0JKOo4dO1ZsmVjiiIiIqNj07NkT8fHxGDp0qGzsyJEjsLKywu+//64Wq3JSqRS/79oD/Vp2H12B+5BO+QrQq2WH7Tt3F9t7ZIkjIiKiYmViYoJt27bhwIEDqFKlCgDg9evXGDp0KAICAoQNVwRpaWm4c/8BTOo1VWi/SnWb4O79B0hPTy+WXCxxREREVCJ69+6N+Ph4DBw4EACgr68vt0KnqrKzsyGRAlp6Bgrtp6VnAIn03YWQiwOvE0dEREQlxtTUFDt37kS/fv2QmpqKunXryj0vlUohEokESlc4AwMDaIiAvLfZCu2X9zYbGqJ3950tDlyJIyIiohLXt29fjBgxQm4sOzsbrVu3xt69ewVKVThjY2PUq1MbKXejFNrv1d0o1K1TG0ZGRsWSiyWOiIiIVMKUKVNw8eJFDBgwAG5ubnj58qXQkQAAIpEIQwYOwJtH0cjNSivSPrmZqXj7+AaGDnIrtpVFljgiIiISXH5+Pp4+fSp7vGfPHlhZWeHAgQMCpvo/PXr0QFUTI9w/FQKpJP+T20ol+bgfuhVVTYzQvXv3YsvEEkdERESC09TUxN69e/H777+jYsWKAIDk5GR89913GDx4MF69eiVoPkNDQ6xYugi6Kfdx61AQcjNTC90uNzMVtw4FQTflPlYuW1ys91BliSMiIiKVIBKJMHjwYMTHx6Nnz56y8Z07d8LKygqHDx8WMB3g5OSEjWtWw+TNc/wTPBm3jqzDi1tXkfH0Nl7cuopbR9bhn+DJMHnzHJvWBqFFixbFmocljoiIiFRK1apVcejQIWzduhUVKlQAACQlJaFXr17w8vISNJuTkxPCTv2JRTMno75+Jl6HhyD51Bq8Dg9Bff1MLJo5GWdCTxR7gQN4iREiIiJSQSKRCMOGDUOnTp3g5eWF48ePA0CBS5IIwdDQEAMHDoSbmxtevXqFI0eOoGfPnqhUqVKJXh6FK3FERESksqpVq4ajR49iy5YtcHV1xS+//CJ0JBmRSARjY2OYmJjA2Ni4xK9vxxJHREREKk0kEsHDwwN//vknNDXlbz6/ePFinDhxQqBkwmKJIyIiIrXw4UrX5cuXMXHiRHTt2hVeXl7Fdo9SVcUSR0RERGopJCQEEokEALBx40ZYW1vj9OnTAqcqOSxxREREpJaCgoKwbt06lC9fHgDw9OlTuLi44Mcff0RGRobA6YofSxwRERGpJZFIhFGjRiE2NhYdO3aUja9btw42NjY4c+aMgOmKH0scERERqTVLS0uEhobit99+Q7ly5QAAjx8/RqdOnTB27Fi8efNG4ITFgyWOiIiI1J6GhgZGjx6NmJgYtGvXTjYeEREBLa3SeVlcljgiIiIqNWrXro0zZ85g5cqVqFChAoKDg6GtrS10rGLBEkdERESlioaGBn766Sc8efIEtra2cs/FxMTg/PnzAiVTLpY4IiIiKpUMDQ3lHufm5mLYsGFo27YtfH19kZ2dLVAy5WCJIyIiojJh8+bNiImJgVQqxbJly9C4cWNEREQIHeuLscQRERFRmeDl5YVFixZBV1cXAHDnzh20bt0av/76q1qewcoSR0RERGWCpqYm/Pz8EB0djebNmwMAJBIJFi9ejCZNmuDy5csCJ1QMSxwRERGVKQ0aNMCFCxcwf/586OjoAABu3bqFli1bwt/fHzk5OQInLBqWOCIiIipztLS0MHHiRERFRcHBwQHAu1W5RYsW4Z9//hE4XdGoTYlLSUnBkCFDYGRkhAoVKmDEiBHIzMz85D7r169H+/btYWRkBJFIhNTU1JIJS0RERGrBysoKERERmDt3LrS1tTFp0iQ0btxY6FhFojYlbsiQIYiPj0doaCiOHj2Kv/76C6NGjfrkPtnZ2ejSpQsmT55cQimJiIhI3WhpaWHy5Mm4fv06pk2bJvdcXl4e4uLiBEr2aWpR4m7evIkTJ05g48aNcHR0ROvWrbFq1Srs2rULz58//+h+P//8MyZNmoQWLVqUYFoiIiJSR1ZWVrIzV99buHAhGjdujBkzZiA3N1egZIVTixIXERGBChUqyD6zBgBnZ2doaGio3ZkkREREpB5u3ryJgIAA5OXlYdasWWjevDlu3LghdCwZtbgjbGJiIqpUqSI3pqWlBRMTEyQmJir1e+Xk5MidlZKeng4AEIvFEIvFSv1e9PXezwnnRnVxjlQb50e1cX6EVbNmTUyYMAHz589Hfn4+bty4AQcHB0yZMgUTJkyAtra20udIkdcRtMRNmjQJCxYs+OQ2N2/eLKE07wQGBmLmzJkFxs+ePQsDA4MSzUJFFxoaKnQE+gzOkWrj/Kg2zo9wmjVrhoULF2LlypV4/Pgx8vLyMHPmTGzbtg0+Pj6oVasWAOXNkSK3AhNJpVKpUr7rF3jx4gVevXr1yW1q166N7du345dffsHr169l43l5edDT08PevXvRp0+fT77GuXPn0KFDB7x+/RoVKlT45LaFrcRZWFggISEBlSpV+vybohIlFosRGhoKFxcXaGtrCx2HCsE5Um2cH9XG+VEdOTk5mDt3LhYtWoT8/HwAgLa2NqZMmQIbGxt06dJFKXOUnp4OU1NTpKWlwcjI6JPbCroSV7lyZVSuXPmz2zk5OSE1NRWRkZFo2rQpAODMmTOQSCRwdHRUaiZdXd0CBzUC7yaKP0Cqi/Oj+jhHqo3zo9o4P8LT1tZGYGAgvvvuO3h4eOCff/6BWCzGihUrsHTpUqXNkSKvoRYnNjRs2BBdunSBl5cXrly5ggsXLsDb2xsDBw5EtWrVAADPnj1DgwYNcOXKFdl+iYmJiI6Oxr179wAAsbGxiI6ORkpKiiDvg4iIiNRbs2bNEBkZiUmTJkFDQwMrVqxAxYoVBcmiFiUOAH7//Xc0aNAAnTp1Qrdu3dC6dWusX79e9rxYLMbt27flPkteu3YtGjduDC8vLwBA27Zt0bhxYxw+fLjE8xMREVHpoKenh8DAQPzzzz9wc3MTLIdanJ0KACYmJtixY8dHn7e0tMSHh/cFBAQgICCgmJMRERFRWVS/fn1BzxxWm5U4IiIiIvo/LHFEREREaogljoiIiEgNscQRERERqSGWOCIiIiI1xBJHREREpIZY4oiIiIjUEEscERERkRpiiSMiIiJSQyxxRERERGqIJY6IiIhIDbHEEREREakhljgiIiIiNcQSR0RERKSGtIQOoOqkUikAICMjA9ra2gKnoQ+JxWJkZ2cjPT2d86OiOEeqjfOj2jg/qk/Zc5Seng7g//rHp7DEfcarV68AAN98843ASYiIiKisyMjIgLGx8Se3YYn7DBMTEwDAkydPPvuPSSUvPT0dFhYWePr0KYyMjISOQ4XgHKk2zo9q4/yoPmXPkVQqRUZGBqpVq/bZbVniPkND491hg8bGxvwBUmFGRkacHxXHOVJtnB/VxvlRfcqco6IuGvHEBiIiIiI1xBJHREREpIZY4j5DV1cXM2bMgK6urtBRqBCcH9XHOVJtnB/VxvlRfULOkUhalHNYiYiIiEilcCWOiIiISA2xxBERERGpIZY4IiIiIjXEEkdERESkhljiPiEoKAiWlpbQ09ODo6Mjrly5InQk+v/++usv9OzZE9WqVYNIJMLBgweFjkT/ERgYiGbNmsHQ0BBVqlRB7969cfv2baFj0X+sWbMGtra2sguUOjk54c8//xQ6Fn3E/PnzIRKJ8PPPPwsdhQAEBARAJBLJfTVo0KDEc7DEfcTu3bvh6+uLGTNmICoqCnZ2dnB1dUVycrLQ0QhAVlYW7OzsEBQUJHQUKkR4eDjGjh2LS5cuITQ0FGKxGJ07d0ZWVpbQ0ej/q1GjBubPn4/IyEhcu3YNHTt2RK9evRAfHy90NPrA1atXsW7dOtja2godhf7DysoKCQkJsq/z58+XeAZeYuQjHB0d0axZM6xevRoAIJFIYGFhgZ9++gmTJk0SOB39l0gkwoEDB9C7d2+ho9BHvHjxAlWqVEF4eDjatm0rdBz6CBMTEyxatAgjRowQOgr9f5mZmWjSpAl+++03zJkzB/b29li+fLnQscq8gIAAHDx4ENHR0YLm4EpcIXJzcxEZGQlnZ2fZmIaGBpydnRERESFgMiL1lJaWBuBdSSDVk5+fj127diErKwtOTk5Cx6H/GDt2LLp37y733yNSDXfv3kW1atVQu3ZtDBkyBE+ePCnxDFol/h3VwMuXL5Gfnw8zMzO5cTMzM9y6dUugVETqSSKR4Oeff0arVq1gbW0tdBz6j9jYWDg5OeHt27coX748Dhw4gEaNGgkdi/6/Xbt2ISoqClevXhU6Cn3A0dERwcHBqF+/PhISEjBz5ky0adMGcXFxMDQ0LLEcLHFEVKzGjh2LuLg4QY4XoU+rX78+oqOjkZaWhn379mH48OEIDw9nkVMBT58+hY+PD0JDQ6Gnpyd0HPpA165dZf/b1tYWjo6OqFWrFvbs2VOihyOwxBXC1NQUmpqaSEpKkhtPSkqCubm5QKmI1I+3tzeOHj2Kv/76CzVq1BA6Dn1AR0cH3377LQCgadOmuHr1KlasWIF169YJnIwiIyORnJyMJk2ayMby8/Px119/YfXq1cjJyYGmpqaACem/KlSogHr16uHevXsl+n15TFwhdHR00LRpU4SFhcnGJBIJwsLCeLwIURFIpVJ4e3vjwIEDOHPmDL755huhI1ERSCQS5OTkCB2DAHTq1AmxsbGIjo6WfTk4OGDIkCGIjo5mgVMxmZmZuH//PqpWrVqi35crcR/h6+uL4cOHw8HBAc2bN8fy5cuRlZUFT09PoaMR3v3A/PcvnocPHyI6OhomJiaoWbOmgMkIePcR6o4dO3Do0CEYGhoiMTERAGBsbAx9fX2B0xEA+Pv7o2vXrqhZsyYyMjKwY8cOnDt3DidPnhQ6GgEwNDQscAxpuXLlUKlSJR5bqgL8/PzQs2dP1KpVC8+fP8eMGTOgqamJQYMGlWgOlriPcHNzw4sXLzB9+nQkJibC3t4eJ06cKHCyAwnj2rVr6NChg+yxr68vAGD48OEIDg4WKBW9t2bNGgBA+/bt5ca3bNkCDw+Pkg9EBSQnJ8Pd3R0JCQkwNjaGra0tTp48CRcXF6GjEam8f//9F4MGDcKrV69QuXJltG7dGpcuXULlypVLNAevE0dERESkhnhMHBEREZEaYokjIiIiUkMscURERERqiCWOiIiISA2xxBERERGpIZY4IiIiIjXEEkdERESkhljiiEjtWFpaYvny5ULH+CIeHh7o3bv3V71GdnY2+vbtCyMjI4hEIqSmpiolGxGpF5Y4IioRHh4eEIlEmD9/vtz4wYMHIRKJFHqtq1evYtSoUcqMp1ZCQkLw999/4+LFi7I7LnwtZZRLIipZLHFEVGL09PSwYMECvH79+qtep3LlyjAwMFBSKvVz//59NGzYENbW1jA3N1e4BBen3NxcoSMQlRkscURUYpydnWFubo7AwMBPbvfHH3/AysoKurq6sLS0xJIlS+Se/+/HqVKpFAEBAahZsyZ0dXVRrVo1jBs3TrZtTk4O/Pz8UL16dZQrVw6Ojo44d+7cR793UV5v4sSJsLCwgK6uLr799lts2rQJAJCfn48RI0bgm2++gb6+PurXr48VK1Z88r1KJBIEBgbK9rGzs8O+ffs+un379u2xZMkS/PXXXxCJRLL7027btg0ODg4wNDSEubk5Bg8ejOTkZLl94+Pj0aNHDxgZGcHQ0BBt2rTB/fv3ERAQgJCQEBw6dAgikQgikUj2bxQbG4uOHTtCX18flSpVwqhRo5CZmSl7zfcreHPnzkW1atVQv379T75fIlIeLaEDEFHZoampiXnz5mHw4MEYN24catSoUWCbyMhIDBgwAAEBAXBzc8PFixcxZswYVKpUCR4eHgW2/+OPP7Bs2TLs2rULVlZWSExMxI0bN2TPe3t7459//sGuXbtQrVo1HDhwAF26dEFsbCzq1q2r8Ou5u7sjIiICK1euhJ2dHR4+fIiXL18CeFfIatSogb1796JSpUq4ePEiRo0ahapVq2LAgAGF/psEBgZi+/btWLt2LerWrYu//voLQ4cOReXKldGuXbsC2+/fvx+TJk1CXFwc9u/fDx0dHQCAWCzG7NmzUb9+fSQnJ8PX1xceHh44fvw4AODZs2do27Yt2rdvjzNnzsDIyAgXLlxAXl4e/Pz8cPPmTaSnp2PLli0AABMTE2RlZcHV1RVOTk64evUqkpOTMXLkSHh7eyM4OFiWKSwsDEZGRggNDS30PRJRMZESEZWA4cOHS3v16iWVSqXSFi1aSL///nupVCqVHjhwQPrfX0WDBw+Wuri4yO3766+/Shs1aiR7XKtWLemyZcukUqlUumTJEmm9evWkubm5Bb7n48ePpZqamtJnz57JjXfq1Enq7+9faM5Pvd7t27elAKShoaGff8P/39ixY6V9+/aVPf7vv8Pbt2+lBgYG0osXL8rtM2LECOmgQYM++po+Pj7Sdu3affL7Xr16VQpAmpGRIZVKpVJ/f3/pN998U+j7+jDXe+vXr5dWrFhRmpmZKRs7duyYVENDQ5qYmCjbz8zMTJqTk/PJPESkfPw4lYhK3IIFCxASEoKbN28WeO7mzZto1aqV3FirVq1w9+5d5OfnF9i+f//+ePPmDWrXrg0vLy8cOHAAeXl5AN59FJifn4969eqhfPnysq/w8HDcv3+/0Gyfer3o6GhoamoWukL2XlBQEJo2bYrKlSujfPnyWL9+PZ48eVLotvfu3UN2djZcXFzk8m3duvWj+T4mMjISPXv2RM2aNWFoaCjL+P57R0dHo02bNtDW1i7ya968eRN2dnYoV66cbKxVq1aQSCS4ffu2bMzGxka2IkhEJYcfpxJRiWvbti1cXV3h7+9f6EekirCwsMDt27dx+vRphIaGYsyYMVi0aBHCw8ORmZkJTU1NREZGQlNTU26/8uXLK/x6+vr6n8yya9cu+Pn5YcmSJXBycoKhoSEWLVqEy5cvF7r9+2PLjh07hurVq8s9p6urW9R/AtnHnq6urvj9999RuXJlPHnyBK6urrITDT6X/Wv8t+QRUclhiSMiQcyfPx/29vYFDoRv2LAhLly4IDd24cIF1KtXr0ARe09fXx89e/ZEz549MXbsWDRo0ACxsbFo3Lgx8vPzkZycjDZt2hQ528dez8bGBhKJBOHh4XB2di6w34ULF9CyZUuMGTNGNvapFbVGjRpBV1cXT548+eTq3ufcunULr169wvz582FhYQEAuHbtmtw2tra2CAkJgVgsLnQ1TkdHp8BKZ8OGDREcHIysrCxZUbtw4QI0NDR4AgORCuDHqUQkCBsbGwwZMgQrV66UG//ll18QFhaG2bNn486dOwgJCcHq1avh5+dX6OsEBwdj06ZNiIuLw4MHD7B9+3bo6+ujVq1aqFevHoYMGQJ3d3fs378fDx8+xJUrVxAYGIhjx44p/HqWlpYYPnw4vv/+exw8eBAPHz7EuXPnsGfPHgBA3bp1ce3aNZw8eRJ37tzBtGnTcPXq1Y/+GxgaGsLPzw/jx49HSEgI7t+/j6ioKKxatQohISFF/resWbMmdHR0sGrVKjx48ACHDx/G7Nmz5bbx9vZGeno6Bg4ciGvXruHu3bvYtm2b7GNRS0tLxMTE4Pbt23j58iXEYjGGDBkCPT09DB8+HHFxcTh79ix++uknDBs2DGZmZkXOR0TFROiD8oiobCjswPmHDx9KdXR0pB/+Ktq3b5+0UaNGUm1tbWnNmjWlixYtknv+vyc2HDhwQOro6Cg1MjKSlitXTtqiRQvp6dOnZdvm5uZKp0+fLrW0tJRqa2tLq1atKu3Tp480Jiam0Jyfe703b95Ix48fL61atapUR0dH+u2330o3b94slUrfnajg4eEhNTY2llaoUEE6evRo6aRJk6R2dnYf/XeQSCTS5cuXS+vXry/V1taWVq5cWerq6ioNDw//6L9lYSc27NixQ2ppaSnV1dWVOjk5SQ8fPiwFIL1+/bpsmxs3bkg7d+4sNTAwkBoaGkrbtGkjvX//vlQqlUqTk5OlLi4u0vLly0sBSM+ePSuVSqXSmJgYaYcOHaR6enpSExMTqZeXl+xkicLeDxGVHJFUKpUK3COJiIiISEH8OJWIiIhIDbHEEREREakhljgiIiIiNcQSR0RERKSGWOKIiIiI1BBLHBEREZEaYokjIiIiUkMscURERERqiCWOiIiISA2xxBERERGpIZY4IiIiIjXEEkdERESkhv4fT7n5L6rkUNAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def execute(circuit):\n", + " t = apis.submit_task(\n", + " circuit=circuit,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + " )\n", + " count = t.results(blocked=True)\n", + " a = sum(\n", + " [\n", + " -mit.expectation(count, z=[graph[e][0], graph[e][1]], **info) * weight[e]\n", + " for e in range(len(graph))\n", + " ]\n", + " )\n", + " # a = sum([-counts.expectation(raw_count, z=[graph[e][0], graph[e][1]])*w[e] for e in range(len(graph))])\n", + " return a\n", + "\n", + "\n", + "random_state = np.random.RandomState(0)\n", + "noise_scaling_function = partial(\n", + " zne_option.scaling.fold_gates_at_random,\n", + " fidelities={\"single\": 1.0},\n", + " random_state=random_state,\n", + ")\n", + "factory = zne_option.inference.PolyFactory(scale_factors=[1, 3, 5], order=1)\n", + "# factory = zne_option.inference.ExpFactory(scale_factors=[1,1.5,2],asymptote=0.)\n", + "# factory = zne_option.inference.RichardsonFactory(scale_factors=[1,1.5,2])\n", + "# factory = zne_option.inference.AdaExpFactory(steps=5, asymptote=0.)\n", + "\n", + "result = apply_zne(\n", + " circuit=c1,\n", + " executor=execute,\n", + " factory=factory,\n", + " scale_noise=noise_scaling_function,\n", + " num_to_average=1,\n", + ")\n", + "_ = factory.plot_fit()\n", + "print(\"zne\", result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## DD" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[18, 17], [7, 17], [3, 4], [14, 4], [4, 3], [5, 4], [16, 17], [12, 13], [14, 13], [3, 13], [8, 9], [10, 0], [9, 8], [19, 9], [1, 0], [19, 18], [17, 18], [8, 18], [13, 14], [15, 5], [6, 5], [15, 14], [18, 19], [4, 5], [5, 6], [18, 8], [4, 14], [14, 15], [0, 1], [11, 1], [5, 15], [1, 2], [10, 11], [2, 1], [11, 10], [0, 10], [1, 11], [9, 19], [16, 6], [6, 7], [15, 16], [7, 6], [16, 15], [12, 2], [6, 16], [3, 2], [12, 11], [17, 7], [8, 7], [17, 16], [2, 3], [11, 12], [13, 3], [2, 12], [13, 12], [7, 8]]\n" + ] + } + ], + "source": [ + "d = apis.get_device(\"tianshu_s1\")\n", + "couple_list = d.topology()\n", + "print(couple_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c, ideal = benchmark_circuits.ghz_circuit(8)\n", + "c.to_qiskit().draw(\"mpl\") # logical circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'logical_physical_mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, 'positional_logical_mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}}\n" + ] + } + ], + "source": [ + "c1, info = qiskit_compile(\n", + " c,\n", + " compiled_options={\n", + " \"basis_gates\": [\"h\", \"rz\", \"x\", \"y\", \"z\", \"cz\"],\n", + " \"optimization_level\": 2,\n", + " # \"coupling_map\": d.topology(),\n", + " },\n", + ")\n", + "\n", + "print(info)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ideal 1.0\n", + "raw 0.156\n" + ] + } + ], + "source": [ + "zpauli = [0, 6] # logical\n", + "\n", + "t = apis.submit_task(circuit=c, shots=10000, device=\"simulator:aer\")\n", + "raw_count = t.results(blocked=True)\n", + "ideal = counts.expectation(raw_count, z=zpauli)\n", + "print(\"ideal\", ideal)\n", + "\n", + "\n", + "t = apis.submit_task(\n", + " circuit=c1,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + ")\n", + "raw_count = t.results(blocked=True) # position_counts=logical_counts\n", + "raw = counts.expectation(raw_count, z=zpauli)\n", + "print(\"raw\", raw)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mit 0.1734\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABDYAAAIwCAYAAAB9WutrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAABVBUlEQVR4nO3dfXwU5b3///dkQ+4TboJtQO4lUW6TAqKgtYKhBQFrz6nFHrQ3P8+x/JSCrT9i62lra1VMjXccbL/0VG1Pa/mlR+rRErBymloRxQYjyk00YA0SklUXg4TckOzufP9IoUaCZDezO7l2Xs/HI49IZubK57p23Jl555pZy7ZtWwAAAAAAAAZKcrsAAAAAAACAaBFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYxFsAAAAAAAAYyW7XQB6ZttSR8jtKnovxSdZlttVJA7bttUaNmgHkJSR5JPl4E7AGAAAAADoDYKNfqojJN1S7nYVvVe6REplb3JMazikwZVb3C4jIk1z5ynT59xOwBgAAAAA6A1uRQEAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMYi2AAAAAAAAMbyRLARCARUUlKi8ePHKy0tTSNHjtTKlSvV0tKi6667TpZlae3atW6XiRh696j09GvS7/4qPV4lPfu6dKzd7aoAAAAAAH2V8MHGzp07NWXKFN1zzz3y+/2aOHGiOjs7tWbNGi1ZskQ1NTWSpKKiIncLjZH6vc/qwWssvVxRdtp1HrzG0pNli+JYVfy8fVj66Z+ku/4gPb1LemGf9Hyt9D8vSz98QnrsBam5ze0qYyt4+53qnL9I4d17elwe3r1HnfMXKXj7nXGuLD683n8AAAAg0SV0sBEIBLR48WL5/X7dfPPNamxsVHV1tfx+v0pLS1VRUaGqqipZlqWpU6e6XS4cVtMg/ccWqdbf8/JgWKp6S7r/j9LhY/GtLZ58K5ZLOTkKld0nu637NBW7vV2hsvuknBz5Vi53qcLY8nr/AQAAgESX0MHGihUrVF9fr+XLl6usrEzZ2dknl5WUlKiwsFDBYFBjxoxRTk6Oi5XCaY1HpEe3Sp2hM6/7fou07s9SRzDmZbnCGjSw66K9oVHhXzzcbVn44Uelhkb5bvqmrIEDXaowtrzefwAAACDRJWywUVNTo/Lycg0dOlSrV6/ucZ3p06dLkgoLC7v9/K233tIVV1yh7OxsDR48WF/5yld0+PDhmNcM51TujSyoePeoVF0Xs3Jcl3TRbFnFcxXeuEnhV3ZKksKvvqbwUxtlFV+mpNmz3C0wxrzefwAAACCRJWywsX79eoXDYS1dulRZWVk9rpOeni6pe7DR3NysOXPmqL6+XuvXr9fPf/5zbd26VYsWLVI4HI5L7bEQ7GhVW3Ogx69Ec6xdeuVA5Ns9XyvZtvP19Be+G5ZJubkK3Xu/7MOHFbr3ASk3V74bl7ldWlx4vf8AAABAokp2u4BYqayslCTNmTPntOvU19dL6h5s/PznP9ehQ4f03HPPadSoUZKkESNGaPbs2Xrqqad05ZVXxq7oGNq+4TZt33Cb22XExRuNXc/PiFR9k3SkVRqc6XxN/YGVlSXft29S6NbvKbjsRulos3x3/VhWZoJ2+CO83n8AAAAgUSVssHHgQNef7EePHt3j8mAwqG3btknqHmxs3LhRF1988clQQ5JmzZqlcePG6Q9/+ENUwcaMGTPk95/mCZan4RuQri/csS/i33U6k+dcr/wLrupx2RN3z+tz+wX5+Qp19o+PFzln9tf1qc//OKptL750nj5orHG4osjZKSnSuoccbzdpxjTZly9QeNNmJV2+QEnTpznWdkF+gayODsfai8UYxLL/kvNjAAAAAHhFXl6eduzYEdW2CRtstLS0SJLa2nq+2C4vL1cgEFB2drbGjh178ud79+7VVVedGgBMmjRJe/fujaoWv9+vQ4cORbRNcmpGVL/rdAbl5WvU5GJH2/ywhsYGBY+3xqz9SAx6rzHqbRvqD+iIP7LXKibSUjUgRk1bE8+TNm3u+u6ghsYGqf24cw3GaAxi1X8pBmMAAAAA4IwSNtjIy8tTU1OTqqurNWtW9wcDNjY2atWqVZKkqVOnyrKsk8uampo0aNCgU9obMmSI3njjjahriZRvQHpUv8stw4cN7zczNqy2rmDDtu1ur+2ZdLQeUXZqWJlnnx2r0nrNTknRe24XEaHhw4Y7PmPD62MAAAAAeEU0180nJGywUVxcrJqaGpWWlmrevHkqKCiQJFVVVenaa69VIND10MyioqKY1xLNdJrjQemW8hgUEyO1+/YptZ/sTbYt3fu0VP9+70MNSZo3bZB+Wrc/RlVFpiUU1ODKLW6XEZHafbXK9Dm3EzAGAAAAAHojYT8VpaSkRLm5uTp48KAmTZqkKVOmKD8/XzNnztS4ceM0d+5cSad+1OvgwYN15MiRU9p7//33NWTIkHiUjj6yLOnTBZFtk2RJs/NjUw8AAAAAIHYSNtgYMWKEtm7dqoULFyotLU11dXUaMmSI1q1bp4qKCtXW1ko6NdiYMGFCj8/S2Lt3ryZMmBCX2tF3M8dJ548983onXDVT+mRO7OoBAAAAAMRGQs+ZnjBhgjZu3HjKz48dO6a6ujolJSVp8uTJ3ZYtWrRIt956q+rr6zVixAhJ0ksvvaQ333xT99xzT1zqRt9ZlvTlC6W0AdLW2tOvl5zUFWpccE78agMAAAAAOMeybdt2u4h4e+mll3ThhRfq3HPP1euvv95t2dGjRzVlyhQNHTpUP/rRj9Te3q6SkhKdddZZevHFF5WUFJ9JLqY9Y6N0ifrNMzY+6t2j0rZ90st10rH2f/z8ik91zezISnOttNMy8fkSTXPnef4ZG06PAQAAAIAzS9hbUT7Orl27JJ16G4ok5eTkqLKyUsOGDdPVV1+tf/3Xf9Xs2bO1cePGuIUacNYncqQvTJfu+Od//MySNHdi/ww1AAAAAAC958k/LX5csCFJ55xzTo+3sMB8liTPTVECAAAAgATmySkIZwo2AAAAAACAGTw5Y6OystLtEgAAAAAAgAM8OWMDAAAAAAAkBoINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLMu2bdvtInAq25Y6Qm5X0XspPsmy3K7izL71mGRLsiTdv9Ttak7Ptm21hg3aASRlJPlkObgTMAYAAAAAeiPZ7QLQM8uSUnl1PMuyLGX6vL0DMAYAAAAAeoNbUQAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLEINgAAAAAAgLGS3S4APbNtqSPkdhW9l+KTLMvtKhKHaa+/xD7gNNu21Ro2ayfISPLJcmgn8Hr/AQAA0HsEG/1UR0i6pdztKnqvdImUyt7kGNNef4l9wGmt4ZAGV25xu4yINM2dp0yfMzuB1/sPAACA3uNWFAAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCxPBBuBQEAlJSUaP3680tLSNHLkSK1cuVItLS267rrrZFmW1q5d63aZiLGmFsn++3/bH7smElHYlt75QKoLSA1NUkfQ7YoAAAAAOCHhg42dO3dqypQpuueee+T3+zVx4kR1dnZqzZo1WrJkiWpqaiRJRUVF7hYaI/V7n9WD11h6uaLstOs8eI2lJ8sWxbGq+AmGpJffktY8I/3of7ov++VWad87kp3AKYfXX39Jajku/blGuuspafVG6YE/Sj/ZJP3g99Lvd0jvHHW7wtgL3n6nOucvUnj3nh6Xh3fvUef8RQrefmecK4sPr/cfAAAg0SV0sBEIBLR48WL5/X7dfPPNamxsVHV1tfx+v0pLS1VRUaGqqipZlqWpU6e6XS4c1nJc+umfpF+/IP3tvVOX73xbeuh/pQ1VUjgc//oQew1N0k8qpCerpcCx7svaO6Xn3pBKN0ovvelOffHiW7FcyslRqOw+2W3t3ZbZ7e0Kld0n5eTIt3K5SxXGltf7DwAAkOgSOthYsWKF6uvrtXz5cpWVlSk7O/vkspKSEhUWFioYDGrMmDHKyclxsVI4rSMo/fzPPQcaH/X8PumJlxN75oYXvdcsPfQn6YO2j18vbEvrt0vVdXEpyxXWoIFdF+0NjQr/4uFuy8IPPyo1NMp30zdlDRzoUoWx5fX+AwAAJLqEDTZqampUXl6uoUOHavXq1T2uM336dElSYWHhyZ+dCEJmzpyp1NRUWZYVl3rhrL+8Lh043Pv1t9ZKb/UiBIE5fr+ja9ZOb5W/1DWLI1ElXTRbVvFchTduUviVnZKk8KuvKfzURlnFlylp9ix3C4wxr/cfAAAgkSVssLF+/XqFw2EtXbpUWVlZPa6Tnp4uqXuwsX//fm3YsEF5eXk6//zz41JrPAQ7WtXWHOjxK9GEw9IL+yPfbts+52vpL7z0+ktSoFl6vSGybY4HpZfrYlJOv+G7YZmUm6vQvffLPnxYoXsfkHJz5btxmdulxYXX+w8AAJCokt0uIFYqKyslSXPmzDntOvX19ZK6BxuXXHKJGhsbJUk//OEPtW3bthhWGT/bN9ym7Rtuc7uMuNj3TtcnoERq59vSF8+X0lOcr8ltXnr9Jemvf4vuk2+275cuyne8nH7DysqS79s3KXTr9xRcdqN0tFm+u34sKzPT7dLiwuv9BwAASFQJG2wcOHBAkjR69OgelweDwZOhxYeDjaQk5yexzJgxQ36/P6JtfAPS9YU7nJtCMHnO9cq/4Koelz1x97w+t1+Qn69Q5xkeZhAnYy9Yqun/VBrxdqGwNO3CS9X8bhTTPRxm2usv9a99YObV/6FRn/pCxNvtP/i+RozoHw8StlNSpHUPOd5u0oxpsi9foPCmzUq6fIGSpk9zrO2C/AJZHR2OtOX1/gMAAHhNXl6eduzYEdW2CRtstLR0/cm+ra3nC63y8nIFAgFlZ2dr7NixMa3F7/fr0KFDEW2TnJrhaA2D8vI1anKxo21+WENjg4LHW2PWfiRyjx4780qn8d57h3U4wtcqFkx7/aX+tQ+0tUfwcI1ukiL+fzVm0lI1IEZNWxPPkzZt7vruoIbGBinqsf8Ir/cfAAAAvZawwUZeXp6amppUXV2tWbO6PxSusbFRq1atkiRNnTo15g8IzcvLi3gb34D0GFQSO8OHDe83f61PTYr+wiInw1La2Wc7WE10THv9pf61DyQFm6Pa7vixd3V2P3j9pa4ZC6Y9z3b4sOGOztjwcv8BAAC8Jprr5hMSNtgoLi5WTU2NSktLNW/ePBUUFEiSqqqqdO211yoQ6HpoYlFRUcxriWY6zfGgdEt5DIqJkdp9+5TaT/amjqD0wyek1givL84bJj3wxmuxKSpCpr3+Uv/aBw4elu59OvLtvvzZAj3y7XrnC4pCSyiowZVb3C4jIrX7apXpc2Yn8Hr/AQAA0HsJ+6koJSUlys3N1cGDBzVp0iRNmTJF+fn5mjlzpsaNG6e5c+dK6v58DSSGlGTpgnMi3+7iAudrgTtG5kqjciPbxpckXRjFfgMAAADAXQkbbIwYMUJbt27VwoULlZaWprq6Og0ZMkTr1q1TRUWFamtrJRFsJKq5E6TBEXzQwXnDpInDY1cP4u/KaV1hRW99brKUbd4dQAAAAIDnJfSc2QkTJmjjxo2n/PzYsWOqq6tTUlKSJk+e7EJliLXsdOn/nSv9n0rp/TN89GtBnvS1T0sx+EAcuGjcJ6Svf1r61fNSZ+jj1507QZrHWwEAAABgpIQONk5nz549sm1bBQUFysg49dMnHn/8cUnS3r17u/17zJgxmjFjRvwKdcCIiZdq5W/sj13nTMtN9Ykc6Vvzpb+8Lm3fLx37yDNFP5kjXVQgzR4vJfvcqTHWvPz6S9LkEdK350t/rpGq66RguPvy/E9Kl5wrTRnpSnmuSfrsPCV91pmP+TWR1/sPAACQaDwZbOzatUvS6W9Dueqqq3r891e/+lX98pe/jGltcFZ2mrSoSJo/RXrDLzW3dc3MGJoljT1LivEH4qAfGDZI+pdZ0uenSfv80i+f/8eyG2P7CbgAAAAA4oBgowe2nbh/wfaqZJ80qX98iidckpkqFY2WrOclWxKZFgAAAJAYPPlUgTMFGwAAAAAAwAyenLFRWVnpdgkAAAAAAMABnpyxAQAAAAAAEgPBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMJZl27btdhE4lW1LHSG3q+i9FJ9kWW5XkThMe/0lc/aBbz0m2ZIsSfcvdbua07NtW61hs3aCjCSfLId2Aq/3HwAAAL2X7HYB6JllSam8Op7F6w/LspTp8+5O4PX+AwAAoPe4FQUAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABiLYAMAAAAAABgr2e0C0DPbljpCblfReyk+ybKca8+2bbWGDRoASRlJPlkODYLX+w/z3gMk598HvM7r7wNe7z8AAOg9go1+qiMk3VLudhW9V7pESnVwb2oNhzS4cotzDcZB09x5yvQ5Mwhe7z/Mew+QnH8f8Dqvvw94vf8AAKD3uBUFAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYyxPBRiAQUElJicaPH6+0tDSNHDlSK1euVEtLi6677jpZlqW1a9e6XWZM1O99Vg9eY+nlirLTrvPgNZaeLFsUx6riJ3j7neqcv0jh3Xt6XB7evUed8xcpePudca4sfhgDqblNema39MAfJfvvP7MlHWpys6r48Pp7wAmNR6TH/yrdu1la/Qfp/j9Km1+TjrS6XVns8R7AGAAAkOiS3S4g1nbu3KkFCxbI7/crMzNTEydOVENDg9asWaM333xT77//viSpqKjI3UIRE74VyxXcvUehsvtk/ewhWelpJ5fZ7e0Kld0n5eTIt3K5i1XGlpfHIBSW/udl6YX9Xf/9Ufdsks75hHTtRdKgjPjXh9hrbpd+84L0RuOpyw4EpC27pZnjpC+eLyX74l9fPHj5PeAExgAAgMSW0DM2AoGAFi9eLL/fr5tvvlmNjY2qrq6W3+9XaWmpKioqVFVVJcuyNHXqVLfLRQxYgwZ2nag2NCr8i4e7LQs//KjU0CjfTd+UNXCgSxXGnlfHIBSWHnlO2lrbc6hxwpvvds3kaGqJX22Ij+Y26cE/9hxqnBC2pe1vSv/5rBQMxa20uPLqe8CHMQYAACS2hA42VqxYofr6ei1fvlxlZWXKzs4+uaykpESFhYUKBoMaM2aMcnJyXKwUsZR00WxZxXMV3rhJ4Vd2SpLCr76m8FMbZRVfpqTZs9wtMA68OAZ/3CXtOdS7dY+0doUgtn3mdWGOXz4vBY71bt03/NIfdsa0HFd58T3goxgDAAASV8IGGzU1NSovL9fQoUO1evXqHteZPn26JKmwsPDkzx5//HH98z//s0aPHq2MjAydd955+vd//3cdO9bLs+N+KtjRqrbmQI9fXuC7YZmUm6vQvffLPnxYoXsfkHJz5btxmdulxY2XxqAjKD1fG9k2B9/vmr2RqLz2HvD24chfzxf3S20dsamnP/DSe8DpMAYAACSmhH3Gxvr16xUOh7V06VJlZWX1uE56erqk7sFGWVmZRo0apbvuuksjRozQzp079aMf/Uh/+ctf9NxzzykpycwsaPuG27R9w21ul+EaKytLvm/fpNCt31Nw2Y3S0Wb57vqxrMxMt0uLGy+NQfUBqTWKC9Tna6Xxn3S+nv7Aa+8BkQZbUlcgVvWWdMm5ztfTH3jpPeB0GAMAABJTwgYblZWVkqQ5c+acdp36+npJ3YONP/zhDzrrrLNO/vszn/mMzjrrLC1dulTPP/+8LrnkkohrmTFjhvx+f0Tb+Aak6wt37Iv4d53O5DnXK/+Cq3pc9sTd8/rcfkF+vkKdbX1u5wQ7JUVa95Bj7UlS0oxpsi9foPCmzUq6fIGSpk9ztP2C/AJZHc78uTcW/ZdiOwZO9r+vZlx1r8bMWBLxdi/u9ut7X54Rg4oiZ9p7gOT8+0BfzF/1vLKGjol4uwcffkr/8tsbnC8oCrwP8j4IAICX5OXlaceOHVFtm7DBxoEDByRJo0eP7nF5MBjUtm3bJHUPNj4capwwY0bXhc6hQ728Yf8j/H5/xNsmpzr7EQ2D8vI1anKxo21+WENjg4LHHfzcxLRUDXCutZOsiedJmzZ3fXdYQ2OD1H7cmcZi1H8pdmPgaP/7qDAU3cwq34DMqP8/d5pp7wFSDN4H+sBKTjvzSj0I2r5+sw/wPsj7IAAA6J2EDTZaWro+4qCtree/HpaXlysQCCg7O1tjx4792Lb+/Oc/S5ImTJgQVS15eXkRb+MbkB7V73LL8GHDHZ+x8Z5jrcXH8GHDHf1LpZf731fJSdF9vEWoo0Vnn322w9VEx7T3AMn594G+CHdGF7AkW8F+sw94/X3A6/0HAMBrorluPiFhg428vDw1NTWpurpas2Z1f9J5Y2OjVq1aJUmaOnWqLMs6bTuHDh3S97//fc2fP19FRUVR1RLNdJrjQemW8qh+nStq9+1TqoN7U0soqMGVW5xrMA5q99Uq0+fMIHi9/3214y3pNy9Evt2ni/K07u+3qLnNtPcAyfn3gb743UvSC/sj3+7/u/7zmvWTzztfUBS8/j7g9f4DAIDeM/NJmL1QXNw15bq0tFS1tf94ilxVVZXmzJmjQKDrkwA+Lqw4duyYPv/5zyslJUWPPPJITOsF4JyiUVJmauTbXVzgfC1wx0VRvJZpA6RpYxwvBQAAADGWsMFGSUmJcnNzdfDgQU2aNElTpkxRfn6+Zs6cqXHjxmnu3LmSuj9f48Pa2tq0ePFivfXWW3rmmWc0bNiweJYPoA+SfdKlEd46P+4saXRubOpB/J09WDovwrftTxeo38w4AQAAQO8lbLAxYsQIbd26VQsXLlRaWprq6uo0ZMgQrVu3ThUVFSdncfQUbHR2duqLX/yiduzYoc2bN2vixInxLh9AH102SZo+pnfrnpUtff0S6WPuSoOBvnKRNGxQ79adOlJaMDWm5QAAACBGLNu2bbeLiLdjx44pJydHlmWpublZGRn/+PSBcDisq6++Wk899ZQ2bdp0cmZHvJl2f33pEmf/0mnivdVNc+d5+t5yJ/vvlLAtPf2a9JfXu/6f+ihL0qQR0pcvjO7WlVgy7T1Acv59wAmtHV3P23j1oNTT0W6Ar+sWpEVFkq+fRf1efx/wev8BAEDvefLou2fPHtm2rYKCgm6hhiTdeOON+u///m995zvfUUZGhrZv335y2TnnnNPjx8EC6J+SLOnyQmnuRKnqb9LeBqmtQ0pJlkYOkWbnS7lZbleJWMpIkb72aampRXphn7Rlzz+WfWG6dP64rnUAAABgLk8GG7t27ZLU820omzdvliTdfffduvvuu7ste/TRR/W1r30t5vUBcFbaAOnT53Z9wZsGZ0oLi6T/3SPZ6pqt85kIn8MCAACA/olg4yPq6uriXA0AAAAAAIhWP7ujOD4+LtgAAAAAAADm8OSMjcrKSrdLAAAAAAAADvDkjA0AAAAAAJAYCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxLNu2bbeLwKlsW+oIuV1F76X4JMtyrj3bttUaNmgAJGUk+WQ5NAhe7z/Mew+QnH8fiIVvPSbZkixJ9y91u5qP5/X3Aa/3HwAA9F6y2wWgZ5YlpXr41bEsS5k+7w6A1/sP3gPA+4DX+w8AAHqPW1EAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxkt0uAD2zbakj5HYVvZfikyzLufZs21Zr2KABkJSR5JPl0CB4vf8AzDsOSM4fC7zOtGOB08cB0/ovcSwEALcQbPRTHSHplnK3q+i90iVSqoN7U2s4pMGVW5xrMA6a5s5Tps+ZQfB6/wGYdxyQnD8WeJ1pxwKnjwOm9V/iWAgAbuFWFAAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCyCDQAAAAAAYCxPBBuBQEAlJSUaP3680tLSNHLkSK1cuVItLS267rrrZFmW1q5d63aZAIAYOnhYsv/+37akw8fcrAbxFg5LNQ3SX16X/lwjVf1Nau1wuyoAAOCEhA82du7cqSlTpuiee+6R3+/XxIkT1dnZqTVr1mjJkiWqqamRJBUVFblbaIzU731WD15j6eWKstOu8+A1lp4sWxTHquInePud6py/SOHde3pcHt69R53zFyl4+51xrix+GAN4mW1L1XXSfU9L9z7dfdkdT0o//7P05juulBY3nj8OhKT/3SP9+Clp3Z+lJ16WnqyWHntRuu330v+/XQo0u11lbHn9OOD1/gOAFyR0sBEIBLR48WL5/X7dfPPNamxsVHV1tfx+v0pLS1VRUaGqqipZlqWpU6e6XS5iwLdiuZSTo1DZfbLb2rsts9vbFSq7T8rJkW/lcpcqjD3GAF5l210Xsf+1TXr7cA/LJe1tkB76k7R9f9zLQxy0d0o/q5Q27pSaWk5d3hmStr8p3f9H6UAg7uXFjdePA17vPwB4QUIHGytWrFB9fb2WL1+usrIyZWdnn1xWUlKiwsJCBYNBjRkzRjk5OS5WilixBg3sOlFpaFT4Fw93WxZ++FGpoVG+m74pa+BAlyqMPcYAXvXMbum5N868XtiWyl+Sdh2MfU2In7AtPbpVevPdM6/bclz6+bOJO3PD68cBr/cfALwgYYONmpoalZeXa+jQoVq9enWP60yfPl2SVFhYePJnW7duVXFxsYYNG6bU1FSNGDGi2y0rME/SRbNlFc9VeOMmhV/ZKUkKv/qawk9tlFV8mZJmz3K3wDhgDOA1x9q7go3esiU99UrXxTASw+sN0huNvV+/5XjXLSuJyuvHAa/3HwASXcIGG+vXr1c4HNbSpUuVlZXV4zrp6emSugcbTU1NmjJlitasWaNnnnlGpaWl2rNnj2bNmqX6+vq41B4LwY5WtTUHevzyAt8Ny6TcXIXuvV/24cMK3fuAlJsr343L3C4tbhgDeMlLb0qhcGTbvNcs7fPHpp7+wGvHgW37It/m5Tqp9bjjpfQbXj8OeL3/AJDIkt0uIFYqKyslSXPmzDntOieCig8HG1dccYWuuOKKbuudf/75Ovfcc7VhwwatXLkyBtXG3vYNt2n7htvcLsM1VlaWfN++SaFbv6fgshulo83y3fVjWZmZbpcWN4wBvKT6QPTbnTvM2Vr6Cy8dB9o6pL2HIt+uMyTtPiTNHOd8Tf2B148DXu8/ACSyhA02DhzoOqsdPXp0j8uDwaC2bdsmqXuw0ZPc3FxJUnJydMM1Y8YM+f2R/RnQNyBdX7gjij83ncbkOdcr/4Krelz2xN3z+tx+QX6+Qp1tfW7nBDslRVr3kGPtSVLSjGmyL1+g8KbNSrp8gZKmT3O0/YL8Alkdznx2YCz6L8V2DJzsP9BXC2/dofSBeRFv98QftmjVF78eg4oiZ9pxQHL+WBCtzCGjtOCWF6La9jvfv1O1f/mZwxVFx7RjodPHAdP6L3EsBIC+yMvL044dO6LaNmGDjZaWrseft7X1fIJVXl6uQCCg7OxsjR079pTloVBI4XBYBw4c0He/+13l5eXpS1/6UlS1+P1+HToU2Z+OklMzovpdpzMoL1+jJhc72uaHNTQ2KHi81bkG01I1wLnWTrImnidt2tz13WENjQ1Su0NzmGPUfyl2Y+Bo/4E+6uw8rvQotmttaY74/TpWTDsOSDE4FkQpuz36O22PvB/oN/uAacdCx48DhvVf4lgIAG5J2GAjLy9PTU1Nqq6u1qxZ3R8I1djYqFWrVkmSpk6dKsuyTtn+M5/5zMkZHePHj1dlZaXOOuusqGuJlG9ANKfk7hk+bLjjMzbec6y1+Bg+bLijMza83H+gr9qa3lbO0J5n7H2cUItfZ599dgwqipxpxwHJ+WNBtJJ8yepsb9aAtOwzr/wRvs73+80+YNqxwOnjgGn9lzgWAkBfRHPdfELCBhvFxcWqqalRaWmp5s2bp4KCAklSVVWVrr32WgUCXQ9LKyoq6nH7hx9+WEeOHNFbb72le+65R5/97Ge1bds2jRo1KuJaoplOczwo3VIe8Wauqd23T6kO7k0toaAGV25xrsE4qN1Xq0yfM4Pg9f4DffXKAelXz0e+3X/de4PO+s8bnC8oCqYdByTnjwV9saFK2lob2TaDMqTtz/xKvn7yaHXTjgVOHwdM67/EsRAA3NJPDt3OKykpUW5urg4ePKhJkyZpypQpys/P18yZMzVu3DjNnTtX0umfr3Huuefqggsu0NVXX60//elPam5u1k9+8pN4dgEAEKUpI6SctMi2OTdPOisnNvUg/i4qiHyb2ePVb0INAADQewl7+B4xYoS2bt2qhQsXKi0tTXV1dRoyZIjWrVuniooK1dZ2/RnnTA8OlaRBgwZp/Pjx2r9/f6zLBgA4INknXXORlHTqnYY9ykqTrpoZ25oQX3kDpYVnPsSfNHaoNGdi7OoBAACxk9Bz5SZMmKCNGzee8vNjx46prq5OSUlJmjx58hnbeffdd/XGG2/oggsuiEWZAIAYKMiT/vUz0i+flzqCp19vcIb0jbnS0Mgfx4B+rnhS1/eKVz9+vfxPSl+/RBrgi31NAADAeZZt27bbRcTbSy+9pAsvvFDnnnuuXn/99W7LrrnmGo0fP15FRUUaNGiQ9u3bp/vvv1+NjY2qqqrS+PHj41KjafdWly6R55+x0TR3nqefseFk/wEnHW2Ttr8pvbBPOvKhD+wYPqjrdoUZY6TUWH0MUR+YdhyQnD8WOKXxiLRtn1T1t65xPeG8YdLFBdLE4VJSP5zDatqxwOnjgGn9lzgWAoBbPPnOu2vXLkk934Zy4YUX6r/+67/04IMPqr29XSNHjtScOXN06623avToyJ+wDwBwV0669NnJUvFE6Wi7dLxTSk+RstOkHj4UCwlo2CDpi+dLV3xKKvlQWLRsrmslAQAABxFsfMTy5cu1fPnyeJcEAIixpKSuT72Ad6UkS5YkW13fAQBAYuiHEy9j7+OCDQAAAAAAYA5PztiorKx0uwQAAAAAAOAAT87YAAAAAAAAiYFgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGItgAwAAAAAAGMuybdt2uwicyraljpDbVfReik+yLOfas21brWGDBkBSRpJPlkOD4PX+AzDvOCA5fyyIhW89JtmSLEn3L3W7mo9n2rHA6eOAaf2XOBYCgFuS3S4APbMsKdXDr45lWcr0eXcAvN5/ABwHwLHA6/0HAPQet6IAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjJbtdAHpm21JHyO0qei/FJ1mWc+3Ztq3WsEEDICkjySfLoUHwev8BAJwLeB3nAowBgN4j2OinOkLSLeVuV9F7pUukVAf3ptZwSIMrtzjXYBw0zZ2nTJ8zg+D1/gMAOBfwOs4FGAMAvcetKAAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFgEGwAAAAAAwFjJbhcAAAAQD7Yt2Sf+29VK4JawLbV3SElJUmqyZFluVwQAcELCz9gIBAIqKSnR+PHjlZaWppEjR2rlypVqaWnRddddJ8uytHbtWrfLjJn6vc/qwWssvVxRdtp1HrzG0pNli+JYVfwEb79TnfMXKbx7T4/Lw7v3qHP+IgVvvzPOlcUPYwDA6460Sptfk257ovvPf71Neuu9rsAjkXn9XECS6t+Xyl+SvlMu3fq49J3fSd/bID1VLQWa3a4u9rx+LuD1/gNekNDBxs6dOzVlyhTdc8898vv9mjhxojo7O7VmzRotWbJENTU1kqSioiJ3C0XM+FYsl3JyFCq7T3Zbe7dldnu7QmX3STk58q1c7lKFsccYAPCyF/ZJt/+P9Mdd0tG27sterpMefEb65VapI+hGdYi1ULgr0CjbLL24X+oI/WNZy3Gpska68ylpy+7EDri8fi7g9f4DXpCwwUYgENDixYvl9/t18803q7GxUdXV1fL7/SotLVVFRYWqqqpkWZamTp3qdrmIEWvQwK6DVEOjwr94uNuy8MOPSg2N8t30TVkDB7pUYewxBgC8alut9Lu/dt1+8HFePSg98lzXRTASh21Lv32xK9D42PUkVbwq/XF3XMpyhdfPBbzef8ALEjbYWLFiherr67V8+XKVlZUpOzv75LKSkhIVFhYqGAxqzJgxysnJcbFSxFrSRbNlFc9VeOMmhV/ZKUkKv/qawk9tlFV8mZJmz3K3wDhgDAB4TaBZenxH79d/vVF67o3Y1YP4e7mu66u3nn5NqgvEqhr3ef1cwOv9BxJdQgYbNTU1Ki8v19ChQ7V69eoe15k+fbokqbCw8LTtLFiwQJZl6Yc//GEsyoyrYEer2poDPX55ge+GZVJurkL33i/78GGF7n1Ays2V78ZlbpcWN4wBAC/Zti/yWwuerz3z7A6Tee1cYGsUQdW2Wufr6E+8fi7g9f4DiSwhPxVl/fr1CofDWrp0qbKysnpcJz09XdLpg43f/e532rlzZ6xKjLvtG27T9g23uV2Ga6ysLPm+fZNCt35PwWU3Skeb5bvrx7IyM90uLW4YAwBeEQxJL70Z+XaHj0m1fum8Yc7X1B946Vyg/n3pwOHIt3vlgPSF6VJGqvM19QdePxfwev+BRJaQwUZlZaUkac6cOaddp76+XlLPwcbRo0d10003qaysTNdcc02f65kxY4b8fn9E2/gGpOsLd+zr8+8+YfKc65V/wVU9Lnvi7nl9br8gP1+hzrYzr9hLdkqKtO4hx9qTpKQZ02RfvkDhTZuVdPkCJU2f5mj7BfkFsjo6HGkrFv2XYjsGTvYfAPoifeAwLby1Kqptl33rNu1//uEzrxgHXj8X6IuRRVfqgi9H/ql3wbA085IFOnJoVwyqigznApwPAl6Tl5enHTsiuI/0QxIy2Dhw4IAkafTo0T0uDwaD2rZtm6Seg41///d/V0FBgZYuXepIsOH3+3Xo0KGItklOzejz7/2wQXn5GjW52NE2P6yhsUHB463ONZiWqgHOtXaSNfE8adPmru8Oa2hskNqPO9NYjPovxW4MHO0/APTBwGBa1Nsea2mP+JgdK54/F+iDgee0RL3t+00fqLE/7AOcC3A+CKDXEjLYaGnpOpi1tfX8V4Py8nIFAgFlZ2dr7Nix3Zbt2LFD//mf/6mXX37ZsXry8vIi3sY3IN2x3x8Pw4cNd3zGxnuOtRYfw4cNd3TGhpf7DwB9MSA9+vsI0pJDOvvssx2sJnpePxfoi4yUyB+WYtu2LMtSToZPSf1gH+BcgDEAvCaa6+YTEjLYyMvLU1NTk6qrqzVrVvcnHDc2NmrVqlWSpKlTp8qyrJPLQqGQvvGNb2j58uWaNGmSY/VEM53meFC6pdyxEmKudt8+pTq4N7WEghpcucW5BuOgdl+tMn3ODILX+w8AffXTP3U9LyMSviRp8/oyZaeVxaaoCHn9XKAvOoLSbU9IbRFcX1qWpWGDpJpXtupDp4eu4VyAMQDQewn5qSjFxV3TLEtLS1Vb+4/HW1dVVWnOnDkKBLqe/l1UVNRtu7Vr1+qdd95JiE9BAQDAyy4uiHybolFSdvR3saAfSUmWZo6LfLuL89UvQg0AQGQSMtgoKSlRbm6uDh48qEmTJmnKlCnKz8/XzJkzNW7cOM2dO1dS9+drBAIBff/739cPfvADBYNBHTlyREeOHJEktbe368iRIwqHw250BwAARGjS2dKYob1fPzVZKnZusib6gUvPk7IiuCspb6A0I4owBADgvoQMNkaMGKGtW7dq4cKFSktLU11dnYYMGaJ169apoqLi5CyODwcb9fX1am5u1je+8Q0NHjz45JfUNfNj8ODBevvtt13pDwAAiIwvSfrXz0hnDz7zuinJ0nWfkYYNinlZiKPBmdL1c6TMXoQbQ7Olb8xRv7mVBgAQGcu27cifrmSwY8eOKScnR5Zlqbm5WRkZGSd/3tOzMObMmaOvfvWr+trXvqYLL7xQaWnxmaNq2n21pUucPRkw8Z7KprnzPP2MDSf7DwBOae+U/rhLeulNqfUjz1uwLGnKCOlzU3oXgMSb188FnPJes/T0a9LOt6XQRybfpiZLM8ZKC6ZKWf3sNiTOBRgDAL3nuf/r9uzZI9u2VVBQcDLUkKSsrCxdeumlPW4zZsyY0y4DAAD9V9oA6fPTui5cXzsovXu06+I2O00qHNX1V30ktrOypWsvkq6c1hVubPjQ37F+9E9d+wgAwGyeCzZ27dolqfttKAAAILGl/P0v8/Cu7HTp0+dKv98h2ZIsEWoAQKIg2DgDj92pAwAAAACAURLy4aEfhxkbAAAAAAAkDs/N2KisrHS7BAAAAAAA4BDPzdgAAAAAAACJg2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYy7Jt23a7CJzKtqWOkNtV9F6KT7Is59qzbVutYYMGQFJGkk+WQ4Pg9f4DADgXiJVvPSbZkixJ9y91u5rT41yAMQDQe8luF4CeWZaU6uFXx7IsZfq8OwBe7z8AgHMBr+NcgDEA0HvcigIAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIxFsAEAAAAAAIyV7HYB6JltSx0ht6vovRSfZFnOtWfbtlrDBg2ApIwknyyHBsHr/QcAwOtMOxeUnD8f9DrOB80bA86H3UOw0U91hKRbyt2uovdKl0ipDu5NreGQBlduca7BOGiaO0+ZPmcGwev9BwDA60w7F5ScPx/0Os4HzRsDzofdw60oAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWJ4INgKBgEpKSjR+/HilpaVp5MiRWrlypVpaWnTdddfJsiytXbvW7TJjon7vs3rwGksvV5Sddp0Hr7H0ZNmiOFYVP8Hb71Tn/EUK797T4/Lw7j3qnL9IwdvvjHNl8cMYAAC8zralt96T/vuvkn3iZ5L8H7hZVXx4/VzwhFBYevVt6bEXpP98VvrlVmnLbqm5ze3K4sPr54Ne778XJLtdQKzt3LlTCxYskN/vV2ZmpiZOnKiGhgatWbNGb775pt5//31JUlFRkbuFIiZ8K5YruHuPQmX3yfrZQ7LS004us9vbFSq7T8rJkW/lcherjC3GAADgZfvfkZ54WTrUdOqyuzdK4z8pffF8KW9g/GtDfGzbJz2zS/rgIyHGzrelp3dJnxot/dMMKSPFnfriwevng17vvxck9IyNQCCgxYsXy+/36+abb1ZjY6Oqq6vl9/tVWlqqiooKVVVVybIsTZ061e1yEQPWoIFdb1ANjQr/4uFuy8IPPyo1NMp30zdlDUzcsxnGAADgVa8dlH5W2XOoccL+d6QH/yi9fTh+dSF+/vBK10ydj4YaJ4TC0o63pP94Rmo5Ht/a4snr54Ne778XJHSwsWLFCtXX12v58uUqKytTdnb2yWUlJSUqLCxUMBjUmDFjlJOT42KliKWki2bLKp6r8MZNCr+yU5IUfvU1hZ/aKKv4MiXNnuVugXHAGAAAvKahSfqvbV0XrmfS1in9/FnpWHvMy0IcbX9T+tPe3q3b+IH0yHNdty0lKq+fD3q9/4kuYYONmpoalZeXa+jQoVq9enWP60yfPl2SVFhYePJnzz77rCzLOuXL9FtVgh2tamsO9PjlBb4blkm5uQrde7/sw4cVuvcBKTdXvhuXuV1a3DAGAAAv+fPrUjDU+/WPtUsv7o9dPW7z2rlg2Jb+d3dk27z5btezWBKZ188Hvd7/RJawz9hYv369wuGwli5dqqysrB7XSU9Pl9Q92DjhoYce0rRp007+OzMzMzaFxsn2Dbdp+4bb3C7DNVZWlnzfvkmhW7+n4LIbpaPN8t31Y1mGv66RYAwAAF7Rclx6pS7y7V7YJ102UUpKwD/9ee1c8I1GKXAs8u2er5XGfcL5evoLr58Per3/iSxhg43KykpJ0pw5c067Tn19vaSeg42JEyfqwgsvjE1xLpg853rlX3BVj8ueuHtenKtxR9KMabIvX6Dwps1KunyBkqZPO/NGCYYxAAB4wf53pGAvbkH5qKZW6Z2j0rBBjpfkOq+dC77eGN12NVFuZxKvnw96vf+JKmGDjQMHDkiSRo8e3ePyYDCobdu2Seo52HDSjBkz5Pf7I9rGNyBdX7hjn2M1DMrL16jJxY6191EF+fkKdTr3eVl2Soq07iHH2jvBmnietGlz13eHFeQXyOrocKStWPVfit0YONl/AAD6YvSML+n8q+6Latv5C6/U4QM7HK4ocqadC0rOnw/2xfQvlmns+VdHvF1re1gjRoyKQUWR43zQvGsCzof7Ji8vTzt2RPf+m7DBRktLiySpra3nN9fy8nIFAgFlZ2dr7NixpyxfsmSJAoGAcnNzdcUVV+juu+/W0KFDo6rF7/fr0KFDEW2TnJoR1e9yS0Njg4LHW51rMC1VA5xrLS4aGhukdocep+31/gMA0AcZIyI77/qwhvo6BSI8b4sF084FpRicD/ZBflN0zw7pPN4S8Xl7zHA+aNwYcD7snoQNNvLy8tTU1KTq6mrNmtX9CbeNjY1atWqVJGnq1KmyLOvksoEDB2rVqlW65JJLlJWVpRdffFGrV6/W9u3btWPHDqWlpSlSeXl5EW/jG5Ae8TZuGj5suOMzNkx7dtPwYcMdnbHh5f4DANAXVmvX7ca2bXc7zzuTjrYPlJHUorPPPjtWpfWaaeeCkvPng31xvCm62S5HDr3aL15/ifNBybwx4Hy4b6K5bj4hYYON4uJi1dTUqLS0VPPmzVNBQYEkqaqqStdee60Cga4U96OfdvKpT31Kn/rUp07++9JLL9XkyZN1xRVXaP369fr6178ecS3RTKc5HpRuKY94M9fU7tunVAf3ppZQUIMrtzjXYBzU7qtVps+ZQfB6/wEA6Kv/Uym93tj7UEOSiosG6qdvOXf7R1+Ydi4oOX8+2BedIem230utEV5j3vL1i/Xb2+pjU1SEOB80bww4H3ZPAj7zuUtJSYlyc3N18OBBTZo0SVOmTFF+fr5mzpypcePGae7cuZJ693yNRYsWKTMzM+r7fQAAABBfn4nw1nlfknRRQWxqQfwN8EkX5Ue2zZBMafKI2NQDILYSNtgYMWKEtm7dqoULFyotLU11dXUaMmSI1q1bp4qKCtXW1kqK7MGhkUxlBAAAgHsmDJc+N6V361qSvnyh9MmcmJaEOJs/VTpvWO/WTRsg/etnugIuAOaxbNu23S4i3o4dO6acnBxZlqXm5mZlZHz8w5mefPJJXXnllfrVr36lr3zlK3Gp0bTph6VL5PlbUZrmzvP0rShO9h8AACfYtvSX16WNr0rBUM/rZKRISy6QCvvHB2GcZNq5oOT8+aATgiGp/K/Sjr9Jp7voOStb+n8u6X8f88v5oHljwPmwezw56nv27JFt2yooKDgl1Ljmmms0btw4TZs27eTDQ3/yk5+oqKhIV18d+UdGAQAAwB2WJV06QZo5TvrrW9KOt6QPWqUkSxqSJV14jvSp0VKKJ8+IvSHZJy2dJX1usvTCPmn3Iendo/9Y/o050rnDuvYJAOby5Nv4rl27JPV8G8qkSZP029/+Vg888IDa2to0YsQI/du//Ztuu+02paSkxLtUAAAA9FFGqnTpeV1f8Kah2dIV07q+vvVY1+wNS123LAEwH8HGR3z3u9/Vd7/73XiXBAAAAAAAouDJx+N8XLABAAAAAADM4ckZG5WVlW6XAAAAAAAAHODJGRsAAAAAACAxEGwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjWbZt224XgVPZttQRcruK3kvxSZblXHu2bas1bNAASMpI8slyaBC83n8AALzOtHNByfnzwVj51mOSLcmSdP9St6s5Pc4HzRsDzofdk+x2AeiZZUmpHn51LMtSps+7A+D1/gMA4HVePxcE54MSY4De41YUAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgLIINAAAAAABgrGS3C0DPbFvqCLldRe+l+CTLcq4927bVGjZoACRlJPlkOTQIXu8/AACA15l2PSA5f00A9BbBRj/VEZJuKXe7it4rXSKlOrg3tYZDGly5xbkG46Bp7jxl+pwZBK/3HwAAwOtMux6QnL8mAHqLW1EAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxEj7YCAQCKikp0fjx45WWlqaRI0dq5cqVamlp0XXXXSfLsrR27Vq3ywQAAAAQQ8GQtP8dyf77v+2PXRuJqOW49Eaj9NpBqdYvtXe6XRGcktDBxs6dOzVlyhTdc8898vv9mjhxojo7O7VmzRotWbJENTU1kqSioiJ3C42h+r3P6sFrLL1cUXbadR68xtKTZYviWFX8BG+/U53zFym8e0+Py8O796hz/iIFb78zzpXFD2MAAAC87Eir9IdXpB8+Ia393+7LHnlO2ud3p6548fr1gCQdfF967EXptt9LP6vset1/+qeufz/+V+mdo25XiL5K2GAjEAho8eLF8vv9uvnmm9XY2Kjq6mr5/X6VlpaqoqJCVVVVsixLU6dOdbtcxIhvxXIpJ0ehsvtkt7V3W2a3tytUdp+UkyPfyuUuVRh7jAEAAPCquoB0zybpT3ulY8dPXf7aQemhP0mbXpVspnAkpBf3S/c/LVX9TQqGuy87HpSe3yeVbZJ217tTH5yRsMHGihUrVF9fr+XLl6usrEzZ2dknl5WUlKiwsFDBYFBjxoxRTk6Oi5UilqxBA7su2BsaFf7Fw92WhR9+VGpolO+mb8oaONClCmOPMQAAAF7k/0BaV9l1+8GZPLO7K/xAYqmuk8pfksJnCK06Q9KjWxN/9k4iS8hgo6amRuXl5Ro6dKhWr17d4zrTp0+XJBUWFp6y7IknntDs2bOVmZmpgQMH6qKLLtKePT1P40f/l3TRbFnFcxXeuEnhV3ZKksKvvqbwUxtlFV+mpNmz3C0wDhgDAADgNU9VS20RPENh06vSB22xqwfx1RmSNuzo/fqhsPR4FTN3TJWQwcb69esVDoe1dOlSZWVl9bhOenq6pFODjTVr1uhLX/qSLr74Yj311FNav369iouL1dZm9rtcsKNVbc2BHr+8wHfDMik3V6F775d9+LBC9z4g5ebKd+Myt0uLG8YAAAB4xeFjUk1DZNuEbWn7/tjU0x947Xrg1bd7N1vnw945Ku1/Nzb1ILaS3S4gFiorKyVJc+bMOe069fVdN1F9ONh48803tWrVKt1///1avvwfzxu4/PLLY1Rp/GzfcJu2b7jN7TJcY2VlyfftmxS69XsKLrtROtos310/lpWZ6XZpccMYAAAAr6h6K7pPPfnr36TPTXG8nH7Ba9cDf/1b9Nvlf9LZWhB7CRlsHDhwQJI0evToHpcHg0Ft27ZNUvdg45FHHtGAAQP0b//2b47WM2PGDPn9kd2w5RuQri/csc+xGibPuV75F1zV47In7p7X5/YL8vMV6nRuVoudkiKte8ix9iQpacY02ZcvUHjTZiVdvkBJ06c52n5BfoGsjg5H2opF/6XYjoGT/QcAAOiLaf/8E42b+S8Rb/fekQ6NGDEuBhVFzrTrAcn5a4K++OzNzyrnE+Mj3q7imed1y1VXO18QzigvL087dkRw/9CHJGSw0dLSIkmnvX2kvLxcgUBA2dnZGjt27Mmfv/DCCzr33HP1m9/8RnfccYcOHjyo/Px8/eAHP9CXv/zlqOvx+/06dOhQRNskp2ZE/ft6MigvX6MmFzva5oc1NDYoeLzVuQbTUjXAudZOsiaeJ23a3PXdYQ2NDVJ7hPPdTidG/ZdiNwaO9h8AAKAPzj12LKrtwrYd8Xl7rJh2PSDF4JqgD4LBYFTbtbe395t9AL2XkMFGXl6empqaVF1drVmzuj8UsbGxUatWrZIkTZ06VZZldVt26NAhffe731VpaalGjhyphx9+WP/yL/+is846S8XF0b0R5OXlRbyNb0B6VL/LLcOHDXd8xsZ7jrUWH8OHDXd0xoaX+w8AANAXScEPotqu/YNGnX322Q5XEx3Trgck568J+qLz2DuSIv9DXrj9cL/ZB7wmmuvmExIy2CguLlZNTY1KS0s1b948FRQUSJKqqqp07bXXKhDoekBOUVFRt+3C4bCOHTumX//617ryyislSZdddpn27t2rH//4x1EHG9FMpzkelG4pj+rXuaJ23z6lOrg3tYSCGly5xbkG46B2X60yfc4Mgtf7DwAA0BeHj0l3PBn5cza+dNkY/WJlfUxqipRp1wOS89cEffHyW9KvX4h8u3u/s0Tn3L/E+YIQUwn5qSglJSXKzc3VwYMHNWnSJE2ZMkX5+fmaOXOmxo0bp7lz50o69RNRhgwZIkndAgzLslRcXKzdu3fHrwMAAAAAopabJU2M8I/uviTpwnNiUw/ir3CUlJUa2TZ5A6Vxn4hNPYithAw2RowYoa1bt2rhwoVKS0tTXV2dhgwZonXr1qmiokK1tbWSTg02Jk2adNo229vbY1ozAAAAAOdcMU3KSOn9+ouKpBzz7v7AaST7pKtmStaZV5XUFWxdNVOyersB+pWEDDYkacKECdq4caOam5vV3Nysl156Sddff71aWlpUV1enpKQkTZ48uds2n//85yVJzzzzzMmfhcNhbdmyReeff35c6wcAAAAQvU/mSMvmSllpZ1738qnSpc4/Wx4uKxwlfXmWlHSGsCIlWbruEukcZmsYq5/cARU/e/bskW3bKigoUEZG9ycNL168WJ/+9Kd1/fXX6/Dhwxo1apR+8YtfaM+ePdqyxaznHZwwYuKlWvmbj7+78EzLE0nSZ+cp6bPOfJyVqRgDAADgFaNypVWXS9tqpe37paMfmoSdZElTR0qfPjexL2i9fj0wc5w0YrD03BvSy3VSZ+gfy9IGdC3/9LnSWdmulQgHeC7Y2LVrl6RTb0ORup6n8dRTT+mWW27RrbfeqqNHj6qwsFCbNm06+VwOAAAAAOYYmC5dXih9drJ08H2ptUMa4Ot6ngK3nnjD8MHS1RdKV3xKuvXxf/z8R/+kfvOwU/SN517Gjws2JGnQoEFat26d1q1bF8+yAAAAAMRQsk8ae5bbVcBNGaldz9yw1fWdUCNxJOwzNk7nTMEGAAAAAAAwh+cyqsrKSrdLAAAAAAAADvHcjA0AAAAAAJA4CDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxCDYAAAAAAICxLNu2bbeLwKlsW+oIuV1F76X4JMtyrj3bttUaNmgAJGUk+WQ5NAhe7z8AAIDXmXY9IDl/TRAL33pMsiVZku5f6nY1cEqy2wWgZ5YlpXr41bEsS5k+7w6A1/sPAADgdV6/HgAiwa0oAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWAQbAAAAAADAWMluF4Ce2bbUEXK7it5L8UmW5Vx7tm2rNWzQAEjKSPLJcmgQvN5/AAAAwOtMuyaUnL8u7C2CjX6qIyTdUu52Fb1XukRKdXBvag2HNLhyi3MNxkHT3HnK9DkzCF7vPwAAAOB1pl0TSs5fF/YWt6IAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjEWwAAAAAAABjeSLYCAQCKikp0fjx45WWlqaRI0dq5cqVamlp0XXXXSfLsrR27Vq3y4yJ+r3P6sFrLL1cUXbadR68xtKTZYviWFX8BG+/U53zFym8e0+Py8O796hz/iIFb78zzpXFD2MAAAAAL7Ntaf870i+3SvaJn0n67YvS24fdrCw+vHBNmOx2AbG2c+dOLViwQH6/X5mZmZo4caIaGhq0Zs0avfnmm3r//fclSUVFRe4WipjwrViu4O49CpXdJ+tnD8lKTzu5zG5vV6jsPiknR76Vy12sMrYYAwAAAHhVU4v0yHPSwfdPXfbXv3V9FeRJX71YykyNf31wRkLP2AgEAlq8eLH8fr9uvvlmNTY2qrq6Wn6/X6WlpaqoqFBVVZUsy9LUqVPdLhcxYA0a2HXB3tCo8C8e7rYs/PCjUkOjfDd9U9bAgS5VGHuMAQAAALzoSKv04DM9hxofVuuX/mOL1NoRn7rgvIQONlasWKH6+notX75cZWVlys7OPrmspKREhYWFCgaDGjNmjHJyclysFLGUdNFsWcVzFd64SeFXdkqSwq++pvBTG2UVX6ak2bPcLTAOGAMAAAB4za+e7wo3esP/gfS7l2JbD2InYYONmpoalZeXa+jQoVq9enWP60yfPl2SVFhYePJnl156qSzL6vFr2bJlcak9FoIdrWprDvT45QW+G5ZJubkK3Xu/7MOHFbr3ASk3V74bzX1NI8UYAAAAwCvePiy99V5k27x6sPdBiIkS+ZowYZ+xsX79eoXDYS1dulRZWVk9rpOeni6pe7Dx05/+VEePHu22XkVFhe644w4tWmTuw1S2b7hN2zfc5nYZrrGysuT79k0K3fo9BZfdKB1tlu+uH8vKzHS7tLhhDAAAAOAV2/ZFvo1tSy/sky4vPPO6Jkrka8KEDTYqKyslSXPmzDntOvX19ZK6BxsTJ048Zb0777xTZ511lubPnx9VLTNmzJDf749oG9+AdH3hjij+bzyNyXOuV/4FV/W47Im75/W5/YL8fIU62/rczgl2Soq07iHH2pOkpBnTZF++QOFNm5V0+QIlTZ/maPsF+QWyOpy5MS8W/ZdiOwZO9h8AAADoi+KVz2jQ8FOv7c7kV49X6vqFX4lBRZEz7ZpQ6tt1YV5ennbs2BHVtgkbbBw4cECSNHr06B6XB4NBbdu2TVL3YOOj3nvvPT399NO64YYblJwc3XD5/X4dOnQoom2SUzOi+l2nMygvX6MmFzva5oc1NDYoeNzBeVtpqRrgXGsnWRPPkzZt7vrusIbGBqn9uDONxaj/UuzGwNH+AwAAAH3hS4lqs5Dti/jaLVZMuyaUYnBd2EsJG2y0tLRIktraek6LysvLFQgElJ2drbFjx562nfXr1ysYDOraa6+Nupa8vLyIt/ENSI/697lh+LDhjs/YiPCWONcNHzbc0RkbXu4/AAAA0BfhzpaotksKt+vss892uJromHZNKPXtujCa6+YTEjbYyMvLU1NTk6qrqzVrVvdPfGhsbNSqVaskSVOnTpVlWadt59e//rUmTJigGTNmRF1LNNNpjgelW8qj/pVxV7tvn1Id3JtaQkENrtziXINxULuvVpk+ZwbB6/0HAAAA+mLTq9IzuyPfbuXXP6ff3VXvfEFRMO2aUHL+urC3EvZTUYqLu6bYlJaWqra29uTPq6qqNGfOHAUCXU9+LSoqOm0br7/+unbs2NGn2RoAAAAAgPianS8lnf7v1z1KTZZmjIlJOYixhA02SkpKlJubq4MHD2rSpEmaMmWK8vPzNXPmTI0bN05z586V9PHP1/j1r38ty7K0dOnSeJUNAAAAAOijQRnSzHGRbXPpBCk1Vg+6Q0wlbLAxYsQIbd26VQsXLlRaWprq6uo0ZMgQrVu3ThUVFSdncZwu2LBtW4899pguvfRSjRo1Kp6lAwAAAAD66IvnS+cO6926M8ZKn5sS23oQO5Zt27bbRcTbsWPHlJOTI8uy1NzcrIyMU582+5e//EWXXnqpHnnkEX3961+Pe42m3U9VukSef8ZG09x5nn7GhpP9BwAAAJwQDEkVr0ov7Ou6xvqozFTp0vOkyyZFfutKrJl2TSg5f13YW568CtmzZ49s21ZBQUGPoYbUdRtKenq6vvjFL8a5OgAAAACAE5J90uenSfOnSDvqpLr3ugKDtAFSQZ5UNKprHZjNk8HGrl27JJ3+NpT29nY9/vjjuvLKK5WdnR3P0gAAAAAADksdIF2U3/WFxEOw0YO0tDQdOXIkjhUBAAAAAIBoJOzDQz/OmYINAAAAAABgBk/O2KisrHS7BAAAAAAA4ABPztgAAAAAAACJgWADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYi2ADAAAAAAAYy7Jt23a7CJzKtqWOkNtV9F6KT7Is59qzbVutYYMGQFJGkk+WQ4Pg9f4DAAAAXmfaNaHk/HVhbxFsAAAAAAAAY3ErCgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMBbBBgAAAAAAMNb/BRh9PQDhGr0rAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def execute(circuit):\n", + " t = apis.submit_task(\n", + " circuit=circuit,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + " )\n", + " count = t.results(blocked=True) # physical_counts\n", + "\n", + " n = len(info[\"logical_physical_mapping\"])\n", + " physical_qubits = [info[\"logical_physical_mapping\"][i] for i in range(n)]\n", + " count = counts.marginal_count(count, physical_qubits)\n", + "\n", + " # a = mit.expectation(count, z=zpauli,**info)\n", + " a = counts.expectation(count, z=zpauli)\n", + " return a\n", + "\n", + "\n", + "mitigated_result = apply_dd(\n", + " circuit=c1,\n", + " executor=execute,\n", + " rule=dd_option.rules.yy,\n", + " rule_args={\"spacing\": -1},\n", + " full_output=True,\n", + " ignore_idle_qubit=True,\n", + " fulldd=False,\n", + ")\n", + "\n", + "print(\"mit\", mitigated_result[0])\n", + "mitigated_result[1].to_qiskit().draw(\"mpl\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## RC" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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6t8W1pBY+PZcGJVy4XkHIsu27UCvmTNaR0cHqampWJZFe3s7SUlJpx/v7VhWUVER9913H9/61reYM2cOCQkJEclp2jGysrvN3CUh4nRNrf57LZ7vrh0TR8Mds2BcWmRzhdKge+vZuXMntm2Tm5t7usQAhg0bxk033dTrmAkTJpx3mojIQHb5CPj+Amhug+p90HoMbNu/xXZ1FowdEe2EF2/QFdmOHTuAvm9NJSLiNGOGw61XRTtFeKjILmCQ7XkVETGOI0/26Iu2yEREnGXQbZGdug+jiIg4w6DbIhMREWdRkYmIiNFUZCIiYjQVmYiIGE1FJiIiRlORiYiI0VRkIiJiNBWZiIgYTUUmIiJGU5GJiIjRBt33kZnCtuGEN9op+i8+Fiwr2ilEZDBSkYmIiNG0a1FERIymIhMREaOpyERExGgqMhERMZqKTEREjKYiExERo6nIRETEaCoyERExmopMRESMpiITERGjqchERMRoKjIRETGaikxERIymIhMREaOpyERExGgqMhERMZqKTEREjKYiExERo6nIRETEaCoyERExmopMRESMpiITERGjqchERMRoKjIRETGaikxERIz2/wHX/E5Spy81bwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = tc.Circuit(5)\n", + "c.x(0)\n", + "c.h(2)\n", + "c.cz(0, 1)\n", + "c.cz(2, 3)\n", + "c.y(1)\n", + "c.h(2)\n", + "c.cz(0, 1)\n", + "c.cz(2, 3)\n", + "c.h(4)\n", + "c.cz(3, 4)\n", + "\n", + "c.to_qiskit().draw(\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "circuit = qem.rc_circuit(c)\n", + "circuit = qem.washcircuit(circuit, qlist=list(range(circuit.circuit_param[\"nqubits\"])))\n", + "circuit.to_qiskit().draw(\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'logical_physical_mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}, 'positional_logical_mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}}\n" + ] + }, + { + "data": { + "image/png": "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6t8W1pBY+PZcGJVy4XkHIsu27UCvmTNaR0cHqampWJZFe3s7SUlJpx/v7VhWUVER9913H9/61reYM2cOCQkJEclp2jGysrvN3CUh4nRNrf57LZ7vrh0TR8Mds2BcWmRzhdKge+vZuXMntm2Tm5t7usQAhg0bxk033dTrmAkTJpx3mojIQHb5CPj+Amhug+p90HoMbNu/xXZ1FowdEe2EF2/QFdmOHTuAvm9NJSLiNGOGw61XRTtFeKjILmCQ7XkVETGOI0/26Iu2yEREnGXQbZGdug+jiIg4w6DbIhMREWdRkYmIiNFUZCIiYjQVmYiIGE1FJiIiRlORiYiI0VRkIiJiNBWZiIgYTUUmIiJGU5GJiIjRBt33kZnCtuGEN9op+i8+Fiwr2ilEZDBSkYmIiNG0a1FERIymIhMREaOpyERExGgqMhERMZqKTEREjKYiExERo6nIRETEaCoyERExmopMRESMpiITERGjqchERMRoKjIRETGaikxERIymIhMREaOpyERExGgqMhERMZqKTEREjKYiExERo6nIRETEaCoyERExmopMRESMpiITERGjqchERMRoKjIRETGaikxERIz2/wHX/E5Spy81bwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c1, info = qiskit_compile(\n", + " c,\n", + " compiled_options={\n", + " \"basis_gates\": [\"h\", \"rz\", \"x\", \"y\", \"z\", \"cz\"],\n", + " \"optimization_level\": 2,\n", + " # \"coupling_map\": d.topology(),\n", + " },\n", + ")\n", + "\n", + "print(info)\n", + "c1.to_qiskit().draw(\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ideal -1.0\n", + "raw -0.3894\n" + ] + } + ], + "source": [ + "zpauli = [1, 2] # logical\n", + "\n", + "t = apis.submit_task(circuit=c, shots=10000, device=\"simulator:aer\")\n", + "raw_count = t.results(blocked=True)\n", + "ideal = counts.expectation(raw_count, z=zpauli)\n", + "print(\"ideal\", ideal)\n", + "\n", + "\n", + "t = apis.submit_task(\n", + " circuit=c1,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + ")\n", + "raw_count = t.results(blocked=True) # position_counts=logical_counts\n", + "raw = counts.expectation(raw_count, z=zpauli)\n", + "print(\"raw\", raw)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mit -0.39233333333333337\n", + "mit -0.4132\n" + ] + } + ], + "source": [ + "def execute(circuit):\n", + " t = apis.submit_task(\n", + " circuit=circuit,\n", + " shots=10000,\n", + " device=d,\n", + " enable_qos_qubit_mapping=False,\n", + " enable_qos_gate_decomposition=False,\n", + " )\n", + " count = t.results(blocked=True) # physical_counts\n", + "\n", + " n = len(info[\"logical_physical_mapping\"])\n", + " physical_qubits = [info[\"logical_physical_mapping\"][i] for i in range(n)]\n", + " count = counts.marginal_count(count, physical_qubits)\n", + "\n", + " # a = mit.expectation(count, z=zpauli,**info)\n", + " a = counts.expectation(count, z=zpauli)\n", + " return a\n", + "\n", + "\n", + "mitigated_result = apply_rc(\n", + " circuit=c1, executor=execute, num_to_average=6, simplify=True\n", + ")\n", + "\n", + "print(\"mit\", mitigated_result[0])\n", + "\n", + "\n", + "mitigated_result = apply_rc(\n", + " circuit=c1, executor=execute, num_to_average=6, simplify=False\n", + ")\n", + "\n", + "print(\"mit\", mitigated_result[0])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.13 ('tf')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "4d2770c334f3778740193ba4b3686745ae5c2e3ee10c8c0d673798cf1c2fcefe" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/tutorials/imag_time_evo.ipynb b/docs/source/tutorials/imag_time_evo.ipynb new file mode 100644 index 00000000..f698e793 --- /dev/null +++ b/docs/source/tutorials/imag_time_evo.ipynb @@ -0,0 +1,1301 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "dc0db886", + "metadata": {}, + "source": [ + "# Solving the Ground State of Hamiltonian by Imaginary-time Evolution" + ] + }, + { + "cell_type": "markdown", + "id": "aecf6615", + "metadata": {}, + "source": [ + "## Overview" + ] + }, + { + "cell_type": "markdown", + "id": "b533d43e", + "metadata": {}, + "source": [ + "Imaginary-time evolution (IME) is a method to solve the ground state of the Hamiltonian, which is more efficient than naive gradient descent and will not fall into a local minimum.\n", + "\n", + "However, exact imaginary-time evolution takes exponentially more space and time to execute on a classical computer. On the other hand, it is non-unitary and also cannot be implemented on a quantum computer. Therefore, we consider the approximate imaginary-time evolution, also known as the quantum natural gradient (QNG), that is, at each step we adjust the parameters in the quantum circuit to realize the imaginary-time evolution in a very short time $\\tau$. Let the parameters in the circuit be $\\boldsymbol{\\theta}$ and the output of the circuit is $|\\psi\\rangle$, define\n", + "$$\n", + "\\begin{split}\n", + " |\\psi_\\tau\\rangle&=e^{-\\tau\\hat{H}}|\\psi\\rangle\\approx|\\psi\\rangle-\\tau\\hat{H}|\\psi\\rangle,\\\\\n", + " |\\psi'\\rangle&=|\\psi(\\boldsymbol{\\theta}-\\tau\\boldsymbol{\\delta})\\rangle\\approx|\\psi\\rangle-\\tau\\sum_j\\boldsymbol{\\delta}_j|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle,\n", + "\\end{split}\n", + "$$\n", + "and the overlap is\n", + "$$\n", + "O=\\sqrt{\\frac{\\langle\\psi_\\tau\\rangle|\\psi'\\rangle\\langle\\psi'|\\psi_\\tau\\rangle}{\\langle\\psi_\\tau\\rangle|\\psi_\\tau\\rangle\\langle\\psi'|\\psi'\\rangle}}.\n", + "$$\n", + "Let $\\partial|O|^2/\\partial\\boldsymbol{\\delta}=0$, we can get $\\boldsymbol{A\\delta=C}$, then the update method is as follows\n", + "$$\n", + "\\boldsymbol{\\theta}^{n+1}=\\boldsymbol{\\theta}^{n}-\\tau\\boldsymbol{\\delta}=\\boldsymbol{\\theta}^{n}-\\tau\\boldsymbol{A}^{-1}\\boldsymbol{C},\n", + "$$\n", + "where $\\boldsymbol{A}$ is the quantum Fisher information matrix and the matrix element\n", + "$$\n", + "\\boldsymbol{A}_{ij}=\\Re\\left[\\frac{\\langle\\partial_{\\boldsymbol{\\theta}_{i}}\\psi|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}-\\frac{\\langle\\partial_{\\boldsymbol{\\theta}_{i}}\\psi|\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}\\frac{\\langle\\psi|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}\\right];\n", + "$$\n", + "$\\boldsymbol{C}$ is the gradient vector of energy versus parameters and the vector element\n", + "$$\n", + "\\boldsymbol{C}_j=\\Re\\left[\\frac{\\langle\\psi|\\hat{H}|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}-\\frac{\\langle\\psi|\\hat{H}|\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}\\frac{\\langle\\psi|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle}{\\langle\\psi|\\psi\\rangle}\\right].\n", + "$$\n", + "Since $|\\psi\\rangle$ is represented by quantum circuit and naturally normalized, the second term of $\\boldsymbol{C}$ vanishes. And because the global phase is not important, we can add a $U(1)$ gauge to make the second term of $\\boldsymbol{A}$ vanishes. Related theoretical work can refer to [Yuan, Endo, Zhao, Li and Benjamin](https://doi.org/10.22331/q-2019-10-07-191) and [Stokes, Izaac, Killoran and Carleo](https://doi.org/10.22331/q-2020-05-25-269), which will also show how to measure $\\boldsymbol{A}$ and $\\boldsymbol{C}$ in circuit." + ] + }, + { + "cell_type": "markdown", + "source": [ + "In fields other than quantum computation, equivalent forms of imaginary-time evolution are stochastic reconfiguration in variational Monte Carlo method and natural gradient method and Gauss-Newton method in classical optimization. In stochastic reconfiguration, $|\\psi\\rangle$ is not normalized, so $\\boldsymbol{A}$ and $\\boldsymbol{C}$ are the form shown above. In classical optimization, the second terms of $\\boldsymbol{A}$ and $\\boldsymbol{C}$ vanish automatically when the output is the classical probability distribution. Therefore, when $|\\psi\\rangle$ is similar to the classical probability distribution, that is, when there is no sign structure and phase information, the second term of $\\boldsymbol{A}$ will automatically vanish." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "In this tutorial, we solve a classical Hamiltonian and a quantum Hamiltonian by the approximate imaginary-time evolution and demonstrate various forms of code implementation." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Setup" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0def04d", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "from tensorcircuit import experimental\n", + "import optax\n", + "import jax.numpy as jnp\n", + "import tensorflow as tf\n", + "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import cotengra as ctg\n", + "import time\n", + "from functools import partial\n", + "from IPython.display import clear_output\n", + "\n", + "K = tc.set_backend(\"jax\")\n", + "tc.set_dtype(\"complex128\")\n", + "\n", + "# cotengra package to speed up the calculation\n", + "opt_ctg = ctg.ReusableHyperOptimizer(\n", + " methods=[\"greedy\", \"kahypar\"],\n", + " parallel=True,\n", + " minimize=\"combo\",\n", + " max_time=20,\n", + " max_repeats=128,\n", + " progbar=True,\n", + ")\n", + "\n", + "tc.set_contractor(\"custom\", optimizer=opt_ctg, preprocessing=True)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Classical Hamiltonian" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "The classical Hamiltonian is the Hamiltonian of NAE3SAT, which can be solved by QAOA. Please refer to the tutorial of [QAOA for NAE3SAT](qaoa_nae3sat.ipynb) for details.\n", + "\n", + "Let the set of clauses in the NAE3SAT be $\\mathcal{C}$. In each clause, there are three literals and each literal is represented by a spin. Spins up ($s=1$, $\\text{bit}=0$) and down ($s=-1$, $\\text{bit}=1$) represent false and true respectively. For the clause $(s_i,\\ s_j,\\ s_k)\\in\\mathcal{C}$, $s_i,\\ s_j,\\ s_k$ cannot be 1 or -1 at the same time. The Hamiltonian of the NAE3SAT is as follows\n", + "$$\n", + "\\begin{split}\n", + " \\hat{H}_C&=\\sum_{(i,j,k)\\in\\mathcal{C}}\\left[(s_i+s_j+s_k)^2-1\\right]/2\\\\\n", + " &=\\sum_{(i,j,k)\\in\\mathcal{C}}(s_i s_j+s_j s_k+s_k s_i)+|\\mathcal{C}|,\n", + "\\end{split}\n", + "$$\n", + "where $|\\mathcal{C}|$ is the number of clauses in $\\mathcal{C}$. When all clauses are true, $\\hat{H}_C$ takes the minimum value 0, and the corresponding bit string is the solution of the NAE3SAT." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "id": "6e407437", + "metadata": {}, + "source": [ + "### Define the Hamiltonian" + ] + }, + { + "cell_type": "markdown", + "source": [ + "We select the hard problem in the tutorial of [QAOA for NAE3SAT](qaoa_nae3sat.ipynb). We first construct the graph by the clauses." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f1532831", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-13T02:33:37.851074700Z", + "start_time": "2023-07-13T02:33:37.537921300Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAGFCAYAAACCBut2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOyddVhUXdfG7wm6QQEl7QBbUcSmFLDz8bFRsbAD48HuwsbuDmxFUQwMsAULwSBUVLpjZn1/+DIfSM0MM2Ds33VxAefss/Y6zDD7PmuvvTaHiAgMBoPBYDD+arjl7QCDwWAwGIzyhwkCBoPBYDAYTBAwGAwGg8FggoDBYDAYDAaYIGAwGAwGgwEmCBgMBoPBYIAJAgaDwWAwGAD44jQSCoX49OkTNDQ0wOFw5O0Tg8FgMBgMGUBESE5ORuXKlcHlFh8DEEsQfPr0CSYmJjJxjsFgMBgMRtkSGRkJY2PjYtuIJQg0NDREBjU1NUvvGYPBYDAYDLmTlJQEExMT0TheHGIJgtxpAk1NTSYIGAwGg8H4zRBnup8lFTIYDAaDwWCCgMFgMBgMBhMEDAaDwWAwwAQBg8FgMBgMMEHAYDAYDAYDTBAwGAwGg8EAEwQMBoPBYDDABAGDwWAwGAwwQcBgMBgMBgNMEDAYDAaDwQATBAwGg8FgMMAEAYPBYDAYDDBBwGAwGAwGA0wQMBgMBoPBABMEDAaDwWAwwAQBg8FgMBgMAPzydoDB+N1IzczBh9hUZOUIocjnwlxPDWpK7F+JwWD83rBPMQZDDN7GJONgYAT833xFRFwaKM85DgBTXVW0r6WPf5ubooaBRnm5yWAwGFLDISIqqVFSUhK0tLSQmJgITU3NsvCLwfgliIxLwyyfYNwO+w4elwOBsOh/l9zzratXwJLu9WCiq1qGnjIYDEZBJBm/WQ4Bg1EERx5EwG7tTdx9FwsAxYqBvOfvvouF3dqbOPIgQu4+MhgMhqxgUwYMRiFs9H+LVVdCpbpWICQIhASPU8H4npKJce1ryNg7BoPBkD0sQsBg/MSRBxFSi4GfWXUlFEdZpIDBYPwGsAgBg5GHyLg0zD37osjzwqx0JAWeQuanN8j6HAphRgr0nCZCvb5dkdd4nn2BltUqsJwCBoPxS8MiBAxGHmb5BCOnmFwBYVoSEu8cRnZsJBT0q4hlM0dImOUTLCsXGQwGQy6wCAGD8T/exiTjdtj3Ytvw1HVhPG4/eOo6yPz8Fl/2TirRrkBIuB32HWFfk1Fdny1JZDAYvyYsQsBg/I+DgRHgcTnFtuHwFcBT15HYNo/LwYH7LJeAwWD8ujBBwGD8D/83X0tcWigtAiHBP/SrXGwzGAyGLGCCgMEAkJKZg4i4NLn2ERGbhtTMHLn2wWAwGNLCBAGDAeBjbCrkExv4fwjAh9hUOffCYDAY0sEEAYMBICtH+Ef1w2AwGJLCBAGDAUCRXzb/CmXVD4PBYEgK+3RiMACY66mh+PUFpYfzv34YDAbjV4QJAgYDgJoSH6ZyriQoSIzBqOFDceDAAcTExMi1LwaDwZAUVpiIwfgf7WvpY3/gxxKXHiY9OgdhRioEKXEAgPSwIOQk/yhopNmkM7jKBaMAXA5QU0uAF/df4MCBAwCAhg0bwtHREY6OjrCxsYGioqKM74jBYDDEh0NEJSZXS7KfMoPxu/I2Jhn2XrdKbBe1eRgESYXXFDAatRN8bYNCz/lNaoPq+hr4+vUrrl69Cl9fX1y5cgUxMTFQU1ND+/bt4eDgAEdHR9SoUQMcjrwnMRgMxp+OJOM3EwQMRh4G7gzE3Xexsi1QREI0N9fG0VGtC5wSCoV4/vw5rly5Al9fXwQEBCArKwvm5uZwdHSEg4MDbG1toaWlJTt/GAzGXwMTBAyGlETGpcFu7U1kymx5IIFyspF5ag42r1yIHj16FNs6NTUVN27cgK+vL3x9fREaGgoej4cWLVqIpheaNGkCHo8nI/8YDMafjCTjN0sqZDDyYKKriqH1ZLkSgINp7c3Qol4N9OzZE//88w++fy96AyU1NTU4Oztj/fr1ePPmDd6/f4/NmzfDwMAAq1evRvPmzaGvr4++ffti165diIqKkqGvDAbjb4ZFCBiMPNy8eROdO3eGaaeRSKnavtT2Uu8ehiU3GmfPnsXZs2fh7u4OBQUFeHt7o3v37hLZysnJQWBgoGh6ISgoCEQECwsLUe5BmzZtoKKiUmq/GQzGnwGbMmAwpODChQvo1asXbGxscPr0aZx/FYc5Ps+RnSMAhyfBghwSQkmBjwVdLGCUGQEnJyfUq1cPFy9eRHp6OkaNGoUzZ86gX79+2LBhAypUqCCVv3FxcfDz8xNNL0RHR0NZWRlt2rQR5R9YWFiw5EQG4y+GCQIGQ0KOHDmCgQMHwtnZGUeOHIGysjLS0tJQt1lrqLUfjlQNU/C4nGKTDXPPp79/jI2DbNDbqQMAICgoCI6OjqhevTp8fX2ho6ODQ4cOlSpa8DNEhFevXonEwc2bN5GRkQEjIyNR9MDOzg56enql6ofBYPxeMEHAYEjAtm3bMGrUKPz777/YtWsXFBQUAABz587FsmXLEBISAmga4mBgBPxDvyIiNi3/RkhEUMxOQv+2DfBvc1P829kWABAYGCh6On/y5Ans7e1hbGyMq1evomLFivj8+TNGjRqFs2fPol+/fti4caPMBuz09HTcvn1bNL0QEhICDoeDpk2bipITmzdvLrpXBoPxZyLR+E1ikJiYSAAoMTFRnOYMxm/DihUrCACNHTuWBAKB6Hh4eDgpKSnRrFmzClzz6FkIKehXoT3nblBIdAJN9ZhNhoaGJBQKiYjI39+fANDRo0fzXRcSEkIGBgZUp04d+vTpExERCYVC2r9/P+no6JC+vj6dOnVKLvcZFRVFu3btor59+5Kuri4BIE1NTerevTtt2bKF3r17J5d+GQxG+SLJ+M0EAeOvRCgU0uzZswkAzZo1SzSY59KlSxcyNjamlJSUAtfeuXOHANDLly+JiMjHx4cAUGRkpKiNi4sLVa1alTIzM/Nd++bNGzIyMqLq1avTx48fRcc/ffpEnTt3JgD0zz//0Pfv32V5u/nIycmhoKAgWrhwIbVq1Yp4PB4BoBo1atC4cePo3LlzlJycLLf+GQxG2cEEAYNRDAKBgMaNG0cAaPny5QXOX7hwgQDQsWPHCr3+3LlzBIA+f/5MRETR0dEEgE6ePClqExISQlwul9avX1/g+vDwcDI3NyczMzMKDw8XHS+raMHPJCQkkI+PD40aNYqqVKlCAEhBQYHatWtHS5cupcePH+eLnjAYjN8HJggYjCLIzs6mgQMHEofDIW9v7wLnMzIyqHr16tShQ4cCUYNc9u7dSwAoIyNDdMzY2JhmzJiRr52rqytVqFCBEhISCtiIiIigGjVqkJGREb1+/TrfubKMFvyMUCik0NBQ2rBhA3Xu3JnU1NQIAOnr69OAAQNo37599OXLlzLzh8FglA4mCBiMQkhPT6du3boRn8+nQ4cOFdpmyZIlxOfz6cWLF0XaWbt2LampqeU71qNHD2rfvn2+Y1FRUaSiolJoHgLRj4G/bt26ZGBgQMHBwfnO5Y0WGBgYkI+Pjxh3KHsyMzPJ39+fPDw8qFGjRgSAAFDDhg1pxowZdO3atXzCiMFg/FowQcBg/ERycjLZ2tqSsrIynTt3rtA2kZGRpKqqSpMmTSrWlqenJ5mYmOQ7tmzZMtLQ0KCcnJx8x2fNmkUqKioUFRVVqK2vX79SgwYNSE9Pjx4/flzgfN5oQf/+/cs0WlAYMTExdODAARo4cCAZGBgQAFJTUyNnZ2dav349vXnzpsjICoPBKHuYIGAw8hAXF0ctWrQgdXV18vf3L7Jd3759ycDAoNAQf17GjRtH9evXz3fs+vXrBKBAZCEhIYEqVKhArq6uRdqLjY2lZs2akba2Nt2/f7/AeaFQSPv27SNtbe1yjRb8jEAgoCdPntDy5cupQ4cOpKioSADI3NycRo4cSSdPnizxb8lgMOQLEwQMxv/48uUL1a9fn3R1dSkoKKjIdrkD+t69e0u02b9/f2rXrl2+Y4mJicThcGj37t0F2q9fv564XC6FhIQUaTMhIYFatmxJGhoadPv27ULb/GrRgp9JSUmh8+fPk7u7O9WsWZMAEI/HIxsbG5o/fz7dv3+/QASFwWDIF0nGb1aYiPHH8vHjR9jb2yMlJQVXrlyBpaVloe2ys7PRqFEjaGlp4fbt2+Byi9/zq1OnTlBVVcXJkyfzHbewsEDbtm2xefPmfMezsrJQt25d1KlTB+fOnSvSbkpKCrp06YLAwECcPXsWtra2BdoQEQ4cOIDx48dDSUkJW7duRdeuXYv1t7z48OGDqDDStWvXkJiYCF1dXdjZ2YlKKxsbG5e3mwzGHw0rTMT463n9+jWZmJhQlSpVKCwsrNi2a9euJQ6HU+gcfmE0b96chg8fXuD4kCFDqEmTJoVec/ToUQJQ7JQFEVFaWho5OjqSkpISXbhwoch20dHR5OLi8stGC34mOzubAgICyNPTk5o3b04cDocAUN26dWnSpEl0+fJlSktLK283GYw/DjZlwPirefLkCVWsWJHq1q1bZDJfLp8/fyZNTU0aPXq02PZr1KhB06ZNK3B88+bNxOfzKT09vcA5oVBIzZo1o2bNmpWYdJeRkUFdu3YlBQWFYmsR/JxbcPr0abHvobyJjY2lo0eP0rBhw8jIyIgAkJKSEtnb29OqVasoODiYJScyGDKACQLGX0tAQABpaWlRkyZN6Nu3byW2Hzx4MOnp6VFsbKzYfejp6dHSpUsLHH/48CEBoHv37hV63Y0bNwotaVwYWVlZ1KdPH+LxeHT48OFi2+aNFvz7778S3cuvgFAopBcvXtCaNWvI0dGRlJWVCQAZGRnR0KFD6fDhw798BITB+FVhgoDxV+Lr60uqqqrUpk0bsd6ruSWIt27dKnYfAoGAuFxuoddkZmaSkpISrVu3rsjriyppXBi5RZS4XC7t2bOn2LZCoZD27t37W0YLfiYtLY2uXLlCU6ZMIUtLSwJAHA6HmjVrRnPmzKHbt29TVlZWebvJYPwWMEHA+Os4efIkKSoqkpOTk1hz0Tk5OdSoUSNq3LixRJnvCQkJBICOHz9e6PkWLVrQv//+W+T1uSWNixMNeREIBDRixAgCUGhlxZ+Jjo4mZ2fn3zZaUBi5GzP169eP9PT0RBszdevWjW3MxGCUABMEjL+KPXv2EJfLpb59+4r15E1E5O3tTQDo7t27EvX17t07AkB+fn6Fnh8/fjzVqFGjWBvFlTQuDKFQSO7u7gSAvLy8xGr/p0QLfqa4jZnGjh1LZ8+eZRszMRh5YIKA8dewbt06AkAjRowQ+0n/+/fvpKurS0OGDJG4v9w8gaJWJBw4cIAAFPtkXlJJ48IQCoU0ffp0AlBo/kJh5I0WDBgw4I+IFvxMSRszPXr0iG3MxPirYYKA8ccjFAppwYIFBICmTp0qUUb6qFGjSFNTU6pNeq5cuUIA6MOHD4WeDw0NJQDk6+tbrJ2SShoXhlAopLlz5xIAmjt3rlj3LBQKac+ePaSlpUWGhoZ05swZsfv73ShuY6Z///2XbczE+CthgoDxRyMUCmny5MkEgBYtWiSRGHj06BFxOByxQu+FkVtPICkpqUjftLW1aeHChcXaEaekcVEsXbqUAND06dPFvveoqKg/PlrwM8VtzDR9+nS2MRPjr4AJAsYfS05ODrm6uhIAWr9+vUTXCgQCsra2JktLS8rOzpaq/y1bthCPxyt2IHZwcKDOnTuXaEucksZF4eXlRQDI3d1d7JD4z9GCs2fPStzv70xhGzOpqqqSs7MzrVu3jl6/fs1qHzD+OJggYPyRZGZmUp8+fYjL5Yq158DP7NmzR6xqgcWxePFiqlixYrFt5syZQwYGBiUOLpmZmVStWjVycXGRypfcxMgRI0ZINE8eFRVFTk5Of1W04GeK2pjJzMyMbczE+KNggoDxx5GamkqdOnUiRUXFYqv3FUVCQgLp6+tTv379SuXHlClTqFatWsW2OXv2LAGgjx8/lmhP3JLGRZG7wmLgwIESRT3+9mjBzxS1MVPLli3ZxkyM3xomCBh/FAkJCdS6dWtSVVWlK1euSGVj4sSJpKamRpGRkaXyZdiwYWRtbV1sm8+fPxdbqyAvkpQ0LoojR44Qj8ej3r17S1ywh0ULCuf9+/e0detW6tGjB2lpaREA0tHRod69e9OOHTtK/T5iMMoKJggYfwzfvn2jxo0bk7a2Nt25c0cqGyEhIcTj8cRerlcc3bp1IycnpxLbmZqa0tSpU8WyKUlJ46I4deoUKSgoUNeuXSVOlBMKhbR7927S0tKiSpUq/fXRgp/Jzs6mO3fuiDZm4nK5bGMmxm8DEwSMP4KoqCiqU6cO6evr09OnT6WyIRQKqX379lSjRg2ZZJS3adOGBgwYUGK7Xr16UZs2bcS2K0lJ46K4cOECKSkpUceOHaUaoPJGCwYOHEhxcXFS+/InwzZmYvxOMEHA+O0JCwsjc3NzMjExoTdv3khtJ3eO/tKlSzLxy9LSksaPH19iuxUrVpCqqqrY8/qSljQuCj8/P1JVVaX27dtLVbGPRQsko6iNmSpXrkxDhgxhGzMxyh0mCBi/NcHBwWRoaEg1a9YUKzGvKJKTk8nY2Ji6du0qM9+MjIxo3rx5JbbLnQZ4/vy52LYlLWlcFLdu3SINDQ2ysbGR2lbeaMGgQYNYtEBMituYafbs2XTr1i22MROjTGGCgPHbEhgYSDo6OtSgQYNSV5WbOXMmKSkpyXTzGxUVFbGe4pOTk4nL5dKOHTvEti1NSeOiuH//Pmlra1PTpk2lThT8OVpw7ty5Uvv1t1HSxkzh4eHl7SLjD4cJAsZvyfXr10ldXZ2sra1L/UT65s0bUlBQoLlz58rGOfrx9AeA9u/fL1Z7S0tLGjlypER9SFPSuCgeP35Menp61KBBA/r69avUdiIjI6lTp04sWlBKitqYqXr16r/NxkwpGdkUEp1Ajz/GUUh0AqVkSFfgi1F2SDJ+c4iIUAJJSUnQ0tJCYmIiNDU1S2rOYEjMuXPn0Lt3b7Rp0wY+Pj5QU1OT2hYRwcnJCa9fv8bLly+hoqIiEx8/ffoEIyMjXLhwAU5OTiW2d3V1xePHj/HkyROx+0hMTET16tXRtWtX7NixozTuAgBevHgBW1tb6Orq4tq1a6hUqZJUdogIe/bswaRJk6Cqqopt27bBxcWl1P79zSQmJsLf3x++vr7w9fXF+/fvoaCgABsbGzg4OMDR0RENGzYEl8stVz/fxiTjYGAE/N98RURcGvIOGBwAprqqaF9LH/82N0UNA43ycpNRBJKM3+X7TmMwABw6dAjdu3eHk5MTzp07VyoxAPwQF5cvX8batWtlJgYAID4+HgCgq6srVnsrKysEBwcjLS1N7D60tLTg6emJ3bt348WLF1L5mRcLCwvcunULSUlJaNOmDSIjI6Wyw+FwMHToUISEhKBhw4bo3LkzBg8eLPqbMCRHS0sL3bp1w5YtWxAeHo7Q0FCsWbMGGhoaWLx4MZo0aYJKlSphwIAB2L9/P758+VKm/kXGpWHgzkDYe93C/sCP+PiTGAB+bA7xMS4N+wM/wt7rFgbuDERknPjvd8avBYsQMMoVb29vjBkzBoMGDcKOHTvA5/NLZS8jIwN169ZFjRo1cPnyZXA4HBl5Cty+fRtt2rTB69evUatWrRLbP3nyBI0bN0ZAQABsbGzE7icrKwt169ZFnTp1cO7cudK4LOLdu3ewtbUFAFy/fh1VqlSR2lZutGDixIlQV1fHtm3b4OzsLBM/GT/IysrC3bt3RdGD3ChTgwYN4OjoCEdHR9jY2EBJSUku/R95EIG5Z18gR0gQCEscIkTwuBzwuRzM72KBfs1M5eIbQzJYhIDxW7B8+XKMHj0a48aNw65du0otBgBg5cqViIqKwvr162UqBgAgLi4OgPgRAktLSygrKyMoKEiifhQVFbFkyRKcP38eN27ckNTNQqlatSpu3boFPp+P1q1bIzQ0VGpbudGCFy9eoH79+nBxcWHRAhmjqKiIdu3aYenSpXj8+DFiYmJw4MAB1K9fH3v37hVNAzk7O2P9+vV48+YNxHi2E4uN/m/hcSoYmTlCicQAAAiEhMwcITxOBWOj/1uZ+MMoO1iEgFHmEBFmz56NpUuX4r///sP8+fNlMnh/+PABderUwfjx47F8+XIZeJqf3bt3Y9iwYcjOzhZbvNjY2MDU1BSHDx+WqC8iQvPmzQEAgYGBMhM3nz9/hq2tLeLi4nDt2jVYWFiUyh6LFpQ9QqEQz58/x5UrV+Dr64uAgABkZWXBzMwMjo6OcHBwgK2tLbS1tSW2feRBBDxOBcvM1+U96qEvixSUKyxCwPhlEQqFGDt2LJYuXYpVq1ZhwYIFMhvspkyZAl1dXcyZM0cm9n4mPj4empqaEkUyrKysJI4QAD+ewleuXIkHDx7g+PHjEl9fFJUqVcKNGzdgYGCAdu3a4enTp6WyV1i0YMiQISxaIEe4XC4aNmyI6dOn49q1a4iLi8P58+fRpUsX3Lx5E7169UKFChVgY2ODBQsWIDAwEAKBoES7kXFpmHu26LyV7LhofDuzHFGbBiNiVU9EbxuFhIDDEGZnFHmN59kXLKfgN4IJAkaZkZ2djUGDBsHb2xvbtm3DlClTZGb7ypUrOHXqFFatWgUNDflkOsfFxUFHR0eia6ysrPDu3Tt8//5d4v7atm0LFxcXzJw5E1lZWRJfXxT6+vrw9/eHubk52rdvL5Vg+RljY2NcvHgRO3fuhI+PDywtLXHhwgUZeMsoCTU1NdHUwevXr/H+/Xts3rwZhoaGWLNmDVq0aIGKFSuiT58+2LlzJ6Kiogq1M8snGDlFTBHkJH3Dl72TkRn9BhqNXaBjNwJKRrWRGHAQ38+sLNK3HCFhlo/sIg4M+cIEAaNMyMjIQK9evXD06FEcPnwYI0aMkJntrKwsjB8/Hm3atEG/fv1kZvdn4uLixM4fyMXKygoA8ODBA6n6XLZsGT58+ABvb2+pri8KXV1d+Pn5oW7durCzs0NAQECpbXI4HAwbNgwhISH5ogUJCQmld5ghNubm5hg5ciROnjyJ79+/486dO3B3d0dERARGjhwJExMTWFhYYNKkSbh8+TLS0tLwNiYZt8O+F5kzkBriD2FmKvR7z4WWdW9oNOyICs4ToWbZAelhgRBkpBR6nUBIuB32HWFfk+V5ywwZwQQBQ+6kpKTA2dkZV65cwZkzZ9C3b1+Z2l+3bh3CwsKwYcMGmScS5kUaQVC1alXo6upK/RRuYWGBoUOHYuHChUhMTJTKRlFoaWnB19cXTZs2haOjI65duyYTuyYmJvmiBRYWFrh48aJMbDMkg8/no2XLlpg/fz7u37+Pb9++4ejRo2jRogWOHz+OTp06QVdXF71nrQenwKLC/0eY9SPsz1PTznecp64LcLjgcIueRuNxOThwP0Im98OQL0wQMORKXFwc7Ozs8ODBA/j6+opV0EcSPn36hAULFmDs2LGoX7++TG3/THx8vMSCgMPhSJ1HkMv8+fORmpqKFStWSG2jKNTV1XHhwgW0bt0azs7OuHTpkkzs5o0W1KtXD87Ozhg6dCiLFpQzurq6oqmDyMhIvHjxAkuXLkWqljkIRYtpZdN6AIDYi+uRFfMOOUnfkPrqFpKfXIRGk87gKioXea1ASPAP/Srze2HIHiYIGHLjy5cvaNeuHcLCwnD9+nW0adNG5n1Mnz4dKioqmD9/vsxt/4w0OQTA/ycWSrsszMjICJMmTcLatWsRHR0tlY3iUFFRwZkzZ+Do6IiuXbvi9OnTMrNtYmKCS5cuYceOHTh16hSLFvxCcDgc1K1bFyPGuCNHSbvYtipVm0Cr9QBkfHiKz7vHI3rzUHw/swIaTTpD167k6b+I2DSkZubIyHOGvGCCgCEXPnz4gFatWiE2Nha3bt1C06ZNZd7HrVu3cPDgQSxbtkyqJVaSIs2UAfBDEHz//h0fPnyQuu/p06dDTU0Nc+fOldpGcSgpKeHEiRPo1q2bKNdDVnA4HLi6urJowS/Kx9jUYiYL/h++lgGUTCyg23EcKnafBbX69ki6ewxJj0ounkUAPsSmltpXhnxhgoAhc16/fo3WrVuDiBAQEIC6devKvI+cnBy4u7vDysoKQ4YMkbn9wpBWEDRr1gwASjVtIOuSxoWhoKCAQ4cOoX///ujfvz/27t0rU/s/RwssLS1ZtOAXICtHWGKb1Jc3EXd5I/Q6jYdGw45QrdUSFZwmQK2eLRJu7IEgPUkm/TDKFyYIGDLl8ePHaN26NbS0tHD79u1SlcgtDm9vbwQHB2Pjxo1lsvmLQCBAYmKiVIJAX18f5ubmpV7e5+bmhipVqsDDw6NUdoqDz+djz549GDZsGIYMGYJt27bJ1H7eaIGlpSWLFvwCKPJL/v9JfnwRigZVwdeskO+4anUrUHYmsmLeyaQfRvnCXiGGzAgICED79u1RpUoV3Lx5E5UrV5ZLP1+/fsV///2H4cOHi56+5U1iYiKISKocAkD6AkV5kUdJ48LgcrnYunUrxo0bBzc3N6xbt07mfRQWLZBVQiNDPGJiYrBhwwaM+rdnifktgrQEEBV8wifh/woeCYsvfMQBYK5Xuk3LGPKHCQKGTPD19YWDgwMaNWqEa9euQU9PT259zZo1CxwOB0uWLJFbHz8j6T4GP2NlZYVHjx4hJ6d0iVW9e/dGs2bNMH36dJnVri8MLpeL9evXY9q0aZg4cSKWLVsm8z5+jhY4OTlh2LBhLFogJ759+4bdu3ejY8eO0NHRgaGhIcaPH4+AG9dAycWvAlDQqYysmHBkx+VPak19eRPgcKFQ0bzY6031VKGmVPq9Shjyhb1CjFJz4sQJ9O/fH46Ojjh27JhMtxz+maCgIOzcuRObNm1ChQoVSr5ARshCEKSnp+PFixdo0KCB1H7kljRu164djh8/jj59+khtS5y+li9fDlVVVcycORMZGRmYO3euzGs95EYLdu7cicmTJ+PKlSvYvn07OnXqJNN+/ja+f/8OPz8/HD16FAEBAfmqZWpqasLe3h49evSAUCjEuoB3yFCvAA6XV6gtzeY9kf7uEb4cmAGNJs7gqWgiLSwIGe8eQb2BA/gaRT8A8LgctK+pL/P7Y8getrkRo1Ts2rULI0aMQN++fbF3714oKCjIrS+hUIgWLVogOzsbDx8+BI9X+IeXPPD19UXHjh0RGRkJY2Njia9PTU2FpqYmvL29ZVKlsXPnznj58iVevXoFRUXFUtsriWXLlmHmzJmYPn06li1bJrcCUBERERgxYgSuXLmCoUOHYs2aNWWyguRPIDY2Fjdu3MDJkyfh7++PL1++iM4pKyujYcOG6NmzJ3r37g1lZWV4e3tj8+bN+Pr1K0wsmoHbufgVLJmf3iAh4BCyY95BkJ4MvrYB1C1todmiZ5FCIhe/SW1QXV8+JcUZxSPJ+M0iBAyp8fLywqRJk+Dm5oZNmzbJfYDevXs3Hjx4gICAgDIVA8D/RwikzSFQU1ODpaUlgoKCZCIIli1bhvr168Pb2xvjx48vtb2S8PDwgLKyMiZNmoSMjAx4eXnJRRSYmpri8uXLLFogBnFxcbh16xbOnz8PX1/ffHsU8Hg8WFhYoEuXLujduzcaNGgALpeLp0+fYt68eTh06JCoTXJyMlI/h8NCMQ3ROWpFli9WqlwLBn0kq/fB43LQsqoeEwO/CUwQMCSGiLBgwQLMmzdP7k+MucTHx8PDwwMDBgyAjY2NXPsqjLi4OCgqKkJVVVVqG7JILMwlb0njwYMHQ0tLSyZ2i2PixIlQVlbG6NGjkZGRgS1btshlhQeHw8Hw4cPh4OCA4cOHi3ILVq9e/VdHC+Lj43H79m1cuXIFFy9exPv37/OdNzMzQ6dOndCzZ0/Y2NiIpu4EAgHOnTsHLy8v3LhxA0ZGRnB2dsadO3cQHByMCRMmYObMmUgWKsJu7c0iBYE08LkcLOleT2b2GPKFJRUyJIKIMHnyZMybNw9LlizB8uXL5S4GAMDT0xMZGRlyKd8rDrk1CEpzr1ZWVggJCUFqqmwKtMizpHFRjBo1Crt378aOHTswdOjQUidJFoepqSl8fX2xbds2HD9+/K9biZCYmIjz589j4sSJqFWrFnR1ddG1a1ds2rQJ79+/h56eHvr27YujR4/i27dv+PDhA7Zs2QI7OzuoqKggOTkZ69evR61atdCtWzdkZGRg6tSpUFNTw+nTp+Ho6IjQ0FAsX74c2traMNFVxfwuFjK9hwVdLGCiK72IZpQtLELAEBuBQICRI0di165d2LRpE8aMGVMm/T579gybN2/GihUrUKlSpTLp82ek2cfgZ6ysrCAUCkW1GkqLkZERJk+ejDVr1mDMmDEwMjIqtU1xGDJkCJSVlTFgwABkZGTgwIEDcssd4XA4GDFiBBwdHf/4aEFSUhJu374Nf39/XL58GS9fvgQRgcPhgIigoqKC1q1bo2vXrnBwcEC1atUKFajv37/Hhg0bsHPnTqSlpaF3796YOXMm9u7di1WrVsHW1hZHjhxBo0aNClybFuyH+Ju+0Gk7qNT3M82hFvo2My21HUbZwSIEDLHIzMxEv379sHfvXuzfv7/MxAARYdy4cahVq1aZzJUXhbT7GOTFwsICqqqqMps2AORf0rgo+vXrh+PHj8PHxwe9e/dGZmamXPsrLFpw+fJlufYpb5KTk3Hp0iXMmDEDjRo1gra2NlxcXODl5YUXL16Ay+XCyspKtFNhUlISfH19MWbMGFSvXj2fGCAi3Lp1Cz169ED16tWxd+9ejB07Fv7+/hAIBBg+fDgSEhJw6dIlXL16tVAxcO3aNbi5uaFfPW0s7V4PfA6BBJJFgHhcDpT4XCzvUQ9j21cv9d+IUbawCAGjRNLS0tCjRw/4+/vj5MmT6Nq1a5n1fejQIQQEBODq1atyXcFQEtKWLc4Ln89HkyZNZCoINDU14enpiYkTJ2LixImwtLSUme2S6N69O06fPo0ePXqgW7duOHXqlFyXnP4cLejUqROGDRuGNWvWlEkORWlJSUnBnTt34O/vj2vXruHx48cQCoXg8/miqZeaNWvCyckJ9vb2aNOmDdTV1Yu1mZmZiaNHj8LLywtPnjxB7dq1sXnzZjg5OWH16tXo0KEDKlasiF27dmHQoEFFJuO+fPkSPXv2RIcOHbBx40bweDwsGjcACk37IV3LDDwOICgmtYCEAnC4PLSsqocl3euxaYLfFRKDxMREAkCJiYniNGf8QSQkJFCrVq1ITU2N/Pz8yrTvxMREMjQ0pF69epVpv4VhY2NDgwcPLrWdKVOmkLm5eekdykNmZiZVq1aNnJ2dZWpXXPz8/EhVVZXat29PycnJZdKnUCikbdu2kYaGBhkbG9OlS5fKpF9JSElJIV9fX5o5cya1aNGCeDweASBFRUXicrkEgPT19WnQoEG0f/9++vTpk9i2Y2JiaMGCBWRoaEgAqGPHjnT58mVKSUmh5cuXk5aWFmloaNDixYspNTW1WFtfvnwhc3NzsrS0pISEBCIiOnHiBAGg27dvU+iXJHLdfJkqj9xGpjPOkZnHedGXucd5arPiOlXtPYNc+g8v1d+LIR8kGb+ZIGAUydevX6lRo0akra1N9+7dK/P+p06dSioqKvTx48cy7/tn6tatS5MmTSq1naNHjxIAiomJkYFXBe36+/vL1K643Lp1izQ0NMjGxkY0qJQFHz9+JHt7ewJAw4YNK9O+fyY1NZWuXr1Ks2fPppYtW4oEgJKSEikqKhIAUlVVJRcXF/Ly8qIXL16QUCiUqI9nz57RsGHDSElJiVRUVGjUqFH08uVLEggEtG/fPjIxMSE+n09jx44V6z2WlpZGzZs3J0NDQ9H/mUAgoPr165Otra2o3bp160hBQYE4Csp08OJNevwxjkKiEyglI5uIiDZs2EA8Ho+ioqIkuh+G/GGCgFFqIiMjqXbt2mRgYEDPnj0r8/5fvXpFfD6fFi1aVOZ9F4ahoSEtWLCg1Hbev39PAOj8+fMy8Or/EQqF1KxZM2rWrJnEg4ysuH//Pmlra1OzZs0oNjZWrGtSMrIpJDqhwAAjCUKhkLZu3Urq6upkbGxMly9fltiGNKSlpdG1a9dozpw51KpVK+Lz+QSAlJWVSU1NjQAQj8cja2tr8vT0pFu3blFmZqbE/QgEAjp79ix16NCBAJCRkREtW7ZM9De+evUqNWzYkABQjx496M2bN2Lb7dWrF6moqNCDBw9Ex0+ePEkA6NatW6Jjw4cPp2rVqhEACg0NLWArMTGR1NXVac6cORLfH0O+MEHAKBWhoaFkZmZGpqamhf7zyxuhUEh2dnZUtWpVSk9PL/P+C/NHUVGRNm7cKBNbFStWJE9PTxl4lp8bN24QADp69KjMbYvL48ePSU9Pjxo0aEBfv34ttE3olySaeyaE2qy4TuZ5ws95Q9Bzz4RQ6Jckifr+8OED2dnZEQBydXWVebQgPT2d/P39ydPTk9q0aUMKCgoEgFRUVEhHR4c4HA4BoFq1atHYsWPp9OnTpfIhOTmZNmzYQNWrVycAZGVlRYcPH6asrCwiInr+/Dl17NiRAJC1tTUFBARIZH/GjBnE4XDIx8dHdEwgEFCDBg2oQ4cO+do2b96cWrduTQAoPj6+UHvjxo0jfX19ysjIkMgPhnxhgoAhNc+fPycDAwOqVasWRURElIsPuU8o586dK5f+fyYlJYUA0KFDh2Riz9nZmTp27CgTWz/j4uJCVatWlepJVFYEBweTgYEB1a1bN9+8eERsKg3YcZ/MPM5T1VkX8gmBn79yzw/YcZ8iYoufA8+LLKMFGRkZdOPGDZo3bx61bdtWFPZXUVEhfX19kSCoWLEi/fPPP7Rz506ZTG+9f/+epkyZQlpaWsTj8ahv3775puyioqJo2LBhxOVyqXr16nTixAmJo0Lbtm0jALRmzZp8x318fAgA3bx5U3RMIBCQmpoadevWjRQUFIrs69WrVwSA9u/fL5EvDPkiyfjN9jJgiLh//z6cnJxgZmYGX19f6OuX/YYkaWlpqFOnDurVq4fz58+Xef+FERUVBRMTE1y+fBmOjo6ltrdgwQKsW7cO379/l3lRpxcvXqB+/fpYu3ZtuS7TfPPmDWxtbaGqqopr167hzhfC3LMvkCMkiSrh8bgc8LkczO9igX4SrGn/+PEjhg8fDj8/P7i6umL16tUlrkTIzMxEUFAQ/P39cePGDdy7dw8ZGRlQVVWFrq4uEhISkJKSAmVlZbRp0wb29vaws7ND/fr1S12xkYhw584deHl5wcfHB1paWhg5ciTGjh0LExMTAD8+h1esWIE1a9ZATU0Nnp6ecHNzk3gvi6tXr6JTp05wc3PDxo0bRe9BIkLjxo2hra0Nf39/Uft3796hWrVq+Pfff3H9+nV8+vSpSNsODg5ITExEYGCgFH8FhjxgexkwJOb69evo0qULGjZsiPPnz5db0Zdly5bhy5cvuHbtWrn0Xxil3cfgZ6ysrBAXFyf6oJUl5VHSuDBq1aqFW7duoUOHDmg9ajFQv7NUdgT/ExAep4LxPSUT49rXEOs6MzMz0T4IU6ZMga+vL3bs2JFP0GVlZeHBgwciAXD37l2kp6dDTU0N+vr60NTUREZGBtLT02FgYIABAwbA3t4eLVu2hLKyslT38zNZWVk4duwYvLy88OjRI9SqVQsbN27EoEGDoKamBgDIzs7Gtm3bMH/+fCQnJ2PSpEmYMWOGVK9tSEgIevXqBQcHB6xbty6fID179iyePn2aTwwAQHBwMIAfy2YrVqxYrH13d3d06dIFQUFBsLKyktg/RvnCChMxcObMGTg5OcHGxga+vr7lJgbCw8OxYsUKTJs2DdWr/zpFTUq79fHPNGvWDABkWo8gL+VR0rgwqlatiunep6UWAz+z6koojj6IELs9h8PByJEjERISgtq1a6Njx47o0qULPD094eDgAB0dHbRq1QrLli1DZGQkDAwMwOPxRKWlu3XrhmPHjuHbt294+PAhli5dig4dOshEDHz//h2LFy+Gubk5Bg4cCD09PVy8eBEvX77E6NGjoaamBiLCqVOnYGFhAXd3dzg7O+Pt27dYsmSJVGLgy5cvcHZ2hrm5OY4ePQo+//+fB4kI8+fPR9u2bdGuXbt81wUHB0NHRwdpaWklCgInJydUqVIFGzdulNg/RvnDBMFfzsGDB9GzZ0+4uLjg7NmzoqeS8mDSpEnQ19fHzJkzy82HwpC1INDT00O1atXkJghySxqvXbsW0dHRculDHCLj0rDuzmex2ibePYqPy1zwaUfxFTA9z75AZFyaWDazs7Nx//59HD58GBwOB4qKijh37hwWLlyIN2/ewMzMDKqqqkhNTcW3b9/QpEkTbNq0CWFhYXj37h22bt2K3r17Q09PT6z+xCEkJAQjRoyAiYkJFi1ahM6dOyMkJAS+vr7o1KmTaOrh3r17aN26NXr27ImqVaviyZMn2L17t1RbbwM/puI6d+6M7OxsXLhwARoa+XcfPH/+PJ48eVJoxcvg4GDUq1cP3759K1EQ8Hg8jBkzBkePHsXXr1+l8pVRfjBB8BezefNmDBw4EIMGDcKRI0egpKRUbr5cvHgR586dE82P/krEx8eDw+HINPwuy50PC6O8ShrnZZZPMHLEyBfISfqOxHvHwFEo+ck7R0iY5RNc+LmcHAQFBWH58uXo1KkTdHV1YW1tjYULFyImJgb16tUTDe4RERFISEjAlClTEBQUhG/fvuHEiRNwc3OT+TSOUCjEhQsXYG9vj3r16uHixYvw9PREZGQktm7dCguL/99Q6O3bt+jVqxdatmyJlJQUXLlyBZcvX0aDBg1K1f+AAQPw8uVLnD9/voCoICLMmzcPrVu3LhAdACQTBAAwbNgw8Hg8bNu2TWqfGeUDEwR/KUuXLsXYsWMxfvx47NixI1/4sKzJzMzEhAkTYGtri549e5abH0URFxcHLS2tIsu+SoOVlRUeP36M7OxsmdnMS25J4927dyMkJEQufRTH25hk3A77LlYCYbz/TihVrgVFw5KniQRCwu2w7wj7moycnBw8ePAAK1euhLOzM3R1ddG8eXMsWLAA3759Q8OGDVGtWjWkpaXh+fPnyM7OxuDBg3Hx4kWsW7cOycnJ2LNnD+Lj42X62uaSkpKCzZs3o06dOnBxcUFCQgIOHjyI9+/fY+bMmahQoYKo7bdv3zB+/HjUrVsXgYGB2Lt3Lx49egR7e/tS+zFjxgycPn0aR44cQePGjQucv3DhAh4/fox58+YVSHLNzMxEaGioRIJAV1cXAwYMgLe3t9ze3wz5wATBXwYRwcPDA7NmzcLcuXOxdu1auexpLwlr1qzBhw8fsH79+jLZSllSZLGPwc9YWVkhIyNDroO1m5sbqlSpAg8PD7n1URQHAyPA45b8WmZEhCDt9R3o2I4U2zYHhD6zN0JPTw9WVlaYO3cuYmNj0aJFCzRu3Bg5OTl49OgR3r9/j9atW+PgwYP48uULnj17htWrV6NTp04YP348goODUbNmTTg6OmLEiBFISkoqzS2LiIiIwPTp02FiYgJ3d3c0aNAAd+7cQVBQEPr3759vVUB6ejqWLl0q2pBo4cKFCA0NLXbfAUnw9vbGqlWr4OXlhc6dC+Zy5OYOtGrVCu3bty9w/tWrVxAIBLCwsEBsbKxYggAAxo0bh+joaJw+fbq0t8AoQ9gqg78IoVCIsWPHwtvbG2vWrMGkSZPK2yVERkZi0aJFoqejXxF5CIJGjRqBx+MhKCio0J3nZIGioiKWLFmCvn374saNG4WGg+WF/5uvJUYHSChA3FVvqDdwgKK+udi2CRwkqhmjXbt2SExMxLNnzxAYGAgNDQ20a9cOQ4YMgb29PWrVqlWswDQ3N8fVq1exbds2TJ06VbQSwcHBQWxfRD4R4d69e/Dy8sKpU6egrq4uWjZoZmZWoL1AIMD+/fvx33//4cuXLxgzZgz++++/fFGD0nL58mWMGzcO7u7uRS5BvXjxIh4+fIirV68W+rfKXWFgbGwMgUAgtiCoX78+2rRpgw0bNqB3797S3wSjTGERgr+E7OxsDBw4ENu2bcPOnTt/CTEAAFOnToWGhka5znWXRHx8vMwFgYqKCurXry/XPAIA6N27N5o1a4Zp06ZBKBTKta9cUjJzECFG4l/Kk0vISfoG7TYDJe4jR1kHF69cQ05ODiZMmICAgADExsbi7NmzcHd3R+3atcWKNnE4HLi5ueWLFowcOVLsaEF2djYOHTqE5s2bw8bGBk+fPsW6desQFRWFFStWFCoGrly5gsaNG2Po0KFo0aIFXr16hXXr1slUDDx//hx9+vRBp06dsHbt2kLb5EYHbGxsYGtrW2ib4OBgmJmZISMjAwDEFgTAjyWIt2/fxrNnzyS/AUa5wATBX0BGRgZ69uyJ48eP48iRIxg2bFh5uwTgR+2DY8eOYeXKlb90wau4uDiZ1SDIi7wTC4EfA97KlSvx8OFDHD9+XK595fIxNhUlZQ4I0pOQcPsgtFv2BU9V8mRNDoeDO89DERAQgHnz5sHGxqZU22PnRgu2bNmCw4cPw9LSEleuXCmyfWxsLJYuXQpzc3P8+++/0NLSwvnz5/H69WuMHTu20G2Lnz17BkdHRzg6OkJDQwP37t3D8ePHZb7E9tOnT3B2dkb16tVx+PDhIqceLl++jAcPHmDu3LlFiqe8CYWAZIKga9euMDIyYksQfyOYIPjDSU5OhpOTE/z8/HD27NlfJnyXnZ0Nd3d32NjYYMCAAeXtTrHIY8oA+CEIXrx4geTkZJnbzkvbtm3h4uKCWbNmISsrS659AUBWTsmRiIRb+8FVUYdGU+lrFCgoqUh9bWFwOByMGjUKwcHBqFGjRqHRgpcvX8LNzQ3GxsaYP38+nJycEBwcjKtXr8LZ2bnQfJzIyEgMGTIEjRo1wocPH3Dq1Cncvn0bLVq0kKn/AJCamorOnTuDiHDu3LlChQnw/9EBa2tr2NnZFWmvNIJAQUEBo0ePxsGDB0VLdxm/NkwQ/MHExsbC1tYWjx49gq+vLzp27FjeLonYuHEjXr9+na906q+KPAUBEeHx48cyt/0zy5Ytw4cPH+Dt7S33vhT5xX+sZMdFI+WpLzSadIEgOQ45CTHISYgBCbJBQgFyEmIgSC9ZJJXUj7SYm5vDz89PFC2wsLDA4sWL4ejoCAsLC5w7dw5z5sxBZGQktm/fDktLy0LtJCYmYubMmahZsyYuXryIjRs3IiQkBN27d5fLe14gEKB///4IDQ3FhQsXYGRkVGRbX19fBAYGFhsdiI+PR3R0tEgQcLlcif8PRowYAYFAgF27dkl0HaN8YILgD+Xz589o164d3r9/D39/f7Ru3bq8XRLx5csXzJ07F6NGjULDhg3L250SkUcOAQDUqVMHampqcp82APKXNE5MTJRrX+Z6aihuuBMkxwIkRLzfVkR7u4q+sj69QU5cNKK9XZF453CxfXD+14+84HA4GDhwIDw8PBAXF4c5c+bg8ePH2LZtGz58+IDZs2cX+bSclZWF9evXo1q1ali3bh2mTp2KsLAwjBkzplTTGiUxdepUnD9/HkePHi22bkFudKBFixbFJlDmJhTmCoIKFSpIvCJJX18fffv2xaZNmyAQCCS6llH2sFUGfyDv37+HnZ0dMjMzcfv2bdSuXbu8XcqHh4cHFBUVsXDhwvJ2pUSys7ORlJQklxwCHo+Hpk2bltlGMPPnz8ehQ4ewYsUKLF68WG79qCnxYaqrio9FJBYqVDRDxR6zCxxPuLUfwqx06NqNBF+7UrF9mOqpQk1JPh9fkZGR2LRpE7Zt24bExER069YN5ubm8Pb2xqJFi2Bubl5ofQAiwsmTJzFz5ky8e/cOQ4cOxfz584t9UpcVGzduhJeXFzZu3AgnJ6di2169ehX379/HpUuXio1UBAcHQ0FBAbVq1RK7BkFhuLu7Y//+/bhw4QK6dOkilQ1G2cAiBH8Yr169QuvWrcHhcBAQEPDLiYG7d+9i7969WLJkiVyeumVNQkICANmVLf6ZskgszEXeJY2JCC9evPhR9Cf0PkhY+BMhT1ULqjWtC3xxVTTBVVSBak3r4pchkhDVVTMhxkatEnH//n3069cPVapUwZYtWzBs2DCEh4fj5MmTWL16NV68eIHq1avDwcEBbm5u+XIL7ty5g5YtW6J3796oUaMGnj59ih07dpSJGLhw4QImTJiAiRMnYuzYscW2za1KaGVlVeLOncHBwahduzYUFBTw9etXqQVBs2bN0Lx5c5Zc+BvABMEfxKNHj9C6dWvo6Ojg9u3bMDc3L2+X8iEQCDBu3Dg0adIErq6u5e2OWMh6H4OfsbKyQmRkJD5/Fq/mf2mRdUnjz58/Y//+/Rg8eDCMjY1haWn5o49Pj8Hhyr76HwCAw8U+zxGwsLDA5s2bkZKSIrWp7OxsHDlyBC1atIC1tTUePXoELy8vREVFYdWqVfn+h3JXImzevBkHDx5EvXr1sHv3bvTo0QOtWrVCZmYm/Pz8cPHiRdSrV08GN1oyT58+Rb9+/eDi4oJVq1aV2N7Pzw/37t0rtCrhz+QmFAIoVYQA+FGo6OrVq3j9+rXUNhjyhwmCP4Tbt2+jQ4cOqFatGm7evIlKlYoPuZYH27dvx5MnT7Bx40a5lIqVB2UhCADgwYMHcrH/M6UtaZySkoKLFy9i0qRJsLS0ROXKlTFo0CA8e/YM/fv3h6+vL2JjY9HfpQMyPz4FCXLEtm347zJUHr652DY8DtCqegVcOb4PderUgbu7O4yMjDBx4kS8fftW7L7i4uKwfPlyVK1aFf/88w/U1NRw9uxZvHnzBuPGjSuw+U8uXC4Xo0ePxo0bNyAQCDBs2DBRcaOHDx8WuZ5fHkRHR8PFxQU1a9bEoUOHSvyfys0daNasWYkJxkSEkJAQmQmC3r17Q19fn0UJfnGYIPgDuHTpEhwcHNC0aVP4+fn9kqH42NhYzJ49W1SM5XchPj4eAOSSQwAAJiYmMDAwKLNpA0CyksY5OTm4f/8+Fi1ahLZt20JXVxfOzs44efIkmjdvjkOHDiEmJgZPnz7FypUrYWRkhPbt22PMmDH4fnGDWOWLxYWIkJOdhc6GyWjfvj1OnjyJ9+/fY8yYMThw4ABq1qwJJycnXLp0qcgiTK9evcLo0aNhbGyMuXPnwsHBAc+ePcO1a9fQuXPnEpPm0tLSsGjRIrRv3x4pKSno3r07hEIhFi1ahOvXr8vsXksiJSUFLi4u4HK5OHfunFgbgl27dg137twpdmVBLhEREUhKSpKZIFBSUoKbmxv27t0rsxLRDNnDBMFvzrFjx9ClSxc4ODgUuq3pr8Ls2bMhEAiwdOnS8nZFInIjBPISBBwOp0zzCID/L2l84cIF3LhxI985IsLbt2+xefNm9OjRAxUqVIC1tTVWrlwJHR0drF27Fq9fv8bHjx+xc+dO/PPPP9DX10dGRgb+++8/NGzYEI8fP4aOjg5OH9yJJT0bysxvDocDg8gb+KezA+bMmYOcnByYmppi6dKliIyMxK5du/Dlyxc4OTmhdu3aWLduHRITE0FEou2F69atCx8fH8ycORMRERHYuXMn6tevX2LfAoEAO3fuRI0aNbBgwQKMGDEC4eHhOHXqFEJCQlCtWjXY29vDzc1N7nUlBAIB+vXrh/DwcJw/fx6VK1cu8Zrc6EDTpk1LTDoE8q8wICJ8//69VIIA+CFEMzIysHfv3lLZYcgREoPExEQCQImJieI0Z5QRO3bsIC6XS//++y9lZWWVtztF8vDhQ+JwOLRu3brydkVi1q1bRyoqKnLtY+HChaStrU0CgUCu/eRFKBRSs2bNqGnTpvTlyxc6cuQIubq6kpmZGQEgPp9PrVq1ovnz59Pdu3cpOzu7SFvXr1+natWqEZfLJQDUpUsX+vr1q+j8huuhZOZxnkxnnCMzj/NSf228/pZycnJoyZIlxOPxyMbGhj5+/FjgvgICAqhfv37E4/FIUVGRdHR0CAA1atSI9u7dSxkZGRL9nS5evEiWlpYEgPr27Uvh4eEF2gkEAtq0aROpqamRqakpXb16Vew+JMXd3Z14PB5dvnxZ7GuuXbtGAOjcuXNitV+yZAlpaWmRUCik+Ph4AkBHjx6V1mURffr0oZo1a5bpe/1vR5Lxm0UIflPWrFmD4cOHw83NDfv27ZPr+ubSIBQKMW7cOFhYWGDMmDHl7Y7EyKsoUV6srKyQkJCAsLAwufaTS3p6Oq5du4bq1avj4cOHMDQ0RL9+/XDv3j107doV586dQ1xcHG7fvg1PT09YW1sXuj12bGwshg0bhg4dOiAqKgrKysrYs2cPTp8+ne9pckzbatB5exEcQTZ4Es4g8LgcKPG5WN6jHsa2rw4ej4eZM2fi1q1biIqKQoMGDeDj4yNqz+FwYG5ujipVqkBDQwNZWVlIS/ux/FFHRwdaWlpib/X9+PFj2Nvbw8nJCTo6OggMDMSRI0dQtWrVAm25XC7GjBmD4OBgVK1aFfb29hg1apTMowXr16/Hhg0bsGnTphJXCeRC/4sONGnSBM7OzmJdExwcDEtLS3A4HKmqFBaFu7s7QkNDcfXq1VLbYsgBWSsMhnwRCoXk6elJAMjDw4OEQmF5u1Qsu3fvJgB048aN8nZFKsaPH0+WlpZy7SM2NpYA0P79++ViXyAQ0KNHj2j58uVkZ2dHysrKBIAMDQ3JyMiIKlasSO/evRPbnlAopAMHDlCFChVISUmJAFDr1q3p/fv3hbZfu3YtAaDjF6/TgB33yczjPFWddaHYaEDu+QE77lNEbGqhduPi4qhnz54EgMaMGUO3bt2if/75h/h8PmloaNCkSZMoPDycMjIy6MCBA9S8eXMCQObm5rRixQqKjY0t1O6HDx9owIABBIBq165NZ86ckej/TF7RgjNnzhCHw6GpU6dKdN3169cJAJ05c0bsaywtLWnUqFFERHTnzh0CQMHBwRL1WxhCoZAaNmxILi4upbbFEA9Jxm8mCH4jBAIBjR8/ngDQ0qVLy9udEklISCB9fX36559/ytsVqRkwYAC1adNG7v3UqFGD3N3dZWbvw4cPtH37durTpw/p6ekRAFJVVaVOnTrRmjVrKDg4mIRCIYWEhBCXyxV7Oic8PJwcHBwIAGlpaZGCggKtXLmScnJyCm0fGhpKKioq+e4t9EsSzT0TQm1WXiezn6YRzD3OU5uV12numRB6G5NUoj9ZWVk0fPhw4nA4BIBMTExo3bp1RX5WBQUF0cCBA0lRUZGUlZXJ1dWVnj59SkRE8fHxNG3aNFJSUiIDAwPy9vYudqqkJN69e0ft2rUjAOTm5kZJSSXfT1E8fPiQVFVVqUePHhKH29u2bUuNGjUSW9RkZmYSn8+nTZs2ERHR6dOnCQB9+fJFYr8LY8eOHcThcAqdemHIHiYI/kCys7NpyJAhxOFwaMuWLeXtjlhMnDiR1NTUKCoqqrxdkRonJyfq1q2b3Pv5999/qXnz5lJfHx8fT6dOnaLRo0dT9erVCQBxuVxq3rw5zZ49m27cuEGZmZmFXuvq6koVKlSghISEIu1nZWXR8uXLSUVFhbS1tYnP51O9evXo2bNnRV6Tk5NDNjY2VK1aNUpJSSm0TZMWLamv2xRauHk/KehXodjEwtv9TFxcHK1YsYJMTEwIADVr1oyMjY1JRUWFdu7cWeLgFxMTQ4sWLSIjIyMCQFWrViV1dXVSVVWluXPnlmrwzkveaIGZmRn5+flJbCMiIoIqVapEzZo1o9TUwqMlReHv708A6PTp02JfExwcTADo1q1bRES0fft2AlAqcZSXtLQ00tXVpcmTJ8vEHqN4mCD4w8jIyKAePXoQj8ejgwcPlrc7YhEcHEw8Ho+WLVtW3q6UihYtWtCwYcPk3s+6detIUVGxyEH7ZzIzM+nGjRs0e/Zsat68uSihr3r16jR69Gg6efIkxcXFiWUrKiqKVFRUaNasWYWeDwoKogYNGhCXyxUNoNOmTSsxOW/NmjUEgG7evFlkG3Nzc5o5cyZdvnyZANCHDx+Ktfn69WsaM2YMqaqqkqKiIg0ZMoSePHlCRESpqak0YsQIAkD//PNPiZ9XuVMf+vr6BEA0jbJo0SKKiYkp9lpJCQ8PF0ULRo0aJbbgSEpKovr165OpqSl9/vxZ4n7btWtHDRs2lGjK49ChQwRA9P5ZsmQJ6erqStx3cUyfPp20tbWLFIoM2cEEwR9ESkoKOTg4kJKSEp09e7a83RELoVBI7dq1o5o1a0qU0f0rUqtWLZoyZYrc+7l37x4BoAcPHhR6XigUUnBwMK1Zs4acnJxITU2NAJCenh716dOHtm/fXuQcvjjMnj2bVFRU8kVzkpKSaPz48cThcMjMzIxUVVXJzMxMrHyQN2/ekLKyMo0fP77Ydurq6rR69Wp6/vw5AaC7d+8WaCMUCunKlSvk5OREAEhfX5/mzZtXZAj7yJEjpKmpSVWrVqWgoKBC29y8eZOaNWtGAMjFxYVevHhBT58+JVdXV1JWViZFRUUaNGhQka+HNAgEAtq4caPY0YLs7Gzq1KkTaWpqSjV/f/PmTQJAPj4+El03c+ZMMjY2Fv0+adIkqlWrlsT9F8f79++Jy+XS1q1bZWqXURAmCP4Q4uPjqWXLlqSurk7Xr18vb3fE5siRIwRAomVRvyoVK1akxYsXy72f9PT0fPO2RETR0dG0d+9eGjBgABkaGhIAUlJSIjs7O1q2bBk9evRIZsu3EhMTqUKFCuTq6kpEPxLYjI2NSVVVVbTkbvDgwWJ9BuTk5JC1tXWxUwVEP+4ZAO3bt4++f/9OAOjEiROi82lpabRt2zaysLAgANSgQQPas2ePWCIzPDycrKysiM/n08qVK0V/p5cvX1KXLl0IADVp0oT8/f0LXBsbG0srVqwQLcFs3rw5HThwQOzojTi+lRQtEAqFNHr0aOLxeHTlyhWp+unQoQM1aNBA4sRjFxcX6tixo+j3AQMGUKtWraTyoTi6du1KlpaWv3xi9O8OEwR/ADExMdSwYUPS0dGh+/fvl7c7YpOcnExGRkZlMu8ub4RCIfF4vDLL2WjYsCF16NCBJkyYQHXr1hWFsRs1akTTp0+nK1euUFpamtz6X79+PXG5XLKzsxMNmBUqVCA9PT06efKk2HZWrVpFHA5HNAddFJGRkQSALl68SEKhkBQVFWn9+vUUHR1Ns2fPJj09PeJwONS1a1fy9/eXeODIysqi6dOnEwBq3749DRo0iHg8Hpmbm9OhQ4dKFFM5OTl0+vRpsrW1JQBkYGBAnp6eFB0dLZEfhZEbLciNuly7di3f+dzplm3btkll/9atWwRAotctFzMzM5o2bZrod0dHR+revbtUfhSHn5/fb70C6XeBCYLfnIiICKpZsyYZGhrKZKlPWeLh4UHKysoSLWP7Vcl938uiIEthZGdn0927d2n+/PnUunVrUR6Aqakpubq60pEjR/IV+JEnAoGANmzYQBwOhxQVFUWDoJOTk0Rz169fvyZlZWWaOHFiiW0fP36cb5qkUqVKZGFhQXw+n9TV1WnChAkUFhYm9T0R/RCoAwYMIA6HQxwOh0aNGiXVNNaLFy9o9OjRpKamRnw+n/r160d37twp9dNteHg4tW3bNl+0wMfHhzgcDs2YMUNqu7a2tlSvXj2JI0i57/l9+/aJjjVu3JhGjhwptS9FIRQKqU6dOtSzZ0+Z22b8P0wQ/Ma8efOGTE1NydzcvNQfhmXNmzdvSEFBgebNm1fersiEDx8+EACpQ7Y/IxQK6fXr17Rx40bq2rUraWpqipbvde/enQYOHEgAKD4+Xib9iUtISAi1bNlSFBXInZrw9vaWaMDLnSqoUaOGWNnwV65cIQC0adMmsrGxIQCkrq5Oa9euLXbFgzhkZ2fTtm3byNDQkBQVFWnUqFHUtm1b4nA4NGvWLKkre8bHx9PatWtFKzkaN25Mu3btovT0dKl9zRstMDQ0JCUlJerVq5fU00EBAQEFpl/EJbfmQG6iJhGRiYkJzZkzRypfSmLTpk3E4/EoIiJCLvYZTBD8tjx79oz09fWpdu3aFBkZWd7uSIRQKKSOHTuSubm5XMPaZUnuE+zDhw+ltvH161c6dOgQDRs2TLRETkFBgdq0aUMLFy6ke/fuiZZzvXjxggAUCB/Li/T0dJozZw4pKChQzZo1aeDAgcThcEhNTY0sLS0lHpBWrlxJHA6HAgICSmwbHx9P/fv3F02LtG3blqytrcnOzk7a2yGiH+/Dc+fOiaZc+vfvL4pWCQQCWrp0KfF4PLK2ti5xRUNxCAQCunDhAnXq1EmU3Onh4VGglLIk3Lp1ixQVFQkAjRgxgpKTk6WyY29vL9XrR0Tk7e1NPB5PFEURCoWkrKwst7LjycnJpKmpWeQKF0bpYYLgN+Tu3bukra1NjRs3LrMwsSw5c+aMVBnNvzK5c5ySTH+kpaWRr68vTZ06lRo2bCga8CwsLGjixIl04cKFIj/oc3JySENDo0yKTl2/fp1q1KhBioqKNHbsWGrUqBHx+XxasGCBqO79kSNHxLb36tUrUlJSokmTJhXbLjQ0lMaNG0dqamrE4/GIy+WKBJe7uztZWFhIfU8PHjwQJeu1a9euyBUCd+/eJTMzM9LW1pbqKfpnQkNDacKECaSpqUlcLpd69Oghcc5DQkICWVpakrm5OS1ZsoRUVVXJ3NxcYnGY+4R/7NgxSW+DiIjGjh1LderUEf2enJxMAOjQoUNS2ROH8ePHU4UKFUoVZWEUDRMEvxlXr14lNTU1at26dalDpeVBWloaValShRwdHf+ojOFjx44RgGJfk5ycHHr48CEtXbqUOnToICrlW6lSJRo0aBDt27ePPn36JHaf7du3l0sCVy7fv3+noUOHisoNz5w5k5SVlal27dr5BlAXFxeqWrWqWJn1OTk51KJFiyKnCoRCIfn5+ZGLiwtxOByqWLEieXp60sSJE8nExETUbunSpaSjoyPxPb1//57++ecfAkB169al8+fPl/g+jI+Pp169eonm7mUR1UpKSqJNmzZRnTp1CABZWlqSt7d3iWvts7KyyN7enrS0tOjly5dERBQWFibKLRg9erTY0QIHBweysLCQerqhTZs21KdPH9Hv7969IwBy3azpzZs3BID27Nkjtz7+Zpgg+I3w8fEhRUVF6tSpk8RVyH4V5s+fTwoKCvT69evydkWmbN26lbhcboEP13fv3tG2bduod+/epKurSwBITU2NnJ2dycvLi0JCQqQWRjNmzCAjIyNZuJ+PvPsPaGlp0fLly0WJg+7u7gXee5KUNF6xYkWhUwVpaWm0Y8cO0bLFevXq5ZtvHzVqFDVq1EjUfu/evQRA7ME5NjaWpkyZQoqKilSpUiXavn27RNX0hEIhbd26lZSVlcnS0pJevHgh9rUl2b169Sp17dqVOBwOaWtr0+TJkwst1SsUCmnkyJHE5/MLRANyEz3FjRbcvXu3VEmwQqGQdHR0aOHChaJjgYGBBEBU3lledOzYkZo0afJHPVD8KjBB8Juwb98+4vF41Lt3b5mtcS5r3r9/T8rKyqXKiP5VWbp0Kenp6VFcXBydOHGCRo0aRdWqVROVBW7RogX9999/dOvWLZm9fidPniQAMi33nHf/gb59+9KWLVtIW1ubKleuXGzCpKurK+np6RUbIXn58iUpKSnlK0P76dMn+u+//6hChQrE4XCoc+fOdO3atQIf9j179iQHBwfR71evXiUAJda4z8jIoFWrVpGOjg6pqanR/PnzS1XxLjg4mCwsLEhFRYW2b98u00Hp/fv3NG3aNNLR0SEOh0MuLi7k6+sr6mPlypUEgHbt2lWkjbCwMGrTpo1oE6eiogWOjo5Ut25dqaMDUVFRBcocnz9/ngDIZKllceT2c+/ePbn28zfCBMFvwMaNGwkAubq6FrkxzO9A9+7dqXLlylInQP2KZGRkkL+/P7Vo0YKUlJREywFr1qxJY8aMIR8fH7mtBMhdmy+LXIy8+w+YmprS0aNHRaH1vn37FrnbXy4llTTOzs4mKysrqlmzJqWlpdGjR49o4MCBpKCgQGpqauTu7k6hoaFF2m/bti31799f9HtuUuXt27cLbS8QCOjgwYNkbm5OPB6PRo0aJbMNd1JTU2nkyJGiv42sp+5SU1Np+/btVL9+fQJAtWrVIldXVwIgVkKdQCCg9evXi6IFPxcqu3//vsR5Hz9z6dKlAoIsd7dSeT+wCAQCqlatWr73A0M2MEHwCyMUCmnx4sUEgCZPnvxbh8hy688fPny4vF0pFUKhkJ49e0arV6+mjh07kqqqKgEgZWVl0tPTo507d5Yqe1xSXypVqkQzZ84slZ28+w9MnjyZzp49S0ZGRqStrS1RglhhJY1zWbZsGXE4HFqyZAm1bt2aAJCZmRmtXr1aLMFUt25dmjBhguj3+Pj4IkPe169fFy2J7Nq1K7169Urse5CEY8eOkaamJlWpUkUuBcGEQiHdvHmTOnToQACIz+fTuHHjxJ5uKypa0KlTJ6pTp06pHi5WrFhBampq+SIMy5cvJy0tLaltSsKaNWtIQUFBqj0bGEXDBMEvilAopGnTphEAWrBgwW8tBjIzM6lmzZrUtm3b3/I+oqKiaPfu3dS/f38yMDAQCQB7e3tasWIFPXnyhLp3756vhGtZ0bVrV7K1tZXq2rz7DzRq1IgCAgJEW2bb2tpKvN7755LGudy/f594PJ6olkKrVq3o5MmTEs3h6+vr55uvFgqFpKKiQl5eXqJjISEh5OzsTADIysqq2I2SZMW7d++oefPmxOfzacWKFTIrD53L+/fvSV9fn5o2bUozZsygihUrEgBycHCgc+fOldhf3mhBlSpVaNOmTTJZCTBw4MACO25OnTqVqlevXiq74hIfH0+qqqo0f/78Munvb4EJgl+QnJwcUUhSXmt6y5IVK1YQj8ej58+fl7crYpGYmEhnz54ld3d3URY4h8OhJk2a0IwZM8jPz6/Asqd27dqVSwhz8eLFpKmpKfFAlHf/gdWrV9P9+/epTp06pKysTF5eXlIPbLkljYODg+nt27c0btw40TTKP//8I9UGQAKBgHg8Hnl7e+c7Xq1aNZo+fTp9+vSJhg8fTlwul6pWrUpHjx4tU+GZlZVFHh4eBIAcHR1lNjURHx9PdevWpapVq4qWF6enp9PevXupadOmBPzYilmcKEveaIG2tnappzkaNmxIw4cPz3ds8ODBZG1tXSq7kuDm5kaVKlX6bXOqfkWYIPjFyMrKon79+hGXy6Xdu3eXtzulJioqitTV1Uvcya48ycrKooCAAJo3bx7Z2NgQn88nAGRubk4jRoygo0eP0rdv34q1Ub9+fRo3blwZefz/5CbXiRsWj46Opp49exIA6tSpE719+5YWLVpEfD6fGjVqVOrs+YyMDKpcuTIZGBiIChcBKNXum7GxsYVW02vRogXVq1ePVFVVSVdXl9auXVuuO2b6+vqSvr4+GRgYlLpiZVZWFtna2pKOjk6hUwRCoZDu3btH/fv3JwUFBVJVVSU3N7diy5fn5g4oKipSlSpVpN4ELTs7m5SUlAo8rDg5OVGXLl2ksikNwcHBpc6FYOSHCYJfiLS0NHJ2diYFBQWpNhr5Fenfvz9VrFixzEvsFodQKKRXr17R+vXrqUuXLqShoSF6curRowdt2bKFwsLCJHrKNDY2Jk9PTzl6XTgJCQkEgPbu3VtsO4FAQFu2bCFNTU3S19enI0eOUGhoKFlbWxOXy6XZs2eX6kkrPT2ddu3aJUqEA0BDhgwhBQWFfJvfSMPr168JgGgKIDs7m7Zs2ULKysrE5XJp+vTpv8z768uXL+Tg4EAcDoc8PDykKnssFArJ1dWVFBQUCt1h8Wc+f/5M8+fPp0qVKokKLRU2JePi4kK1atWiN2/eiLUSoShevnxJAESCIiUjm0KiE6ihbTfqM3IypWSIPxVUWtq1a0c2NjZl1t+fDhMEvwiJiYnUtm1bUlFRIV9f3/J2Rybk7rFe3DKpsuLLly908OBBGjJkCBkbG4vKArdr144WLVpEgYGBpUqyUlNTo7Vr18rOYQmoXbs2jR07tsjzefcfGDFiBMXGxtK2bdtITU2NqlatSnfu3JG678+fP9PcuXNJX1+fAJCzszNduXKFmjRpQqqqqlSrVq1SV5XLrbcfEhJCp0+fplq1ahEAqlOnDlWrVq1UtuWBQCCg5cuXE5/PpxYtWtD79+8lun7p0qViibyfyczMpMOHD4tea1NTU1q6dCl9+/aNHjx4QABo//79Ih/XrVtHKioqVKVKFbGERy5Hjx4lBT0Tmn70AbVZcZ3MPc6TWZ4vc4/z1GbFdZp7JoRCvxTcrlmW5C69ffz4sVz7+VtgguAX4Pv379S0aVPS0tISq7b770B2djbVq1ePmjdvLvNEK3FITU2lS5cu0ZQpU/I9tdarV48mT55MFy9eLNV69LxkZGRI9QEuKwYNGkTNmjUrcDzv/gO1atWimzdv0ufPn8nFxaXUNfCfPHlCgwcPJkVFRVJVVaWxY8fSmzdvROeHDx9OAPIlAkqLj48PASBra2tRwuPjx49pxYoVpKmpWWr78uL+/ftkbm5OWlpaYpcHPnr0KAEodbTp0aNHNGTIEFJSUiIlJSUyMTEhMzOzAlGDt2/filZ9jB07tsT3Q0RsKrXwOEBmHuep6qwL+YTAz1+55wfsuE8RsfIppJadnU0mJiY0bNgwudj/22CCoJyJjo6munXrUsWKFfPtGva7s379euJwOFIlkUlDTk4OBQUF0eLFi6l9+/aijV8qV65MgwcPpgMHDshtidLnz58JAJ07d04u9kti48aNpKCgkG/+PO/+A3PnzqWMjAzy8fGhChUqkL6+vlS+5uTkkI+Pj6hMrqmpKa1cuZLi4uLytQsODiZFRUWqVq2a2CWNiyI8PJyaNWsmKu976dIl0VTOgQMHCMAvXdciPj6eevfuTQDIzc2t2MqKd+/eJSUlJerfv7/MkiK/fv1KY8eOFQliGxsbOnLkSL6pDHGjBYeDPlLNORfJbMbZYoVAYcKg5pyLdDhIPstxlyxZQsrKyvT9+3e52P+bYIKgHAkPD6cqVaqQsbHxH1XKNyYmhrS0tOSyL3pewsPDydvbm3r27Ek6OjoE/NgSt3PnzrRu3Tp6+fJlmWSb5xbJKU3ovTQEBQURAAoMDCyw/8DLly8pMTFRdKxbt24Sb4iVmJhIa9eupSpVqogGlePHjxe6bDArK4uaNGlCderUoUePHold0vhnvn//ThMnTiQFBQXS1NQkNTW1AlM6169fJwDFFjT6FRAKhbRt2zZSUVEhCwsLCgkJKdAmPDycKlasSK1atZJ5YmSXLl2oevXqdOzYMdGGTpUqVaL58+fnWxGRN1owbty4fEJrw/VQiURAUV8brsv+tfr27RspKSnRsmXLZG77b4MJgnLixYsXVLlyZapRo0aptlb9FRk2bBjp6OiUmJkvKbGxsXT8+HEaOXKkaHDi8XjUsmVLmjt3Lt2+fVvqvetLQ+4cd+5mM2VNRkYGKSoq0qBBg0T7D2zbto0EAgHdvHmTzM3NSV1dnXbt2iWRQAoPD6cJEyaQhoYG8fl86t+/PwUGBhZ7zaJFi4jL5YraDR8+vMSSxnlJT08XFbjR0NCgRYsWkbu7O9WqVatA25+TDX91QkJCRGWPt27dKnot4uLiqHbt2lS9enWZ/8/kbsuddzrr+fPnNHLkSFJRUSEFBQX6999/RYWVCosWHA76KBMxkPt1RA6RgiFDhpCpqalEtS0YBWGCoBx48OAB6enpUf369WW2ZvlXIXeDk82bN5faVkZGBl27do08PDyoadOmxOFwRKVcx40bR2fOnPkldnw8e/YsASi31zI8PFxU9Kdv3770+fNnysjIoOnTpxOHw6FWrVqJvS2zUCikGzduULdu3YjD4ZCuri7NmjVLrP0Snj9/TgoKCuTh4SE6Fh0dXWxJ41wEAgHt27ePTE1Nic/n09ixYykmJoaIfhTBadWqVYFrkpKSfrvql2lpaTRq1CgCQL1796aYmBhq37496erqyiXS0a1bN6pevXqhA2VcXBytWrVKJK6bNWtG+/bto4yMDFG0gK9lQFVmnCGTycdJy+YfUq7SmLjK6gSA9JwmFhjsDQetJvVGTqRoUI3A5f2oSPlTm5pzLso8p+DRo0cyK+P9N8MEQRlz48YN0tDQoBYtWhSYe/3dEQgE1LRpU2rYsKFUGfsCgYCePn1KK1euJAcHB1JRUSEApK+vT/3796ddu3ZJXD2vLNizZ0+Z1HD/mbz7D6irq5OxsTER/RiY69evTwoKCrRs2TKxXouMjAzas2cPNWzYkIAfWwNv27ZN7F01s7KyqHHjxlS3bt0CIe/Zs2eTsrIyRUZGFnqtn58fNWrUiABQjx498iUnEv0otdutW7dCr1VTU6PVq1eL5eOvxPHjx0lTU5PU1dVJQUGBbt26JfM+njx5QgBKrGeSk5ND586dE21qpa+vT3PmzKGIiAhq7XmMTKefIaNRO39E5DQrkpJpvSIFgZbNPwQunxQNqxNf16hQQVB11gUasEP2pZ6tra2pQ4cOMrf7NyHJ+M0Fo1RcuHABHTt2hJWVFa5evQodHZ3ydkmm7Nq1Cw8fPsTGjRvB4/HEuiYyMhK7d+9G//79UalSJTRs2BCenp7gcDhYuHAhnj59is+fP+PgwYMYOnQoTExM5HwXkhMXFwd1dXUoKiqWWZ8PHjxAs2bNMHPmTIwePRpr1qxBVFQUFi1ahKZNm0IoFCIoKAgzZswo9rWIiYnB/PnzYWZmhiFDhqBSpUrw9fVFSEgIRowYAVVVVbH8Wb58OZ49e4Y9e/ZASUkp37np06dDXV0dc+fOzXc8ODgYnTp1gp2dHZSVlREQEICTJ0+iZs2a+dp9+/YNFStWLLTfypUr49OnT2L5+CvRq1cvjBgxAikpKRAIBLh79y6EQqFM+1iwYAGqVq2KAQMGFNuOx+PBxcUFvr6+ePXqFfr06QMvLy/UaNoGEVmq4HB54KnrwnjcfhiP2Q2d9sOKtKXR2Akmk46i0hAvqJg3LLSNQEi4HfYdYV+TS3N7BXB3d8f169fx4sULmdplFA4TBKXg6NGj6NatGzp27Ijz589DXV29vF2SKXFxcfDw8MDAgQNhY2NTZLvExEScOXMG7u7uqF27NkxNTeHq6oq3b9/C1dUV169fR1xcHC5fvowpU6agQYMG4HJ/7bdefHx8mYm75ORkTJgwAc2bNweXy0VQUBBWr16NatWqAQD+++8/uLu748GDB2jYsGGRdp49e4Zhw4bB1NQUK1asQI8ePfDq1StcvHgRDg4O4HA4Yvv0/PlzLFiwANOnT0ezZs0KnNfU1ISnpyf27NmDkJAQREdHw9XVFQ0bNkRYWBhOnDiBO3fuFPm++f79OypUqFDoud9VEBw+fBirV6+Gp6cnZsyYgZkzZ6Jjx4748uWLTOw/f/4cPj4+mDNnDvh8vtjX1a5dGxs2bEB0dDQ6uS8GhAIAAIevAJ56ye9xnpoOuApKJbfjcnDgfoTYfolDz549YWhoiE2bNsnULqNwxH9XMfKxfft2uLm5YcCAAdi1a5dE/6C/C56ensjKysLy5cvzHc/OzkZgYCCuXr2Kq1evIigoCAKBAFWrVoWdnR0WLVqEDh06QFdXt5w8Lz1xcXFl4v/Zs2cxduxYxMXFYdWqVRg/fjx4PB727duHcePGgcPhYNiwYVi1alWh1wsEAly4cAFeXl7w9/eHsbExFi5ciOHDh0vtf3Z2NoYMGYKaNWsWiADkxc3NDWvXrkX37t0RHR0NVVVVeHl5wc3NrcTIyp8WIQgICMCQIUMwcOBAzJs3DxwOBx06dMCAAQPQoEED7N+/Hw4ODqXqY8GCBahSpUqJ0YGi0NTURJxSJSA1rVR+FIVASPAP/Yp5sJCZTUVFRbi5uWHVqlVYunQptLS0ZGabUZBf+zHtF2XVqlUYOXIkxowZgz179vyRYuDp06fYsmUL5s2bB0NDQ7x8+RLr169H586doauri9atW2PDhg0wMjLC5s2bER4ejvDwcGzduhW9evX6rcUAIH9B8OnTJ/Tq1Qtdu3ZFvXr18OLFC0yePBkJCQno3bs3Bg8ejO7du6Nt27b4/v17geuTk5Oxfv161KpVC127dkV6ejqOHj2Kd+/eYfr06aXyfdmyZXj+/HmhUwW5ZGdnY/v27YiNjUVYWBi6d++O8PBwuLu7lygG0tPTkZqa+sdECMLCwtCtWzdYW1tj+/btokiMnZ0dnj17hkaNGsHR0REeHh7Izs6Wqo/nz5/j5MmTmD17NhQUFKSykZKZg4g4+YiBXCJi05CamSNTm25ubsjMzMTu3btlapdRECYIJICIMGfOHEybNg2zZ8/Ghg0bfvnQtzQQEUaOHAlDQ0M8ffoUJiYmsLCwwLRp05CamopZs2bhwYMH+PbtG44fP46RI0eiatWq5e22TJGXIBAKhfD29kadOnVw+/ZtHDlyBBcuXIC5uTkuXbqEevXqwd/fH8ePH8fevXvRsmVLBAYGgogAAO/fv8eUKVNgbGyMyZMno1mzZrh37x7u3buHPn36SD1Y5PL8+XMsXLgQM2bMQNOmTQucJyL4+PjA0tIS7u7u6N69O+rXr4/Q0FBoaGiI1UeuwPkTIgRxcXFwdnaGnp4eTp06VUBAGRgY4OLFi1i5ciVWr16N1q1b4/379xL3s3DhQpibm2PQoEFS+/oxNhUk9dXiQQA+xKbK1GalSpXQu3dvbNq0SeY5GYz8/HmPtnJCKBRiwoQJ2LhxI1asWIFp06aVt0syJTU1Fbdu3cLVq1dx4sQJREZGAvgxQPTr1w/29vZo3bq12Alpvzvx8fEyT3Z88eIFRo4cibt372L48OFYvnw5dHV1kZqaiqlTp8Lb2xsdO3bErl27UKlSJQCAlZUVlixZglOnTuHQoUM4ffo0tLS0MGbMGIwdOxbGxsYy8y87OxuDBw9GrVq14OnpWeD8vXv3MG3aNNy5cwcODg44duwYGjRogJs3b6Jdu3Y4fvw4+vbtW2I/uYKguAhBamoqkpOTxRYZ5UFmZia6d++OuLg43L9/v0gByeVyMXXqVLRp0wb9+vVDw4YNsX37dvTp00esfkJCQnDixAls375dLMGXnZ2NhIQEJCQkID4+XvT9xZdUAAaS3KJUZOXIftAeN24cbGxs4Ovri06dOsncPuMHTBCIQU5ODlxdXbF//35s3boVI0eOLG+XSo1AIMCjR49EeQB3795FdnY2jIyMEBcXh+bNm+PMmTMwMJD/B8iviCwjBBkZGVi8eDGWL1+OqlWr4ubNm2jTpg0AIDAwEAMHDkRUVBQ2b96MUaNGiULOWVlZiIj4kaTVq1cv1K5dG5s3b8aAAQOgpqYmE9/ysmTJEgQHByMwMDDfk25YWBhmzpyJEydOoH79+vD19c03H962bVu4uLhg1qxZ6N69u1j5A0DxEQLgx7RKrVq1SntbcoGIMGLECNy/fx/Xr18XJYAWh5WVFZ48eQI3Nzf07dsXfn5+8PLyKiCyiQhpaWmigXz8+PHQ19cHl8vF+vXrER8fn2+gz/2e+5WaWvgTuoJ+FVQetkEm918cinzZR02tra3RuHFjbNiwgQkCOcIEQQlkZmaiX79+OH/+PA4dOoR+/fqVt0tSQUQIDw/H1atX4efnh+vXryMhIQEaGhpo37491qxZA3t7e2zfvh1btmzBsWPH/loxAMhOEPj7+8PNzQ0fPnzArFmzMHPmTCgpKSE7OxuLFi3C4sWL0aRJE5w/f160NO/bt2/w9vbG5s2b8eXLFygpKaFLly44cuSI3Kaonj59ikWLFmHmzJlo0qQJgB9P8gsWLMCWLVtgaGiIPXv2YMCAAYUueVy2bBnq168Pb29vjB8/vti+SooQ5EZHfmVBsHDhQuzfvx+HDh0qdCWFQCBAYmJioYN248aNkZycjF27duHo0aOoV68ecnJy8g30heUauLq6QlFREaqqqlBUVASHwwERITs7GxkZGUhPT8/XXllZGQYGBqhcuTLMzMxgZF4VJ0AAxF9tIikcAOZ6sherHA4H7u7uGDp0KMLCwlC9enWZ98FggqBYUlNT0a1bNwQEBOD06dNwdnYub5ckIjY2FteuXROJgA8fPoDP56NFixaYOHEi7O3tYWVlJUqKfPXqFdatW4d58+bB1NS0nL0vP4RCIeLj40slCGJjYzFt2jTs3r0brVu3xpkzZ1CnTh0AwJs3bzBgwAA8efIEnp6emDVrFvh8PoKDg7Fu3TocOHAAXC4XgwYNwvjx4/Hff//h+/fvchMDWVlZGDJkCOrUqYP//vsP6enp8PLywrJlywD8GPwmTJgAFRWVIm1YWFhg2LBhWLBgAQYPHlxsNvi3b9+goqJSZJQjryAoTzIyMvIN5Lk/X7lyBfv27YONjQ38/Pxw/PjxAk/siYmJRdrV0tKCjo4OatSogcjISNy7dw/16tVD3bp1IRAIkJ2djbS0NCQlJSE0NBTp6emiHJKsrCxkZWWhQoUKMDIygrGxcZHfNTU1Cyw1fbDSHx/lmFhoqqcKNSX5DCt9+/bF1KlTsWnTJqxdu1YuffztMEFQBPHx8XB2dkZwcDAuXbqEdu3albdLJZKRkYE7d+6IpgGePHkCIkKdOnXQpUsX2NnZoV27doXOyxIRxo8fDzMzM0yZMqUcvP91SEpKAhFJVYeAiHDo0CFMnDgR2dnZ2LZtG1xdXcHlckFE2LRpE6ZPnw4TExPcu3cPTZo0wcWLF+Hl5YVr167ByMgI8+bNw4gRI6CnpwfgR6h58eLFEAgEYheHkoQlS5YgJCQE9+7dw+HDhzFnzhx8+fIFY8aMwZw5c4oM7f/M/PnzcfDgQaxYsQKLFy8usl1xNQgAQF1dHZqamqUWBEKhEMnJyYUO6uIcy8jIKNK2srIyvn37hpycHOjo6MDQ0BB16tSBjo4OtLW1oaOjAw0NDQiFQmRmZiI1NRWJiYmIjY3Fp0+fEB0djaioKGRnZ0MoFOLZs2d49uwZeDweKlWqBCMjI1SsWBFPnz5Fjx490LNnTxgbG8PY2BiVK1eGsrKyVH+TdrUqYv+9DxD+L0qQ9OgchBmpEKTEAQDSw4KQk/wjgqPZpDO4ymrISfyKlJDrAIDML2EAgIQ7RwAAfC19qFt2APCjDkH7mvpS+SUOKioqGDFiBDZv3oyFCxf+cXVffgWYICiEmJgYODg4ICoqCtevXy+0MMuvQO4HiZ+fH65evYrbt28jIyMDBgYGsLOzw/jx42FraytW4tmpU6fg5+eH8+fPS/1h86cQF/fjw1HSCMG7d+8wevRoXLlyBX379oWXlxcMDQ0B/HjaHTp0KK5cuYKxY8fC09MTx44dw7///ou3b9/CysoKhw8fRs+ePQskjllZWSE5ORlv3rxB3bp1ZXOT/+Pp06dYvHgx+vbtixEjRuDZs2fo1asXli5dKnFYtnLlypg8eTJWr16N0aNHF/m+K64GQV5bnz59QnZ2tsQDee7PiYmJRWalq6urQ0dHJ98AXqNGjQLHcr/r6OggLi4O3bp1Q4MGDXDq1Cl8+/YNUVFRosE9KioKL1++FB378uWL6Mke+DGg5T69m5qaomXLlqLf37x5g6VLl0JbWxtHjhyBtbU1/vnnH5iYmODw4cOlrpiZk5ODAwcOYPuy9VDsvlB0PCnQB4Kkr6Lf00LvAqF3f/yNLNr/EAQJX5B4+0A+e7m/K5lYigSBQEgY0EK+kcXRo0djxYoVOHDgAEaNGiXXvv5GOJT3HVsESUlJ0NLSQmJiIjQ1NcvCr3IjIiICdnZ2SElJwdWrV2FhIbsiG7IgIiJCFAG4du0avn//DlVVVbRt2xZ2dnawt7eHpaWlRFXp0tLSULt2bTRo0ADnzp2To/e/Bw8fPkSzZs3w5MmTYisD5pKdnY21a9di3rx5qFixIjZv3pxveunYsWMYNWoUlJWVRWv8d+zYgZSUFPTq1QsTJ05EixYtirSflJQEbW1t7Nq1C0OGDJHBHf4gKysLlpaW+Pz5M1JSUmBjY4NVq1YV60tJJCUloVq1aujSpQt27twJIkJqamq+wdrDwwNJSUkYPnx4kYP627dvIRAIkJNT+Jp2Ho9X6KAtzjFtbe0ia4cQEeLj4/MN9NHR0QgLC4OPjw8EAgGUlZULTAno6OiUGMLX0dEp9v/y48eP6N+/PwIDA+Hu7o5169aJEk2lJTMzEzt37sTcuXNFuRt1xmxGppYpBDJcg8jjctCyqh72uzaXndEi6NGjB0JDQxEcHCzR59zfiiTjN4sQ5OHNmzewt7cHn89HQEDAL7G2PiEhATdu3BCJgLdv34LL5aJp06Zwc3ODnZ0drK2tiywgIw5Lly5FTEwMvLy8ZOf4b4wkEYIHDx5gxIgRCA4OxsSJEzF//nxRKDMhIQHjxo3DwYMH0b59e2hoaGDo0KHQ1NSEm5sbxo4dK1auhqamJurUqYOgoCCZCYLIyEh07twZb9++hampKfbt24du3boV+gErEAjyLWMr6elcTU0Nu3btgo+PD5KTk4sc1GfNmlVg0DY3NxcNnCkpKfD09Cx0UFdXV5d4MBAIBIiJicHjx4/zDfa5T/e5P+edKuBwODAwMEBKSgpycnLQt29f1K1bt8CAL4vluGZmZrh58ybmzZuHxYsXQ0lJSeqM+tTUVHh7e2Px4sWIj48HANja2mL9+vXQMDSH3dqbEGQLABkNqHwuB0u615OJrZJwd3dHhw4d4O/vjw4dOpRJn38LLELwP54+fQoHBwdUrFgRV65cgZGRUbn4kZWVhfv374umAYKCgiAUClGtWjXY29vD3t4e7du3l1md/fDwcNStWxfTp0/HwoULS77gL+Do0aPo168fkpKSilwHn5ycjDlz5mDDhg2ideW52fkAcP36dQwaNAhxcXEwNDTE+/fvUatWLUyYMAGDBg2SeNng0KFD8fz5czx69Eiqe0pPT0d8fDwiIyOxceNGHD16FNnZ2ahbty569+6NpKSkIgf65OTCN6zhcDiiBLm8g7WmpiZOnToFQ0NDjB8/vsATe5cuXWBvb4+NGzcW6e+MGTNw8uRJhIWFiXV/GRkZiI6OLjDQ5/3++fNnCAQC0TWKioolPtUbGBhg6NChOHXqFPz9/UsVPRGX169fo27dutDQ0ICysjL27dsHR0dHsa5NSEjAhg0bsHLlStHr1qZNG6xduxaNGzcWtTvyIAIep4Jl5vPyHvXQt1nZJCITEerVq4eaNWvi1KlTZdLn78xfGyFIzczBh9hUZOUIocjnwlxPTayM17t378LJyQk1atTApUuXik14kjVEhJcvX4pWAty4cQOpqanQ09ODra0thg0bBjs7O1SpUkUu/U+aNAmGhoaYOXOmXOz/jsTFxYHP5xeZtJR3/4GVK1diwoQJohB0RkYGJk2aBG9vbygqKiIrKws1atTApk2b4OjoKPVKgaZNm2L//v149eoVMjIyJJpPT0hIQGZmZqF2w8LC4O3tnW/QNjIygoWFRYmhd01NzSLvp2PHjqKn6Z8TcuPj40UrCYqiUqVK+PTpkygxsKhBPvf7z+WdNTU1RYN63bp1YW9vX2DAr1ChQolRhrlz5+LQoUM4duxYmYgBAFi0aBEqV66Me/fuwc3NDR07dsS0adOwaNGiInMJvn79ijVr1mDDhg2iVQktWrTAqlWrCl0W2dWyIkZN3A/tNgOl9pOIwOFwMM2hVpmJAeCHEB03bhzGjh2Ljx8/wszMrMz6/tP57QXB25hkHAyMgP+br4iIS8tXmpMDwFRXFe1r6ePf5qaoYVDwae/q1avo1q0bmjVrhrNnz5ZJBOTz58+iCICfnx8+f/4MJSUltGrVCv/99x/s7OzQqFEjuZdFvnDhAs6dO4cTJ078sRUIpRGJuTUIfh4sPn36hPHjx+PkyZPo1KkTNm/eDHNzc9H5EydOYMSIEUhISACfz8egQYMwceJEUR5KVlaWxAN53gQ5Iio0qVBDQ6PAoF2nTh1oa2tDW1sbHz58wMWLF/H161c4OTlBR0cHhw8fRkBAgNwGud69e2PVqlWYNm0aAgMDRe9loVCI2NhYVKhQAUKhsEBiXu73x48fIz09HZqamgUK7ejr64sG9byJeXm/y6LC4b59+7BgwQIsW7YMvXv3LrU9cXjz5g0OHz6M9evXw8TEBOfPn8fatWvh4eGBGzdu4MiRI/mmMiMjI7Fq1Sps3boVOTk5EAgEaNSoEVauXIkOHToUKXhevnyJxLtHMX38aOwNSUOOkCAQip9UwONyQAIBvl/aDPNW7gDKti7AgAED4OHhgS1btoiWxzJKz287ZRAZl4ZZPsG4HfYdPC6n2Ddz7vnW1StgSfd6MNH9MfidOnUK//zzD+zt7XH8+PFi11mXhpSUFNy8eVMkAnL39m7YsKFoGqBVq1Zy678wMjIyYGlpCXNzc1y9evWPSs4prUicMmUKLl68iFevXgH4MYht3boVM2bMgJKSEubNm4dWrVohISEBcXFxuHnzJg4ePCiqFVCjRg2YmZkhNTU136D+c+GYXPh8fomJcerq6pgwYQJGjBiBYcOGic5raWkVmSB3584dTJs2Dffu3UOnTp2wfPlyZGVloXnz5vjvv/+K3cmwtGRlZcHHxwf9+vUTLWeNiorCu3fvcObMGVSsWLFAAR4+n4/KlSvD2NgYSkpK8Pf3x7Rp09CkSRPRQF+pUqVS5cuIy40bN+Dg4IBBgwbl27BI3gwcOBDXr19HeHh4vtU+Dx48QL9+/fD9+3ds27YNTZo0wbJly7B3715wOBxkZ2fDwsICS5cuhYuLS4n+7tmzB0OHDkVycjLis7iiz1IOCFRM4aK8n6ULu9TFpJGD4Ofnh4CAADRo0EBmfwdxmDx5Mvbt24fIyMgy/ez83ZBk/P4tBcGRBxGYe/aFVKqWz+VgfhcLZL70x7Bhw9C7d2/s27ev1Mt68pKTk4OHDx+KIgD37t1DdnY2TExMRALA1tZW7PXd8mDJkiWYO3cunj17JvOlbOWFJCKRywGEBNTR4aBrpVRw0uJET+U+Pj6IjY1F48aN8enTJ4SHhyMjI0NUGa4olJWVUaVKFejp6YmV9Z77s5qamlgDjrW1NapWrYqDBw8W2y40NBQeHh7w8fERPS3a2toiMzMTTZs2BZ/PR1BQkPS75qWklBjCj4mJyXeNmpqaKNP+/v37+Pfffws83eeW5wV+LOGsVq0arl69Cjs7O6n8lJbXr1/D2toaTZo0waVLl0q9YZS4hIaGok6dOli3bh3GjRtX4HxSUhL69euHS5cuAQCUlJSQmZmJGjVqYNGiRejVq5fYUcUpU6bg9OnTCA8PFx17G5OMQQu34yuvAoSqegWFtJ4q2tfUx4AWpqiu/0NIp6amok2bNvj69SuCgoJKnAqSJWFhYahZsyZ27tyJoUOHllm/vxt/tCDY6P8Wq66EltpO/M196GuphS1btpS62AsRISwsTLQSwN/fX/S36tChg2g5YI0aNX6JJ/GIiAjUrl0bY8aMwapVq8rbHYkgIlGCXN6nb7/36Tj/WQVCcIp9wilgT5ADEgqQcG0b+B+DoKOjg9jYWPD5fOjr6+P169fQ1tZGr1690KhRIwgEAty6dQuXL19GSkoKuFwuKlasiGPHjqF169ZyvHNgwoQJuHjxIt6+fVvo+a9fv2L+/PnYunUrjIyMsHjxYvTv3180SMyZMwfLly/Hw4cPC32aIyLExsYWmX2f+z0pKSnfdXp6eoUm5BkbGyM9PR3du3fH2rVrMWHCBAQEBKB169Z4+fKlqHJjYaSnp0NVVRV79+4t1Q5/kvLt2ze0aNECysrKuHPnDrS1tcus78GDB8PPz69AdAAAgoKCsHjxYpw9e1aUm8Ln8zF37lx4eHhIvAW7g4MDVFVVcfr06XzHq1Spgm7dumHRspViT7V9+vQJVlZWMDQ0xM2bN+Wyz0ZRODs74/Pnz3j06NEv8dn6K/LHJhUeeRAhEzEAADptB6FDj3pSi4Fv377h+vXrIhEQEREBPp8Pa2trTJkyBfb29qKnsV+NqVOnQktLq9Ad7coCoVCIxMREqebTExISkJWVlc+epnUf6LQdJEpykgQOjw8Ojw/dju6Y6lAT49rXQP369fHhwweEhYXB09MTHh4eePLkCby8vHDy5EmoqalBX18fycnJGDJkCNauXVsmu/JZWVlh/fr1BfZZSEtLw9q1a7F8+XJwuVwsXboU7u7u+QaV+/fvY+nSpRg2bBjevn2LGzduFBjso6Oj8yUfcrlcVK5cWTTA16lTp8DAX7ly5RLDta6urli4cCGGDBlS4j4GuaioqEBHR6dMyxdnZGSga9euSElJwbVr18pUDLx9+xYHDhzA2rVrRa8bEeHGjRtYsmQJ/Pz8oKWlBQ6HAz09PYwYMQKnTp3CokWLoKenl29TLHEIDg7G8OHD8x379OkTPnz4ABsbG6gp8WFRuejy03mpXLkyzp8/j1atWmHgwIE4ceJEmW0L7+7ujk6dOuHevXto2bJlmfT5J/PbRAgi49Jgt/YmMgvZWjPr20ckBhxC1pcwCFITwFFQgoKeCTSb94BqjaILZSjxufCb1FaUU1Ac6enpCAgIEE0DPHnyBMCPGu65EYC2bdv+8uU0r127Bjs7O+zfvx8DBgyQ2k5mZqZU5WDj4+NFpYELQ0tLS6wwe+73wO88rLv3vVBblJONhNsHkPrCH8KMFChUNId2m4FQqdKoyPuqlfgQV7bMQ+XKlXHp0iW8ePECXl5eCAoKQo0aNdC+fXucOnUKHA4HO3bsQJcuXaT+G0rK27dvUbNmTVy+fBmOjo4QCATYu3cv5syZg+/fv6Nr167o0KEDkpKSCjzlf/78OZ8tZWXlYpfbGRkZwcDAQCaC9tOnT6hevTomTZoEc3NzuLm5ITs7u0QxbmlpCVtbW6xbt67UPpSEUChE//79cebMGdy8eRNWVlZy7zMvQ4YMga+vL969ewdlZWVcuHABS5Yswb1791ChQgUkJCRAW1sbs2bNwqhRo6CiooKMjAxRbf8ePXpgx44dYi1H/v79OypWrIijR4/m24L5+PHj6NOnDz59+iRV6P/8+fPo2rUrpkyZghUrVkh8vTQIhULUrl0bTZo0weHDh8ukz9+NP3LKYODOQNx9F1vovHB6+AMkPTwHJaPa4KnrgrIzkfbmLjKjXkC34zhoNOxYqM3iqmsJhUI8ffpUFAEICAhAZmYmDA0NYW9vDzs7O9jZ2Ym2av0dyM7ORoMGDaCnp4ebN28iJSVF4nKwuT8XVeddQUFB7IpxPx/T0tKSKGJTnEgEgG9nViDtzR1oNu0Kvm5lpAb7IfPzWxj8swTKJgUrUBIRIMhG0uFpaFzLDG/evEF0dDTs7OwwcuRIXL58Gbt27UKXLl2wfft26OvLr257rj8JCQmiwT0yMhLu7u6wsLAAh8NBSEhIocsJtbW1RSF7IyMjvHnzBvfu3cP69evRqlUrsarmyZo5c+Zg9erVmDBhAnbs2FFgmWBhODg4QEtLC8ePH5e7f7Nnz8bSpUtx/Phx9OzZU+795SU8PBy1atXCypUrYWRkhCVLluDZs2cwMjLCt2/foKysjOnTp2PChAmFPnD4+PjA1dUVGhoaRe6+mJfcgj4/T9tMnDgRZ8+exbt376S+l/Xr12PChAnYtm0bRowYIbUdSVi3bh2mTp2Kjx8//lafx2XFHycI3sYkw97rlkTXkFCAz3smgnKyYTTSu9i2fpPaoLq+Bj58+CBaCXDt2jXExsZCTU0Nbdu2FYmA3A/jX4Hs7GyJns5fv36NqKgoaGlpITk5udg675KWg839WVVVtewysosRiZmf3uDLvinQbj8MWs17AAAoJwufdowFT00LhgOLyJ0gIdI/PEXcyR+79k2YMAGJiYkYNGgQvn37Bi8vLwwbNqzU95hbNa+4xLyoqKh8KxM4HA74fD6EQiEEAgEqVaqE7t27o0WLFqLB38jIKN8c7sOHD9GiRQvMnTsX//33X6l8Lg25JY0NDAwgEAhEKziKY/DgwQgLC8OdO3fk6tuuXbvg6uqKlStXYurUqXLtqzCGDBmC06dPo2LFiggLC0PVqlXx+fNncDgcTJo0CVOmTCnxyT8iIgL9+/fH/fv3sWDBAsyYMaNIcb1+/XpMnz4dKSkp+SJAzZo1Q+3atbF//36p74WI4O7ujq1bt+LSpUtlkhCamJgIIyMjTJ06FfPmzZN7f78bf1wOwcHAiBKzxn+Gw+WBr1EBmV8KT8DKhQuC67K9+HRuHcLCwsDlcmFlZYXRo0fD3t4eLVq0kOkKhLwQEdLS0qQOvf+8PjuX3DrveQdtFRUVxMTEoFGjRujTp0+Rg7qWllaZZVWXhrcxybgdVvRTZtqbOwCHmy86xOErQr2BPRJu7kNO0jfwNQtZ5cHhQqVKY3iu3owZowZj7ty5WL58OVq2bAk/Pz+xyllnZmYWWzUvN4RfXNW8pk2b5vsdADZu3IhDhw6Bx+Ph9OnT6NKlS7HCJDMzE0OGDEGDBg3g4eFRot/yRFNTE56enpgwYYJY+0MAP+amb92S7EFAUq5duwY3Nze4ubmV+S6f6enpWL58Ofbu3QsAMDIygqamJqKjozF27FjMmDFD7CiUqakpbty4gfnz52POnDm4du0aDhw4UGjoPzg4GHXq1MknBlJTU/HkyRO4urqW6p44HA68vLwQHh6OXr164d69e8Umj8oCLS0tDBo0CFu3bsWsWbPk9nn9N/BbCAL/N1/FEgPCrAxQTiaEmWlIfxuI9HePoFqn+MxvITj4mK0OZwcHrFixAu3bt5comUggEBSbIFfcoP7zOuy85CZV5R20zczM0LBhwxKf2DU0NAoMFLl71Pv5+Um8i9+vSEkiMSvmHRR0jcBVyp8folippuh8oYIAP6JLT5M10Lx5c7x48QJLlizBtGnTwOPxRPPzxT3VF1c1r3bt2rCzsyswZ19U1byEhAQsWbIE69evh5aWFkaPHo0tW7agYcOGJUYp5s+fj9DQUDx69OiXEHlubm7w8PAQO1Ewd8dDaZJFxeHVq1fo2bMnbG1tsXHjxjKLbCUnJ2PLli1Ys2YNYmJiwOfzoaGhgdDQUIwYMQKzZ8+WqnQ6n8/HwoUL0b59ewwYMAANGjTA3r17C+yHEBwcjHr18u87EBQUBIFAUOJ0g7h+HD16FDY2NnB2dkZgYKDcl1iPGzcOW7ZswYkTJ9C/f3+59vUn88sLgpTMHETEpYnVNv76DqQ8vfzjFw4XqjWtoeswusTrOOoVMXnUTGSmJuHly5cSPbH/vARLZPN/dd5/HrSNjY3FCr3LsvjKnTt3sG/fPmzbtu2PEANAySJRkBIHnnrBMCtPXVd0vig4XB7uRyQjKyoKHTt2hJ+fH/bu3YuoqCikpKTka6uvry8a1K2trWVWNS8rK0u073tGRgZmzJiBqVOnIjU1FVu2bEFQUFCxJVsfPHiA5cuXY8GCBQU+/MsLRUVFGBoa4t27d7hx40aBksY/U7lyZWRlZSEuLg56enoy9SUmJgZOTk4wNTXFsWPHymQ1UGxsLDZs2ID169cjJSUFDRo0QExMDAQCAbp27QpPT0+ZlCjv0KEDnj17hiFDhsDJyQlTpkzBkiVLoKioCKFQiJCQkAJ5Enfu3IGWlpbMdnfV1NTE+fPn0bx5c3Tr1g3Xrl2T67bqdevWha2tLTZs2MAEQSn45QXBx9hUiDtRoNmsK1Rrt4IgORZprwNAJAQEhT+B54UA1LFqg+yv7/Md5/P50NTUhIaGBjQ0NEQ/16hRQ/R73vO5x7S0tKCmpiZaelPYk8fPxzgcDrKyshATE4OYmBixrympjVAoxPDhw2FhYQFra2u8evVKKjuyuEZWbdKyBCWKRMrJAngFn4o5fMX/P18MfJ1K4GloIzY2FkZGRqhfv36BwV4eVfOICMeOHcOsWbPw4cMHuLq6Yt68eaJkKQ0NDZiamiIoKKjIcroZGRkYPHgwGjVqhBkzZsjUv9KSk5ODSpUqFShpXBi59/zp0yeZCoL09HR07doVGRkZuHnzptzzoj5//ow1a9Zgy5YtEAqFaNOmDd68eYOHDx9CSUkJ9+7dQ6NGRa98kYaKFSvi3LlzWLduHWbMmIGbN2/iyJEj4HA4SE1NLSAS79y5A2tra5kuFzQzM8PZs2fRrl07DB06FIcOHZJrFMbd3R3dunXDw4cP0bRpU7n18yfzywuCrCIyyAtDQc8ECnomAAD1eraIOfIfvp5YAMNBa0p8I3IKGTxycnIQFxcn2g73d+dXeVIsLQr6VVB52IZi23D4ioWKwVwhkCsMiryew8HFgIdir8WWBbdv38bUqVMRFBQEFxcXnD17ttAnNisrKwQFBRVpZ968eQgPD8ejR49+uToYsbGxGDx4MDZv3ozjx4+jb9++RbbNKwhk9d4VCoUYNGgQnj9/jlu3bom1/bS0fPjwAStXrsTOnTuhpKQER0dHvHjxAr6+vrC1tUVUVBQWLVokczGQC5fLxaRJk9C6dWv069cPjRo1EmX+5/17CoVC3Lt3Ty4JlVZWVti/fz969eqFmjVrYv78+TLvIxcXFxeYmZlh48aN2LNnj9z6+ZP5tT4tCkGRL71iVa1tg7jLG5ETFw0FPeNi23IhRMWKFaGnpwc9PT1UqFABurq6qFChguhY7u+5c/SFLdD4+Zg0bWRlNz4+Hv369UObNm0wa9asX84/aduEJwiw7LGgwPG88NR1IUiOLXA8d6ogd+qgOCQRo6Xh9evXmDFjBs6ePYsmTZrg+vXraN++fZHtraysMG/ePOTk5BQY8AMDA7Fy5UosXLgQlpaW8nZdItLT05Gamgpra2tERERg1qxZ6N69e5FJYIaGhgBQoIZCaZg1axZOnjyJU6dOye0p8vXr11i2bBkOHjwIbW1t9O3bF8+ePcOpU6dgZ2eHPXv2YNeuXXj+/DlGjy55SrO0NG3aFI8fP8bo0aOxZs0aKCoqQkvr/4XuixcvkJiYKJP8gcLo2bMnli1bBg8PD9SoUaNU9U+Kg8fjYcyYMfD09MTKlSvLtTT878ovLwjM9dTAAcSeNsgLZf9Yoy3MLDwbP09LLJs9BfHfvuDLlx9fMTExePbsGWJiYgpsSqOoqAgDAwMYGBjA0NCw2O+amprltkzRzc0NXC4Xu3btkvua+bKk8qdELHscUGwbRf2qSPr4HMLMtHyJhVmfflS6VDQoebXArh3b4NCsLpo0aSKX9c1fvnzB/PnzsX37dpiYmODQoUPo27dviWFbKysrpKWl4dWrV/me9DIyMjBkyBA0btwY06dPl7m/pSVvlcJly5ahfv36+D/2rjueyvd/X+dw7D0TItqlokI7LWnSHkZ7a0ehNBQq7a1FgzSotPcuSoMW7RKysznO+/eH33m+5OAcjurz+XS9XudVnue+7+d+znju636P671z507MmjVLYHtpaWloaGiITa3Q398fvr6+WL9+PWxtbcUyZmk8efIEq1evxokTJ6Cjo4MpU6YgKioKgYGB6NChA65fv45u3brh48eP2L9/P1avXv3LZH6VlJRw6NAhxMXF4fHjx2jXrh2Cg4PRqlUr3L17FxISErUqxuTi4oLY2FhMmDABBgYGtSbzPWHCBHh6emLPnj1/S7pXA388IZCXlkQ9NTl8qsRnXJyTAQl5lTLHqJiLnJhrYElKg6NRuVlQXZowwcleoOgHESErKwtJSUkMUfj53+fPn+Py5ctITEwsJ6srIyNTJWng/ytOlcNHjx7B398fmzZt+leRAUA4kijXpCN+RJxE1tMLpXQIipAdfRlSdRtXmGHAgAhBuzdj68qSxahOnTpo06YN2rZtizZt2tSIJOTk5MDPzw9r1qwBh8OBr68vZs6cKXQ8Qps2bcBmsxEREVGGEHh6euL9+/eIior641wFQIncN1Di327evDnGjx+PFStWMBkwgqCjoyMWQnD58mVMmzYN06dPx5w5c2o8Xmncu3cPq1atwrlz52BkZIRFixYhIiIC27Ztg5mZGc6dO4c+ffowGwNvb2+oqKhg+vTpYp1HVWCxWMjOzsbIkSPx4sULWFhYYP369UwMQ22SExaLhR07duDDhw+ws7PDgwcP0KCB+Esmq6urY/To0dixYwcWLlz4R/4O/mT8I4SJlp1+gYMPP1UYVf79hBeoMBfS+i0goaiO4ux05Ly8AW7qV6h2nwAlc7uKB+cV40fUWeTeDkDPnj1hZ2eHgQMHVsvcRETIzMwUSBx+PpaUlAQul1umv7y8vFDEoU6dOpXqx/N4PHTs2BE5OTl/7OJQU3Rde71SkggAyWE+yI29D6V2gyCpWhc50VdRkBAL7ZGrIFOvcnO6gbocbszvhs+fP+Px48fM69GjR0hNLXFFiEoSuFwu9u/fj6VLlyItLQ3Ozs5wc3OrVuaHiYkJOnTogF27dgEoqVXQsWNHeHl5/bE7o0uXLsHa2hofP36EgYFBGUnjVatWCezTp08fyMnJ4eTJk9W+bkxMDDp27IiOHTvi9OnTYvk9EBGuXLmCVatW4ebNm2jWrBns7e1x7949hIeHo1mzZli5ciXs7OzKWAg/f/6MBg0awMvL65dbcQoKCiAvL49t27bByckJLi4u2LJlC+Tk5ODg4ICdOysXcBMH0tPT0b59exAR7t+/XytZT0+fPoWpqSmOHz/+y1Un/0T855QKc17eRPbzyyhM/gheXhbYUrKQqtMAim0GVFrLgI8Dw4zx5OZ5hIWF4c6dElN0x44dYWdnB1tbW7GkAv0MHo+H9PT0Cq0Opf/9/v17OVVBJSWlCslCTEwMNm3ahJCQEAwcOPCX1I//1aiKJAIlAYQZt0pqGRTnZ0NKyxAqne0ha9Sm8sF5xRjb0RjLBgqWN/6ZJDx+/Jgxh/NJQmmioKOjg7Nnz8LV1RUvX77EqFGjsGrVqhp9ryZMmICoqCg8efIE+fn5MDU1haKiIu7du/fHEsDDhw/D3t4eOTk5kJMrcePwJY3j4uKgp1c+zmf8+PF4+fIlHjx4UK1rJiYmwsLCAioqKrhz506Ni1DxeDycPn0aq1evRmRkJNq2bYuxY8fi1q1bCAkJgbGxMZYtW4ZRo0YJVAqcNm0ajh8/jg8fPvzyuif8hfLu3btMIaD9+/dj/PjxUFdXR1hYGDp16lTr83j79i0sLS1hYmKCixcv1oqQUOfOnSEpKYnr16+Lfex/Gv51hACoXKa2uqBiLjR56bi4eACT1vT9+3ecOXMGYWFhuHz5MgoKCtCqVSuGHLRs2fKXxwQUFxcjNTW1QmtD6X9TUlLKBeKpqKgIJA4/H9PS0vojBGyEQXXkrEVBn+JI+LjNEUqkiojw5csXPHr0SCBJ4JerNTAwgLOzM0aNGlXjmIRdu3ZhxowZ+PHjB5YtW4ZNmzbhyZMnaNasWY3GrU1s2rQJixcvRm7u/yw7fEnjgQMHYu/eveX6eHh4IDAwEJ8/fxb5erm5uejWrRvi4+Px8OFDgYRDWHC5XBw9ehTe3t548eIFunTpggkTJuD69esIDAxE3bp1sXTpUowdO7bC3xDfOrBixYrfohx58OBBODo6lnmOHz9+HMOGDUO7du3w+PFjLF++HIsXL65xSfiqcOfOHfTo0QNjxozB3r17xf5MPXr0KEaOHInnz5//a7Krqot/JSGoqpCNqCAisHhcpB2aC07BD6xatQqTJk0q80PIysrChQsXEBYWhvDwcPz48YOpF25nZ4cOHTrU+g9HVMyaNQt79uxBWFgYeDxepdYHvum7NNTV1YVyWWhqav72ex+8+Rqi4rMBthjnwSsGJ+0Dvh1xg4yMDJYsWYLp06eLvIv58OEDUyxGXV0dBgYG+Pz5s0BLQml3g7APxidPnsDMzAw7d+7E9OnTsXr16j9Oc+BneHh44ODBg/j06VOZ41u2bMGcOXPw7NmzcpkR27dvx+zZs1FQUCBSjjyPx8PQoUNx6dIl3Lp1C2ZmZtWac0FBAQIDA+Hr64t3797BxsYGkydPxqVLl5jqgu7u7pg8eXKVwjvTp09HSEgIPnz48EvKZf8MFxcXhISE4OPHj8yxuXPnIiwsDHFxcVi5ciVWrlyJbt264dChQ7VeKIhvMfL29hY7QSoqKoKhoSH69+/PuNX+q/hXEgIACI78jEUno8U2XsHtfeDF3UHr1q1x6dIltG7dGlu2bBFoNissLMSNGzcQGhqKU6dOISEhAZqamhg4cCDs7OzQo0ePWlXiEgbR0dEwNTXF6tWrhfJPFhYWIjk5uUqrQ1JSEjIyMsr0ZbFY0NTUrNLqUKdOHairq4u9Pvrhw4cxbaEH1Ow3CBQgqja4hRgo+RyLZ02Gp6cn9u7dC0NDQ3h7e2PYsGFVLthpaWlYvXo1tmzZAjU1NaxYsQLjxo2DpKQkY0koHY9Q2pKgra1dJh6hMpJQVFTEiGLVr18fd+/e/WNdBXxMnToVkZGRePz4cZnjhYWFaNasGZo0aYLw8PAy58LCwmBnZ4ekpCSRgmMXLlyI9evX49SpU+jfv7/Ic83JyYG/vz/WrVuHb9++YciQIZg6dSrOnz+Pbdu2QVZWFi4uLnB2dhYqGO/Lly9o0KABli1b9ttiPGxsbCApKYkzZ84wx8zNzdGoUSMcOnQIAHDjxg2MGTMGhYWFOHDgAPr161erc1q2bBmWL1+OY8eOYejQoWIde+XKlfDx8cHXr1+FKgv9b8W/lhAAwNbrcVh3KbbG4yzs3RiDm8jDwcEB165dg6OjI6KjoxEVFYUxY8ZgzZo1FTJkHo+HiIgIhIaGIjQ0FHFxcVBQUICNjQ3s7OzQt2/fCqOmawtEBCsrKyQkJCA6Olrsfrn8/Hx8//69UuLA/39WVlaZvhISEtDS0hIqYFJNTa3SRTcvL4+xgtjb26PH5KVYdq7m3wc+cq/vhsvQzoxIy4sXL+Dq6oqzZ8/CwsIC69atE0gYCwoKsHXrVqxatQqFhYVwcXHBvHnzqvQT/0wS+EShNEkQFLjIYrGgq6uLxMRExMTE1HoBGXFgyJAhyMnJwYULF8qdO3bsGIYPH86k5vEREREBCwsLPH36FK1atRLqOjt37sS0adOwefNmODs7izTHzMxMbNu2DRs2bEB6ejrGjBmD6dOnIzw8HBs3bgSLxcK8efMwd+5ckX7jM2bMQHBwMD5+/PhbrAMAoKenB0dHR6xevRpAiUtFWVkZmzdvLqOHkJKSgrFjx+Ls2bOYN28evL29a7XA25gxYxAaGoqbN2+KNfUxMTER9erVg4+PD+bNmye2cf9p+FcTAqDEUuB5+gW4PBIppkCCzYIkm4UVA5tjRLuSVEQejwdfX18sWbIE5ubmGDhwIPz8/JCfn48lS5Zgzpw5lf4YiAivXr1iyAG/kEz37t2ZjAVBFcfEjeDgYIwaNQoXL15E7969a/16lSE3N7fKQEn+v6X9yQDA4XCgpaUl0NpQXFyMrVu34tu3b1i7di2mT58ONpstNpI4v2dDzOrZGHv27ClX9e369etYsGABoqKiYGtrCx8fHzRu3Bg8Hg9Hjx6Fm5sbvnz5gkmTJsHT05MR1akOBJGEx48fM2l72traMDIywv3796GgoIDXr1+L5G74XejatSv09fWZ3WhpEBEsLS3B4/HKSBp//foV9YwaYufhE2hn0R5SkmwYqstDXlqwNeTChQvo378/pk+fjs2bNws9N35p661bt6KgoADjx4/H9OnTcfr0aaxduxYFBQWYOXMmXFxcoKGhIdJ9f/36FcbGxli6dCnc3d1F6isupKenQ01NDUeOHMGoUaMAlFgDrKys8OzZM7Rs2bJMeyLCpk2b4OLigpYtWyI4OLhW0gSBks1Gjx498O7dOzx8+LDSGh2iwt7eHvfv30dsbOxvd3H+LvzrCQFQElPgFhqN229TqiyNzD/fuYEGVtuZQF9Nrlybe/fuYfTo0cjIyMCmTZsQFRWFbdu2wdjYGBs3bixXMazCeX35grCwMISFheHmzZvg8XiwtLRk4g4aNmxY7XuuCNnZ2WjcuDEsLCxqlJ71O5CdnS2U1SE+Pr5cmqa0tDRDGAr02iDdqBfAlgBLhJgC4hVDRoqDFQObo6eRPDQ0NHDy5EnY2ZVPVeXxeAgODoabmxu+fv2Kfv364fPnz3j69CkGDhwIHx+fWtupExG+fv2KR48e4cGDB9i6dSvy8/OZ7BO+JaF0hsOfRhKaNWsGa2trbNiwQeD5mzdvolu3bggODoZZt744/PAzrr1JwqfU3DL3wQJQT00OVo21MMaiHhpql+y4nz9/jk6dOqFr164ICwsTagH4+vUr/Pz8sHv3brBYLEydOhUzZszAqVOn4O3tjfT0dEyZMgVubm7VJvbOzs44fPgwPn78+Nuen7du3ULXrl0RHR3NxGmsWrUKa9asQVpaWoXv1ePHjzFy5EgkJiZi586dGDNmTK3MLzk5GRYWFpCTk2MKLYkDDx8+hKWlJcLDw2vd/fGn4j9BCPiIS8rC4YefcT32Oz6n5pYRqyEiGGrIw6qRFuwt66GBVuWmuvT0dEyaNAknTpzA1KlTMX78eLi4uODGjRsYMGAANmzYAGNjY6HnlpqaivDwcISFheHixYvIy8tD8+bNGXJgZmYmlgf24sWLsXHjRrx69QqGhoY1Hu9PQl5eHmbPng1/f38MHz4crq6uZUjE169fce7cOcTExEC5rhGUekwBW7c5iFdcKTFgEQ/EYiP/41O05cXCfc5U5ObmomfPnrhx4wa6du1aYd8nT55gzJgxePXqFdhsNsaNG4fNmzczqXS1jfnz52Pbtm04ffo0rK2t4eHhASISaEn4OXBRV1f3t5EELS0tzJ49u9JdsvXg0XijbAbUaSoS0Z/dQQt2vbtAU1MTt27dqtJV8+7dO/j6+uLAgQOQl5fHrFmzMG3aNJw6dQorV65EYmIixo4diyVLltRoxxofHw8jIyMsWbIEHh4e1R6npti2bRvmzp2LnJwcJguib9++4PF4Al04pZGVlYXp06fj0KFDGDt2LLZs2VIrKZOvXr1C+/btmQVcXHoR5ubmUFdXr/I+/60Qaf0mIZCZmUkAKDMzU5jmvw3Z+UUUE59BUZ/SaFfIWWJxZOj9+/cijcHj8WjHjh0kIyNDLVq0oJiYGDp69Cjp6emRtLQ0ubu7U3Z2tshzy8nJodDQUHJ0dCRVVVUCQPr6+uTs7EzXrl2joqIikcckInrz5g1xOBxavnx5tfr/yXj16hWZmJiQjIwM7d27l3g8XpnzT548oRYtWpCUlBT5+flRcXExERG9Scgk15BH1H7VBTJYFF725XqGGsw9RI1GuZNOE1NisViEEtFD5iUnJ0cNGjSgjh070pAhQ2j69Om0YsUKWrNmDfXu3ZtYLBbp6enR9u3bac6cOcThcKhu3bq0d+9e4nK5tfqe3Llzh1gsFq1Zs4Z4PB6pq6vTsmXLmPM8Ho8+f/5MoaGh5OHhQX369CFNTU3m3rS0tKhv3760ZMkSCgsLoy9fvpR7X2sDxcXFxGazadeuXRW2CYr4RA3dz1K9hWHlP7dKXkaLw8lgYSjpdR1OX79+rXQeMTExNGbMGGKz2aSlpUU+Pj6UlpZGAQEBZGRkRCwWi0aNGkVv3rwRy307OzuTiooKZWRkiGW86mLKlClkYmLC/F1cXEwqKiq0YsUKoccICAggeXl5aty4MT158qQWZkl05coVkpSUpGnTpontexkQEEAA6PXr12IZ758GUdbvfxUhKI34+HgCQKGhodXq//z5c2ratCnJysqSv78/ZWVlkbu7O0lJSZGenh4FBwdX+wtbWFhIV69epZkzZ5Kenh4BIDU1NXJycqKwsDDKyckRahwej0fW1tZkaGhIubm51ZrLn4pDhw6RvLw8NWnShJ4/f17mHJfLJR8fH+JwONSqVaty50uDTxKXbtpHUtpG9CO3oMz5tLQ0UlVVpWHDhtHq1asJAHl4eNDChQvJwcGBevfuTS1atCB5eflyxAEAKSsrk5GREbPoqqurk5OTE/n7+1N4eDhFRkbSly9fqKCgoIIZCo+cnBxq2LAhWVpaMsTDxsaG+vbtW2m/n0mCjY1NOZJgY2NTqyQhJSWFANCJEycEnt9yLVYkEvDzq57rGTJYFE5brsUKHD8yMpJsbW0ZIr5lyxbKzs6mkJAQatKkCQEgW1vbSr9LoiI+Pp6kpaVFWnRrCx06dKDRo0czf0dHRxMAunr1qkjjvH79mlq3bk1SUlK0ZcuWWiGT/v7+BIA2btwolvHy8vJIU1OTZs2aJZbx/mn4Swio5CGooaFRo51zTk4OTZo0iQDQiBEjKCMjg96+fUsDBw4kANStW7caP0B4PB5FRkaSm5sbNWvWjNmh2tnZUWBgIKWmplbYNywsjABQWFhYjebwJyE3N5d5z+3t7SkrK6vM+ffv31OnTp2IxWKRq6sr5efnCzVuSEgIAaD09PRy59atW0cSEhK0bt06AsAQsqKiItqxYwdpa2uTtLQ0LViwgN68eUNPnz6lCxcuUEBAAPn6+tK8efNo9OjR1K5dO5KTkxNIHPikr2nTpmRlZUUjR46kOXPmkLe3N+3fv5/OnTtHUVFR9O3btwqtRXPnziVpaWl69eoVc8zT05M0NDREfjALIglaWlrlSIKHh4dYSMKrV68IAN26davcuaCITzUiAz+/giM+Mfd448YN6t27NwGghg0b0t69eyk/P5/Cw8OpdevWBICsra0pIiKi2vdWEWbPnv1HWAd4PB4pKSmRt7c3c2znzp0kISFRLWtnfn4+zZo1iwDQoEGDKCUlRZzTJSIiFxcXYrFYdPr0abGM5+bmRoqKivTjxw+xjPdPwl9C8P/o0aMHDR48uMbjBAcHk5KSEtWvX58ePnxIRETnz5+nRo0akYSEBDk7O1NaWlqNr0NU4gLw8fEhS0tLAkASEhLUo0cP2rJlC3358oVpl5ubS4aGhtSnT59fYvL9FXj9+nWFLgIej0f79u0jBQUFMjQ0FLiwVIbLly8TAIEupLy8PNLT0yNTU1OSlpam4uJiOnXqFLNztLe3p48fPwp1HR6PR2FhYdSoUSMCQP369aOAgADat28feXt70+zZs2nkyJHUrVs3atq0KeM+Kv1isVikqalJLVq0oJ49e9KYMWNo5MiRBIBGjRpFFy9epGfPnlFiYiKdPn26wvsSFTwej758+SIUSQgNDRWJJNy+fZsA0MuXL8sc/5yaQ408zpH+vGOk3HEUydQ3I7aMQom1pe8cgQt+3Yk7SKa+GbE4MsSWUSD55lakN+swc76RxzkKPHGWOnbsSACoZcuWFBwcTFwul65evUrt27cnANSlSxeRv0fC4tu3byQjI1PGnfO78PHjRwJA4eHhzDEHBwdq06ZNjcY9deoUqampkZ6entjfx+LiYho8eDDJy8uLxT3x5csXkpCQoK1bt9Z8cv8w/CUE/4+5c+eSsbGxWMZ69+4dmZubk6SkJK1Zs4aKi4upoKCAfH19SUFBgTQ0NMjf31+sPuT4+HjasWMH9e7dmyQlJQkAtWvXjlatWkUzZswgDocjNl/n78bhw4crdBEkJSXRoEGDCACNHz++Wt/DyMhIAkBRUVECz+/du5dxAXTp0oUAUPfu3enx48fVup/CwkLavn07aWlpkYyMDC1atKjCnWJ+fj59/vyZIiIi6MyZM+Tv709eXl40c+ZMGjZsGHXs2JE4HA5JSEiUIw9sNpsAkIGBAfXu3ZscHR3JxcWF/Pz86PDhw3TlyhWKiYmh5ORkJsZCFPBJQlhYmFAk4fPnzwJJwsmTJwkAJScnlzluv+cBGbmdJd2pJe+/hJImSdczqZAQ6E4/QGxZJZJU0SHVnpNJpYsjsWUUiKNVn+otDC1p53KKtEasIAsLCzp9+jTxeDy6d+8ede/enfkNXbx4sVaJ9Jw5c0hZWVmgRepXIzw8nADQp0+fmGNGRkZiMaF/+fKFunTpQmw2m1asWCHW519OTg61bduWdHV1q4wNEQZDhw6lJk2a/Gs2UMLiLyH4fxw4cIAAiM1MVFBQQC4uLoyZMTExkYhKFm57e3sCQG3atKH79++L5XqlkZ6eTocPH6ahQ4cyZmk1NTVydXWlBw8eVOth/yegKhfB6dOnSUtLizQ0NKodD0JE9Pbt20p9pm/evCEpKSkCQC1atKBz586J5cHx48cPWrJkCcnKypKGhgZt3rxZ5HiC2bNnk4yMDL1584Zyc3Ppw4cP9ODBAwoLC6Ndu3aRiooKtWrVigYPHkwdO3YkY2NjgTEPkpKSVLduXTIzMyMbGxsaN24cLVq0iDZu3EhBQUF0/fp1evnyJaWlpVV676VJwpIlS8qRBE1NzXIkYdeuXcRiscosGLGJP/4XA7AglPRmHiSDReFUx2lDhYRAwbQvsSSlSXfaPuaY1kivkt9Dn5ll2sYm/qCoqCjq168fASATExMKCwur9QUhISGBZGRkyNPTs1avIyy8vb1JWVmZue+EhAQCQEePHhXL+Fwul5YtW0ZsNpu6desmlsWbj2/fvjHWu5+fDaLixo0bBIAuX74sptn9M/CXEPw/njx5QgDo7t27Yh33woULpKWlRdra2mW+XHfu3GH8kk5OTpSQkCDW6/IxYMAAUlNTIwcHB9LQ0CAAVLduXZo2bRpdunRJLAFsvwKvX7+mli1bkoyMDO3Zs6fMgzorK4shCv3792fIV3WRmppKAOj48eNljqekpDCZAnxCcPHixRpdSxDi4+NpwoQJxGazqUGDBnTs2DGhFqZbt24Ri8UiPz+/CtuMGDGCOnXqVO54VlYWvX37lu7evUsnTpyg7du309KlS2nKlCk0aNAgsrS0JENDQ5KRkSlHHqSkpEhfX5/atm1L/fv3p4kTJ5K7uztt2bKFQkJC6NatW/TmzRvKzMwkHo9XjiT07du3DEmQl5cnDodThiQsPRVNRm5nyy36lRECtpwKyTXpVO64pJouyRi0Yv6uvzic2k1dw8QOBAUF/TLSPHfuXFJSUhKbG7GmGD16NHXs2JH5+/jx4wRArAs3UcmCq6urS+rq6nTmzBmxjfv06VNSUFCggQMH1sgCwePxyMTEhAYOHCi2uf0T8JcQ/D/y8/NJUlKStm/fLvaxExISqGfPnsRisWjx4sVUWFhIRCVseefOnaSmpkaKiork5+fHnBMHLly4QAAoODiYud7Nmzdpzpw5ZGBgwJi9x4wZQ8eOHasxq64t8F0EjRs3LuciuHv3LhkZGZG8vDzt3r1bLDs6LpdLAGjPnj1EVBI34OvrS8rKyqSgoEBeXl5kbW1Nqqqq1LZt21rbRT5//pxsbGwIALVv375SspqdnU3GxsbUsWPHSh+Efn5+JCsrW+3UVR6PR5mZmRQbG0u3bt2iY8eO0ZYtW8jd3Z0mTpxI/fv3p3bt2pG+vj5Dmkq/ZGRkyNDQkCwsLGjQoEE0efJkWrp0KW3dupV2795N3t7e1KpVK5KTkyNtbW2mn/70vQJjBCoiBLozSix+Kt3Glusj39yK2DKKZTMPZuyjvXv3Vvt9qQ4SExNJVlaWlixZ8suuWRVMTExo6tSpzN9z584lAwODWrlWcnIy9e/fnwDQnDlzhA76rQpnz54lNptN8+fPr9E4u3fvJhaLRR8+fBDLvP4J+EsISsHExISmTJlSK2MXFxeTt7c3SUhIkKWlZZkvWWpqKk2fPp3YbDY1adKELl26VOPrFRQUUKNGjahbt24CFywej0dPnjyhpUuXUsuWLQkASUtL04ABA2jv3r30/fv3Gs+hpijtIhgzZkwZwlJQUEBubm7EZrOpffv2FBcXJ9ZrKykpka+vLx08eJDq1atHEhISNH36dEpKSiKiktQsa2trAkDHjh0T67V/xpUrVxhr0uDBgyk2tny63KxZsxhXQWXgB+w9ffq0tqbLgMfjUVpaGr169YquX79OwcHBtHHjRlq8eDGNGzeO+vbtS2ZmZqSrq8vEvZR+ycvLk4GBATVu0YoM/j9VUFhCwBzvP69cHyWLwQSA6i0IZY4ZLgqn7PxfRwaIiObPn09KSkqVZgf9ShQWFhKHw6Ft27Yxx8zNzcukIIobPB6PNm3aRFJSUmRmZibwu10dbNmyhQDQzp07qz1GdnY2qaio0MKFC8Uyp38C/hKCUrC3t6f27dvX6jXu3btHBgYGpKysXG4hefLkCXXu3JkAkJ2dXY2Yqa+vL0lISFB0dLRQ7d++fUt+fn5Mmh6bzaYuXbrQhg0bfgtDrsxF8OLFCzI1NSVJSUlatWpVrezq+G4e/mfxs1BJ06ZNae7cudSnTx9q1KhRre8si4uLKTAwkPT19UlSUpJmzpzJkLabN28SAFq/fn2V42RnZ5OEhATt3r27VucrKoqLiyklJYViYmKoXbt21LZtW/Lz8yMXFxcaPH5WhWmDFREC7TE+BIA0BrmW66PcoSQLQ39OcJnjMfG/LuWPbx3w8PD4ZdesCny9gZs3bxJRSaCepKRkGYJQW4iKiqKGDRuSgoICHTx4UCxjOjs7k4SERI02WPPnzydVVVWh9V7+6RBl/RZvTdo/EC1btsTz588ZzffaQPv27fH06VP06tULw4YNw9SpU5GXlwcAaN26NW7evIkjR47g4cOHaNq0KZYtW8acFxbx8fFYsWIFZs6cWa5mfEUwNjbGvHnzcPv2bSQkJGDXrl1QUFCAq6sr6tevDzMzM6xYsQLR0dGgqhWsa4SgoCC0bdsWBQUFiIiIwIQJE8BiscDj8bBp0yaYmZkhPz8fDx8+hJubm1hL+cbExKBv3774/v07AOD27ds4efIkGjduXKZdWloa1NTUsHr1asTGxmL//v1im4MgsNlsODg44M2bN/Dy8kJgYCCMjY2xbNkyODk5oWPHjpg1a1aV48jLy6NFixaIiIio1fmKCjabDXV1dTRv3hw8Hg9mZmaYN28efH194eG5TOTxWJLSAAAqLip3jooLy7Tho5Bbe7/7n7Fu3TpISkpi7ty5v+yaVSE6uqRcvImJCQAgMjISXC4XHTt2rPVrm5qa4vHjxxg8eDAcHBzg5OSE7OzsGo25fv16WFtbY+jQoXjx4kW1xpg+fToyMjJw5MiRGs3l34h/PSFo1aoVcnJy8P79+1q9joqKCkJCQrBr1y4EBATA3Nyc+cKyWCyMGjUKb968wZw5c7B69Wo0bdoUJ06cEHohXrhwIeTl5bFs2bJqzU9bWxsTJ07E2bNnkZKSgqNHj6Jx48ZYt24dWrZsiYYNG2LBggW4e/cuiouLq3UNQcjLy8OUKVMwevRoDBo0CI8ePWIeTl++fEHv3r0xZ84cTJ06FY8fP4aZmZnYrh0fH48JEyagVatWiI2NRbNmzWBlZSWwfDERMYTA1NQUo0aNqhZxqw5kZWXh6uqKd+/eYfz48Vi5ciU+ffqEAQMGCD2Gubn5H0cISiMlJaVMlUApSdEfPRIKJTXti7PTyp0rzk4HW0YRLElOmePVuU518P37d2zfvh2zZs2CmpraL7mmMIiOjoauri5UVUveu7t370JJSUnoTUVNoaioiICAAAQGBuLEiRNo06YNnjx5Uu3xJCUlERwcDAMDA/Tr1w9JSUkij2FkZIR+/fph69attb4R+qfhP0EIAODZs2e1fi0Wi4XJkycjMjISPB4P7dq1w549e5gvnYKCAry9vfHixQs0b94cQ4cORa9evfDy5ctKx7158yaCgoLg6+sLFRWVGs9TUVERw4cPR1BQEJKTk3H+/Hn06NEDhw4dQqdOnVC3bl1MnjwZ586dQ0FBQbWv8+bNG1haWiIwMBB79uzBwYMHmaIoR44cgYmJCV6/fo3Lly9j48aNkJWVrfG9ASXFPDw8PNCwYUOcOnUKGzduxMuXL9G4cWNkZGQI7JOTk4OioiLmYb5ixQp8//4dW7ZsEcuchIGGhgbs7OzA4/HQsmVLLFq0CG3atMGlS5eq7Gtubo6YmBjk5OT8gpmKjuTk5DKEgH58ByDaw1hSUQNsOWUUJr4td64gIRZS2vXLHiTCpROHa91CCAB+fn5gs9l/lHUAKCEEfAIOlBACS0vLX14K2MHBAVFRUZCXl4elpSU2b95c7cVYUVER4eHhKCgogK2tbbVIu7OzM549e4Y7d+5Uaw7/VvzrCYG2tja0tbV/CSHgo0WLFoiMjIS9vT0mTZqEkSNHIjMzkznfsGFDnD17FmfOnMHHjx/RsmVLzJ07t0wbPrhcLmbOnAlLS0s4OjqKfa7S0tLo06cPdu3ahW/fvuHu3btwcnLC9evX0a9fP2hqamLkyJEIDg7Gjx8/hB6X7yLguwH4LoK0tDSMHDkSY8aMQd++fREdHY2ePXuK5V6Kioqwfft2NGjQAH5+fpg9ezbevXsHZ2dnSElJQVVVFenp6QL78o/zd1INGjTA5MmTmRK4vwLZ2dkYP348OnfujKioKNy/fx8KCgqwtraGtbU1nj9/XmFfc3Nz8Hg8REVF/ZK5ioLc3Fzk5uYiISEBs2fPRqNGjWDStBG46YkijyXXuAPy3kaC+yOZOZb38Sm4afGQa1LW8iORlw7X+XPQqlUrqKmpoV+/fvDx8cGdO3dqRHR/RnJyMrZu3QpnZ2eoq6uLbVxxoDQh4PF4uHfv3i9xFwhCo0aNcP/+fUyfPh2zZ8/GoEGDkJqaWq2x6tWrh9OnT+PZs2cYN26cyISvZ8+eaNy48S8l/P8IiDso4U9E7969f1vu6dGjR0lJSYkMDQ3pwYMH5c7n5+fT6tWrSU5OjrS0tGjfvn1l8qU3bdpELBaLHj169CunTTwej6Kjo2nlypVkZmbG5Kbb2NjQrl27KtQFyM3NpcmTJxMAGj16dBlRqEuXLlHdunVJRUWFgoKCxDrXkydPUqNGjYjFYpGTkxN9/vy5XLv58+dTo0aNBI7x9OlTAlBG0z4hIYHk5ORo0aJFYptrZZgxYwbJysqWya7g31vDhg2JxWLR2LFjy0hY81FUVERycnK0bt26XzJXYRAXF0ebN2+mbt26/S/VUF+fJk+eTKGhobT4eFQZHQLVXlNIubM9KZj2JQAk16gDKXe2J+XO9qQ/5+j/KxXuL6VUOIVUuv6/UqGmYZkMAyO3s+R5KoZycnLo+vXrtHLlSurduzcpKCgw2TedO3emxYsX07lz52pUb8DV1ZUUFBTKqTD+bvCf24GBgURUUukRAF25cuU3z6xEcExdXZ10dXWZgMfq4MSJE8RisaoVyLllyxaSkJAQux7Dn4a/WQY/YeHChWRoaPjbrv/+/XtG9tjX11egQMqXL18YvXoLCwuKiIigpKQkUlZWrrW0SVHw6dMn2rRpE3Xr1o3YbDaxWCzq0KEDrV27lt6+fUtEJWp//CwCf39/JosgJyeHnJ2dCQD16tVL4IJWXdy7d4/RrO/Vq1eluucrV64kLS0tgeeuXbtGAJh74cPd3Z1kZWUpPj5ebHOu7PqbNm0SeL6wsJC2bt1KmpqaJCsrS25ubuV+j507d6bhw4fX6jwrQ25uLp07d46cnZ2pQYMGBIA4HA61a9eOUcYrnVlSWqnQYFE4SSj9T8jo55fu1P9pFuhM2EYy9U2JxZEmtrQ8yTfvRnrOB8tlHsQllVcoLSoqosePH9PGjRtpyJAhjHgSi8WiVq1a0cyZM+no0aNCf97JyckkLy//y0ijKLh79y4BYH4Tu3btIgkJiT9Gm+Tr16/UtWtXYrPZtGzZsmqLDq1ZUyJAFRAQIFK/zMxMUlBQ+KOyQmoDfwnBTzh48CAB+K1VxwoLCxnZ4969e1e4w75x4waZmJgQi8WiRo0akYqKSq1UE6sJkpOTaf/+/TRo0CBG5U5PT4+kpKTIwMCgTD58ZGQkNWnShGRkZGjz5s1iU4uLi4ujoUOHElBSvEYYdcGtW7cSh8MRqOHAV2/7WV0uIyOD1NTUapWUZWVlkaGhIXXp0qXK9yczM5Pc3NxIRkaGNDU1aevWrYzw1fz583858Y2NjaVNmzZRnz59mO9CvXr1aMqUKRQWFkY/fvxgxLQEFYji1zIQZ7VDI7ezZL+nvDVOEHg8HsXGxtLevXtp3LhxDJEBQEZGRkwp69evXwv83ixatIjk5eX/OOsA0f8qGvLFgRwdHcnMzOw3z6osuFwuLV++nEmJrs5mgcfj0cSJE4nD4dCNGzdE6jtz5kzS0tISm4DSn4i/hOAnPH/+nADBpVd/NS5evMjkw1eUS1tUVEQLFiwgACQrK0sbN278pWproiA5OZkpL8vhcAgoKbTj7OxM48aNIwkJCWrTpk25Knc1uZ6zszNJSkqSnp4eHThwQOidxeHDhwmAwJKv/v7+xGKxBC7I/PLItVVIavr06SQnJ1fOOlEZvnz5QmPHjiUWi0UNGzakEydOUHBwMAFghJZqAzk5OXT27FmaOXMmGRsbM66kHj160Lp16+jFixflFs5Dhw4RAIF5359SsqmBW3iFIkXVeTXyOEefU6ufY/7t2zc6duwYzZo1i0xNTZkCUpqammRnZ0fr16+niIgISkxMJAUFBXJxcan2tWoTM2bMoKZNmzJ/Gxsbk7Oz82+cUcW4efMm6enpkZqaWrVKHhcWFlL37t1JVVVVpN8pvyy3uHQS/kT81SH4CU2aNIGUlNQvDSysCL1798azZ8/QsmVLWFtbY/HixSgqKptXzWKxcP36dZiYmMDe3h5z585F69atcf369d80a8GIjY1Fz549cevWLfj7+yM7OxuXL19Gp06dsHPnTuzfvx9SUlJo0aIF4uLiapTCl5eXBx8fHxgbG+PAgQNYsWIFYmNj4eTkJHTEND9gUFCmQVpaGlRUVMBml/9JzJgxAzo6OliyZEm1518Rrl27hu3btzP3Jiz09PSwf/9+PH36FEZGRhgyZAjWrVsHoCTXXFwgIsTGxmLTpk3o06cP1NXV0a9fP5w5cwa9evXCqVOnkJqaiitXrmD+/Plo1qwZWCxWmTGSk5MhKysLOTm5Msfv3LkDh8F9kRi+GfipT02wYmBz6KvJVd2wAujo6GDo0KHYtGkToqKikJ6ejgsXLmDy5MlIS0uDm5sbzM3Noa+vj9zcXAAlnyP//38KSgcUJiUl4d27d78toLAqdOnSBU+fPkWnTp0wcOBAzJ49W6TATw6Hg+PHj0NbWxv9+/cXOlixSZMm6NWr19/gQj7EzTD+VLRu3ZomTpz4u6fBoLi4mHx8fATKHu/evZsA0J07d4iI6PHjx9ShQwcCQMOGDStTxvR34ciRI6SgoECNGjWiZ8+eEVGJ6W7nzp0kJydHxsbGtGfPHlq8eDE1adKEka0dMmQIHTx4UOjCL1wulw4cOEB6enokKSlJzs7O1ZZgvnfvHgEQqPTo6upaaalsfnlkcQZ38l0FXbt2rbEr5dKlS9SqVSsCQE2bNq2R7HNOTg6Fh4fTjBkzyMjIiLEC9OzZk/z8/Ojly5ci1Xpwd3enevXqMX9HRkZSnz59CAC1atWKzpw5Q5uvxtbMMvD/FgafM0+qfd/CIj8/n86dO0dSUlJkbGxMqqqqBJRUk7SwsKD58+dTWFjYb3Uj8Hg8UlVVpZUrVxJRSfAdALHG79QGeDwebdmyhaSkpMjU1FRkq9zbt29JQ0ODunTpInSRt9OnTxMAevjwYXWm/Mfjr8tAAJycnKhdu3a/exrlUFr2OCQkhFJTU0ldXZ0cHR3LtOPxeBQYGEh16tQhWVlZWrlyJeXl5f3y+ebm5tKUKVMIAI0aNYrJIkhISKC+fUuiw6dMmVIucOnVq1fk7e1N5ubmzMOzZ8+etG3btgqjfEsvckOHDq2xJjrfPCjIdTRp0qRKvx9FRUXUtGlT6tWrV43mUBrTpk0jOTk5evfunVjG43K51KpVK5KRkSEOh0OzZs0SalHi8Xj0+vVr2rBhA/Xu3ZukpaUJABkaGtK0adPo9OnTNQpEmzx5MpmZmVF0dDTZ2dkRAGrSpAmFhISUIUJBEZ+okcc5kWMKjNzOUkP3s1S381CysLCg3Nzcas9VWLi7u5OcnBwlJSVRcXExRUdH0/bt22nUqFGkp6fHxCE0bdqUJk+eTIGBgfThw4daL73Mx9evXwkAhYWFERHRvHnzaq2gUW3gyZMn1KhRI5KXlxc5WPDOnTskJSVFTk5OQr3fXC6X6tevTw4ODtWd7h+Nv4RAANavX0+ysrI1Kp9ZW0hPT6dhw4YRAGrWrBkpKChUWDo5MzOTFixYQJKSklS/fv1fUt+djzdv3jALTukqhCdOnCB1dXXS1tam8PDwKsf5+vUrbdu2jXr27MkUwDE3Nydvb2969eoVPX36lIlL6NChA927d08s809MTCQAdOrUqXLnhg4dSr179660/8mTJ8WWtnX16lUCQFu2bKnxWKWxfPlyUlVVpVWrVpGioiIpKSmRj49PuUUyOzubzpw5Q9OnT6f69eszVoBevXrR+vXr6dWrV2L7XvXu3Zt0dHSIxWJR/fr1KSAgoMLf4efUHLLf86BkoV9cNREwWBRO9nse0OfUHIqMjCQ5OTkaPHhwrZY6Tk1NJUVFRVqwYEGFbT5+/EgHDx6kKVOmULNmzRiCoKenRyNHjqRt27bR8+fPa22e58+fJwAM2bSwsKjVgka1gaysLHJyciIA5ODgUCaFuSrw44VWrVolVPu1a9eSlJRUrcbf/C78JQQCcOXKFQJQrqDNnwIej0ceHh4EgOrUqUMxMTGVtn/16hWzaFpbW9f6fQUFBZVzEWRkZDA/WDs7u2qZ8tPS0ujgwYM0ZMgQJkodAKmqqpKvr69YCVx+fn6F6Undu3enkSNHVtqfx+ORhYVFjcsj//jxgwwMDKhbt25iXxD4C0FcXBx9//6dZs6cyQRg+vj4kJ+fH/Xq1YuxAtSvX5+mT59OZ86cERhsWRN8+vSJJkyYwATH7ty5U2gzbmziD3LaHE51J+8uRwQMF4VTl7XXyPNUTLnUwlOnThGLxapxmdzKsGTJEpKVla0wU0gQkpOT6dSpU7RgwQKytLRkiLCKigr169ePfHx86M6dO2KLdl+zZg3Jy8tTcXEx5ebmlqt4+E/CwYMHSUFBgRo2bEiPHz8Wut/y5cuZdNeqkJqaylhe/234SwgEIDk5Wegvx+8Aj8ejjh07kpGRETVr1oxkZWXL7MIr6hMWFkb169cnSUlJWrBggdg/o7y8PJo6dWo5F8GNGzfIwMCAFBUV6cCBAzVaIDMyMmjx4sUkIyNDysrKZGlpSWpqaiX557q6NGPGDLp8+TKTXlcT8LM2fkbr1q1p+vTpVfa/fv06ATUrjzx16lSSl5en9+/fV3uMipCSkkIA6PDhw5SdnU2nT5+mUaNGkZycHJNv37ZtW9q4cSO9efOmVqxLCQkJ5OzsTFJSUqSpqUlaWlo0c+ZMkcfx8vIiZWVlysorpJj4DIr6lEYx8RlVljTevHkzAaCtW7dW9xYqRFpaGikpKdG8efNqNE5OTg5du3aNVqxYQb169SJ5eXkCQDIyMtSlSxdyc3Oj8+fPV/v37ODgQBYWFkT0v8qZv6I8dm0hNjaWzMzMiMPh0MaNG4X63vJ4PLK3tydpaWm6f/9+le0nTZpEurq6YnnO/En4SwgqQN26dcnNze13T0Mg+FoJV69epZycHEbtb9iwYZSenl5p39zcXFqxYgXJyspSnTp1KDAwUCwPer6LQFpamiEn+fn5tHDhQmKxWNSlS5calVEuKCigzZs3k4aGBsnKypK7uzvzHSsqKqIbN27Q7NmzqV69esxuyt7enk6cOFHt3WzdunXJ09Oz3PF69eoJLVBSk/LIly9fJgC1slvj8Xj08uVLUldXJ319fZKSkmLy6WfMmEFr165lYjj69OlDz58/F+v1U1JSyMXFhWRlZUlFRYVWrVpFWVlZpKGhQV5eXiKPN3jwYLKysqrWXObMmUNsNpvOnDlTrf4VYenSpSQrK1uhS6+6KCoqokePHtGGDRto8ODBjGASm82m1q1bk7OzM4WEhNC3b9+EGq90EPXq1atJSUnpj3SXioL8/HyaO3cuAaD+/fsLFR+Tn59PnTp1Ik1NzSoJ+LNnzwgAhYSEiGvKfwT+EoIKYGNjQ/369fvd0yiHzMxMqlOnTjmVuZCQEEb2WBiG++nTJyYWoUOHDiKZ135GaRcBf2fx7NkzMjExISkpKVq7dm21HzA8Ho+OHTtGDRo0IBaLRePHj680+pnH41FUVBQtWbKETExMmJ3UwIEDaf/+/SJFczdv3pxmz55d7riioiL5+fkJNUZUVBQBoN27dwt9XaKSz7levXpkZWUlNldBVlYWnTp1iqZOnUoGBgbMIqKsrCzQCsDj8ej48ePUoEEDYrPZNH78+BpLt2ZmZpKnpycpKiqSvLw8eXh4MCSWy+USm82mXbt2iTyuoaFhtU3/XC6XbG1tSU5OTmyZIenp6aSsrExz584Vy3iVgcfj0Zs3b2jPnj00duxYRvMBABkbG9PYsWNpz549Aq08RUVFJC0tzahe9uvXr8r4mH8SwsPDSUNDg+rWrUvXr1+vsn1ycjJjea1KnK5Lly7UuXNnMc30z8BfQlABFi1aRHp6er97GuUwf/58kpOTE6i///79e7KwsCBJSUny8fERaiG5evUqNW/enFgsFk2ePFmkBVOQi4DL5dKaNWtISkqKTExMmBiC6uDOnTvUvn37Gu1S4+LiaO3atdSxY0disVjEZrOpW7dutGnTJoFqeKXRsWPHchkchYWFBID2798v9BxGjRpFdevWFSmiffLkyTV2FfB4PHrx4gWtW7eOevTowVgBjI2NaebMmXT27Fny9fUlaWnpSk2ffOuMuro6ycrKkoeHh0hBW0QlgYm+vr6kpqZGMjIyNH/+/HJxJHxX3YkTJ0QaOzU1lXF9VBc5OTnUrl07qlOnjlhSdT09PUlGRkbs1gFhER8fTyEhIeTs7EytW7cmFotFAEhLS4sGDx5MGzZsoEePHjFCbNeuXaPi4mJSVVWl5cuX/5Y51xa+fv1K3bp1IxaLRUuXLq3SWvfq1StSUVGhXr16Vfq7OHbs2D/evfIz/hKCChAUFEQAKDU19XdPhcGLFy9IUlKy0mjYwsJCcnV1JaBEr1+YYKbCwkLauHEjKSsrk6qqKm3durXKH01sbGw5F8GHDx+oS5cuxGKxaOHChdUOenrz5g2Tcta6dWu6fPlytcb5GQkJCbRr1y6ysbFhlBLNzMxoxYoVFB0dXW731L9/fxowYECZY0lJSRVmH1SEuLg4pjaFMLh06RIBoO3btwt9DT6ysrIoLCyMpkyZwrhPZGRkyMbGhjZv3lxOc4CvYS+MhSgjI4MWLVpEMjIypKWlRdu3b6/Sh5qfn0+bN28mbW1t4nA4NG3atAqtDJWlelYGcQUBJyYmkqGhIbVo0aJG0uV864Ag69LvQkZGBp0/f57c3NyoS5cuTKAoPzjX1dWV9u3bJ7bMmD8NXC6XVq5cSWw2mzp37ixwQ1UaV69eJUlJSZoyZUqFLtXCwkLS1dX9ozRraoq/hKACvHjxggAIZWb6FeDxeNSjRw9q0KCBUAutMLLHPyMpKYkmTJhALBaLWrZsWWFlseDg4DIuAh6PRwcOHCBFRUUyMDAQWSO89PWnT59OEhISpK+vT4GBgbWWapWZmUlBQUE0YsQIUlRUJADUoEEDWrBgAd29e5eKi4vJwcGBOnXqVKYff9G6ffu2SNebPn06qaioVCmylJmZSfr6+tS9e3eh7p3H41FMTAytXbuWunfvzhCdhg0b0qxZs+j8+fOVWiZyc3NJQkKCduzYIfS9fP78mRwdHYnFYlHjxo0FprMWFhaSv78/6evrE5vNprFjx1Zp7bh16xYBEFm6es2aNaSgoCCW78rLly9JRUWFevbsWe2AseXLl5OMjIzQPvzfgfz8fLpz5w51796dpKWlSUVFhXEztGvXjhYsWECnTp3642qj1BS3bt1iZI+rIvV8grR+/foK23h5eZGsrOwftXGsCf4SggrA960JijL/HeCbp86ePSt0n4SEBOrVqxezAxD2ARcREcEElI0cOZLx2QtyESQnJ9PgwYMJADk5OVXrc8/JySEvLy9SVFQkZWVl8vX1/aVCSnw1uUmTJjEBWtra2tSiRQsyMDAok/7GVzCsKtXzZwhbHnnSpEmkoKBQaQDmjx8/KDQ0lCZPnkz6+vrMTq9v3760ZcsWkeocEBGZmprSuHHjROpDVCII07NnTwJAnTt3pgcPHhCXy6VDhw4xhX9GjBhBr169Emo8vnaDqKp9I0eOLEfcaoJr164Rh8Oh8ePHixxwm5GRQSoqKjRr1iyxzac2MWjQIOrVqxcVFxfTwIEDSV9fn0aOHEm6uroMQWjWrBlNmTKFDh48WKWb7Z+A1NRUsrW1JQDk7Oxc6bNm0aJFxGKxGNGmn5GUlMTESf0b8JcQVII2bdpU60EpbmRnZ5O+vn4587UwKC4uJl9fX0YqVVifdHFxMe3bt4+0tLRIXl6e5s2bx7gIdu3aRTwej8LDw0lbW5vU1dVF9vsSlZjx9u7dS3Xr1iUOh0Nz5sz57TsSLpdLd+7cofnz5zMys0pKSjRy5Eg6evQohYSEEIBq7f6qKo988eJFAlBut87j8Sg6OprWrFlDVlZWIlsBqsKUKVOoefPm1erL4/Ho/PnzTACnkpISAaABAwaI7FvdtWsXsVgskQNQGzVqJPYFODAwkACInPGwYsUKkpaWrvUS2OKCkZERkxbZoEEDpqAR3wUYGBhIkydPpqZNmzIEQV9fn0aNGkXbt2+n6OjoWhV2qi3weDzaunUrSUtLU6tWrSp0NxUXF9OQIUNITk6uQreag4MDGRoa/uMzM4j+EoJKMX78+D+iBKiHhwdJS0uLvPMrjfv375OhoSEpKSmJlCqTkZHByAxzOBzavHkzZWVlMZLEffv2FTlw6udFZMSIETW6t9rC+vXrSUZGhpYvX06mpqYEgBGJ2b59u0hiM0SVl0fOyMggfX196tmzJ/F4PMrMzKSTJ0/SpEmTGHlbWVlZ6tevH23dulWs79fevXuJxWKJHChI9L/P0szMjACQtLQ0SUpKVovcrVq1ijQ0NETqw3/eHDhwQKR+woAvVnPo0CGh56KqqvrHVgn8GVlZWUyALF+ZMzg4uML2ycnJFBYWRvPnzydzc3Pmt6Cqqkr9+/cnX19funv3rtCCUn8Cnj59So0bNyZ5efkKNVL4Aad169YVmOEUEREhclzRn4q/hKASbNq0iaSlpX9rOeG4uDiSkpKiJUuW1His0rLHkydPFlhitjRKuwhsbGyoa9euBIDk5ORIRkaGdu7cKbJJNSoqinr06FHGzPyn4sCBAwSAecB9+PCBbG1tic1mE5vNJhaLRZ06dSI/Pz+hawzwyyP/XGthwoQJjEuhW7duzMO2cePGNGfOHLp48WKtuVGio6OrFS9z48YN6tSpEwGgjh070vXr1xn3j4KCAikrK9OaNWuEnvecOXOoSZMmIs2BH3cgbp0EohKy4+TkRFJSUhXG05SGl5cXSUlJ1Tg181fhwYMHBJQU4eK7a0QpaJSdnU1Xr16lZcuWUc+ePcsIJnXt2pXc3d3pwoULf/xakJ2dTePGjSMANGbMGIHEOCEhgerVq0etW7cWWKvDwsJCrLVLfhf+EoJKwFeaE9VfLE7079+f6tWrV+XiLSx4PB7t3r2bZGRkqHnz5hXeW2xsLLVu3ZpxERQUFJC7uzuxWCySkpIiDodDixYtErqQzadPn8jBwYFYLBY1adKETp069cvqKlQXp06dIgBlNMs9PT1JV1eXvn//Tvv27aMBAwYwEdstW7akpUuX0pMnTyq8t7y8PNLT06Phw4dTZmYmnThxgqnmxydb/fv3p23btomtkFFV4HK5JC8vL3QWxMOHD5nYlDZt2tD58+fL3W/pAFEDAwM6dOhQlaZle3t7kfO6N27cSDIyMrVG2gsKCqh79+6kqqpaaRYD3zowY8aMWplHbcDf35/YbDbl5ubS/Pnzy1SZrA4KCwspMjKS1q9fT3Z2dqSpqcloXZiamtKsWbPo2LFjvy0VsyocPnyYFBUVqUGDBgL1KJ4/f06Kioo0YMCAcu4BvlicsPEyfyr+EoJKkJaWRgDoyJEjv+X6Z86cIQB0/PhxsY8dExNDzZs3JxkZGSYmgI/g4GBSVFSkhg0b0tOnT+nly5fUpk0bkpSUpBUrVlBmZiYtXbqUpKWlSVdXl44cOVLhApienk4uLi4kLS1NWlpatGPHjt9qcREFfBnX0guBs7MzmZiYlGmXlZVFx48fpzFjxpCysjIBJdX/5syZQzdv3mQeHjwej549e0ZDhgwhACQhIcG4IerVq1erVoCq0LVrVxoyZEilbZ4+fUoDBw5kAs1OnDhRJal7/fo1E8BlZmZG165dq7CttbU12dnZiTRvR0dHMjc3F6mPqEhPT6dmzZqRkZFRhQVtVq1aRVJSUn98yeDSmDVrFjVq1IiIiCwtLWnUqFFiHZ9fGdPf35+cnJyY8tj8jJ5x48bR3r17KTY29o/ZHMTFxVGbNm2Iw+HQ+vXry83r3LlzxGazywlO5efnk5aW1j+KEArCX0JQBfT19cnV1fWXXzcvL4+MjY0Zn3JtICcnh4kFGDZsGCUkJNC0adOY7IKMjAzavHkzycjIUOPGjSkyMrJM//fv3zN6AZ07dy4TRFZQUEAbNmwgNTU1kpOTo6VLl1bLR/07wRdtKa38OGbMGOratWuFfQoKCujSpUs0bdo00tHRIQCkqKhIjRo1InV1dSYWQEFBgZo0aULDhg0jRUVFsYjh1AQLFy4kfX19gedev35NI0aMYESNDh06JHIA1a1bt8jCwoIAUL9+/QRaptq0aUOTJ08WadwWLVrQ1KlTRepTHXz8+JG0tbUFlkz+8eMHqampCVXf4k+ClZUVDRkyhCloVBv1HH5GfHw8HT16lGbOnEmtWrViBJO0tbVpyJAhtHHjRnr8+PFv3TQUFBTQ/PnzmRipnwW0tm3bJlAnZMmSJaSgoPCPXvv+EoIq0L9/f+rTp88vv66XlxdJSkqKnJNdHYSEhJCioiJxOBzicDi0a9cu+vLlC2MWdnZ2rtRlcenSJWrSpAmx2WyaNm0a7dmzh4yMjIjNZtPEiRP/MRHXP+PLly8EgM6fP88cs7GxqXQXy+Px6OnTp+Tt7U1dunRhrAB8lUAZGRmys7Oj2bNnM7slUWWNawP8tNbS2RMfPnygsWPHEpvNJn19ffL3969RMRcej0dHjx4t890ofb169eqJVD8kJyeH2Gz2L3v/KiqZvHr1auJwOFWK3fxJ4PF4pKGhQcuWLWPiMJ48efLL55GRkUHnzp2jxYsXU+fOnRn3m6KiIvXu3ZtWrlxJ169fr1EWTXVx9uxZ0tDQIB0dnXKWrdmzZ5OEhESZZ8PXr19JUlKSNm/ezBzLzi8SqdjW78ZfQlAF3N3dSUdH55de89OnTyQrK1tpDXVxIjg4mOTl5UlGRoYkJCRo1KhRpKysTHXr1hVa1KiwsJBmzJhBbDabANRYtvhPAD8Ku7TLyNLSksaPH1+mXXp6OoWEhND48eOpbt26BIDk5eVp4MCBtGPHDkZT4OXLl7R69Wpq164dQwYkJCRo69atv500ffr0iYmUjo+Pp2nTphGHwyFtbW3atGmTWF0Z+fn55axHWVlZJCcnRxs2bBB6nNJBcb8KP5dMzsrKInV19V9ipRAnEhISCCiRifb29iZFRcU/Im0uLy+Pbt++Td7e3tS3b1/GBcfhcMjS0pIWLlxIp0+f/mVCQPHx8dS9e3disVi0ZMkSxnLB5XKpX79+pKioSNHR0Uz74cOHU4M2nWnpqWjqsuYaGQoqx72mpBx3bOKfZzH9SwiqAD/v/GezUW1i6NChpKOjU+vvYV5eHuMiGDFiBMXFxTH5xtra2kJbJ169esX4lk1MTKh3794EgExNTenOnTu1eg+1CR6PR5KSkmWqDTZq1Ijmz59PUVFRtGrVKurUqRNjBWjWrBnNnz+frly5UqWa5PDhwxk9AT6JsrS0JB8fH3rz5k1t31o58Hg80tTUJAsLC5KRkSFVVVXy8fGpdqVIYZCenk4LFy5k4ktETR/ctm0bSUpKVlsiu7rgl0zetm0b+fj4EIfD+e0uH1HBl8eOjY2l/v37/7ER8lwul549e0Zbt26lESNGMIQbADVv3pymTp1Khw8frtX3n8vlkpeXF0lISFCnTp2Ya/348YNatWpF9erVo4SEBPqcmkP91p0ng0XhVP8nIvDzy8jtLBksCif7PQ/oc6p4AsbFgb+EoAq8fv2aAIhNT78q8HXZhc19ri7i4uKYLIKdO3fSpUuXSFdXl1RUVGjx4sWkra1NWlpadPHixQrHSEhIoKlTpzKR5IcPH2ZMqffu3aM2bdoQALK3t/+jZVwrg6amJnl5eTFWAGlpaUbqWF5engYNGkQ7d+4UScHt7NmzBID8/f2pT58+ZGxsTPv37yc7OzuSlZVlyIWbmxtFRkbWesBVeno6eXh4kISEBElISJCnp2eNtPxFxcePH5lYlHr16tHp06eFuucJEyZQ69atf8EMy2POnDnEYrFISUlJoK7En47169eTrKwsFRYWkpqaGi1btux3T0ko8Hg8ev/+PQUEBNCkSZOoSZMmDEGoV68ejRkzhnbs2EExMTFiF0y6c+cO1atXj1RVVSk0NJSISmS8dXR0qMWgKdTI4xyz0Av7MnI7S408zlFQxJ9BKP8SgirA5XJJVlZW6HK3NUFhYSE1bdqUOnXqVKuLwNGjR5ksgvv37zP+7B49ejB+0MTERGan7+LiUsZ3nJ2dTcuXLyd5eXlSUVGhdevWCTQpc7lc8vf3Jw0NDVJQUKA1a9b8Y0RL+GWU1dXVSVdXl7ECACVFo65evVqte0lPT6e6deuStbU1c43ScQQ5OTkUFhZGTk5OpKamRgBIT0+PZs6cSVevXq2RD/9nZGVl0apVq0hFRYVkZWWpU6dOpKSk9FuU5x49ekQAGHdK165dKSIiotI+pqam5dw3vwpcLpeaN29OACg8PPy3zKEmGDduHLVt25Zevnz5Szc8tYHv379TaGgozZs3j9q1a8f8VtXU1GjAgAG0Zs0aunfvnliePWlpaQx5nTFjBuXl5dGigzdKFnjXMyKRgZ9fW67FVj2BWsZfQiAEzM3Ny5XBrQ34+fkRm82utXKaeXl5NH36dMZFcPPmTWratCnJyMjQxo0byy0EP8sex8bGkr+/P+no6JCUlBTNnz9fKF9eWloaOTs7E5vNpsaNG9OFCxdq5f5qirS0NAoODqaxY8dSnTp1GHO+gYEB7dq1i2JiYggAHT16tNrXGDt2LCkpKZVJT6uoPHJRURFdu3aNnJ2dmZoFqqqq5OjoSKGhodXWpsjLy6MNGzaQlpYWSUlJkbOzM3379o2RTv4dLosLFy4QAPr48SOdPXuWWWxHjhwpUG47Pz//l0XGC0J2djZpaGiQpqYm6ejo/ONcBm3btqVx48YxWgT/tAygypCdnU1XrlwhT09P6tGjB8nJyTHZPd26dSMPDw+6ePFite+Zx+PR9u3bSVpampr0HV8jEvDzK/g3Wwr+EgIhMGnSJGrVqlWtXuPbt2+kqKhIM2fOrJXx4+LiyNTUlKSlpWnbtm20cuVKkpSUJFNTU3rx4kWlfe/fv0/a2tqMr3vUqFFC10QojefPnzNqhwMHDvxlwjsVobi4mB49ekQrV66kDh06MPfXokULWrhwIV27do169epFgwcPJqKSqPua7KbCw8MJAO3du7fMcWHKI/N4PHr06BF5eHgwi6WsrCzZ2trSgQMHhCJmBQUFtHPnTsbiMWHChDKujtTUVAJABw8erNb91QR8YRc+ySkqKipDPufNm1fmHh8/fkwA6N69e798rkREa9euJUlJSYqIiBBLyeRfCb7Vc/369TR27FgyNTX93VOqVRQWFtLDhw/Jz8+PbG1tSUNDgyH7ZmZmNHv2bDp+/LjIUuQX7z4mg4WhVE+AZaCO03pSNOtHHI16xOJIk4SSJsk16UR1J++qlBA08jj3W2MK/hICIbB161bicDi1au52cHAgDQ2NKsvjVgd8F0GDBg3o9OnT1L59e2Kz2eTu7l7lPT169IisrKwIAKM8NmnSpGrvTvmpZ3p6eiQtLU0eHh5iU2EUBqmpqRQUFESOjo6kra3NpDjZ2dnR7t27y6WOjRw5krp3705E/1uEKipyUhnS0tJIR0eHbGxsBLqDhC2PzEdsbCytWbOG2rdvz2QrdO/enTZv3lzuHrhcLgUEBFD9+vWJxWLR6NGjy0kn89GwYcPfosW/YcMGkpOTK3c8OzubVqxYQfLy8qSqqkrr1q2j/Px8Zmf7K787peekqalJEydOJCLxlEz+lYiNjWWIbcOGDWttE/Kngsfj0atXr2j37t3k4OBA9evXZ9yBDRs2pPHjx9O+ffsoLi6uUtet/Z4HZLRY8MIu17gDScirkmKbAaRm40zKne2JLa9CLI4M6UzYWmlMgf2e3yfn/pcQCIHbt28TgFpLo+OP7+/vL9Zxf3YRbNq0ieTl5cnIyIju3r1bad8PHz7Q6NGjCQA1bdqUzpw5Q8XFxeTv70+ysrLUrFmzMuk2oiI7O5vc3d1JSkqK9PX16ejRo7USN8G3AqxYsYIhQvxsCBcXF7p+/XqlpGjatGnMDury5csEoNLSxBXB0dGRlJWVK1SyE7Y8siB8+/aNdu7cSdbW1kzmQps2bWjlypW0fv16aty4MQEgOzu7KjX/x4wZQxYWFiLPoaZwc3OrVDo3MTGRCWA1NDSknj17VrtCY02xbt06kpSULGMlq0nJ5F+NEydOEACmhkVQUNDvntJvx9evXyk4OJhmzJhBLVu2ZAST6tSpQ0OHDqVNmzZRVFQUk5oZm/ij0p2+tv1aqrcwtMyxupN3ESQ4JN+8W5Wug7ik3+PC+UsIhEBGRgYBoMDAQLGPzeVyqVWrVtSuXTuxBnOVdhH4+vpSv379mN19ZfUH0tLSaP78+SQlJUV16tSh3bt3l1MNKy17XJ0CR6Xx9u1bGjBgAAEgKyurGpEMPlJSUujIkSPk6OjIpLMpKirS4MGDyd/fXyR52cWLF5OhoSER/S8FVVTT8OnTpwkA7du3r9J2VZVHFgYZGRl0+PBh6tSpE0N+5OTkyNHRke7du1fld2zTpk0kJSX1y4M/J0+eTG3atKmy3cuXL5kUV3V1dbpx48YvmN3/kJOTQ1paWjRhwoRy5/glk1etWvVL5yQqli1bRhoaGkxBo3+SoNKvQnp6Op09e5YWLVpEnTp1YoTFFBUVydramvou2U/1K7AOVPaS0jYmKW3jKjMPPE/9nvo5oqzfbPxHoaysDENDQzx//lzsY+/atQvPnj3D1q1bwWaL5y0+duwYzMzMkJWVBW9vb6xduxaRkZE4c+YMdu/eDQUFhXJ9CgoK4OfnB2NjY+zcuRNubm6Ii4vDpEmTICkpWaZt8+bNERkZibFjx2Lq1KkYPnw4MjIyqjVXY2NjnD59GufOncPXr1/RunVrzJ49W6TxeDweIiMjsWLFCrRv3x5aWloYPXo0nj59inHjxuHGjRtITU3FiRMnMHHiROjp6Qk9tqqqKtLT0wEAaWlpkJCQgJKSktD909PTMWXKFPTt2xdjx46ttO3ChQshKyuLFStWCD3+z3j8+DG2bt2KO3fuoEOHDvD19cXo0aNx/vx5dOjQAXp6epg2bRouXryIwsLCcv0tLCxQWFhYK9/1ypCcnAwNDY0q2zVt2hQnTpyAlJQU5OTk0K1bNwwcOBCvXr36BbMEdu7cidTUVLi5uZU75+DggOXLl8Pd3R1Hjhz5JfOpDqKjo2FiYoJ79+5BX18f+vr6v3tKfxxUVFTQt29feHt74/bt28jMzMStW7ewePFisNlsPE8pBo9EG5OIUJybAbZc5c+PYh7heuz3Gsz+1+A/SwgAoFWrVnj27JlYx0xJSYGHhwcmTJgAc3PzGo+Xn5+PmTNnYvjw4ejVqxcsLCwwb948dOrUCTExMejfv3+5PjweD0FBQWjSpAlcXV0xfPhwvH37Fp6engKJAx+ysrLYsWMHjh07hsuXL6N169a4f/9+teduY2ODmJgYrF69Gvv27UPDhg2xZ88e8Hg8ge1TU1Nx5MgRODg4oE6dOjA3N4efnx90dXWxe/dufP36Fc+ePYOPjw+6du0KDodTrXmpqqrix48f4PF4SEtLg6qqKlgsltD9Z8+ejdzcXOzevbvKfsrKynBzc8OePXsQFxcn0jzv37+PHj16oEePHuByubh06RJu3boFFxcX+Pv7IyEhAbdu3cKoUaNw8eJF9OnTB1paWhgzZgyOHTuG7OxsACXfcw6Hg4iICJGuX1OkpKRAU1NTqLavX79GYWEhAgMDERQUxCxwU6dORWJiYq3NMTc3F2vWrIGjoyOMjIwEtlmyZAmcnJwwbtw43Lp1q9bmUhPw36+7d++iY8eOv3s6/wjIyMigc+fOWLx4MUJCT0NSuY7IY+S8uIHirFTIN+lcZdvPqbnIKeBWZ6q/DH8JgZgJgbu7O4gI3t7eNR7r7du36NChA/bs2YP58+fj8ePHOHXqFPbt24eTJ08KfNjeuHEDFhYWGD16NFq2bIno6Gjs3LkTdeoI/2UfOnQonj59irp166Jz587w8fGpcBGvClJSUnBxccGbN2/Qp08fTJo0CRYWFnj48CF4PB4iIiKwfPlyWFpaQlNTE2PGjEF0dDQmTJiAmzdvIiUlBcePH8eECROgq6tbrTn8DFVVVRARMjMzkZaWBjU1NaH7njlzBgcPHsTGjRuFns+MGTOgo6MDDw8Podo/efIE/fv3R4cOHZCcnIywsDA8fPgQvXr1KkNAJCQk0LlzZ/j5+eHdu3d4+vQp5s6dixcvXmD48OHQ0NDAgAEDcPjwYTRr1uyXEwJhLQQAEBUVBQAwMzPDyJEj8fr1a6xZswYhISFo0KABVqxYgZycHLHPcffu3UhJSYG7u3uFbVgsFnbv3o1OnTrB1tYWb968Efs8aoK8vDy8ffsWTZo0wePHj/8SgmrgU2oORDQOoCj1C9Iu74C0bhPIm/Sosj0B+Jgq/u+wOPGfJwTfv38X2w7k0aNH8Pf3x8qVK4XeGVUEvovgx48fGDVqFNavXw99fX08f/4c48aNK7czffnyJQYMGAArKyuwWCzcuHEDp06dQtOmTat1fUNDQ9y8eRMuLi5wc3ODtbV1jd6nunXr4uDBgwgPD8f3799haWkJOTk5WFhYYMOGDdDX18eePXsQHx+Pp0+fwtvbG126dKm2FaAyqKioACgx/aenp0NVVVWofmlpaZg8eTL69esHJycnoa8nIyOD5cuXIyQkBI8fP66w3cuXLzFs2DCYmZkhLi4OQUFBePr0KQYNGlSlJYLFYqFVq1bw9PTE06dP8e7dO3h7eyMzMxOTJk3C8+fPERISgg0bNuDDhw9Cz70mEMVCEBUVhYYNGzKuG2lpacybNw/v3r3D1KlTsWrVKjRo0AD+/v7gcsWzy8rLy4Ovry8cHBxgbGxcaVspKSmcOHECOjo66Nu3L75//3PMvy9fvgSPxwObzUZhYeF/nhAUFBQgISEB0dHROHfuHHbs2IElS5Zg0qRJsLW1RefOndGiRQsYGBhAXV0d8vLyaGfRXqRrFGen4/ux5WBLy0PDdjFYbAmh+hVyq7ex+lVgEVGVxOjHjx9QVlZGZmamSL7WPx3v3r1DgwYNcOHCBVhbW9doLB6Phw4dOiAvLw+PHz8u56MXFvn5+ViwYAG2bdsGa2trxMfH482bN1i5ciUWLFgACYmyX7yEhAR4enpi7969MDAwgLe3N4YNGya22AUAuHLlCuzt7UFECAwMFOm9Ki4uxqNHj3D+/HmcP38ekZGRICLo6ekhJSUFbDYby5cvx+zZs2tl8ReEqKgotGnTBo8fP4aXlxfy8/Nx7ty5Kvs5ODggPDwcL168QN26dUW6JpfLRcuWLaGnp4dLly6VOff+/XssW7YMhw8fhr6+Pjw9PeHg4FDt79DP+P79OxYtWoT9+/dDWloaBQUFaNWqFezs7GBnZwcTExORXCbCoLi4GBwOBzt37sTkyZOrbN+lSxfUrVsXwcHBAs9/+PAB7u7uCAoKQvPmzeHr64u+ffvWaN6bNm3C/Pnz8fr1azRo0ECoPh8/foSlpSXq16+Pa9euQVZWttrXFxcOHDiAcePGYfny5Vi7di3S09PF9t35XSgqKkJGRgbS09ORlpaGpKQkfPnyBfHx8UhMTERycjJSU1ORkZGBrKws5OTkIC8vD0VFRVVaM9lsNjgcDmRkZCAvLw9FRUXI6zVGaruqv6cAwMvPQeKRxSj+kQxte19IadQT+r7OOndC87rKQrcXB0RZv//Z35oaon79+lBQUMCzZ89qTAgCAgLw8OFD3Lx5s9o/xnfv3mH48OF48eIFBg8ejDNnzqBx48aIiIhA69aty7TNzs7G2rVrsW7dOsjIyMDPzw/Tpk2DtLR0je5DEHr27Ilnz57ByckJffr0wcKFC+Hl5QUpKSmB7ZOTk3Hx4kWcP38ely5dQkpKCpSVldG7d29MnToVffr0gY6ODlJTU7FkyRK4urpi37592Lx5M3r27Cn2+f8MvkWA/7ARJiDx9OnTOHToEAICAkQmAwAgKSmJVatWYfDgwbh69Sp69OiBr1+/YuXKldi3bx80NTWxZcsWTJw4scL3tbrQ0tLCwoULsX//fhw/fhx5eXkICwvD+vXrsWzZMhgZGcHW1ha2trbo0KFDOdJZHaSnp4OIhLIQ8Hg8xk1SEerXr48jR45g3rx5WLBgAfr37w8rKyusXbsWbdq0EXl++fn58PX1hb29vdBkACixnIWHh6Nr165wcHBASEiIWMl3dRAdHQ0jIyM8evQIlpaWfwwZKC4uRmZmJmOJS0tLQ1paGr59+4Zv374xC3taWlqZhT0/P19oK5CUlBSzsGtpaUFVVRVqamrQ1NSEjo4O6tatCz09PdSvXx86OjpQU1MT+PvKKeCixbKLVboNiFuI78dXgJseD+2RXiKRARYAQ3V5odv/DvwZ35zfBDabDRMTkxrHEWRkZMDV1RWjR49Gly5dqjXGsWPHMHHiRKipqaFFixYIDQ3FvHnz4OXlBRkZGaYdl8vF3r174enpiYyMDMyaNQuLFy8W2uxdXWhra+PcuXPw8/ODm5sbbt68iaCgIBgZGaG4uBiRkZGMFeDRo0cgIpiammLy5MmwsbER+KBSV1fH9u3bMXnyZDg7O6NXr14YPHgw/Pz8YGhoWGv3UtplkJaWhpYtW1baPjU1FVOmTEH//v3h4OBQ7eva2trCwsICCxYsQNeuXbFz504oKCjAx8cH06ZNg5ycXLXHrgqNGzeGoqIiYmJisGjRIgwbNgyFhYW4fv06wsLCcOTIEaxfvx5aWloYOHAgbG1t0aNHjzLfPVGQnJwMAELFELx9+xbZ2dkwMzOrsm3btm1x/fp1nD17Fi4uLmjbti3GjBkDLy8vkb4z/v7+SEpKqjR2oLI5BAUFwdbWFq6urli7dq3IY4gT/IDCO3fuYObMmWIdm4iQlZWFtLQ0ZmHn/25SUlLw7ds3JCUlMQt7ZmYms7AXFBQIfR0JCQnIyspCXl4eOjo6UFFRgbq6OjQ1NVGnTh3o6upCX18fdevWhYaGBjQ0NKCkpCQWMkZEiH0ZDTleLnLYFf8GiVeM5DBfFHx7Da0hHpDWFc0dW09dDvLSf/aS+2fP7hegVatWuHPnTo3G8PT0RF5eXrUeDAUFBZg/fz62bdsGc3NzvHr1CsXFxbh69SqsrKyYdkSEM2fOwNXVFa9fv4a9vT28vLxgYGBQo7mLAjabjYULF6JLly4YPnw4WrRoAVNTU7x58wapqalQUVFB7969MX36dFhbW0NHR0eocVu3bo1bt24hKCgICxcuRNOmTbFo0SK4uLjUiklWWVkZLBZL6BiCWbNmIT8/H7t27aqRiTojIwPGxsY4cuQI3rx5A3d3d8yZMweKiorVHlNYsNlstGvXrkxgoZSUFKytrWFtbY1t27YhIiICoaGhCA0NxZ49e6CgoAAbGxvY2dmhb9++UFYW3tSZkpICAEJZCPgBhaampkKNzWKx0L9/f/Tp0wf79u3D0qVLcezYMcyaNQtubm5Vfp75+fnw8fHBmDFj0LBhQ6Gu+TMGDhyITZs2YdasWahfvz6mT59erXHEgejoaNja2iI1NVVg/AARITc3t8xi/vOu/fv37/j+/Xu5hT03NxdCeJXLQEZGBgoKCtDV1YWKigo0NDTKLOy6urrQ0NCAuro68/odrpeEhAQcOXIEAQEBiI6ORt0Bs8Fp1gNgCSYZ6df2Iu/tQ8g2MEdxXjayY66XOa/QwkpgPwCQYLNg1UhLrPOvFYhb2OCfhh07dtSo/vqzZ8+IzWbTmjVrRO779u1bMjMzIykpKTI1NSUA5ODgUE4kJyIigrp06UIAqHv37tWS2a0puFwu3bt3j5YsWUJt27ZlZEEBUOvWrenKlSvlxI6qgx8/fpCrqytxOBwyMDCgEydO1IpKnIqKCq1Zs4bk5ORo48aNFbYLDQ2tsYDVjx8/aMWKFaSsrExycnJkZGREDRo0EMv7JQoWLVpEurq6Vbbj8Xj04sUL8vLyYspdczgcsra2pp07dwpV9pqvnJecnFxl24ULF5KBgYEwtyAQWVlZ5OnpSXJycqSmpkbr16+v9Pe8ZcsWYrPZYin4NHv2bGKz2b+kOmJ+fj59+/aNXrx4QXfu3KEzZ87Q1q1bGRVLADR8+HDq1asXtW7dmgwMDEhFRYUkJSXL/F5Lv/jqfYJeEhISpKSkRPr6+mRiYkLdu3enkSNH0pw5c2jNmjW0f/9+On36NN29e5dev35NycnJjOrfn4rc3FwKCgoiGxsbYrPZJCUlRUOGDKFZs2aRgYlFpeJC0votKnyvAPwrlAr/00GFQEmud4cOHRAVFSX0DoUPIkK3bt2QlJSE58+fi+T75bsI5OXlUVhYCCLCrl27MHToUKbN+/fv4ebmhqNHj6JFixZYs2YN+vTpI/YAsIqQlJRUJhaAn7Pfu3dv2NjYoHfv3jh37hycnZ1Rv359BAcHw8TERCzXjouLw5w5c3Du3Dn07NkTmzdvrnbGhCAYGRlh6NChWLt2LQIDAwW6AlJTU9G8eXOYm5vj1KlTIr/veXl52LZtG3x8fJCdnY1p06Zh0aJF+PbtG8zMzLB7925MmjRJXLdUJUJDQzF48GB8/fpVpBTOL1++ICwsDGFhYbh58yZ4PB4sLS1hZ2cHW1tbgbvs3bt3Y9q0aSgsLKwyJqFHjx5QVlbGyZMnRb6n0hAUYDt8+PAyn1t+fj4aNGgAKysrHDx4sEbXA0r85EOGDMGVK1dw69atKt0ePwfLCdq18/9OTU1FSkoK0tLS8OPHj0pN8CwWq9KdvKysLJSUlKCqqgoNDQ1oaWmhTp060NbWLrNTL/2Sl5f/Zc+a2gQR4e7duwgMDERISAgyMzPRvn17ODg4gMPhYM2aNYiLi8OwYcNQ1Gkqniflo1hUhaJKIMFmoYOROg5OsBDbmKJApPVb3Azjn4asrCwCQPv37xe5b1BQEAGgixcvCt0nPz+fZsyYQQDI2NiYAFCfPn3K7LpSUlJozpw5xOFwSEdHh/bs2fNLmDeXy6W7d++Sh4cHs+PA/+8+PDw86O7duwJ3tS9evKAWLVqQjIwM7dixQ6w7+jNnzpCxsTFJSkrSvHnzxPYdbN3WggaPn0VSOo1oR3A4ZeeXv69Ro0aRqqqqUDvi0igoKKCtW7eSjo4OSUpK0pQpU8pJyVZUHrk28fXrVwJAoaGh1R4jJSWFDhw4QLa2tiQrK0sAqHnz5uTh4UGPHj1iPnsvLy/S0NCocjwej0cqKiq0cuXKas/pZ8TExFD//v0JAJmbm9OtW7eYc1u3biU2m02vX7+u9vhcLpdSU1Pp7du3FBkZSadOnSIjIyNSUlIiFxcXWrBgAU2YMIEGDx5M3bp1o1atWpGenh7Jy8tXuLvk71alpaVJSkqKkagW1E5FRYWMjIzI3NycmjVrRhISEqSiokLt27enPXv2UGhoKN26dYtevHhBiYmJ/4jiTLWB9+/f0/Lly5nnbL169cjDw4Nev35NoaGh1KJFyY6/X79+FBUVRUREn1NzqJHHObGWP/4nVTv8z1sIAKBBgwYYMGAANmzYIHSf7OxsNG7cGJaWljhx4oRQffhZBNHR0VBRUUFWVhbWr1+PqVOngsViIT8/H1u2bMGqVatQXFwMV1dXzJ07F/LytReZmpSUhAsXLjBWgPT0dKipqTFWAGtra2hra1c5Tl5eHubNm4edO3diyJAh8Pf3F1ugY35+PtavX49Vq1ZBUVERPj4+cHR0FDmgKC4pC4cffsb1N9/xKTUHKLX7YQGopyYHq8ZaGGNRDzH3rmDw4ME4ePAg7O3thRqfy+Xi4MGDWL58OT5//gx7e3t4enoKzHF/+/YtmjZtilWrVsHFxUWk+6gJdHV14eTkhNWrV9d4rNzcXFy6dAmhoaE4c+YM0tPTUa9ePdja2iI+Ph4vXryoUn74w4cPMDIywtmzZ9G3b98az6k0rl+/joULF+Lx48cYNGgQVq5cib59+6JLly44dOgQsrKyKt2pC9q1p6enIzMzs8LdOIvFgqysLNhsNogIXC63wp29rKwsVFVVoampyQTKCdqplz6upKRUZtc+adIkPHjwADExMThy5AhGjRol1vfwn4YfP37g2LFjCAwMxK1btyAvL49hw4bB0dERXbp0wdWrV+Hh4YHIyEh0794dXl5eaN++rAZBcORnLDoZLbY5+Q42wYh2wmcjiBuirN9/CQGAIUOGID09HdeuXRO6z6JFi7Bp0ya8fv1aqMA+vtqehIQEMjMz0bZtWxw8eBCNGjUCj8fDkSNH4O7ujvj4eEyZMgVLly4VaiEWFVwuFw8fPmQyAvgBXW3btoWNjQ1sbGxgbm5e7dSzEydOYMKECVBRUUFQUFC5H1tN8OXLFyxcuBBHjx6FpaUltmzZgrZt21bdLy0XbqHRuP02BRJsVqXmQP754q8xaJ4XjfPHDlZpNuXxeAgJCYGnpydiY2MxdOhQLF++HM2aNau034wZM3DkyBG8f/++1rNE+LCzs0NWVhauXLki1nGLiopw+/ZthIaGIiwsDF+/foWkpCTGjBkDOzs79O7dW2Dg2IkTJzB06FAkJCSIpKYJVB4sVzpg7unTp3jy5Any8/MBlASVZmdno7i4uNyYLBYL0tLSkJKSgoSEBFgsFng8HrOwFxUVCZyLqqoqFBUVER8fD1VVVdjY2EBTU7PCBV5NTa3aGRylYWlpCVlZWdy4cQOfPn1CvXq/b+H5XSguLsaVK1cQGBiI0NBQ5Ofno0ePHnB0dMTgwYMhLy+P27dvw93dHbdv34alpSVWrVqF7t27Vzjm1utxWHcptsZzW9i7MWZYCZ/WWhv4SwhExIoVK7B582YkJycL5TN78+YNTExM4OHhgaVLl1batqCgAAsWLMDWrVuhqqqKzMxMeHp6ws3NDZKSkrh69SoWLlyIJ0+ewNbWFj4+PmjcuLG4bg0AkJiYyFgBLl++zFgBrK2tGSuAlpb4ImA/fvyI0aNHIyIiAitXroSrq6tYc7Vv3rwJZ2dnxMTEYPz48fD29q4wmj048jM8T78Al0ci+QWJVwwZjiSWD2qBkRWweyLC6dOnsWTJEkRHR6Nfv35YuXKl0LEoiYmJMDY2xqxZs8QidS0MvL294ePjg/T09FrLnycidOjQgbnGq1evICcnB2tra9jZ2aF///4MAXJ3d8e+ffsQFRUlcDde1a5dUDEnoCTSXUZGhlnYeTwevn//zuzsK/K5S0lJVbpbF/RSUVFhCPT169dhbW0NR0dH+Pv716oPnsfjQUlJCW3btsW7d+/w5cuXWrvWn4gXL14gMDAQhw4dwrdv39CkSRM4OTlhzJgxTHGnyMhILFmyBBcvXkTr1q3h5eUltKBVdZ8dEmwWJNksrBjY/LdaBvj4SwhExKlTp2BraytUsBURoU+fPoiLi8OLFy8qTZd59+4dRowYgWfPnoHFYsHQ0BCHDx9Gu3btEBMTAxcXF5w/fx6WlpZYu3YtOnXqJJb74XK5ePDgAWMFePLkCVgsVhkrQLt27cQiQFMRioqKsGzZMnh7e6NHjx44ePCgyDvAysDlcrFz504sWbIERIQVK1Zg+vTpZbQOxMXyF/RuhJlW/wucIyJcuXIFHh4eiIiIgJWVFby8vNChQweRx/bw8MD69evx9u3bagkeiYqrV6+iZ8+eePXqFZo0aSK2cX8OlrO3t4eBgQHs7OwQFxeHqKgovHnzhtEnkJeXh6SkJLKysipUlpOWloa8vDyzY2ez2WCxWCguLgaXy0V+fj5yc3ORl5cnsL+ysjKzaOfk5DDS0F+/fkVERASUlJQwfvx4jBw5ElpaWlBXV4ecnFyNF/GDBw/C0dERq1atElhBUVx4//49jI2N0bRpU7Rs2bJClcd/E5KTkxEcHIyAgAA8fvwYampqGDVqFBwdHdGuXTvms4uJicGSJUsQFhaGpk2bYsWKFRg8eLDIJLg61sXODTSw2s4E+mq1pysiCv4SAhHx8eNH1K9fXyg/ZlhYGOzs7HDq1CkMHDiwwnbHjx/H+PHjweVykZeXhxkzZmDNmjVIT0/H0qVLceDAAdSvXx8+Pj4YMmRIjR9CCQkJZawAGRkZUFdXL2MFqGl9hergypUrcHBwAI/HE1n2WBgkJyfDw8MD/v7+aN68ObZs2YJu3brVmh/wzp07cHd3x61bt4QyPVaFzMxMGBkZYdiwYdi5c6fY5lvZ9VRUVBAQEABHR8cy535WlhNlp56VlSXwehwOB4qKipCTk4OMjAxYLBays7ORlZXFVGNks9mQlpZGYWGhQDO+pKRklb71n19qamoMOSwsLETDhg3RoUMHBAUFAaj9DJ7ly5czctSjR48Wy5g/g7+R4XA48PPzg7Ozc61c53ejsLAQZ8+eRUBAAM6ePQsA6NevHxwdHdGvX78y6qxxcXHw9PREcHAw6tevj2XLlmH06NE13vww8Uex3/E5NbeMoiELJaJDVo20YG9ZDw20al9XRBT8zTIQETwej5SUlGj16tWVtsvNzSUDAwOysbGpMJI+Pz+fZs6cyeRua2tr04ULF+jHjx/k4eFBsrKypK6uTps2baKCgoJqz7moqIhu3bpFixcvptatWzM5xebm5uTp6UkPHjz4Y3KCk5KSyNramgDQwoULa3TfFeHRo0fUvn17AkADR4+nhu5nBUb8yrfoUWkuse6MAwL7NXQLJ6sBwxjdhfDwcLFlU6xbt44kJCQoNja2xmPxeDzKzMykjx8/UlRUFF29epWOHz9Ou3fvJl9fX1q0aBGpqKiQsbEx9ezZk9q0aUP169cnFRWVCnPSJSQkSE1NjerVq0dNmjShVq1aUbt27cjCwoIsLCyobdu21LJlS2rUqBHp6emRkpJShe+vgoICGRgYkJmZGfN51alThzgcDgEgHR0dGj58OO3fv5/evn1LmZmZNX6fd+3aRSwWi168eFHu3MOHD6lz584EgHr06MFEm9cUPB6PHB0dSUpKqkyWgzixcuVKUlRUJAC/RZukNsHj8ejhw4c0Y8YMUlNTY7KdNm/eTN+/fy/X/uPHjzRhwgSSkJAgXV1d2rVrV61lV2TnF1FMfAZFfUqjmPgMgRlKfxL+ZhlUA507d0YdPQMs89uGQi4PUpJsGKrLl5Ga5JvAY2JiBOZev3v3DkOHDsXz58/B4/EwdOhQbNmyBSdPnsSyZcuQlZWFOXPmYNGiRSKpvvHx7du3MlaAzMxMaGhoMFaA3r17/xYrgDDg8XhYv349Fi9eDFNTUwQHB1dYf74m1zh06BDcrySCrdNEYAWygvhXKEr/uWojIe3iNkgqa6PuxO0Cx6ZiLiRS32GNTb1qmR4rQ35+PrODPXr0qFDBchX9PyMjo8JgOWVlZeZ3XFRUBFNTU0hJSTG74uLiYhQWFiIvLw85OTnIyspCRkaGQJM8m82GmpqawN25oqIili1bhlmzZmHw4MFldu2ld3NnzpzBwIED8fnzZ2hoaODq1asIDQ3F6dOnkZKSgrp162LQoEGws7ND165dq1XjgW8dsLS0xNGjRwW2of+PBXF1dUVsbCyjAlrTAL3CwkL06dMHz549w71798QeGzRixAhERkbi+/fvyMjI+GNqGNQEX79+ZWqGvH79GnXr1oW9vT0cHR3RvHnzcu0TEhKwevVq7Nq1CyoqKnBzc8PUqVPFErD5b8Ffl4EI4JuCQu6+QC5LrsJUtK56Eujb0RRz584VmLJ14sQJODk5IT8/H7KystixYwfk5eWxaNEixMXFwcHBAV5eXkywizAoKirC/fv3mVgAfiyCubk5EwvQpk2bWo0FEDciIiIwatQopKSkYPfu3RgxYoRYx49LykKvjbdE6pP/5QWSDrtCpYsjlDsMr7TtlbldhDYJFhQUCG12f/PmDd6+fQt1dXVkZWVVGCynqKgIVVVVqKioQEFBAXJycpCWloakpCST6vbzwv7jxw/mOoLIgqysrNABdHwzvbKycoWk6NOnTzA0NKyyiujy5cuxdetWfP/+vYypnsvl4t69e4yM8qdPn6CsrIz+/fvDzs4O1tbWUFBQEOoz8Pf3x+TJkxEdHY0WLVpU2raoqAh79uzBsmXLkJmZiTlz5mDx4sXVIu98ZGRkoGPHjsjPz8eDBw/EStibNWuGvLw8GBsbiz1r5FciJycHoaGhCAgIwNWrVyEjIwM7Ozs4OjqiZ8+eAp9vqamp8PX1xdatWyEtLQ0XFxc4OzsL/b34L+EvIRAC1QkWoW8vcWnVODTW+1/BloKCAsydOxc7duwAUGJpmDdvHvz8/HDnzh306tULa9asKVetsCLEx8eXsQL8+PEDmpqaZawAwhSM+ZORmZmJKVOm4OjRo5g4cSI2bdoktsI+y06/wMGHn0SKCk69uB3ZT85Dd+oeSKpUnOrJZgFddIDe6plCLfQVBbvx88/V1NSYdDUZGRlcuXIF8vLy6N27N4CShbH0ws7376ekpFTos+drx1e2qCcnJ2PmzJk4ffo0evToIfaiSo8fP0bbtm3x+PHjSpX7Bg0ahPz8fFy8eLHCNkSEZ8+eMemMz58/h4yMDHr16gU7OzsMGDCgwt9DYWEhGjdujHbt2iEkJETo+WdlZTGVROXk5LBkyRJMmzat2lUoa6NkckFBAeTl5SEjI4P58+dj+fLlNR7zV4LH4+HWrVsICAjA8ePHkZ2djS5dusDR0RHDhg2rcJ3JzMzE+vXrsWHDBhAR5s6di3nz5jEFy/6iPP4SgipQ3XQSNggcSQksH9gcI9vVw/v379G/f3+8fv0aEhISWLBgAeLi4nDixAmYmJhg7dq1VQbRFRUV4d69e4wV4Pnz52CxWLCwsChjBfjdJVbFDSLCvn374OzsDENDQxw9elQsssdd117Hp7Rc4edRzMXXrY7gqOuhjv2aKtsXpX3Dt92TweFwmAWdv7irqKhAVlYW0tLSTA47/b84UroltgAAO+VJREFUDX9hz87ORkZGBlJTU5mXIGsAh8MROoCO/1JVVRXKbFxQUAAlJSX4+fmJvToeAFy4cAE2NjZV5sXr6+vD3t5epJTLd+/e4dSpUwgNDcXdu3fBYrHQuXNnRka5tCbInj17MGnSJDx//rxa361v375h6dKl2L9/P+rXrw9vb28MHTq0WoGHjx49QteuXWFjYyOWkslPnz5l0lsvXrzIkMg/HXFxcQgMDMTBgwfx6dMnGBkZwcnJCfb29pW6EHNycrBlyxasWbMGeXl5mDlzJlxcXP5YF+mfhL+EoBKIKxWtj04hDriMQkFBAYyNjWFpaYmQkBBoaWnBy8sLDg4OFZry4+PjGQJw5coVxgrQp08fxgqgrq5e4zn+E/Dy5UuMHDkScXFxZVQbfwb9fxnWynbmyek/cEXFpozbpyrkvo1A8vEVUOs9HYpmQijlEaFP9mXkZKYxevP8V0ZGhsDcdkVFRaEi5NXU1DBp0iSw2WxERkbWKgm0sLBA48aNERgYKPaxDx06BAcHB+Tk5FRoffj+/Tu0tbUREhKCYcOGVes6SUlJOHPmDEJDQ3HlyhUUFhbC1NQUdnZ26NevH4YMGYI2bdrg+PHjNbkdREdHw9XVlUkRXrduncCqglXh1KlTsLOzw/z582tcMpmf2shisZCRkfFHP5fT09MREhKCgIAA3L9/H0pKShgxYgQcHR3RsWPHSglWfn4+du/ejdWrVyMtLQ2TJk2Cu7v7L0nR/bdAlPX7nx+FIgKCIz9XSAYKEt8i42YgCuJLpFal6zaBqtU4SGkLZq0XEqTAadwF7ZTy8Pz5c5w+fRrLly/H7Nmzyz0Ei4qKcPfuXYYEREdHg81mw8LCAgsWLICNjQ3MzMz+dVaAn/FzsBx/QZ8xYwYCAwMxffp0rFu3DqampsjOzi7TriL/N1BiJldVVYVivaZAe9F2bzkvbwJsScg1FVIDgsXC9Ucx0JQsgLq6Opo1a1bpDl5NTU0kU/OGDRtgZWWF0NBQDBkyRKR7EQXm5ua4fPlyrYydnJwMOTm5Sl0RT548AYAqiwFVBm1tbUycOBETJ05EVlYWzp8/j9DQUKxdu5YRDOvSpQvu3r0LS0vLasfamJiY4Ny5c4yIWKdOnWBnZwcfHx80atRI6HEGDRqEjRs3Yvbs2TAyMsK0adOqNR+ghKQoKCjA2Nj4jyQDRUVFuHTpEgICAnD69GkUFRXB2toaQUFBGDRoUJVuk6KiIhw4cAArV65EfHw8nJycsHTpUhgaGv6aG/iP4j9jIfiSloueG26igFteBKUg8S2SDrlAQlEDiq37gEDIijoHXn4WdBzXg6OuV64PEQHFRUjaPxOTRw/BkiVLypivvn79WsYKkJWVBS0trTJWADU1tVq959qCKMFyP/9dUbCcgoICZGRkkJaWBg6HAwsLCzRs2LCMSV7Q/5WVlZkH/ZPP6bDbcU/o++AV5uHrFnvI1GsJrWGeQvdb3lEBnZrqoU6dOrVSZ8LGxgYfPnxATExMrUWO83eY6enpYve/uru74/Dhw/j48WOFbby9veHr64v09HSxq/llZ2ejYcOGkJGRQV5eHpKSkqCtrY2BAwfCzs4O3bt3L5PtIApKy4x/+/YNU6ZMgaenp0im6zlz5mDLli04c+ZMtes32NjY4Pbt23BycsK2bduqNUZt4NmzZwgICMDhw4fx/ft3tGjRglEP1NHRqbJ/cXExgoKCsGzZMrx79w4jR47EsmXLxJ6h8V/CXwuBALiFRoNbQbxA5u1DYElKoY7jOkjIlrxh8s2t8G33FGTcDITm4PJqYywWC5CQRF/PQ9jsbIXCwkJcv36dIQExMTFgs9mwtLSEi4sLbGxsYGpq+sdYAbhcbrXS2oQJliu9aDds2LDMAi5ocVdRUQGHwwFQEqE+evRo3L17F9bW1nB1dRV6ZyclKdp7mxv7AFRUAPnm3UTqN2nCOBR9/wCgxB1Qp06dci8dHZ0yf2tqagq9uK9evRpmZmY4cOAAJk6cKNLchIW5uTmAEmnXXr16iXXs5OTkKgNf+eXGa0Pa99ixY0hMTMTTp09hYmKCBw8eMBkL/v7+UFRURN++fWFnZwcbGxuRNjlsNhv29vYYOnQoNm/ejNWrVyMwMBCLFi3CnDlzhArQ9PPzw8ePHzF8+HDcvn1b5LLrQMnCm5OTUy3XhbiRmJiII0eOICAgAM+fP4empibGjBkDR0dHtG7dWqjPmIhw8uRJLF26FC9fvsTAgQNx8uRJtGzZ8hfcwV/w8Z+wEFSVivZ5/TDIGrWBpu2iMse/H1uOvI9PoD87CGypik1cTd8fx51zJZGy2trajBWgV69etWoF4PF4yMzMrNZOvTJluaoWcEH/V1VVFVvuL5fLxbJly7B69Wp0794dBw8eFGp3kVPARYtlFyFsmGhSiCcKvr6EnvNBsDnCzZ0F4PhIA2SkJCExMbHMKyEhgfl/ampqmX5sNhuamppVEoc6depASUkJY8aMwa1btxAXFyeWqPSfwePxoKamhoULF8Ld3V2sYw8ePBh5eXk4f/58hW2MjY1ha2sLPz8/sV6by+WiSZMmaNmyJU6ePFnmHBHhxYsXCAsLQ2hoKKKioiAlJYUePXrA1tYWgwYNErmgWEpKCry8vLB9+3ah4of4yMnJgZWVFb5+/YqHDx+KlI7Mr0UClGQwCFNcTdzIz8/H6dOnERAQgIsXL0JCQgIDBgyAk5MT+vTpwxD8qkBEuHDhAjw8PBAVFYVevXrBy8uLIax/UXP8tRD8hMMPP1eaWkjFRWBJlvfzsjjSQDEXRcmfIK0rWPedeMX4Im2IRYsWwcbGBq1btxbJClBRsJwwO/WKyrCy2exyi7a2tjaaNm1a5UIvDi33mkJSUhJeXl6wsrKCvb09WrVqhcDAQPTp06fSfvLSkqinJidUlkFxbibyPz6FfNMuQpMBoESitE2rFgAqz2kvLCzE9+/fyxEF/is2Nha3bt1CQkICU4WPD74uwLdv39CuXTt06dJFIHnQ1taudiocm81Gu3btEBERUa3+lSE5OblSX296ejrev39fo/iBinD48GG8e/dOYCAhi8VCixYt0KJFC3h4eODTp09MxsK0adMwdepUdOjQAba2trCzsxNYtvpnaGhoYOPGjXB2dsbixYsxbtw4bNiwAWvXrq008l9eXh5nzpyBpaUl+vbtizt37lSqd5BTwMXH1BwUcnmIef4ULI4MNFWVfml1QyLC/fv3ERAQgKNHjyIzM5OpOjpixAiRNz83btyAh4cH7t69i06dOuHGjRvo2rVrLc3+L4TBf4IQXH/zvdL0Qo6aHgq+vQHxihl1OyouQsG3NwAAblYqKvI4stgSUG/ZBXOmmSM9PR0vXrwQaacuTLBc6UXbyMioyp26oqLiH+OaqAl69OiBZ8+ewcnJCTY2NliwYAFWrVpV6SJo1VhLKB2CnFe3AF6xSO4CCTYLVo2EqwopJSUFPT096OmVjz8pDT4hFEQcwsLCEBsbCxaLheTk5DLV+vhQV1cXymWhpqZWjuiZm5tj7969ICKxksCUlBS0a9euwvPiCCgUBC6Xi5UrV2LQoEFC6X4YGBhg1qxZmDVrFlJSUhAeHo7Q0FAsWbIECxcuRIsWLWBnZwc7O7sqTd/GxsYICQnBgwcPsGDBAlhbW6N3795Ys2YNWrVqJbCPtrY2zp07hw4dOmDYsGE4e/ZsmZ01o5//5js+p5XVz9efdwwyRVlYfuYlxljUQ0Pt2tPP//jxIw4ePIjAwEC8ffsW+vr6mDFjBhwdHavl23/48CE8PDxw5coVtGnTBhcuXEDv3r1/+0bkL/4DhCC7gIvPVewYFc36Iu3idqSe2wwlyyEA8ZB57yiKs9MBAMQVHAjHx8eUHCiqaoCK8sudU1BQKLdom5iYVLlTLx0s91+GlpYWzp49y8ge37x5s1LZ4zEW9XDg/scqx815cQNsORXIGLYWei7FPIK9pXh3ZCwWC0pKSlBSUioXsT579mwYGxujf//+8Pb2BpfLRUpKSoVWhy9fviAiIgKJiYnlXEIcDqccacjMzERSUhL27NmDFi1aMMdr6qKoKoYgKioKcnJyIkXoC4MjR47g3bt3IokQ8aGhoYGxY8di7NixyMnJwcWLFxEaGootW7Zg5cqVMDAwYCwHHTt2rDAexNLSErdv30ZYWBhcXV1hamoKR0dHeHl5CSSHTZs2xcmTJ2FtbY1p06bB398fX9PzqhRNY7FYKJBSwsGHn3Dg/kexV9jLysrC8ePHERAQgJs3b0JeXh5Dhw7Frl270K1bt2ptOJ49e4YlS5bgzJkzaN68OU6ePAlbW9u/ROAPwr8+huDFt0z023KnynbpNwPx4+FJgMcFAEjVaQgZIzP8uHcUmoPdIdeofaX9le9vhwplQ0FBAUpKSlBWVoaKigrk5eUhKysLGRkZyMrKlvn/z//+fExYP9x/BXzZ4+TkZOzevRsjR44U2M5h70Pce58qkuhUVZBgs9DBSB0HJ1iIbUxhUN3yyDk5OUhKSqqQPCQmJiI+Ph4JCQnl+iopKQmMbfjZ8qChoVGOtBYXF4PD4WDXrl2YNGmSwLmNHj0anz59wt27d0V7MyoBl8tFs2bN0LRpU5w6dUps4xYVFeHmzZsICwtDWFgY4uPjoa6uzmQs9OzZs0ICVVRUhN27d2P58uXIysrC3Llz4erqKtA1EBgYCCcnJzgs24mH3Hoii6ZJsFmQZLMY0bTqoLi4GNeuXUNAQABOnjyJ/Px8WFlZwcnJCYMHD662LPDr16/h6emJkJAQNGjQAMuXL8eIESP+bnh+Ef4KE5WCKKloxfnZKEr+BLa0PKS0DJF+MwA/7h+DzsTtkNKo/Edm9PYE2OmfkZeXh/z8fOTl5ZX5f35+PgoKCkSau4SEhFDEoapzoo7xJ/9Qf/z4gSlTpiA4OBgTJkzApk2byqX+VZZiWl1IS7JxZW7XX17jvLbLI+vp6cHOzg5TpkyplDwkJCQgPT29TF82mw0tLa0yJEFJSQmbNm3C/PnzMWjQIOa4goICsxNs0qQJevXqhS1btojtPvhplI8ePUKbNm3ENm5p8Hg8PHr0iAlKfP36NeTl5dGnTx9GDElQCuePHz/g6+uL9evXQ0FBAZ6enpgyZUo5wj94yW5EcXVRUhiy+rvmBb0bYaZV+eJrFeHVq1cICAjAoUOHEB8fj0aNGjHqgTWJUfjw4QOWL1+OgwcPQldXF56ennB0dPy70fnF+EsISkFYC4EgJATMRXF2OnSn7wOLVbmJ7KxzJzSvW3kRFB6Ph/z8/DIkQRBxqOiYqO35/y8qKhLpvjkcTo1JhajHZGRkhDZDEhH279+PmTNnVih7HBz5GYtORot035XBd7AJRlRz51VT+Pn5wdXVFa9evRJYZbMmGDJkCNLS0nD9+vUq2xYUFDBWh8rcFvHx8eX6ysnJMemXDx8+RPfu3WFlZVXO8qClpSXyglFcXIxmzZqhUaNGOHPmjEh9a4LXr18z5CAiIgKSkpKwsrJiMhZ0dXXLtP/69SuWLFmCgIAANGjQAD4+PrCzswOLxfrl39fU1FQEBQUhICAAjx49gqqqKkaOHAknJyeYm5vXyIwfHx8PLy8v7NmzB+rq6nB3d8fkyZOrrf3wFzXDX0JQCqKmojH9Xt1Cyqk1ULUaDyWLwZW2ZQGIWWZdplTyn4Ti4uJaIRpVHasoWLIiSElJiUQ0cnNzcenSJaSlpaF///7o1q0b00ZWVhY3U2QQ/rnmwZU594Jw1HM8unfvXuOxqoOfyyOLE76+vvDy8kJGRoZYLEO3bt1C165d8fDhQygpKZUjD8+ePcPFixfRsGFDZGZmIjk5uVygpIaGRoUpmaWPqaiogMVi4fDhw7C3t0dkZCTatm1b43uoDuLj45mMhRs3boDL5cLCwoKJOygdfPf8+XO4uLjg4sWL6NChA1yW+8LlZpZAi1b+p+dICiqvgwIAdRzWVZj9JMiiVVhYiHPnziEgIABnz54FEaFv375wdHRE//79a7xgJycnw8fHB9u3b4ecnBxcXV0xc+ZMsRfP+gvR8JcQ/ISqCt7kf45B5t0gyNQ3BVtWCYXfXiP7+RXI1DeF1tClTOZBRTBQl8PNBVbinvY/HkVFRbVOPnJzc5GUlIScnBxISEiUIyEKLXtDtdcUsNgSYEmIQNh4xQDxoPnpOj5dD0Jqaiq6d+8OIyMjsbhmpKSkRNqF7du3DxMmTBC7Sfz69evo3r07YmJiBNabFxUnT57EkCFDkJKSIrAex+bNm+Hi4oKsrCxwOBwUFRUhOTm5Qj2H0sdycnLKjCUlJQVtbW0kJydDWVkZtra2AsmDtra22DQyhEF6ejrOnj2L0NBQXLhwAbm5uWjSpAmTsdC2bVuwWCxcvnwZCxcuREKTIZA1bA0IsELyCYFimwGQ0ikbhClrZAYJOcFWSX7MS+B4czx+/BgBAQEICir5HpuamsLJyQmjRo2ClpZwWTOVISMjA+vWrcPGjRvBZrMxf/58zJ079x+5Vvwb8VeH4CdUlYomoagOsNn48fAkeIV5kFTRhkoXByiZ21ZJBkRJRfuvgcPhgMPhQFGx9lKi+Dh58iQmTJgAJSUlBAQEwNTUlCENH77/wMZ7SXiWVAg2C6gsVosFAoEF9eJUGKdFApQCbXNzPHjwAFevXsWnT5/A4XAEEh1RwGKxRCIVUlJSUFNTw9ChQzF+/Phqu2Z+Nse3adMGLBYLERERYiEEycnJjA6GIERFRaFly5bMPDgcDurWrStUwGR2dnY5knD16lWcOnUKZmZmiIyMRGJiIpKSksoRQxUVlUrFoPjH1NXVa5yyq6qqCnt7e9jb2yMvLw+XL19GaGgodu/eDW9vb+jq6sLW1ha2trY4dOYK+m9/WOWY0vrNId9EyHobKMmIuf02Bc0su+N1xA3UqVMH48aNg6Ojo1iqigIln8emTZuwbt06FBQUYNasWVi4cOF/pjDbvxH/CQtBVUqFNcWVuV3QQKv2F72/qBx82eOHDx9ixYoV5WSPmbzu2O/4nFo2r5uFEtEhq0ZasLesV+7zLCgowPDhw3HhwgWcOHEC/fv3L3OeiFBQUCB2a0jpc9+/f0d8fDxUVVXB4/GQl5dXYW2IiiAhIVGOLHz+/BnKyspo2rRpjWNGDh06hMOHD+PZs2cCA1VbtmyJDh06iCVAsri4GC1atED9+vVx7ty5MsdTU1OrtDokJiYiIyOj3Pujra0tFHkQtY4Fl8vFnTt3mLiDz58/o06/WZBu0VOgdQD4n4VAw3YRZOubgcWRrnKTwgfxiqGTHYdlA5qjZ8+eYquLkZeXh507d8Lb2xuZmZmYOnUqFi9ejDp16ohl/L8QL/66DATg35SK9hcVo7TssZWVFQ4dOiRQ9ri08puUJBuG6vJVxoAUFhZi5MiRCA8PR0hICGxtbWvpLgSDiNC+fXvweDw8fPgQLBarXKBqdchHeHg4kpOT0adPH6HHEDVQVVJSEjIyMsjOzoaamho0NTVrHJz68OFDeHt7Y9++fWjXrp3AMara7fOLHwlDHn4mXwoKCpUSB/5xQXUsiAhPnjyB47EPyEbF7gw+IWBJyYIK8wAWG9L6zaFqNf7/2rvzuJrT93/gr/fp1GmhVLKLbGVL0YKQaETDDDNDJEPTZwwfa4VhlCTiY2f4GutkMJhpaux79i1KMhliMBFaLC1KdXpfvz9m6jdNdTrndKK4nv/Mo3Pe93XuzKPeV/f7vq8LsoYVbzDV5OPM/Px8bNmyBfPnz8fTp0/h7e2NwMDAN1otkamOE4IyvEtH0VjFoqKiMHLkSBQWFmLr1q0YMGCARuIWFBRg5MiRiIyMxK5du6q0RXFZTp06BRcXF4SHh2vss9etW4fJkycjMzNT6aJEcrm8zBMzM2bMwJMnT/C///2vVDJx+/ZtrF69Gt7e3jAxMVE5gcnNzYUoqvbzW7RRtbKnZnR1dVFYWIjc3Fy8evUKr169QmZmJl6+fFlcfTQ9PR2pqaml+lgIglCij0VR8mBSryH+L60lFB0xfP3od2RdiYReCztI9I1QkJ6EzOhIUMFrNPBaAp0Gissra2LDc2FhIbZv347g4GA8ePAAnp6emDt3Llq1aqV2TPbmcEJQjnfpKBqrWGpqKsaMGYNDhw7B398foaGhatf+/ye5XI5Ro0bh559/xo4dO+Dh4aGB2SpP0+2RY2JiYGdnhwsXLqBbN8UFuCri5uaGWrVq4Zdffin13nfffYdJkyYhKytL7U1+RRtVd+7cWVyPwtLSsspP0Sjxa7IEmUwGHR0daGtrQyKRFG8gFUURcrkcBQUFEI0aof7olar/G7x4jCebJ0HWtD3qe8yr8HpljkSXRRRFhIeHIygoCLdu3cInn3yC4OBgdOiguI8Hq154U2E5htubIz07D0uPJlY61vR+lpwMVHP16tXD/v37sWLFCsycObO47LEyTWsUkUql2LZtG6RSKTw9PVFYWAhPT08Nzbpimm6P3LFjR8hkMkRHR1c6IUhPT4eFhUWZ78XGxqJ9+/aV2vGvra0NLS0trFq1Cm5ubm8kGSMi5OfnazzReCExwkM15qNt3Ah6rR2Rk3ihRP+V8uSruCpKRDhw4AACAgJw/fp1DBgwANu3b6+ygk+s+nivEgIAmOjSGnVryRC0N0Ht8qDzPmrPyUANUXQMqlevXhg+fDhsbW2xfv16jBgxolJxpVIpwsLCIJVKMWrUKMjlcnz++ecamrVitra2GDFiBObOnYuRI0dWuveAjo4ObG1tNdL5UFEfg9jYWI00NAoPD8fNmzexadOmSsdShiAIkMlkkMlkCjsSqqoyRdOkhnWBQjmoIA+CTPEjSx2p8qcmTpw4gYCAAFy6dAnOzs44e/YsevRQ/nQDq9lqfks8NQy3N8dxX2d0b/HX8RgtieLz4EXvd29hiuO+zpwM1ED29va4du0aBg4cCE9PT/j4+JQ6164qLS0tbN68GV988QXGjBmDLVu2aGi2FZs3bx5SUlKwZs0ajcRzcHDQSEKQnp4OMzOzUq/n5+fjxo0blU4IRFHEvHnz8MEHH1R6NeNta25qoHaBYvnLpxCkOhB0FK+2CH9/TkUuXLiAPn36wNXVFaIo4tixYzh58iQnA++Z9zIhAICmJvrY5uOIY1N7YZRjMzQz1S/1wyngr126oxyb4bhvL2zzceQNhDWYoaEhduzYgS1btmDXrl2ws7NDfHx8pWJKJBKsX78e48aNg4+PDzZs2KCh2SrWqlUrjB07FgsXLix1dE4dDg4OuHv3Lp4/f652jFevXiE3N7fMFYKbN28iPz+/0glBREQEEhISEBQUVKk41YGBTArzCn6fFOZklHotP+Uecu5EQ7e5bYUl1c1N9RVuKIyNjcWHH34IJycnPHv2DHv27MGlS5fg6urKXQjfQ+/dI4N/a12/NuZ+1B5z0V6to2isZhEEAd7e3ujatSuGDx8OBwcHLF++HOPHj1f7F6BEIsHatWshlUrx1VdfoaCgABMmTNDwzEsLDAxEWFgYFi9ejNDQ0ErFcnBwAABcuXIFbm5uasVIT08HgDJXCGJjYyEIAjp16qT2HEVRRHBwMFxdXeHk5KR2nOqkoqJpab/+DxJtHcgat/37lMFDZF8/DEFbBuPeYxTGVlQ07ebNm5gzZw5++eUXtGnTBrt27cLQoUMrXZSJ1Wz8f/8fDGRStG9kBFtzY7RvZMTJwDusbdu2uHTpEnx8fDBhwoTiJj/qEgQBq1atgq+vLyZOnIhVq1ZpcLZla9CgAXx9fbFy5Uo8fvy4UrFatWqFOnXqVOqxQVpaGgCUuUIQExMDKysrlYv5/FNkZCR+++23d2J1oMhIR3OF+5j023RFYU4mMqN/xfOj65Bz6yz023RHwzEroF23qcLYhSLBq2vJx5t//PEHRo0ahQ4dOiAmJgbff/89EhIS4OHhwckA4xUC9v7S09PD2rVr4erqii+++AI2NjbYuXOn2n99CoKAZcuWQVtbG1OnToVcLoe/v7+GZ13S9OnTsW7dOoSEhGDdunVqxxEEodL7CCpaIajM44KivQN9+vR5p55rt65fGzYNZIh7nAOUcVrA0O4jGNp9pHLcoqJpRRU3Hz58iJCQEGzZsgX169fH2rVr4ePjo5FjuOzdwSkhe+8NGTIE169fh7m5OZydnbFgwQKVOzUWEQQBixYtwjfffINp06Zh0aJFGp5tSUZGRvjmm2+wceNG3Llzp1KxHB0dER0drfKZ+yLlrRDI5XJcv369UgnBnj17EB8f/06tDsjlcixatAhH53sDpLmCaQAglQgIHdIRKSkpmDp1Klq1aoXIyEgsXrwYd+/exfjx4zkZYKVwQsAYAHNzc5w6dQqzZs1CYGAg+vXrp/YyvCAImD9/PoKCgjBr1izMnz9fw7MtacKECWjYsCECAgIqFcfBwQGpqalISkpSa3x6ejoMDAxKHYO8ffs2cnNz1U4IivYOuLi4oFevXmrFqG5u376NHj16YPbs2Zj0hSdCBmum4VCRr/s2x/8tCUGLFi0QFhaGwMBA3Lt3D35+fpU+psreXfzIgLG/SaVShISEwMXFBV5eXujUqRO2bt0Kd3d3lWMJgoC5c+dCKpUiMDAQcrkcQUFBVbJzW1dXF8HBwfDx8cGMGTPULiBjb28PAIiOjkazZs1UHl9eDYLY2FgAgI2NjVrz2rt3L65fv45Tp06pNb46EUURq1evxqxZs9C0aVOcO3eu+PhkRp6okaJpXaTJ8P34r4JZU6dOxbRp08rtPsnYP/EKAWP/0qdPH1y/fh329vb48MMP4e/vr3JXwSIBAQFYuHAhgoODERgYqPZyfEU+//xztG3bFrNmzVI7Rv369dGsWTO19xGUV4MgNjYWLVu2RJ06dVSOSUQIDg5G79694ezsrNa8qot79+7BxcUFvr6+GDt2LOLi4krUUpjo0hqLPukImVRSYW2Uf9OSAFoQ8frMZhxYMhk+Pj64d+8eFixYwMkAUxonBIyVwczMDPv378eyZcvw7bffwsnJCXfv3lUr1syZM7F06VIsWLAAM2fOrJKkQCqVYsGCBTh27BhOnDihdpzKbCxUtEKg7qrF3r17ERcXV6P3DhARvvvuO1hbWyMpKQknT57EqlWroK9fugaBukXTCh4mIHnjOAyxro+7d+9i+fLlqFev7COHjJWHEwLGyiGRSODn54cLFy7gxYsX6Ny5M3bu3KlWLH9/f6xcuRKLFy+Gv79/lSQFgwcPhqOjI2bNmqV2fAcHB1y9ehVyuVzlsWWtEIiiiGvXrqm1f6BodaBXr17o3bu3yuOrg4cPH8LNzQ3jx4+Hl5cX4uPjK/xelC2aZqwth/z3KDzZ9F/0kdzEzeizWLduHZo0aVJV3w5715ESMjIyCABlZGQoczlj75yMjAzy9PQkAOTt7U3Z2dlqxVmzZg0BoEmTJpEoihqeJdHJkycJAIWHh6s1/vTp0wSA4uPjVR5raWlJvr6+JV5LTEwkAHT06FGV4+3du5cAUFRUlMpj3zZRFGnLli1kaGhIjRs3psOHD1cqXvbrAvot+SXFPHhGSzfvolZW7QkADR06lG7evKmhWbN3kSr3b04IGFOSKIr0/fffk76+PllZWVFcXJxacdavX08AaPz48VRYWKjhWRL179+fLC0tqaCgQOWxWVlZJJFIaNOmTSqPNTU1pdDQ0BKv7dq1iwBQWlqaSrFEUaTOnTtTz549qyRxqkqPHz+mgQMHEgAaPXo0vXjxotIxRVGkyMhI6tChAwGggQMH0rVr1yodl737OCFgrAr9/vvvZG1tTTKZjNasWaPWDWvz5s0kCAJ9+eWXGk8KYmNjCQBt3LhRrfEdO3aksWPHqjRGLpeTIAi0YcOGEq/PmDGDzM3NVZ7Dvn37CAAdP35c5bFviyiK9OOPP5KxsTHVr1+f9uzZo5GYR44cIXt7ewJAffv2pQsXLmhgtux9wQkBY1UsNzeXJkyYQABo8ODB9OzZM5VjhIWFkSAI5O3tTXK5XKPzGzFiBDVu3JhycnJUHuvj40M2NjYqjUlNTSUAFBkZWeJ1V1dXGjx4sEqxRFEkOzs7cnJyqjGrA6mpqfTZZ58RAPLw8KD09PRKxzxz5gz17NmTAFC3bt1q5KMT9vZxQsDYGxIREUHGxsbUtGlTOnv2rMrjd+zYQRKJhEaNGqXRpODOnTsklUpp8eLFKo9dv349aWlp0atXr5Qek5CQQABK/BuIokgmJiY0b948lT7/wIEDBICOHTum0ri3JSIigszMzMjU1JR2795d6XjR0dHk5uZGAMjW1pYOHDhQYxIjVv1wQsDYG/Tnn39Sjx49SCKRUEhIiMo39l27dpGWlhaNGDFCref+5fnvf/9LxsbGKj/DvnbtGgGgc+fOKT2maDPirVu3il978OABAaD9+/crHUcURbK3t6fu3btX+5vg8+fPaeTIkQSAPv74Y3r69Gml4sXHx9PgwYMJALVt25bCw8OrZI8Je79wQsDYG1ZQUECBgYEkCAK5uLhQcnKySuPDw8NJKpXS0KFDKT8/XyNzevLkCenr69OsWbNUGpefn096enq0fPlypceEh4cTgBJL5REREQSAHj9+rHScgwcPEgA6cuSISnN+0w4cOEANGzYkIyMj+uGHHyqVvCQmJtKIESNIEARq0aIF/fDDDxp/hMTeX5wQMPaWREVFUcOGDalu3boq/WVMRPTrr7+StrY2DRkyhPLy8jQyn9mzZ5Oenp7KCYqTkxMNHz5c6eu/++47kkgkJf6iDQgIoAYNGigdQxRFcnR0pG7dulXb1YGMjAzy8fEhAOTm5kYPHz5UO9aDBw/oiy++IC0tLWrSpAmtX79eY8kgY0U4IWDsLUpNTSV3d3cCQH5+fird3Pft20c6Ojo0aNAgev36daXn8vLlSzIxMaFx48apNM7X15datGih9PUhISFkZmZW4jV3d3dyd3dXOsahQ4cIQKXP7FeV48ePk7m5OdWqVYs2bNigdtLy+PFjmjhxImlra1O9evVo5cqVlJubq+HZMvYXTggYe8sKCwtp+fLlpK2tTV26dKE7d+4oPfbQoUMkk8nI3d1dIzeKpUuXkpaWFiUmJio9ZufOnSrVD5gyZQq1a9eu+GtRFKl+/foUEBCg1HhRFKlr167k6OhY7VYHsrOzi0+UuLi40P3799WKk56eTtOnTyc9PT2qU6cOhYaGUlZWlmYny9i/cELAWDVx9epVatmyJdWqVYt27Nih9LijR4+Srq4uubm5qXV08J9yc3OpSZMm5OHhofSYP/74gwDQwYMHlbre09OTevXqVfx1cnIyAaCIiAilxh85coQA0KFDh5Se45tw9uxZatmyJenp6dHq1avV2uT38uVLmjNnDtWuXZtq1apFgYGBGilWxJgyOCFgrBpRt+zxiRMnSF9fn1xdXVU6AliWzZs3EwC6evWqUteLokimpqY0d+5cpa7v168fffrpp8VfFxUWevDggVKf1a1bN3JwcKg2qwM5OTnk7+9PgiBQ9+7dVVpdKZKdnU0LFy4kY2Nj0tXVpWnTpqlcsZGxyuKEgLFq5p9ljy0tLZUuO3v69GkyMDCg3r17V2p5uaCggNq2bUv9+vVTesyAAQOU3gNga2tLX331VfHXwcHBZGJiotQN/ujRowSADhw4oPTcqtLly5fJysqKZDIZLVmyROUd/7m5ubRy5UqqV68eaWtr04QJE1Q6acGYJqly/+Zuh4y9AYIgYMyYMYiJiYGuri66du2KNWvWVNiVsFevXjhy5AiuXr0Kd3d3ZGVlqfX5Re2Rjx49iqioKKXGFLVCrmiOQOlOh7GxsejcuTMEQXH7Xvq7o6GdnR0GDBig1LyqSl5eHmbPno3u3bujVq1aiI2NxbRp06ClpaXU+IKCAmzcuBGtW7eGn58fBg4ciMTERKxZswYNGzas4tkzpgGazjAYY4rl5ubSxIkTiwvaKFP2+OLFi2RoaEjdu3dX++ew6Fifvb29Un+5F1UMvHfvXoVxdXV1aeXKlcWvNW3alGbMmFHhZxw/flzl4kVV4dq1a2RtbU1SqZRCQkJUOv4nl8tp27Zt1LJlSwJAw4cPp9u3b1fhbBlTHj8yYKwGiIyMVKnscXR0NNWpU4ccHR3V3pSmSnvkov4Eu3btUnhddnY2AaDt27eXGFdRGV9RFKlHjx5kZ2f31vYO5Ofn07x580gqlZK1tbVKHQRFUaTw8HBq165dcXJ3/fr1qpssY2rghICxGiIpKam47PG8efMqfF4dExNDxsbGZGdnp1ZDJSLV2iNbWFiQn5+fwmvu379forpg0YmBio5anjhxggDQ3r17lZ+8BiUkJJCdnR1paWnR7Nmzla4XIYoiHTx4kDp37kwAqF+/fnT58uUqni1j6uGEgLEapKCggObMmUOCIFDv3r3p0aNHCq+Pi4sjU1NTsrGxUaurnirtkT08PKhHjx4Kr7ly5QoBoJiYGCIiWrhwIRkaGio8oieKIvXq1Ys6d+78xlcH5HI5LV68mGQyGVlZWal0Mz958iQ5OTkRAOrRowedPn26CmfKWOVxQsBYDRQVFUWNGjUiU1PTCp+px8fHk5mZGVlbW1NqaqrKn6Vse+Rly5aRnp6ewtWEov4DSUlJREQ0dOhQcnZ2Vhg3KiqKANCePXtUnntlJCYmUvfu3UkQBPL391e6xsPFixfJ1dWVAJCdnR0dPny42hyRZEwRPmXAWA3k4uKCuLg4ODo6YuDAgfDz80NeXl6Z13bs2BGnTp1CSkoKXFxckJKSotJnzZs3DykpKVizZo3C6xwcHJCbm4uEhIRyr0lPTwcA1K1bF8D/P2GgSHBwMGxtbTFo0CCV5q0uURTx7bffolOnTkhJScGZM2ewdOlS6OnpKRwXFxeHQYMGoVu3bnj69CkiIyMRHR0NNze3Ck9QMFbjaDrDYIxVjiiKSpc9/v3336lhw4ZkZWWl8ll3ZdojZ2dnk5aWFq1fv77ca5YtW0YGBgZERPTixQsCQNu2bSv3+qKNjb/++qtK81XX/fv3ycXFhQDQhAkTlCoM9fvvv9OwYcMIALVu3Zp+/PFH7kDIaiReIWCsBhMEAb6+vrh48SIyMjJga2uLHTt2lHmtlZUVTp8+jaysLPTu3RvJyclKf05gYCDy8vKwePHicq8xMDBAhw4dEB0dXe416enpxasDcXFxAKBwhSA4OBg2Njb46KOPlJ6rOogIGzduRMeOHfHHH3/g+PHjWLNmDQwMDModc//+fYwZMwbt27fHpUuXsGnTJty8eRMjRoxQuh4BYzUVJwSMVVNdunRBbGwsPv74Y3h5ecHb2xvZ2dmlrmvdujVOnz6N169fw9nZGQ8fPlQqfoMGDeDr64uVK1fi8ePH5V5XVKCoPGlpacVFiWJjY6GnpwdLS8syrz1z5gxOnTqFOXPmVOmS+6NHj+Du7o6xY8fCw8MDN27cQN++fcu9Pjk5GePHj0ebNm1w5MgRrFq1ComJifDx8YFUKq2yeTJWrWh6yYExplmiKFJYWFiFZY/v379PzZs3JwsLC6V6CBAp1x5548aNJJFIyi2dPHjwYOrfvz8REY0cOZK6detWbqw+ffqQtbW1Wk2ClCGKIm3dupWMjIyoYcOGFZZDTk1NJT8/P9LV1SUTExNavHhxpftGMFad8CMDxt4hgiBg9OjRiI2Nha6uLhwdHcsse9y8eXOcPn0agiDA2dkZ9+7dqzC2kZERvvnmG2zcuBF37twp8xoHBweIoojY2Ngy3//3CkF5jwvOnj2LqKgoBAUFQSLR/K+elJQUDBkyBKNHj8bAgQPx22+/wd3dvcxrX7x4gYCAAFhYWGDTpk2YNWsW7t+/j+nTp0NfX1/jc2OsRtB0hsEYqzq5ubk0adKk4sp4ZdUhePjwIbVu3ZqaNm1aYXGgopiK2iMXFBSQvr4+LVmypMz3LS0tydfXl7Kzs0kQBNq8eXOZ1/Xt25c6duxYJasDP/30E5mampKZmZnClstZWVk0f/58qlOnDunp6dHXX3+tVi0HxmoKrkPA2Dvu119/JRMTE2rSpAmdOXOm1PvJyclkaWlJjRo1UqqufkXtkXv27ElDhw4t8z0TExMKDQ2lc+fOEYAyH2kUvffzzz9XOBdVpKenk4eHBwGgTz/9tNyaDDk5ObRs2TKqW7cu6ejo0OTJk+nJkycanQtj1REnBIy9B5KSkqhnz57llj1+8uQJtWvXjho0aEA3b95UGKui9sj+/v7UrFmzMscJgkAbNmyg1atXk46OTpklgD/44APq0KGDRlcH9uzZQ/Xr1ydjY2P68ccfyywUlJeXR+vWraNGjRqRlpYWffnll/Tnn39qbA6MVXecEDD2nqio7HFKSgp16NCB6tWrR7/99pvCWBEREQSATpw4Ueq93bt3EwB6+vRpqfgAKDIyksaMGUNdunQpNfb8+fMEgH766Sc1vsPSXrx4QZ9//jkBoIEDB5ZZf0Eul1NYWBhZWFiQIAjk5eWl1OMTxt41nBAw9p45efJkcdnjffv2lXgvLS2NOnXqRHXr1lXYjU9Re+SiBkb/jp2QkEAA6OzZs2RtbU1ffvllqbj9+vWj9u3ba2R14PDhw9S4cWMyNDSkLVu2lJpnYWEh7d69m6ysrIofI1SUCDH2LuNTBoy9Z3r37o3r16+ja9euGDRoEHx9fYvLHtetWxdRUVEwNzeHi4sLrl27VmYMQRCwaNEiXLlyBRERESXea9asGczMzErVI0hLSwMAGBoaIiEhodQJg4sXL+Lo0aOYM2dOpU4WZGVl4auvvkL//v3Rrl073LhxA97e3sW1DIgI+/fvR+fOneHh4QELCwtcvXoV4eHhaN++vdqfy9h7RdMZBmPs7RFFkVasWEHa2trUuXNnSkxMLH7v+fPnZG9vT3Xq1KErV66UG6O89sgffvghubm5lXgtPDycANDRo0cJQKnOgW5ubtSuXbtKrQ6cPHmSmjdvTgYGBrRu3boSqwKiKNLx48epa9euBIB69+5N586dU/uzGHvX8AoBY+8pQRAwdepUXLx4EZmZmejcuTO2b98OADA2NsaxY8dgZWUFV1dXXL58ucwYoaGhuH37NsLCwkq8XlSxkP5R/yAtLQ0SiQR3796FlpYWrK2ti9+7fPkyjhw5gsDAQLVWB3JycjBlyhS4uLjA3Nwc8fHxGDduXPGqwIULF9CnTx+4urpCFEUcO3YMUVFRcHJyUvmzGGPgFQLG3lWZmZnk5eVFAGj06NHFlQYzMjLIycmJateuTefPny9zbFntkQ8dOkQASmzOCwkJITMzMxo7dixZW1uXiDFgwACysrJSqynQ+fPnqXXr1qSrq0srVqwoscIQExNDAwYMIADUqVMn2rt3L7ciZqwcvELAGEPt2rWxbds2bN26FeHh4ejSpQvi4uJgaGiIw4cPw9bWFm5ubjh79mypsWW1R7a3tweAEvsIiqoU/rtCYXR0NA4dOoQ5c+ao1BTo9evX+Prrr9GzZ0+YmJggLi4OU6dOhUQiQUJCAj777DN06dIF9+7dw+7duxEbG4tBgwZxK2LGNEHTGQZjrPq5desW2djYkI6ODq1evZpEUaTs7Gzq06cP6evr08mTJ0uNKas9csuWLWnKlCnFX3t6elKPHj2K4xZxd3dXeXXg6tWr1K5dO9LR0aGFCxcW72G4e/cueXl5kSAI1Lx5cwoLCyu1v4ExVjZeIWCMlWBpaYmLFy9i3LhxmDx5MgYPHozXr19j3759cHJygru7O06cOFFiTFntkf/d+TAtLQ0ymQz5+fnFKwRXrlzBwYMHERAQoNTqQH5+PoKCguDo6AiZTIaYmBjMnDkTT548wdixY2FpaYmoqCisXbsWt2/fxujRo7kDIWNVQdMZBmOsetuzZ09x2ePTp09Tbm4u9e/fn3R1denw4cMlrp09ezbp6elRcnIyERGtWLGCZDIZvcjKod+SX1LH3oOo64ChJNHRK96jMHDgQGrTpo1SqwPx8fFkY2NDUqmUgoKCKD8/n54+fUpTpkwhHR0dqlu3Li1btqzEXgbGmPJUuX8LRP9qmVaGzMxMGBkZISMjA4aGhlWfpTDGqtSjR4/g6emJ8+fPIygoCNOmTYOHhweOHTuGiIiI4i6BGRkZaNGiBYYNGwa/uYuxdM9l7I+9D23jRiUDEqGZqQHaGRM2zxyDLStD4eXlVe7ny+VyLFmyBEFBQWjTpg22bt0KCwsLLFmyBKtXr4a2tjamT5+OyZMno3bt2lX5T8HYO02V+zcnBIy9p+RyOebPn4+QkBD07NkTW7ZsgZ+fHw4dOoTw8HAMGjQIADBn8WpsiM2EroUttASgUNFvDBIBQQKnlqZY9Ik1mpqUbiV869YtjB49GlevXsX06dPh7++PdevWYdmyZSgsLMTUqVPh7+8PY2PjKvrOGXt/qHL/5j0EjL2npFIp5s6dixMnTuDOnTtwcHDAmDFjMGjQIHzyySeIjIzEritJ2J3VGrJmf9UXUJgMAIDw16+US/efw3XFaey6klT8VmFhIZYvXw5bW1u8fPkSJ06cgKmpKdq2bYvQ0FD85z//wb179zB//nxOBhh7C3iFgDGG9PR0eHt7Y//+/Zg0aRKePHmC40+kMOpZ/rK/sqb1a4MB5hKMGTMG586dw8SJE4sfD6Snp+M///kPAgIC0LhxYw18J4yxf+JHBowxlRERvv32W0yfPh0t+41CTochGouddXwdDNMTMGzYMOzatQuPHj3CqFGjEBQUBAsLC419DmOsJE4IGGNqO3Q2GuP3JYMk2uUW/Ml7ehcZ535E3qObIHkBpHXqo5ZNfxjafVTqWiKChOSQHArFvRtXMGzYMMydOxdt27at6m+FsfeeKvdvPszLGCvhx0SCllSn3P0CufdjkRo+Dzr1W8Ko+3AIOrqQv3yKwqz0Mq8XBAGiKMCg1xe49sMG2NjYVN3kGWNq44SAMVbsTkoWzt4t+8YOAGJeDtL3L4deS3uYDZkFQVBuX7KgJUV27aao1ailpqbKGNMwPmXAGCu243IStCTl9wV4dfMUxFcvYdzrcwiCBGL+axCJSsXWkgjYfimp4gsZY28FrxAwxoqdvJ2KQrH8bUWvH8RBkOlDnv0MqRHzIX+eDEFbFwYdXGDS90sIUp1yxxaKhJOJqZiL9lUxdcZYJXFCwBgDAGTnyZH0PEfhNQXPHwNiIdJ+CUEt637QdR6N10k3kBWzD+LrVzD7eIbC8UnPcvAqTw4DGf/qYay64Z9KxhgA4M9nr1DRkSMqeA0qyEMt2wEw+eArAIC+ZXdQYQGy4w6joOdIaJuUX0+AADx49grtGxlpbuKMMY3gPQSMMQBAvrzivQBFjwQM2jqXeN2gXW8AQF7yLY18DmPszeOEgDEGANCRVvzrQKuW6V//NahT8nWDv/7iF19na+RzGGNvHv9kMsYAAM1NDVD++YK/6DT469igPOtZidflWc8BAFr6ih8FCH9/DmOs+uGEgDEGADCQSWFeRnfCEtdY9QQAZMcfLfF6dvxRQKIFmXlHhePNTfV5QyFj1RT/ZDLGirlY1sO2y3+We/RQp0FLGFh/gFfxx5AmitA174DXSTeQc+scDLsNhbS2abmxtSQCXNrUq6qpM8YqiRMCxlixkY7mCLv4QOE1pm4TIDU0Q3b8ceQkXoTUyAzGfb+Eof3HCscVigSvruYanC1jTJM4IWCMFWtdvzZ6tqqLC/eelbtKIGhJUaeHJ+r08FQ6rpZEQPcWpmhVr7ampsoY0zDeQ8AYKyF0SEdIFZQvVodUIiB0iOL9BYyxt4sTAsZYCU1N9BH8kWbLC8/7qD2aVrBhkTH2dnFCwBgrZbi9Oab1a6ORWNP7WcLDnvcOMFbd8R4CxliZJrq0Rt1aMgTtTYBcJIVNj/5NSyJAKhEw76P2nAwwVkPwCgFjrFzD7c1x3NcZ3Vv8XaGwgr0FRe93b2GK477OnAwwVoPwCgFjTKGmJvrY5uOIOylZ2HE5CScTU5H0LKdEIyQBfxUdcmlTD15dzfk0AWM1kEBEFa4DZmZmwsjICBkZGTA0NHwT82KMVWOv8uR48OwV8uUidKQSNDc14AqEjFVDqty/+SeYMaYyA5mUWxgz9o7hPQSMMcYY44SAMcYYY5wQMMYYYwycEDDGGGMMnBAwxhhjDJwQMMYYYwycEDDGGGMMnBAwxhhjDJwQMMYYYwycEDDGGGMMnBAwxhhjDJwQMMYYYwycEDDGGGMMnBAwxhhjDJwQMMYYYwycEDDGGGMMgFSZi4gIAJCZmVmlk2GMMcaY5hTdt4vu44oolRBkZWUBAJo2bVqJaTHGGGPsbcjKyoKRkZHCawRSIm0QRRGPHz9G7dq1IQiCxibIGGOMsapDRMjKykKjRo0gkSjeJaBUQsAYY4yxdxtvKmSMMcYYJwSMMcYY44SAMcYYY+CEgDHGGGPghIAxxhhj4ISAMcYYY+CEgDHGGGMA/h9PKG8N4ZfesAAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# a classical Hamiltonian instance\n", + "clauses = [\n", + " [4, 1, 7],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [4, 11, 8],\n", + " [4, 1, 10],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [1, 11, 8],\n", + " [4, 1, 7],\n", + " [0, 11, 8],\n", + " [4, 1, 10],\n", + " [4, 11, 8],\n", + " [5, 0, 10],\n", + " [0, 6, 7],\n", + " [5, 0, 11],\n", + " [0, 6, 7],\n", + " [5, 0, 9],\n", + " [3, 6, 7],\n", + " [5, 0, 8],\n", + " [5, 6, 7],\n", + " [5, 0, 10],\n", + " [3, 6, 7],\n", + " [5, 0, 10],\n", + " [1, 6, 7],\n", + " [2, 4, 6],\n", + " [1, 8, 11],\n", + " [2, 4, 6],\n", + " [2, 8, 11],\n", + " [2, 4, 9],\n", + " [5, 8, 11],\n", + " [2, 4, 10],\n", + " [2, 8, 11],\n", + " [2, 4, 10],\n", + " [4, 8, 11],\n", + " [2, 4, 8],\n", + " [4, 8, 11],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [2, 11, 7],\n", + " [3, 0, 9],\n", + " [0, 11, 7],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [3, 11, 7],\n", + " [3, 0, 7],\n", + " [4, 11, 7],\n", + " [5, 0, 10],\n", + " [4, 0, 10],\n", + " [2, 5, 6],\n", + " [2, 11, 10],\n", + " [2, 6, 10],\n", + " [2, 4, 9],\n", + " [0, 9, 10],\n", + " [3, 0, 7],\n", + " [2, 5, 6],\n", + " [1, 10, 9],\n", + " [1, 4, 11],\n", + " [5, 10, 11],\n", + " [0, 4, 8],\n", + " [0, 9, 8],\n", + " [2, 11, 10],\n", + " [2, 8, 6],\n", + " [3, 6, 7],\n", + " [0, 8, 10],\n", + " [4, 0, 9],\n", + " [3, 5, 8],\n", + " [5, 11, 10],\n", + " [2, 11, 10],\n", + " [4, 11, 8],\n", + " [1, 3, 11],\n", + "]\n", + "factor = 1 / len(clauses) / 4\n", + "\n", + "# convert to a NetworkX graph\n", + "graph = nx.Graph()\n", + "for i, j, k in clauses:\n", + " graph.add_edge(i, j, weight=0)\n", + " graph.add_edge(j, k, weight=0)\n", + " graph.add_edge(k, i, weight=0)\n", + "for i, j, k in clauses:\n", + " graph[i][j][\"weight\"] += 1\n", + " graph[j][k][\"weight\"] += 1\n", + " graph[k][i][\"weight\"] += 1\n", + "pos = nx.spring_layout(graph)\n", + "nx.draw_networkx(graph, with_labels=True, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Then we construct the Hamiltonian from the graph." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "def b2s(bit):\n", + " return 1 - 2 * int(bit)\n", + "\n", + "\n", + "def energy(cfg):\n", + " E = 0.25\n", + " for a, b in graph.edges:\n", + " E += cfg[a] * cfg[b] * graph[a][b][\"weight\"] * factor\n", + " return E\n", + "\n", + "\n", + "def construct_Ham():\n", + " num_nodes = graph.number_of_nodes()\n", + " Es = []\n", + " for i in range(2**num_nodes):\n", + " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", + " Es.append(energy(list(map(b2s, case))))\n", + " return jnp.asarray(Es)\n", + "\n", + "\n", + "Hv = construct_Ham()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Here we calculate $e^{-\\tau\\hat{H}}$ in advance to perform exact imaginary-time evolution for comparison with approximate imaginary-time evolution." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 5, + "outputs": [], + "source": [ + "tau_c = 0.025\n", + "exp_tauHv = K.exp(-tau_c * Hv)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T02:33:37.999586200Z", + "start_time": "2023-07-13T02:33:37.923540200Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "### Variational wave function" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Here we choose regular QAOA ansatz as the parameterized quantum circuit ([PQC](https://tensorcircuit.readthedocs.io/en/latest/textbook/chap5.html?highlight=变分))." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 6, + "outputs": [], + "source": [ + "nlayers = 20 # the number of layers\n", + "\n", + "\n", + "@partial(K.jit, static_argnums=(1, 2))\n", + "def wfn_classical(params, each=1, return_loss=False):\n", + " n = graph.number_of_nodes() # the number of nodes\n", + "\n", + " # PQC loop\n", + " def pqc_loop(s_, params_):\n", + " c_ = tc.Circuit(n, inputs=s_)\n", + " for j in range(each):\n", + " # driving layer\n", + " for a, b in graph.edges:\n", + " c_.RZZ(a, b, theta=graph[a][b][\"weight\"] * params_[2 * j] * factor)\n", + " # mixing layer\n", + " for i in range(n):\n", + " c_.RX(i, theta=params_[2 * j + 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(n)\n", + " for i in range(n):\n", + " c0.H(i)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, K.reshape(params, [nlayers // each, 2 * each]), s0)\n", + " c = tc.Circuit(n, inputs=s)\n", + "\n", + " if return_loss:\n", + " loss = 0.25\n", + " for a, b in graph.edges:\n", + " loss += c.expectation_ps(z=[a, b]) * graph[a][b][\"weight\"] * factor\n", + " return K.real(loss)\n", + " else:\n", + " return c.state()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T02:33:38.001837Z", + "start_time": "2023-07-13T02:33:37.969064900Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "### Optimization" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We use two methods to calculate $\\boldsymbol{\\delta}$, one is to calculate directly according to the expressions of $\\boldsymbol{A}$ and $\\boldsymbol{C}$, and the other is to call the existing API to calculate $\\boldsymbol{A}$ and $\\boldsymbol{C}$. The former only needs to calculate the $|\\partial_{\\boldsymbol{\\theta}_{j}}\\psi\\rangle$ once, while the latter needs to calculate that twice, but the code of the latter is more concise. In each method, we set the parameter ``fixed_global_phase`` to decide whether to fix the global phase, that is, whether the second term of $\\boldsymbol{A}$ vanishes.\n", + "\n", + "Then we choose the existing optimizer, SGD, to implement the update step. Since compared with naive gradient descent, the approximate imaginary-time evolution has been corrected on the update step size, the adaptive optimizer improved for the naive gradient descent such as Adam is not suitable for the approximate imaginary-time evolution. When update by the adaptive optimizer, the loss function fluctuates greatly. On the other hand, the update method of SGD without momentum is naive update, which is convenient for comparison with the exact imaginary-time evolution." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 7, + "outputs": [], + "source": [ + "@partial(K.jit, static_argnums=(3,))\n", + "def d_params(params, psi, eps=1e-6, fixed_global_phase=False):\n", + " psi = psi[:, None]\n", + " psiHT = K.conj(K.transpose(psi))\n", + " par_psi = K.jacfwd(wfn_classical, argnums=0)\n", + " jac = par_psi(params)\n", + " jacHT = K.conj(K.transpose(jac))\n", + "\n", + " A = K.real(jacHT @ jac)\n", + " if not fixed_global_phase:\n", + " A -= K.real(jacHT @ psi @ psiHT @ jac)\n", + " # protection\n", + " A += eps * K.eye(params.shape[-1], dtype=A.dtype)\n", + "\n", + " C = K.real((psiHT * Hv) @ jac)[0]\n", + "\n", + " return K.solve(A, C, assume_a=\"sym\")\n", + "\n", + "\n", + "@partial(K.jit, static_argnums=(2,))\n", + "def d_params_api(params, eps=1e-6, fixed_global_phase=False):\n", + " if fixed_global_phase:\n", + " qng = experimental.qng(\n", + " wfn_classical, kernel=\"dynamics\", postprocess=None, mode=\"fwd\"\n", + " )\n", + " else:\n", + " qng = experimental.qng(\n", + " wfn_classical, kernel=\"qng\", postprocess=None, mode=\"fwd\"\n", + " )\n", + " A = K.real(qng(params))\n", + " # protection\n", + " A += eps * K.eye(params.shape[-1], dtype=A.dtype)\n", + "\n", + " vag = K.value_and_grad(partial(wfn_classical, return_loss=True), argnums=0)\n", + " loss, C2 = vag(params)\n", + "\n", + " return loss, K.solve(A, C2 / 2, assume_a=\"sym\")\n", + "\n", + "\n", + "if K.name == \"jax\":\n", + " opt = K.optimizer(optax.sgd(tau_c))\n", + "else:\n", + " opt = K.optimizer(tf.keras.optimizers.SGD(tau_c))" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T02:33:38.002380500Z", + "start_time": "2023-07-13T02:33:37.969607700Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 8, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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6qkK38+tt97K//73vwrfD0gAqjIa3DoIAHXb7awb86eLqxFCiJpn1KhRNG/enKSkJObNm0f79u1JTk7GaDS6ujRSUlIYMWIEcXFxuLm5ERISwm233cbMmTPJz893touKikKlUqFSqfD09KRly5Z89dVX19z2Bx98wCuvvFLsuc2bN6PRaOjVq1ex506cOOHcl0qlIiAggG7durF7925nm9tvv52RI0c6H7/66qu8/PLL2O32G/guXB8JQFVEfMOhFOa5gU8OGWdWubocIYSocRITE+nSpQu1a9fG19cXvV5PaGgoKpXKpXUdP36cFi1asGrVKt555x12797N5s2beemll1i+fDmrVxedQuWNN94gOTmZ3bt306ZNG/r06cOmTZuuuP3PPvuM9u3bU6dOnWLPzZ49m+HDh/Pbb79x7ty5El+/evVqkpOT+fnnn8nNzaVnz55XPGrWs2dPcnJy+Omnn0r/DbhBEoCqCK1Gz9nkWgDUvmUHFlPFp2MhhLgaRVGw5dlcsihK6WfGj4qKYurUqUXWNW/enHHjxjkfq1QqPvvsM+6//348PDyoW7cu33//PXD5SEZ6ejqDBw9GpVIxb968YqfABg8eTNOmTSksLATAbDbTokUL+vfv79zPd999R8uWLXFzcyMmJobx48djtVqdzx89epROnTrh5uZGo0aN+OWXX67Zv6effhqtVsuOHTt4+OGHadiwITExMdx33338+OOP3HPPPUXae3t7ExoaSr169ZgxYwbu7u788MMPV9z+4sWLi20DIDc3lyVLljBs2DB69erFvHnzSnx9QEAAoaGhtG7dmsmTJ5OamsrWrSXf31Kj0XDXXXexePHia/a7rLQVvgdRbvzq3glKIob4LWx8+xi3v1nP1SUJIWowe76dDV4bXLLvjrkd0XhqynWb48eP57333mPSpEl8+OGH9OvXj5MnTxIREUFycjL169fnjTfeoE+fPhiNxmIf4tOmTaNZs2a8/PLLvP/++7zyyitkZmYyffp0ADZs2ED//v2ZNm0aHTt2JDEx0TmuZuzYsdjtdh544AFCQkLYunUrWVlZRU4PlSQ9Pd155MfT07PENlc7QqXVatHpdJjN5hKfz8jI4MCBA7Ru3brYc0uXLqVBgwbUr1+fxx57jJEjRzJmzJir7s/d3R3givsDaNu2LRMnTrzi8+VFjgBVIV3a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" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1999: 6.1109702587127686\tTotal: 12327.309196949005\n" + ] + } + ], + "source": [ + "steps_classical = 2000\n", + "\n", + "# initial parameters\n", + "params = K.implicit_randn(shape=(2 * nlayers,), stddev=0.1)\n", + "params_fgp = K.copy(params)\n", + "params_api = K.copy(params)\n", + "params_fgp_api = K.copy(params)\n", + "psi_exact = wfn_classical(params)\n", + "\n", + "losses, losses_fgp, losses_exact = [], [], []\n", + "losses_api, losses_fgp_api = [], []\n", + "\n", + "eps = 1e-6\n", + "t0 = ts = time.time()\n", + "\n", + "for i in range(steps_classical):\n", + " psi = wfn_classical(params)\n", + " loss = K.real(K.tensordot(K.conj(psi) * Hv, psi, 1))\n", + " delta = d_params(params, psi, eps)\n", + " params = opt.update(delta, params)\n", + " losses.append(K.numpy(loss))\n", + "\n", + " psi_fgp = wfn_classical(params_fgp)\n", + " loss_fgp = K.real(K.tensordot(K.conj(psi_fgp) * Hv, psi_fgp, 1))\n", + " delta_fgp = d_params(params_fgp, psi_fgp, eps, fixed_global_phase=True)\n", + " params_fgp = opt.update(delta_fgp, params_fgp)\n", + " losses_fgp.append(K.numpy(loss_fgp))\n", + "\n", + " loss_api, delta_api = d_params_api(params_api, eps)\n", + " params_api = opt.update(delta_api, params_api)\n", + " losses_api.append(K.numpy(loss_api))\n", + "\n", + " loss_fgp_api, delta_fgp_api = d_params_api(\n", + " params_fgp_api, eps, fixed_global_phase=True\n", + " )\n", + " params_fgp_api = opt.update(delta_fgp_api, params_fgp_api)\n", + " losses_fgp_api.append(K.numpy(loss_fgp_api))\n", + "\n", + " loss_exact = K.real(K.tensordot(K.conj(psi_exact) * Hv, psi_exact, 1))\n", + " psi_exact *= exp_tauHv\n", + " psi_exact /= K.norm(psi_exact)\n", + " losses_exact.append(K.numpy(loss_exact))\n", + "\n", + " eps *= 0.999\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " plt.plot(range(i + 1), losses_exact, c=\"r\", label=\"exact\")\n", + " plt.plot(range(i + 1), losses, c=\"b\", label=\"unfixed GP\")\n", + " plt.plot(range(i + 1), losses_fgp, c=\"g\", label=\"fixed GP\")\n", + " plt.plot(range(i + 1), losses_api, c=\"m\", label=\"unfixed GP (API)\")\n", + " plt.plot(range(i + 1), losses_fgp_api, c=\"y\", label=\"fixed GP (API)\")\n", + " plt.legend()\n", + " plt.show()\n", + "\n", + " te = time.time()\n", + " print(f\"Epoch {i}: {te - ts}\\tTotal: {te - t0}\")\n", + " ts = te" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "id": "98a6b152", + "metadata": {}, + "source": [ + "### Results" + ] + }, + { + "cell_type": "markdown", + "source": [ + "We first show the overlap between the final states obtained by different methods. The final states obtained by different methods but with the same parameter of ``fixed_global_phase`` are almost the same, which are also close to the exact final state. And the final states obtained by the same method but with the different parameter of ``fixed_global_phase`` has a global phase difference." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 9, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "overlap between psi_fgp and psi\n", + "|overlap|: 0.9184369993048669\n", + "overlap: (-0.4580633040968157+0.7960556080651879j)\n", + "\n", + "overlap between psi_fgp_api and psi_api\n", + "|overlap|: 0.9184279183739732\n", + "overlap: (-0.4588479071459403+0.7955931368209131j)\n", + "\n", + "overlap between psi_api and psi\n", + "|overlap|: 0.999999996801054\n", + "overlap: (0.999999545918014-0.0009496135391365943j)\n", + "\n", + "overlap between psi_fgp_api and psi_fgp\n", + "|overlap|: 0.9999999922593946\n", + "overlap: (0.9999999907968652+5.408381530766986e-05j)\n", + "\n", + "overlap between psi_exact and psi\n", + "|overlap|: 0.8876639929202528\n", + "overlap: (-0.45130602703961775+0.7643757153944926j)\n", + "\n", + "overlap between psi_exact and psi_fgp\n", + "|overlap|: 0.9290015132797724\n", + "overlap: (0.9278995939751679-0.04523444679473629j)\n", + "\n", + "overlap between psi_exact and psi_api\n", + "|overlap|: 0.8876569548840061\n", + "overlap: (-0.45202998890392976+0.7639396302624046j)\n", + "\n", + "overlap between psi_exact and psi_fgp_api\n", + "|overlap|: 0.9290084278770248\n", + "overlap: (0.9279048483224752-0.04526865942553761j)\n" + ] + } + ], + "source": [ + "psi = wfn_classical(params)\n", + "psi_fgp = wfn_classical(params_fgp)\n", + "psi_api = wfn_classical(params_api)\n", + "psi_fgp_api = wfn_classical(params_fgp_api)\n", + "\n", + "overlap = K.tensordot(K.conj(psi_fgp), psi, 1)\n", + "print(\n", + " f\"overlap between psi_fgp and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_fgp_api), psi_api, 1)\n", + "print(\n", + " f\"overlap between psi_fgp_api and psi_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_api), psi, 1)\n", + "print(\n", + " f\"overlap between psi_api and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_fgp_api), psi_fgp, 1)\n", + "print(\n", + " f\"overlap between psi_fgp_api and psi_fgp\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact), psi, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact), psi_fgp, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_fgp\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact), psi_api, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact), psi_fgp_api, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_fgp_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\"\n", + ")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T05:59:13.932343300Z", + "start_time": "2023-07-13T05:59:13.843507900Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then we show the exact solution by the brutal force method." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 10, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "min cost: 0.0\n", + "exact solution: ['000000111111', '111111000000']\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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T2vLGe/fD8TGAn366DxVAFQZcw0i+lswQ0BEAAADNwu0rKy0r6Ghrd8fP177eu5cu6ebGbolQUR/GwYERAQA8LC2NhwUuLlpX+/tM9D8s4E9Au73Uf2QiLoWAwIiAgAMd3CAuaHf4L29ta+Vla3fb/7Z2VnvqY0iCGLnQqJuiwEBEQEARjk6tl+DAABCQrSv337b+v1vvtE2QTJQZ2AkAwKiboubCokIABDu6goXCwtUNTbqH+TlpX2qICND+7TBkCFAcTGQnQ3MnPn/txTuYQ7gaWdn9LGx6ZK1E9H9Y0BARAAAazMzzPfwwPpr19DU3sBFi4AnntAGBTk52r8vWABMm6b3lCYAr7ObIVG3xuZGRNSiqqEBPvn5+K2hAYbrDxrHAtrbEceHDuVTBkT/YR35/uYeAiJq4WJpia0+PiYLBhQAFmZmSBs4kMEAUTfHgICIWol0c8NqT8/7nkf588+Xfn4YYGt73/MRUddiQEBEbazo3x//rVIB0G4I7CgLAFaKgv/198fzejYaElH3woCAiNpQFAXv9O+PY4GB6P1nwSJjEv7NwcMIR0ecGTECU9zdu3CVRGRKDAiISK+xzs44P3IkPvDygtdf0v6WigJzaAOAv3ZI/C8nJ+zw80PO0KHwsrP7zy+YiDqNjx0SUbvszc2xoHdv/MvDA2f++AOFajWKa2tR1dgIMwA9rKww3MEBIx0coOJeAaIHFgMCIjKKoigIeOwxBDz22N+9FCLqArxlQERERAwIiIiIiAEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERgQEBERERAbAwZpCIAABqamq6dDFERERkOs3f283f4+0xKiBQq9UAgL59+97HsoiIiOjvoFar4eTk1O4YRYwIGzQaDW7cuAEHBwcoimKyBRIREVHXERGo1Wp4eHjAzKz9XQJGBQRERET0cOOmQiIiImJAQERERAwIiIiICAwIiIiICAwIiIiICAwIiIiICAwIiIiICMD/AesKzAgE7WDEAAAAAElFTkSuQmCC" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "idx = [f\"{bin(i)[2:]:0>{graph.number_of_nodes()}}\" for i in np.where(Hv < 1e-6)[0]]\n", + "print(f\"min cost: {0.}\\nexact solution: {idx}\")\n", + "\n", + "# plot NetworkX graph\n", + "colors = [\"r\" if idx[0][i] == \"0\" else \"c\" for i in graph.nodes]\n", + "nx.draw_networkx(graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T05:59:14.080058300Z", + "start_time": "2023-07-13T05:59:13.925677800Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then we use the bit string with the maximum probability as the approximate solution since we know all information of the probability distribution of the output quantum state, but which is not feasible in the experiment. For the hard problem with rough energy landscape, approximate imaginary-time evolution with 20-layer ansatz gives mediocre results, similar to those obtained by the Adam optimizer with 30-layer ansatz, which can be found in the tutorial of [QAOA for NAE3SAT](qaoa_nae3sat.ipynb). However, this does not mean that approximate imaginary-time evolution is more practical than Adam optimizer because under the same ansatz, the former consumes much more time for each step update than the latter. In contrast, the exact imaginary-time evolution gives excellent results but takes exponential time to compute on a classical computer." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 11, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost by exact IME: 0.01636900218695893\n", + "cost: 0.03377396891545763\t0.02951298530564577 (fgp)\n", + "cost (API): 0.033775089880425574\t0.0295121140061756 (fgp)\n", + "\n", + "max prob by exact IME: 0.13847431901217763\n", + "max prob: 0.03930045644879558\t0.05100224184204695 (fgp)\n", + "max prob (API): 0.03929777441862845\t0.05100594691342963 (fgp)\n", + "\n", + "bit strings by exact IME: ['111111000000']\n", + "bit strings: ['111111000000']\t['000000111111'] (fgp)\n", + "bit strings (API): ['000000111111']\t['111111000000'] (fgp)\n" + ] + } + ], + "source": [ + "loss = K.real(K.tensordot(K.conj(psi) * Hv, psi, 1))\n", + "loss_fgp = K.real(K.tensordot(K.conj(psi_fgp) * Hv, psi_fgp, 1))\n", + "loss_api = K.real(K.tensordot(K.conj(psi_api) * Hv, psi_api, 1))\n", + "loss_fgp_api = K.real(K.tensordot(K.conj(psi_fgp_api) * Hv, psi_fgp_api, 1))\n", + "loss_exact = K.real(K.tensordot(K.conj(psi_exact) * Hv, psi_exact, 1))\n", + "print(f\"cost by exact IME: {K.numpy(loss_exact)}\")\n", + "print(f\"cost: {K.numpy(loss)}\\t{K.numpy(loss_fgp)} (fgp)\")\n", + "print(f\"cost (API): {K.numpy(loss_api)}\\t{K.numpy(loss_fgp_api)} (fgp)\\n\")\n", + "\n", + "\n", + "# find the states with max probabilities\n", + "def find_max(psi):\n", + " probs = K.numpy(K.real(K.conj(psi) * psi))\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{graph.number_of_nodes()}}\")\n", + " return max_prob, states\n", + "\n", + "\n", + "prob, states = find_max(psi)\n", + "prob_fpg, states_fpg = find_max(psi_fgp)\n", + "prob_api, states_api = find_max(psi_api)\n", + "prob_fpg_api, states_fpg_api = find_max(psi_fgp_api)\n", + "prob_exact, states_exact = find_max(psi_exact)\n", + "print(f\"max prob by exact IME: {prob_exact}\")\n", + "print(f\"max prob: {prob}\\t{prob_fpg} (fgp)\")\n", + "print(f\"max prob (API): {prob_api}\\t{prob_fpg_api} (fgp)\\n\")\n", + "print(f\"bit strings by exact IME: {states_exact}\")\n", + "print(f\"bit strings: {states}\\t{states_fpg} (fgp)\")\n", + "print(f\"bit strings (API): {states_api}\\t{states_fpg_api} (fgp)\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T05:59:14.197783300Z", + "start_time": "2023-07-13T05:59:14.080058300Z" + } + } + }, + { + "cell_type": "markdown", + "id": "4ae99ab9", + "metadata": {}, + "source": [ + "## Quantum Hamiltonian" + ] + }, + { + "cell_type": "markdown", + "id": "720dd1a4", + "metadata": {}, + "source": [ + "The quantum Hamiltonian is the Hamiltonian of the transverse and longitudinal field Ising model." + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Define the Hamiltonian" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Here we also calculate $e^{-\\tau\\hat{H}}$ in advance to perform exact imaginary-time evolution for comparison with approximate imaginary-time evolution." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "2115bb6d", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-13T06:54:56.088379500Z", + "start_time": "2023-07-13T06:54:55.808504500Z" + } + }, + "outputs": [], + "source": [ + "N = 10\n", + "g = tc.templates.graphs.Line1D(N, pbc=False)\n", + "h = tc.quantum.heisenberg_hamiltonian(\n", + " g, hzz=1, hyy=0, hxx=0, hz=0.5, hx=1, hy=0, sparse=True\n", + ")\n", + "H = tc.array_to_tensor(h.todense())\n", + "\n", + "tau_q = 0.001\n", + "exp_tauH = K.expm(-tau_q * H)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Variational wave function" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Compared with the regular QAOA ansatz in the classic example, this ansatz has a higher parameter density and the initial state is $|0\\rangle$ instead of $|+\\rangle$." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 14, + "outputs": [], + "source": [ + "l = 10 # the number of layers\n", + "\n", + "\n", + "@partial(K.jit, static_argnums=(1,))\n", + "def wfn_quantum(theta, each=1):\n", + " # PQC loop\n", + " def pqc_loop(s_, theta_):\n", + " c_ = tc.Circuit(N, inputs=s_)\n", + " for i in range(each):\n", + " for j in range(N):\n", + " c_.RZZ(j, (j + 1) % N, theta=theta_[i, j, 0])\n", + " for j in range(N):\n", + " c_.RX(j, theta=theta_[i, j, 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(N)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, K.reshape(theta, [l // each, each, N, 2]), s0)\n", + " c = tc.Circuit(N, inputs=s)\n", + "\n", + " return c.state()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T06:54:58.940024800Z", + "start_time": "2023-07-13T06:54:58.920216200Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "### Optimization" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We also use two methods to calculate $\\boldsymbol{\\delta}$, but make some changes in the method of directly calling the API and the update method. When calculating $\\boldsymbol{A}$, we call ``qng2`` instead of ``qng``, and when calculating $\\boldsymbol{C}$, we call ``dynamics_rhs`` instead of calculating the energy gradient by ``value_and_grad``. For the update method, we do not call the existing optimizer but directly adopt the naive update method." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 15, + "outputs": [], + "source": [ + "@partial(K.jit, static_argnums=(3,))\n", + "def d_theta(theta, psi, eps=1e-6, fixed_global_phase=False):\n", + " psi = psi[:, None]\n", + " psiHT = K.conj(K.transpose(psi))\n", + " par_psi = K.jacfwd(wfn_quantum, argnums=0)\n", + " jac = par_psi(theta)\n", + " jacHT = K.conj(K.transpose(jac))\n", + "\n", + " A = K.real(jacHT @ jac)\n", + " if not fixed_global_phase:\n", + " A -= K.real(jacHT @ psi @ psiHT @ jac)\n", + " # protection\n", + " A += eps * K.eye(theta.shape[-1], dtype=A.dtype)\n", + "\n", + " C = K.real(psiHT @ K.sparse_dense_matmul(h, jac))[0]\n", + "\n", + " return K.solve(A, C, assume_a=\"sym\")\n", + "\n", + "\n", + "@partial(K.jit, static_argnums=(2,))\n", + "def d_theta_api(theta, eps=1e-6, fixed_global_phase=False):\n", + " if fixed_global_phase:\n", + " qng = experimental.qng2(\n", + " wfn_quantum, kernel=\"dynamics\", postprocess=None, mode=\"fwd\"\n", + " )\n", + " else:\n", + " qng = experimental.qng2(wfn_quantum, kernel=\"qng\", postprocess=None, mode=\"fwd\")\n", + " A = K.real(qng(theta))\n", + " # protection\n", + " A += eps * K.eye(theta.shape[-1], dtype=A.dtype)\n", + "\n", + " vag = experimental.dynamics_rhs(wfn_quantum, h)\n", + " C = vag(theta)\n", + "\n", + " return K.solve(A, C, assume_a=\"sym\")\n", + "\n", + "\n", + "@K.jit\n", + "def update(theta, delta, tau):\n", + " return theta - K.cast(tau * delta, dtype=theta.dtype)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T06:55:01.610891800Z", + "start_time": "2023-07-13T06:55:01.549133100Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 16, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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tfesLklEpICMDPDzs2bdaWlwlu/5Iuvbty89e/YE4OWXX+att95i1apVdO7c2XVKKzAwkLCwsDPO7+fnx2effca1116Lv78/kyZNYuHCha6nhI8dO5annnqKPn36ABAVFcULL7zAk08+yXPPPcf8+fPZtm0bc+fOJSIiwlVHly5dzlrzrl27ME2T+vXrFxhftWpVsrKyAHjooYd45ZVXTps3JyeH119/nZSUFDp06HCBP62yTcGnFIqsV5uFH19JjRsXEFznd+d/byw+jywiUp5dfvnlrve+vr4EBASQkJBwQcto27YtI0aM4IUXXmDkyJG0b9/eNW3Dhg0sXbrUdYQHID8/n6ysLDIyMti6dSuRkZGu0HNyeUWxatUqHA4HvXr1cp16O2nkyJE888wzZGVl4efnx/jx4+natWuR1lNWKfiUUtGtnyA7bxF+DXfww7hXuP3/nrK6JBERFx8f55EXq9ZdWDabDfNf58Zyc3NPa+fu7l7gs2EYOByOC6rL4XCwdOlS7HY7u3btKjAtLS2NsWPHcscdd5w2n5eX1wWt56To6GgMw2D79u0FxkdFRQHg7e192jxPPPEEffv2xc/Pj9DQUMs7Z1tBwaeUatetE9++0oyqbdaSnfcToOAjIqWHYRT/6aaSEBwcTFxcnOtzamoqsbGxJbKuCRMmsG3bNv744w86derEtGnT6NevHwAtWrRg+/btREdHn3Hehg0bsn//fuLi4ggPDwdgxYoV51xflSpVuPHGG3nnnXd45JFHztrP51RVq1Y9aw0VhTo3l2I5+d0BCG39F7v+XGVtMSIiZVCHDh349NNPWbx4MX///Td9+vTBbrcX+3rWrVvH6NGj+eijj7jqqquYOHEiQ4cOZffu3QCMHj2aTz75hLFjx7J582a2bt3KjBkzeOaZZwDo2LEj9erVo0+fPmzYsIHFixfz9NNPn3e97777Lnl5ebRq1YqvvvqKrVu3sn37dj777DO2bdtWItta1in4lGL3PDmKnH3VMbyyWTRznNXliIiUOaNGjeLaa6/llltuoWvXrnTv3p06deoU6zqysrLo3bs3ffv2dV0+PnDgQK6//nruvfde8vPz6dSpE7NmzeK3337jiiuu4Morr+SNN96gZs2agPOU3A8//EBmZiatW7fm/vvvL9Af6Gzq1KnDunXr6NixI6NGjaJp06a0atWKt99+29XfSAoyzH+f/KzgUlNTCQwMJCUlxdUb30r/e+Ie6nb9hpz9EXS4ezduXp5WlyQiFUxWVhaxsbHUrl27yP1RRIrDuX4XC/v9rSM+pdwN972ImemFR+QhvnpBNzQUERG5GAo+pVxUk3rEr2oJgFfA/PO0FhERkXNR8CkDPIOcN9Wq3HIj63+aY3E1IiIiZZeCTxlwx9CHyNwZheGWz5pF71pdjoiISJml4FNGHNjRGoAazdaRl3P6zbdERETk/BR8yogO947GzPbAo8YBZo4//bkrIiIicn4KPmVEncsbcnSd81kyOQ718xERESkKBZ8yJCPjRgDCW67n6K6SueW6iIhIeabgU4b0eOo58hOqYvin8+M7z1tdjoiISJmj4FOGePl4sn9dCwCCo/TsLhGR8zFNk4EDB1K5cmUMw2D9+vVcd911DBs2rETXO2bMGJo1a1ai65CiKVPB588//+TWW28lIiICwzCYOXNmgemmaTJ69GjCw8Px9vamY8eO7Ny505piS0i1y+4HwL/xVlZ89aPF1YiIlG5z5sxh+vTpzJo1i7i4OBo3bsz3339fap5h9d1339GhQwcqVaqEt7c39evXp3///qxbt87VZvr06RiGgWEY2Gw2qlevTr9+/UhISLCw8rKrTAWf9PR0mjZtyuTJk884/dVXX+Wtt97i/fffZ+XKlfj6+tKpUyeysrIucaUl58bed5O+LRrDZrJpxTSryxERKdViYmIIDw+nXbt2hIWF4ebmRuXKlfH397e6NEaOHEmPHj1o1qwZP/30E9u3b+eLL74gKiqKUaNGFWgbEBBAXFwcBw4c4H//+x+//vor9957r0WVl3FmGQWYP/zwg+uzw+Eww8LCzAkTJrjGJScnm56enuaXX35Z6OWmpKSYgJmSklKc5RarD0fcZS5ciPnr/2qbpsNhdTkiUs5lZmaaW7ZsMTMzM60u5YL06dPHBFxDzZo1TdM0zWuvvdYcOnSoaZqmuXXrVtPb29v8/PPPXfN99dVXppeXl7l582bTNE3z2LFj5oABA8yqVaua/v7+5vXXX2+uX7++wLrGjRtnhoSEmH5+fmb//v3NkSNHmk2bNj1rbcuXLzcB88033zzjdMcpf9unTZtmBgYGFpj+0ksvmTabzczIyCjkT6N8ONfvYmG/v8vUEZ9ziY2NJT4+no4dO7rGBQYG0qZNG5YvX37W+bKzs0lNTS0wlHZXdhuBmW/DKzqW3975yOpyRKQCMk2T9Jx0SwbTNAtV45tvvsnzzz9P9erViYuLY/Xq1ae1adCgAa+99hpDhgxh3759HDhwgEGDBvHKK6/QqFEjAO6++24SEhL49ddfWbt2LS1atOCGG24gKSkJgK+//poxY8bw8ssvs2bNGsLDw3n33XPfZf/LL7/Ez8+PIUOGnHG6YRjnnN/b2xuHw0FeXl5hfhRyCjerCygu8fHxAISGhhYYHxoa6pp2JuPGjWPs2LElWltxa9K+DT++2ZDApps5uP874AGrSxKRCiYjNwO/cX6WrDttVBq+Hr7nbRcYGIi/vz92u52wsLCzthsyZAizZ8+md+/eeHh4cMUVV/DII48AsGTJElatWkVCQgKenp4AvPbaa8ycOZNvv/2WgQMHMmnSJAYMGMCAAQMAePHFF5k/f/45u1ns2LGDqKgo3Nz++RqeOHEio0ePdn0+ePAggYGBp827c+dO3n//fVq1alUqTtmVNeXmiE9RjRo1ipSUFNewf/9+q0sqlISDzie2V7/8bz3CQkTkIk2dOpWNGzfy119/uToTA2zYsIG0tDSqVKmCn5+fa4iNjSUmJgaArVu30qZNmwLLa9u27QXX0L9/f9avX88HH3xAenrBI1spKSn4+fnh4+ND/fr1CQ0N5fPPP7+ILa64ys0Rn5Np/vDhw4SHh7vGHz58+JyXFHp6erpSfFlyU7+n2b1vBu7VD/HzaxO5/f9GWl2SiFQgPu4+pI1Ks2zdxW3Dhg2kp6djs9mIi4tzfY+kpaURHh7OokWLTpsnKCioyOurW7cuS5YsITc3F3d3d9fygoKCOHDgwGnt/f39+euvv7DZbK4rl6Voys0Rn9q1axMWFsaCBQtc41JTU1m5cmWRkndpV7NhPZI2XAZAWroeYSEil5ZhGPh6+FoynK//y4VKSkqib9++PP300/Tt25devXqRmZkJQIsWLYiPj8fNzY3o6OgCQ9WqVQFo2LAhK1euLLDMFStWnHOdPXv2JC0t7bx9gU6y2WxER0cTFRWl0HORytQRn7S0NHbt2uX6HBsby/r166lcuTI1atRg2LBhvPjii9StW5fatWvz7LPPEhERQffu3a0rugQlJ11JFdYR0XwjOekZePgW//+CRETKu0GDBhEZGckzzzxDdnY2zZs3Z8SIEUyePJmOHTvStm1bunfvzquvvkq9evU4dOgQv/zyC7fffjutWrVi6NCh9O3bl1atWnHVVVfx+eefs3nzZqKios66zrZt2zJ8+HCGDx/O3r17ueOOO4iMjCQuLo4pU6a47tkjxa9M/VTXrFlD8+bNad68OQCPP/44zZs3d3UGe/LJJ3nkkUcYOHAgV1xxBWlpacyZMwcvLy8ryy4x3YY+h5nug71qEt+9PN7qckREypxPPvmE2bNn8+mnn+Lm5oavry+fffaZ6145hmEwe/ZsrrnmGvr160e9evX4z3/+w969e10X0/To0YNnn32WJ598kpYtW7J3714GDx583nW/9tprfPHFF6xbt45bbrmFunXrcvfdd+NwOFi+fDkBAQElvfkVkmEW9rrACiI1NZXAwEBSUlLKxC/dN+NbEXzlWg7Mu47eLy20uhwRKYeysrKIjY2ldu3a5fY/klI2nOt3sbDf32XqiI+cLjWlNQDhl28mNyPb4mpERERKNwWfMu7Wh57GzPLEHnqEHydMtLocERGRUk3Bp4wLqV6NpI3Ou4tmZM23uBoREZHSTcGnHDiW6LyZYUSTLbqZoYiIyDko+JQDnQY8hZntgVtEPL9MetvqckREREotBZ9yILJeHZI3NQTgWKJuZigiInI2Cj7lxNH4ZgBENN4MukOBiIjIGSn4lBMdeg3HzHXDI/IQcyd/YHU5IiIipZKCTzlRp1kTjm+tB8CBPbMsrkZERKR0UvApRw7vbQxAWPR2iysREREpnRR8ypFG7fsB4FMvhk3zfre4GhGR8mPp0qU0adIEd3d3unfvzqJFizAMg+Tk5BJdr2EYzJw5s0TXcT7PPvssAwcOLPH1XHnllXz33Xclvh4Fn3Lkqts7kx1TC8NmsvzXj6wuR0Sk3Hj88cdp1qwZsbGxTJ8+nXbt2hEXF0dgYKDVpREfH8/QoUOJjo7Gy8uL0NBQrrrqKt577z0yMjJc7WrVqoVhGBiGga+vLy1atOCbb74577LffPNNnn766dOmLV++HLvdTteuXU+btmfPHte6DMOgSpUq3HTTTaxbt87V5rrrrmPYsGGuz8888wxPPfUUDoejCD+FwlPwKWcO7WgAQJWILRZXIiJSfsTExNChQweqV69OUFAQHh4ehIWFYRiGpXXt3r2b5s2b89tvv/Hyyy+zbt06li9fzpNPPsmsWbOYP7/gHf2ff/554uLiWLduHVdccQU9evRg2bJlZ13+Rx99RLt27ahZs+Zp06ZMmcIjjzzCn3/+yaFDh844//z584mLi2Pu3LmkpaXRpUuXsx4l69KlC8ePH+fXX38t/A+gCBR8yhn/qp0BqNR4G4l79llcjYiUV6Zpkp+eb8lgXsAtO2rVqsWkSZMKjGvWrBljxoxxfTYMg48++ojbb78dHx8f6taty08//QT8c+QiMTGR/v37YxgG06dPP+1UV//+/bn88svJznY+LDonJ4fmzZtz3333udbz448/0qJFC7y8vIiKimLs2LHk5eW5pu/cuZNrrrkGLy8vGjVqxLx58867fUOGDMHNzY01a9Zwzz330LBhQ6KioujWrRu//PILt956a4H2/v7+hIWFUa9ePSZPnoy3tzc///zzWZc/Y8aM05YBkJaWxldffcXgwYPp2rUr06dPP+P8VapUISwsjFatWvHaa69x+PBhVq5ceca2drudm2++mRkzZpx3uy+GW4kuXS65bo8+xJ8/vYA9OJFZ70+gz3jdyVlEip8jw8Fiv8WWrPvqtKux+9qLdZljx47l1VdfZcKECbz99tv06tWLvXv3EhkZSVxcHPXr1+f555+nR48eBAYGnvbl/dZbb9G0aVOeeuop3njjDZ5++mmSk5N55513AFi8eDH33Xcfb731FldffTUxMTGufjPPPfccDoeDO+64g9DQUFauXElKSkqB00BnkpiY6DrS4+vre8Y25zoi5ebmhru7Ozk5OWecnpSUxJYtW2jVqtVp077++msaNGhA/fr16d27N8OGDWPUqFHnXJ+3tzfAWdcH0Lp1a8aPH3/W6cVBR3zKGXdPNw5vcj601N17rcXViIiUDX379qVnz55ER0fz8ssvk5aWxqpVq7Db7a5TWoGBgYSFhbm+wE/l5+fHZ599xuTJkxk9ejSTJk3i008/JSAgAHAGq6eeeoo+ffoQFRXFjTfeyAsvvMAHHzjvuzZ//ny2bdvGJ598QtOmTbnmmmt4+eWXz1nzrl27ME2T+vXrFxhftWpV/Pz88PPzY+TIkWecNycnh3HjxpGSkkKHDh3O2Gbfvn2YpklERMRp06ZMmULv3r0B6Ny5MykpKfzxxx9nrTU5OZkXXngBPz8/WrdufdZ2ERER7N+/v0T7+eiITzmUldUaWExo423kZWfj5ulpdUki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" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1999: 0.9534459114074707\tTotal: 1922.968999862671\n" + ] + } + ], + "source": [ + "steps_quantum = 2000\n", + "\n", + "# initial parameters\n", + "theta = K.implicit_randn(shape=(2 * l * N,), stddev=0.1)\n", + "theta_fgp = K.copy(theta)\n", + "theta_api = K.copy(theta)\n", + "theta_fgp_api = K.copy(theta)\n", + "psi_exact = wfn_quantum(theta)[:, None]\n", + "\n", + "losses, losses_fgp, losses_exact = [], [], []\n", + "losses_api, losses_fgp_api = [], []\n", + "\n", + "eps = 1e-6\n", + "t0 = ts = time.time()\n", + "\n", + "for i in range(steps_quantum):\n", + " psi = wfn_quantum(theta)\n", + " loss = K.real(K.conj(psi)[None, :] @ K.sparse_dense_matmul(h, psi[:, None]))[0, 0]\n", + " delta = d_theta(theta, psi, eps)\n", + " theta = update(theta, delta, tau_q)\n", + " losses.append(loss)\n", + "\n", + " psi_fgp = wfn_quantum(theta_fgp)\n", + " loss_fgp = K.real(\n", + " K.conj(psi_fgp)[None, :] @ K.sparse_dense_matmul(h, psi_fgp[:, None])\n", + " )[0, 0]\n", + " delta_fgp = d_theta(theta_fgp, psi_fgp, eps, fixed_global_phase=True)\n", + " theta_fgp = update(theta_fgp, delta_fgp, tau_q)\n", + " losses_fgp.append(loss_fgp)\n", + "\n", + " psi_api = wfn_quantum(theta_api)\n", + " loss_api = K.real(\n", + " K.conj(psi_api)[None, :] @ K.sparse_dense_matmul(h, psi_api[:, None])\n", + " )[0, 0]\n", + " delta_api = d_theta_api(theta_api, eps)\n", + " theta_api = update(theta_api, delta_api, tau_q)\n", + " losses_api.append(loss_api)\n", + "\n", + " psi_fgp_api = wfn_quantum(theta_fgp_api)\n", + " loss_fgp_api = K.real(\n", + " K.conj(psi_fgp_api)[None, :] @ K.sparse_dense_matmul(h, psi_fgp_api[:, None])\n", + " )[0, 0]\n", + " delta_fgp_api = d_theta_api(theta_fgp_api, eps, fixed_global_phase=True)\n", + " theta_fgp_api = update(theta_fgp_api, delta_fgp_api, tau_q)\n", + " losses_fgp_api.append(loss_fgp_api)\n", + "\n", + " loss_exact = K.real(\n", + " K.transpose(K.conj(psi_exact)) @ K.sparse_dense_matmul(h, psi_exact)\n", + " )[0, 0]\n", + " psi_exact = exp_tauH @ psi_exact\n", + " psi_exact /= K.norm(psi_exact)\n", + " losses_exact.append(K.numpy(loss_exact))\n", + "\n", + " eps *= 0.999\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Energy\")\n", + " plt.plot(range(i + 1), losses_exact, c=\"r\", label=\"exact\")\n", + " plt.plot(range(i + 1), losses, c=\"b\", label=\"unfixed GP\")\n", + " plt.plot(range(i + 1), losses_fgp, c=\"g\", label=\"fixed GP\")\n", + " plt.plot(range(i + 1), losses_api, c=\"m\", label=\"unfixed GP (API)\")\n", + " plt.plot(range(i + 1), losses_fgp_api, c=\"y\", label=\"fixed GP (API)\")\n", + " plt.legend()\n", + " plt.show()\n", + "\n", + " te = time.time()\n", + " print(f\"Epoch {i}: {te - ts}\\tTotal: {te - t0}\")\n", + " ts = te" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Results" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We first show the overlap between the final states obtained by different methods. Similar to the classical example, all final states obtained by approximate imaginary-time evolution are close to the exact final state. However, the final states obtained by the same method but with fixed and unfixed global phases are closer and have only one global phase difference." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 17, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "overlap between psi_fgp and psi\n", + "|overlap|: 0.9946308905819007\n", + "overlap: (-0.740140807928335-0.6644412637238422j)\n", + "\n", + "overlap between psi_fgp_api and psi_api\n", + "|overlap|: 0.9989073073947322\n", + "overlap: (0.027072660263567746+0.9985403746633621j)\n", + "\n", + "overlap between psi_api and psi\n", + "|overlap|: 0.9986726114097008\n", + "overlap: (-0.7188677460240553+0.6932359976993155j)\n", + "\n", + "overlap between psi_fgp_api and psi_fgp\n", + "|overlap|: 0.9997543606572588\n", + "overlap: (0.9987177429478946+0.04551539930910164j)\n", + "\n", + "overlap between psi_exact and psi\n", + "|overlap|: 0.8722054344579724\n", + "overlap: (-0.6784167782997877-0.5481724134059986j)\n", + "\n", + "overlap between psi_exact and psi_fgp\n", + "|overlap|: 0.8783189735765569\n", + "overlap: (0.8783163699487184-0.002138603442025992j)\n", + "\n", + "overlap between psi_exact and psi_api\n", + "|overlap|: 0.8763977936851081\n", + "overlap: (0.08830490967227977+0.8719376902645599j)\n", + "\n", + "overlap between psi_exact and psi_fgp_api\n", + "|overlap|: 0.8776241084735666\n", + "overlap: (0.876306874146697-0.048065976503842395j)\n" + ] + } + ], + "source": [ + "psi = wfn_quantum(theta)\n", + "psi_fgp = wfn_quantum(theta_fgp)\n", + "psi_api = wfn_quantum(theta_api)\n", + "psi_fgp_api = wfn_quantum(theta_fgp_api)\n", + "\n", + "overlap = K.tensordot(K.conj(psi_fgp), psi, 1)\n", + "print(\n", + " f\"overlap between psi_fgp and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_fgp_api), psi_api, 1)\n", + "print(\n", + " f\"overlap between psi_fgp_api and psi_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_api), psi, 1)\n", + "print(\n", + " f\"overlap between psi_api and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_fgp_api), psi_fgp, 1)\n", + "print(\n", + " f\"overlap between psi_fgp_api and psi_fgp\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact[:, 0]), psi, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact[:, 0]), psi_fgp, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_fgp\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact[:, 0]), psi_api, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\\n\"\n", + ")\n", + "overlap = K.tensordot(K.conj(psi_exact[:, 0]), psi_fgp_api, 1)\n", + "print(\n", + " f\"overlap between psi_exact and psi_fgp_api\\n|overlap|: {K.abs(overlap)}\\noverlap: {overlap}\"\n", + ")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T07:30:17.637583800Z", + "start_time": "2023-07-13T07:30:17.598679600Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then we compare the approximate ground state energy with the exact result. The differences are very small, but the result obtained by exact imaginary-time evolution is indeed the closest to the real ground state energy." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 18, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "exact ground state energy: -12.669360644773814\n", + "\n", + "ground state energy by exact IME: -12.635107323414964\n", + "ground state energy: -12.455023327986686\t-12.457418138786805 (fgp)\n", + "ground state energy (API): -12.454034180766776\t-12.456395342061295 (fgp)\n" + ] + } + ], + "source": [ + "E = K.eigvalsh(H)[0]\n", + "print(f\"exact ground state energy: {E}\\n\")\n", + "loss_exact = K.real(\n", + " K.transpose(K.conj(psi_exact)) @ K.sparse_dense_matmul(h, psi_exact)\n", + ")[0, 0]\n", + "print(f\"ground state energy by exact IME: {K.numpy(loss_exact)}\")\n", + "loss = K.real(K.conj(psi)[None, :] @ K.sparse_dense_matmul(h, psi[:, None]))[0, 0]\n", + "loss_fgp = K.real(\n", + " K.conj(psi_fgp)[None, :] @ K.sparse_dense_matmul(h, psi_fgp[:, None])\n", + ")[0, 0]\n", + "print(f\"ground state energy: {K.numpy(loss)}\\t{K.numpy(loss_fgp)} (fgp)\")\n", + "loss_api = K.real(\n", + " K.conj(psi_api)[None, :] @ K.sparse_dense_matmul(h, psi_api[:, None])\n", + ")[0, 0]\n", + "loss_fgp_api = K.real(\n", + " K.conj(psi_fgp_api)[None, :] @ K.sparse_dense_matmul(h, psi_fgp_api[:, None])\n", + ")[0, 0]\n", + "print(f\"ground state energy (API): {K.numpy(loss_api)}\\t{K.numpy(loss_fgp_api)} (fgp)\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-13T07:30:28.049137Z", + "start_time": "2023-07-13T07:30:27.749665300Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "89ed16e3", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-13T06:54:06.262972100Z", + "start_time": "2023-07-13T06:54:06.180740100Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", + "Python version: 3.10.11\n", + "Numpy version: 1.23.5\n", + "Scipy version: 1.11.0\n", + "Pandas version: 2.0.2\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra version: 0.2.1.dev15+g120379e\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: []\n", + "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", + "Jax version: 0.4.13\n", + "Jax installation doesn't support GPU\n", + "JaxLib version: 0.4.13\n", + "PyTorch version: 2.0.1\n", + "PyTorch GPU support: False\n", + "PyTorch GPUs: []\n", + "Cupy is not installed\n", + "Qiskit version: 0.24.1\n", + "Cirq version: 1.1.0\n", + "TensorCircuit version 0.10.0\n" + ] + } + ], + "source": [ + "tc.about()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/nnvqe.ipynb b/docs/source/tutorials/nnvqe.ipynb new file mode 100644 index 00000000..ba48f3f3 --- /dev/null +++ b/docs/source/tutorials/nnvqe.ipynb @@ -0,0 +1,4015 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "64ba95d6", + "metadata": {}, + "source": [ + "#
Neural Network encoded Variational Quantum Eigensolver (NN-VQE)" + ] + }, + { + "cell_type": "markdown", + "id": "b65f64bf", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this tutorial, we'll show you a general framework called neural network encoded variational quantum algorithms (NN-VQAs) with TensorCircuit. NN-VQA feeds input (such as parameters of a Hamiltonian) from a given problem to a neural network and uses its outputs to parameterize an ansatz circuit for the standard VQA. Here, we take NN-variational quantum eigensolver (VQE) to illustrate concretely." + ] + }, + { + "cell_type": "markdown", + "id": "831930ae", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4e1651b9", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import tensorflow as tf\n", + "import tensorcircuit as tc\n", + "import cotengra\n", + "import quimb\n", + "from tqdm.notebook import tqdm\n", + "from functools import partial\n", + "\n", + "optc = cotengra.ReusableHyperOptimizer(\n", + " methods=[\"greedy\"],\n", + " parallel=\"ray\",\n", + " minimize=\"combo\",\n", + " max_time=30,\n", + " max_repeats=1024,\n", + " progbar=True,\n", + ")\n", + "tc.set_contractor(\"custom\", optimizer=optc, preprocessing=True)\n", + "\n", + "K = tc.set_backend(\"tensorflow\")\n", + "tc.set_dtype(\"complex128\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d78b480b", + "metadata": {}, + "source": [ + "## Energy\n", + "\n", + "The Hamiltonian used in this tutorial is a 1D XXZ model with periodic boundary conditions, with the transverse field strength $\\lambda$ and the anisotropy parameter $\\Delta$. The Hamiltonian energy expectation function is chosen as loss.\n", + "\n", + "$$ \\hat{H}_{XXZ}=\\sum_{i}{ \\left( X_{i}X_{i+1}+Y_{i}Y_{i+1}+\\Delta Z_{i}Z_{i+1} \\right) } + \\lambda \\sum_{i}{Z_{i}} $$" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fff67346", + "metadata": {}, + "outputs": [], + "source": [ + "def energy(c: tc.Circuit, lamb: float = 1.0, delta: float = 1.0):\n", + " e = 0.0\n", + " n = c._nqubits\n", + " for i in range(n):\n", + " e += lamb * c.expectation((tc.gates.z(), [i])) # \n", + " for i in range(n):\n", + " e += c.expectation(\n", + " (tc.gates.x(), [i]), (tc.gates.x(), [(i + 1) % n])\n", + " ) # \n", + " e += c.expectation(\n", + " (tc.gates.y(), [i]), (tc.gates.y(), [(i + 1) % n])\n", + " ) # \n", + " e += delta * c.expectation(\n", + " (tc.gates.z(), [i]), (tc.gates.z(), [(i + 1) % n])\n", + " ) # \n", + " return K.real(e)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "0ad6a7a6", + "metadata": {}, + "source": [ + "## Ansatz circuit\n", + "\n", + "Now we design the circuit. We choose multi-scale entangled renormalization ansatz (MERA) as the ansatz here, $d$ is the circuit depth. (see [MERA tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/mera.html))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "445b7c86", + "metadata": {}, + "outputs": [], + "source": [ + "def MERA(\n", + " inp, n, d=1, lamb=1.0, energy_flag=False\n", + "): # for single-parameter 1D XXZ model, we fix lamb\n", + " params = K.cast(inp[\"params\"], \"complex128\")\n", + " delta = K.cast(inp[\"delta\"], \"complex128\")\n", + " c = tc.Circuit(n)\n", + "\n", + " idx = 0\n", + "\n", + " for i in range(n):\n", + " c.rx(i, theta=params[3 * i])\n", + " c.rz(i, theta=params[3 * i + 1])\n", + " c.rx(i, theta=params[3 * i + 2])\n", + " idx += 3 * n\n", + "\n", + " for n_layer in range(1, int(np.log2(n)) + 1):\n", + " n_qubit = 2**n_layer # number of qubits involving\n", + " step = int(n / n_qubit)\n", + "\n", + " for _ in range(d): # circuit depth\n", + " # even\n", + " for i in range(step, n - step, 2 * step):\n", + " c.rxx(i, i + step, theta=params[idx])\n", + " c.rzz(i, i + step, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " # odd\n", + " for i in range(0, n, 2 * step):\n", + " c.rxx(i, i + step, theta=params[idx])\n", + " c.rzz(i, i + step, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " # single qubit\n", + " for i in range(0, n, step):\n", + " c.rx(i, theta=params[idx])\n", + " c.rz(i, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " if energy_flag:\n", + " return energy(c, lamb, delta) # return Hamiltonian energy expectation\n", + " else:\n", + " return c, idx # return the circuit & number of circuit parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6daa2f64", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The number of parameters is 74\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-08-06T16:31:47.918946\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.3, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# circuit visulization\n", + "n = 8\n", + "d = 1\n", + "cirq, idx = MERA({\"params\": np.zeros(3000), \"delta\": 0.0}, n, d, 1.0)\n", + "print(\"The number of parameters is\", idx)\n", + "cirq.draw()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "bfe2fbee", + "metadata": {}, + "source": [ + "## NN-VQE\n", + "\n", + "Design the NN-VQE. We use a neural network to transform the Hamiltonian parameters to the optimized parameters in the parameterized quantum circuit (PQC) for VQE." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1ac050a8", + "metadata": {}, + "outputs": [], + "source": [ + "def NN_MERA(n, d, lamb, NN_shape, stddev):\n", + " input = tf.keras.layers.Input(shape=[1]) # input layer\n", + "\n", + " x = tf.keras.layers.Dense(\n", + " units=NN_shape,\n", + " kernel_initializer=tf.keras.initializers.RandomNormal(stddev=stddev),\n", + " activation=\"ReLU\",\n", + " )(\n", + " input\n", + " ) # hidden layer\n", + "\n", + " x = tf.keras.layers.Dropout(0.05)(x) # dropout layer\n", + "\n", + " _, idx = MERA(\n", + " {\"params\": np.zeros(3000), \"delta\": 0.0}, n, d, 1.0, energy_flag=False\n", + " )\n", + " params = tf.keras.layers.Dense(\n", + " units=idx,\n", + " kernel_initializer=tf.keras.initializers.RandomNormal(stddev=stddev),\n", + " activation=\"sigmoid\",\n", + " )(\n", + " x\n", + " ) # output layer\n", + "\n", + " qlayer = tc.KerasLayer(partial(MERA, n=n, d=d, lamb=lamb, energy_flag=True)) # PQC\n", + "\n", + " output = qlayer({\"params\": 6.3 * params, \"delta\": input}) # NN-VQE output\n", + "\n", + " m = tf.keras.Model(inputs=input, outputs=output)\n", + "\n", + " return m" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e9afb1a5", + "metadata": {}, + "source": [ + "## Train\n", + "\n", + "Now we can train the NN-VQE with TensorFlow." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "873ebd5e", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "def train(n, d, lamb, delta, NN_shape, maxiter=10000, lr=0.005, stddev=1.0):\n", + " exp_lr = tf.keras.optimizers.schedules.ExponentialDecay(\n", + " initial_learning_rate=lr, decay_steps=1000, decay_rate=0.7\n", + " )\n", + " opt = tf.keras.optimizers.Adam(exp_lr) # optimizer\n", + "\n", + " m = NN_MERA(n, d, lamb, NN_shape, stddev)\n", + " for i in range(maxiter):\n", + " with tf.GradientTape() as tape:\n", + " e = tf.zeros([1], dtype=tf.float64)\n", + " for de in delta:\n", + " e += m(K.reshape(de, [1])) # sum up energies of all training points\n", + " grads = tape.gradient(e, m.variables)\n", + " opt.apply_gradients(zip(grads, m.variables))\n", + " if i % 500 == 0:\n", + " print(\"epoch\", i, \":\", e)\n", + "\n", + " m.save_weights(\"NN-VQE.weights.h5\") # save the trained model" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "e8df3d67", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "epoch 0 : tf.Tensor([[117.53523392]], shape=(1, 1), dtype=float64)\n", + "epoch 500 : tf.Tensor([[-361.85937039]], shape=(1, 1), dtype=float64)\n", + "epoch 1000 : tf.Tensor([[-365.35288984]], shape=(1, 1), dtype=float64)\n", + "epoch 1500 : tf.Tensor([[-366.65891358]], shape=(1, 1), dtype=float64)\n", + "epoch 2000 : tf.Tensor([[-366.94258369]], shape=(1, 1), dtype=float64)\n" + ] + } + ], + "source": [ + "n = 8 # number of qubits\n", + "d = 2 # circuit depth\n", + "lamb = 0.75 # fixed\n", + "delta = np.linspace(-3.0, 3.0, 20, dtype=\"complex128\") # training set\n", + "NN_shape = 20 # node number of the hidden layer\n", + "maxiter = 2500 # maximum iteration for the optimization\n", + "lr = 0.009 # learning rate\n", + "stddev = 0.1 # the initial standard deviation of the NN\n", + "\n", + "with tf.device(\"/cpu:0\"):\n", + " train(n, d, lamb, delta, NN_shape=NN_shape, maxiter=maxiter, lr=lr, stddev=stddev)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c5a7cdb0", + "metadata": {}, + "source": [ + "## Test\n", + "\n", + "We use a test set beyond the training set to test the accuracy and generalization capability of NN-VQE." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "f15f4f68", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4a3ceb8bdf90463f88050b771fde6925", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "test_delta = np.linspace(-4.0, 4.0, 201) # test set\n", + "test_energies = tf.zeros_like(test_delta).numpy()\n", + "m = NN_MERA(n, d, lamb, NN_shape, stddev)\n", + "m.load_weights(\"NN-VQE.weights.h5\")\n", + "for i, de in tqdm(enumerate(test_delta)):\n", + " test_energies[i] = m(K.reshape(de, [1]))" + ] + }, + { + "cell_type": "markdown", + "id": "924027f8", + "metadata": {}, + "source": [ + "## Compare\n", + "\n", + "We compare the results of NN-VQE with the analytical ones to calculate the ground-state energy relative error. From the figure, we can see that NN-VQE is able to estimate the ground-state energies of parameterized Hamiltonians with high precision without fine-tuning and has a favorable generalization capability." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "c8668a13", + "metadata": {}, + "outputs": [], + "source": [ + "analytical_energies = [] # analytical result\n", + "for i in test_delta:\n", + " h = quimb.tensor.tensor_builder.MPO_ham_XXZ(\n", + " n, i * 4, jxy=4.0, bz=2.0 * 0.75, S=0.5, cyclic=True\n", + " )\n", + " h = h.to_dense()\n", + " analytical_energies.append(np.min(quimb.eigvalsh(h)))" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "42799e3e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-08-06T23:44:26.082098\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.3, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# relative error\n", + "plt.plot(\n", + " test_delta,\n", + " (test_energies - analytical_energies) / np.abs(analytical_energies),\n", + " \"-\",\n", + " color=\"b\",\n", + ")\n", + "plt.xlabel(\"Delta\", fontsize=14)\n", + "plt.ylabel(\"GS Relative Error\", fontsize=14)\n", + "plt.axvspan(-3.0, 3.0, color=\"darkgrey\", alpha=0.5) # training set span\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "5f9bda8a", + "metadata": {}, + "source": [ + "To get more detailed information or further study, please refer to our [paper](https://arxiv.org/abs/2308.01068) and [GitHub](https://github.com/JachyMeow/NN-VQA)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "vscode": { + "interpreter": { + "hash": "18d2a9923f839b0d86cf68fd09770e726264cf9d62311eaf57b1fff0ca4bed8e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/nnvqe_cn.ipynb b/docs/source/tutorials/nnvqe_cn.ipynb new file mode 100644 index 00000000..056990bb --- /dev/null +++ b/docs/source/tutorials/nnvqe_cn.ipynb @@ -0,0 +1,4015 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "64ba95d6", + "metadata": {}, + "source": [ + "#
神经网络编码的变分量子本征值求解器(NN-VQE)" + ] + }, + { + "cell_type": "markdown", + "id": "b65f64bf", + "metadata": {}, + "source": [ + "## 概述\n", + "\n", + "在本教程中,我们将使用TensorCircuit展示一个量子计算通用框架——神经网络编码的变分量子算法(neural network encoded variational quantum algorithms,NN-VQAs)。NN-VQA将一个给定问题的参量(如哈密顿量的参数)作为神经网络的输入,并使用其输出来参数化标准的变分量子算法(variational quantum algorithms,VQAs)的线路拟设(ansatz circuit)。在本文中,我们以神经网络编码的变分量子本征值求解器(NN-variational quantum eigensolver,NN-VQE)来具体说明。" + ] + }, + { + "cell_type": "markdown", + "id": "831930ae", + "metadata": {}, + "source": [ + "## 设置" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4e1651b9", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import tensorflow as tf\n", + "import tensorcircuit as tc\n", + "import cotengra\n", + "import quimb\n", + "from tqdm.notebook import tqdm\n", + "from functools import partial\n", + "\n", + "optc = cotengra.ReusableHyperOptimizer(\n", + " methods=[\"greedy\"],\n", + " parallel=\"ray\",\n", + " minimize=\"combo\",\n", + " max_time=30,\n", + " max_repeats=1024,\n", + " progbar=True,\n", + ")\n", + "tc.set_contractor(\"custom\", optimizer=optc, preprocessing=True)\n", + "\n", + "K = tc.set_backend(\"tensorflow\")\n", + "tc.set_dtype(\"complex128\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d78b480b", + "metadata": {}, + "source": [ + "## 能量\n", + "\n", + "本教程所使用的哈密顿量是具有周期性边界条件的一维XXZ伊辛模型。它具有横向场强$\\lambda$和各向异性参数$\\Delta$。我们选择哈密顿量的能量期望函数作为损失函数。\n", + "\n", + "$$ \\hat{H}_{XXZ}=\\sum_{i}{ \\left( X_{i}X_{i+1}+Y_{i}Y_{i+1}+\\Delta Z_{i}Z_{i+1} \\right) } + \\lambda \\sum_{i}{Z_{i}} $$" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fff67346", + "metadata": {}, + "outputs": [], + "source": [ + "def energy(c: tc.Circuit, lamb: float = 1.0, delta: float = 1.0):\n", + " e = 0.0\n", + " n = c._nqubits\n", + " for i in range(n):\n", + " e += lamb * c.expectation((tc.gates.z(), [i])) # \n", + " for i in range(n):\n", + " e += c.expectation(\n", + " (tc.gates.x(), [i]), (tc.gates.x(), [(i + 1) % n])\n", + " ) # \n", + " e += c.expectation(\n", + " (tc.gates.y(), [i]), (tc.gates.y(), [(i + 1) % n])\n", + " ) # \n", + " e += delta * c.expectation(\n", + " (tc.gates.z(), [i]), (tc.gates.z(), [(i + 1) % n])\n", + " ) # \n", + " return K.real(e)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "0ad6a7a6", + "metadata": {}, + "source": [ + "## 线路拟设\n", + "\n", + "现在我们来设计线路。我们选择多尺度纠缠重整化拟设(multi-scale entangled renormalization ansatz,MERA)作为线路拟设,其中$d$为线路深度。(详见[MERA教程](https://tensorcircuit.readthedocs.io/zh/latest/tutorials/mera_cn.html))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "445b7c86", + "metadata": {}, + "outputs": [], + "source": [ + "def MERA(\n", + " inp, n, d=1, lamb=1.0, energy_flag=False\n", + "): # 对于单变量一维XXZ模型,我们固定lamb\n", + " params = K.cast(inp[\"params\"], \"complex128\")\n", + " delta = K.cast(inp[\"delta\"], \"complex128\")\n", + " c = tc.Circuit(n)\n", + "\n", + " idx = 0\n", + "\n", + " for i in range(n):\n", + " c.rx(i, theta=params[3 * i])\n", + " c.rz(i, theta=params[3 * i + 1])\n", + " c.rx(i, theta=params[3 * i + 2])\n", + " idx += 3 * n\n", + "\n", + " for n_layer in range(1, int(np.log2(n)) + 1):\n", + " n_qubit = 2**n_layer # 涉及的量子比特数\n", + " step = int(n / n_qubit)\n", + "\n", + " for _ in range(d): # 线路深度\n", + " # 偶数层\n", + " for i in range(step, n - step, 2 * step):\n", + " c.rxx(i, i + step, theta=params[idx])\n", + " c.rzz(i, i + step, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " # 奇数层\n", + " for i in range(0, n, 2 * step):\n", + " c.rxx(i, i + step, theta=params[idx])\n", + " c.rzz(i, i + step, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " # 单比特门\n", + " for i in range(0, n, step):\n", + " c.rx(i, theta=params[idx])\n", + " c.rz(i, theta=params[idx + 1])\n", + " idx += 2\n", + "\n", + " if energy_flag:\n", + " return energy(c, lamb, delta) # 返回哈密顿量的能量期望\n", + " else:\n", + " return c, idx # 返回线路&线路参量数" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6daa2f64", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The number of parameters is 74\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-08-06T16:31:47.918946\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.3, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 线路可视化\n", + "n = 8\n", + "d = 1\n", + "cirq, idx = MERA({\"params\": np.zeros(3000), \"delta\": 0.0}, n, d, 1.0)\n", + "print(\"The number of parameters is\", idx)\n", + "cirq.draw()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "bfe2fbee", + "metadata": {}, + "source": [ + "## NN-VQE\n", + "\n", + "设计NN-VQE。我们使用神经网络将哈密顿量参数转换为VQE的变分量子线路(parameterized quantum ciecuit,PQC)的优化参数。" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1ac050a8", + "metadata": {}, + "outputs": [], + "source": [ + "def NN_MERA(n, d, lamb, NN_shape, stddev):\n", + " input = tf.keras.layers.Input(shape=[1]) # 输入层\n", + "\n", + " x = tf.keras.layers.Dense(\n", + " units=NN_shape,\n", + " kernel_initializer=tf.keras.initializers.RandomNormal(stddev=stddev),\n", + " activation=\"ReLU\",\n", + " )(\n", + " input\n", + " ) # 隐层\n", + "\n", + " x = tf.keras.layers.Dropout(0.05)(x) # dropout层\n", + "\n", + " _, idx = MERA(\n", + " {\"params\": np.zeros(3000), \"delta\": 0.0}, n, d, 1.0, energy_flag=False\n", + " )\n", + " params = tf.keras.layers.Dense(\n", + " units=idx,\n", + " kernel_initializer=tf.keras.initializers.RandomNormal(stddev=stddev),\n", + " activation=\"sigmoid\",\n", + " )(\n", + " x\n", + " ) # 输出层\n", + "\n", + " qlayer = tc.KerasLayer(partial(MERA, n=n, d=d, lamb=lamb, energy_flag=True)) # PQC\n", + "\n", + " output = qlayer({\"params\": 6.3 * params, \"delta\": input}) # NN-VQE输出\n", + "\n", + " m = tf.keras.Model(inputs=input, outputs=output)\n", + "\n", + " return m" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e9afb1a5", + "metadata": {}, + "source": [ + "## 训练\n", + "\n", + "现在我们用TensorFlow来训练NN-VQE。" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "873ebd5e", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "def train(n, d, lamb, delta, NN_shape, maxiter=10000, lr=0.005, stddev=1.0):\n", + " exp_lr = tf.keras.optimizers.schedules.ExponentialDecay(\n", + " initial_learning_rate=lr, decay_steps=1000, decay_rate=0.7\n", + " )\n", + " opt = tf.keras.optimizers.Adam(exp_lr) # 优化器\n", + "\n", + " m = NN_MERA(n, d, lamb, NN_shape, stddev)\n", + " for i in range(maxiter):\n", + " with tf.GradientTape() as tape:\n", + " e = tf.zeros([1], dtype=tf.float64)\n", + " for de in delta:\n", + " e += m(K.reshape(de, [1])) # 将所有训练点的能量相加\n", + " grads = tape.gradient(e, m.variables)\n", + " opt.apply_gradients(zip(grads, m.variables))\n", + " if i % 500 == 0:\n", + " print(\"epoch\", i, \":\", e)\n", + "\n", + " m.save_weights(\"NN-VQE.weights.h5\") # 保存已训练的模型" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "e8df3d67", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "epoch 0 : tf.Tensor([[117.53523392]], shape=(1, 1), dtype=float64)\n", + "epoch 500 : tf.Tensor([[-361.85937039]], shape=(1, 1), dtype=float64)\n", + "epoch 1000 : tf.Tensor([[-365.35288984]], shape=(1, 1), dtype=float64)\n", + "epoch 1500 : tf.Tensor([[-366.65891358]], shape=(1, 1), dtype=float64)\n", + "epoch 2000 : tf.Tensor([[-366.94258369]], shape=(1, 1), dtype=float64)\n" + ] + } + ], + "source": [ + "n = 8 # 量子比特数\n", + "d = 2 # 线路深度\n", + "lamb = 0.75 # 固定参数\n", + "delta = np.linspace(-3.0, 3.0, 20, dtype=\"complex128\") # 训练集\n", + "NN_shape = 20 # 隐层节点数\n", + "maxiter = 2500 # 最大迭代轮数\n", + "lr = 0.009 # 学习率\n", + "stddev = 0.1 # 神经网络参数初始值的标准差\n", + "\n", + "with tf.device(\"/cpu:0\"):\n", + " train(n, d, lamb, delta, NN_shape=NN_shape, maxiter=maxiter, lr=lr, stddev=stddev)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c5a7cdb0", + "metadata": {}, + "source": [ + "## 测试\n", + "\n", + "我们使用较训练集更大的测试集来测试NN-VQE的准确性和泛化能力。" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "f15f4f68", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4a3ceb8bdf90463f88050b771fde6925", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "test_delta = np.linspace(-4.0, 4.0, 201) # 测试集\n", + "test_energies = tf.zeros_like(test_delta).numpy()\n", + "m = NN_MERA(n, d, lamb, NN_shape, stddev)\n", + "m.load_weights(\"NN-VQE.weights.h5\")\n", + "for i, de in tqdm(enumerate(test_delta)):\n", + " test_energies[i] = m(K.reshape(de, [1]))" + ] + }, + { + "cell_type": "markdown", + "id": "924027f8", + "metadata": {}, + "source": [ + "## 对比\n", + "\n", + "我们将NN-VQE的结果与解析解相比,计算基态能量相对误差。从图中可以看出,NN-VQE能够在无微调(fine-tuning)的情况下准确估计参数化哈密顿量的基态能量,且具有良好的泛化能力。" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "c8668a13", + "metadata": {}, + "outputs": [], + "source": [ + "analytical_energies = [] # 解析解\n", + "for i in test_delta:\n", + " h = quimb.tensor.tensor_builder.MPO_ham_XXZ(\n", + " n, i * 4, jxy=4.0, bz=2.0 * 0.75, S=0.5, cyclic=True\n", + " )\n", + " h = h.to_dense()\n", + " analytical_energies.append(np.min(quimb.eigvalsh(h)))" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "42799e3e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-08-06T23:44:26.082098\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.3, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# 基态能量相对误差\n", + "plt.plot(\n", + " test_delta,\n", + " (test_energies - analytical_energies) / np.abs(analytical_energies),\n", + " \"-\",\n", + " color=\"b\",\n", + ")\n", + "plt.xlabel(\"Delta\", fontsize=14)\n", + "plt.ylabel(\"GS Relative Error\", fontsize=14)\n", + "plt.axvspan(-3.0, 3.0, color=\"darkgrey\", alpha=0.5) # 训练集区间\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "5f9bda8a", + "metadata": {}, + "source": [ + "想要获得更详细的信息或进一步的研究,请参考我们的[论文](https://arxiv.org/abs/2308.01068)和[GitHub](https://github.com/JachyMeow/NN-VQA)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "vscode": { + "interpreter": { + "hash": "18d2a9923f839b0d86cf68fd09770e726264cf9d62311eaf57b1fff0ca4bed8e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/optimization_and_expressibility_cn.ipynb b/docs/source/tutorials/optimization_and_expressibility_cn.ipynb index 3fdaa7a8..e09df93c 100644 --- a/docs/source/tutorials/optimization_and_expressibility_cn.ipynb +++ b/docs/source/tutorials/optimization_and_expressibility_cn.ipynb @@ -276,7 +276,9 @@ "@tf.function\n", "def entropy(v):\n", " ψ = get_state(v)\n", - " ρ_reduced = tc.quantum.reduced_density_matrix(ψ, NA) # 部分描绘出子系统A得到的降密度矩阵\n", + " ρ_reduced = tc.quantum.reduced_density_matrix(\n", + " ψ, NA\n", + " ) # 部分描绘出子系统A得到的降密度矩阵\n", " S = tc.quantum.renyi_entropy(ρ_reduced) # Renyi 纠缠熵\n", " return S" ] diff --git a/docs/source/tutorials/portfolio_optimization.ipynb b/docs/source/tutorials/portfolio_optimization.ipynb new file mode 100644 index 00000000..7ec25888 --- /dev/null +++ b/docs/source/tutorials/portfolio_optimization.ipynb @@ -0,0 +1,499 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", + "metadata": {}, + "source": [ + "# Portfolio Optimization\n", + "\n", + "In this tutorial, we demonstrate the transformation of financial portfolio optimization into a quadratic unconstrained binary optimization (QUBO) problem. Subsequently, we employ the Quantum Approximate Optimization Algorithm (QAOA) to solve it. We will conduct a comparative analysis between the outcomes obtained through QAOA and those derived from classical brute force searching. Additionally, we explore the potential for enhancing results by customizing the QAOA 'mixer' component.\n", + "\n", + "## Introduction\n", + "\n", + "Consider the following scenario: Xiaoming, an astute individual, possesses a sum of money represented by $B$ and is contemplating investing it in the stock market. The market contains $n$ shares, each having an identical price. Xiaoming's objective is to maximize returns while minimizing risk, taking into account the varying levels of risk tolerance among individuals. Xiaoming's personal risk tolerance is represented by $q$. In light of these considerations, the question arises: Which shares should Xiaoming choose to construct an optimal portfolio?\n", + "\n", + "Xiaoming's predicament falls under the purview of portfolio optimization problems. These problems are classified as Quadratic Unconstrained Binary Optimization (QUBO) problems, wherein binary numbers are utilized to represent decisions. In this case, \"1\" signifies selection, while \"0\" denotes the opposite. To address the challenge of portfolio optimization, the Quantum Approximate Optimization Algorithm (QAOA) is employed.\n", + "\n", + "## Solving portfolio optimization problems with QAOA\n", + "\n", + "In a simple boolean Markowitz portfolio optimization problem, we wish to solve \n", + "\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^T x\n", + "$$\n", + "\n", + "subject to a constraint\n", + "\n", + "$$\n", + "1^T x = B\n", + "$$\n", + "\n", + "where \n", + "* $n$: number of assets under consideration\n", + "* $q > 0 $: risk-appetite\n", + "* $\\Sigma \\in \\mathbb{R}^{n\\times n}$: covariance matrix of the assets\n", + "* $\\mu\\in\\mathbb{R}^n$: mean return of the assets\n", + "* $B$: budget (i.e., the total number of assets out of $n$ that can be selected)\n", + "\n", + "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and considering the alternative problem:\n", + "\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2\n", + "$$\n", + "\n", + "The linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be transformed into squared forms, exploiting the properties of boolean variables where $0^2=0$ and $1^2=1$. The same trick is applied to the middle term of $t(1^Tx-B)^2$. Then the function is written as\n", + "\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2\n", + "$$\n", + "\n", + "which is a QUBO problem\n", + "\n", + "$$\n", + "\\min_{x\\in\\{0,1\\}^n}\\quad x^T Q x + tB^2\n", + "$$\n", + "\n", + "where matrix $Q$ is\n", + "\n", + "$$\n", + "Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", + "1 & 1-2B & 1 & \\ldots \\\\1 & 1 & 1-2B \\\\\n", + "\\vdots\\end{pmatrix}\n", + "$$\n", + "\n", + "and we ignore the constant term $t B^2$. We can now solve this by QAOA.\n", + "\n", + "## Set up" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4f4feab6", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import numpy as np\n", + "import tensorflow as tf\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from tensorcircuit.templates.ansatz import QAOA_ansatz_for_Ising\n", + "from tensorcircuit.templates.conversions import QUBO_to_Ising\n", + "from tensorcircuit.applications.optimization import QUBO_QAOA, QAOA_loss\n", + "from tensorcircuit.applications.finance.portfolio import StockData, QUBO_from_portfolio\n", + "\n", + "K = tc.set_backend(\"tensorflow\")\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "55659298", + "metadata": {}, + "source": [ + "## Import data\n", + "\n", + "To optimize a portfolio, it is essential to utilize historical data from various stocks within the same time frame. Websites such as [Nasdaq](Nasdaq.com) and [Yahoo Finance](https://finance.yahoo.com/) provide access to such data. The next step involves transforming this data into an annualized return ($\\mu$) and covariance matrix ($\\sigma$), which can be recognized by the Quantum Approximate Optimization Algorithm (QAOA). To simplify this process, we can utilize the `StockData` class. This class performs the necessary calculations for annualized return and covariance, as outlined in this [paper](https://doi.org/10.1007/s11128-022-03766-5). They are:\n", + "\n", + "$$\n", + "\\mu = \\left[\\prod ^m_{k=1}\\left(1+r_k^{(i)}\\right)\\right]^{\\frac{252}{m}}\\\\\n", + "\\sigma_{ij}=\\frac{252}{m}\\sum^m_{k=1}\\left(r_k^{(i)}-\\overline{r^{(i)}}\\right)\\left(r_k^{(j)}-\\overline{r^{(j)}}\\right)\n", + "$$\n", + "\n", + "Here is a demonstration of how to use this class:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "62bf0673", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "\n", + "# randomly generate historical data of 6 stocks in 1000 days\n", + "data = [[random.random() for i in range(1000)] for j in range(6)]\n", + "stock_data = StockData(data) # Create an instance\n", + "\n", + "# calculate the annualized return and covariance matrix\n", + "mu = stock_data.get_return()\n", + "sigma = stock_data.get_covariance()\n", + "\n", + "# some other information can also be obtained from this class\n", + "n_stocks = stock_data.n_stocks # number of stocks\n", + "n_days = stock_data.n_days # length of the time span\n", + "daily_change = stock_data.daily_change # relative change of each day" + ] + }, + { + "cell_type": "markdown", + "id": "0fb1d227", + "metadata": {}, + "source": [ + "In this analysis, we have carefully chosen six prominent stocks: Apple Inc. (AAPL), Microsoft Corporation (MSFT), NVIDIA Corporation (NVDA), Pfizer Inc. (PFE), Levi Strauss & Co. (LEVI), and Cisco Systems, Inc. (CSCO). We acquired their historical data spanning from 09/07/2022 to 09/07/2023 from Yahoo Finance. Here are the return and covariance associated with this dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a7eb3a74", + "metadata": {}, + "outputs": [], + "source": [ + "# real-world stock data, calculated using the class above\n", + "# stock name: aapl, msft, nvda, pfe, levi, csco\n", + "# from 09/07/2022 to 09/07/2023\n", + "mu = [1.21141, 1.15325, 2.06457, 0.63539, 0.63827, 1.12224]\n", + "\n", + "sigma = np.array(\n", + " [\n", + " [0.08488, 0.06738, 0.09963, 0.02124, 0.05516, 0.04059],\n", + " [0.06738, 0.10196, 0.11912, 0.02163, 0.0498, 0.04049],\n", + " [0.09963, 0.11912, 0.31026, 0.01977, 0.10415, 0.06179],\n", + " [0.02124, 0.02163, 0.01977, 0.05175, 0.01792, 0.02137],\n", + " [0.05516, 0.0498, 0.10415, 0.01792, 0.19366, 0.0432],\n", + " [0.04059, 0.04049, 0.06179, 0.02137, 0.0432, 0.05052],\n", + " ]\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "f6dc53d4-7ed0-436d-aa1f-8674c56e756e", + "metadata": {}, + "source": [ + "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the Pauli terms and weights, which is similar to what we do in the [QUBO tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qubo_problem.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3f6edcd5-3c10-49fc-86ea-160fc6d3187e", + "metadata": {}, + "outputs": [], + "source": [ + "q = 0.5 # the risk preference of investor\n", + "budget = 4 # Note that in this example, there are 6 assets, but a budget of only 4\n", + "penalty = 1.2\n", + "\n", + "Q = QUBO_from_portfolio(sigma, mu, q, budget, penalty)\n", + "portfolio_pauli_terms, portfolio_weights, portfolio_offset = QUBO_to_Ising(Q)" + ] + }, + { + "cell_type": "markdown", + "id": "730da712", + "metadata": {}, + "source": [ + "## Classical method\n", + "\n", + "We first use brute force to calculate the cost of each combination, which is the expectation value $x^TQx$ for each $x\\in\\{0, 1\\}^n$ ($n$ is the number of stocks). It will give us a clue about the performance of QAOA." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "168f7c36", + "metadata": {}, + "outputs": [], + "source": [ + "def print_Q_cost(Q, wrap=False, reverse=False):\n", + " n_stocks = len(Q)\n", + " states = []\n", + " for i in range(2**n_stocks):\n", + " a = f\"{bin(i)[2:]:0>{n_stocks}}\"\n", + " n_ones = 0\n", + " for j in a:\n", + " if j == \"1\":\n", + " n_ones += 1\n", + " states.append(a)\n", + "\n", + " cost_dict = {}\n", + " for selection in states:\n", + " x = np.array([int(bit) for bit in selection])\n", + " cost_dict[selection] = np.dot(x, np.dot(Q, x))\n", + " cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1]))\n", + " if reverse == True:\n", + " cost_sorted = dict(\n", + " sorted(cost_dict.items(), key=lambda item: item[1], reverse=True)\n", + " )\n", + " num = 0\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\t cost\")\n", + " print(\"-------------------------------------\")\n", + " for k, v in cost_sorted.items():\n", + " print(\"%10s\\t |\\t%.4f\" % (k, v))\n", + " num += 1\n", + " if (num >= 8) & (wrap == True):\n", + " break\n", + " print(\" ...\\t |\\t ...\")\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "6a9d41c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\t cost\n", + "-------------------------------------\n", + " 111001\t |\t-24.0487\n", + " 101101\t |\t-23.7205\n", + " 111100\t |\t-23.6414\n", + " 011101\t |\t-23.6340\n", + " 101011\t |\t-23.5123\n", + " 011011\t |\t-23.4316\n", + " 111010\t |\t-23.4269\n", + " 111101\t |\t-23.3742\n", + " ...\t |\t ...\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "print_Q_cost(Q, wrap=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c34f3398", + "metadata": {}, + "source": [ + "### Use QAOA\n", + "\n", + "Here, a standard QAOA ansatz with 12 layers is used. This circuit will be trained for 1000 iterations." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "9249ea96", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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xowZY2bOnGkSiYT5zne+Q10fxHbhhReau+++21x22WXGGGMuvfTSks8Hok7j8bjZsmWLefzxx81JJ51kZs+ebdrb2803v/nNgfgN9iuxnNurr75q5s+f770PBALmww8/NLfeeqv1sh2q27Bhw4wxxnzuc58zkkxdXZ1JJpNm5syZ3jEnnniiMcaY008/3Uj5/+FkMhlz1FFHecdce+21Zvfu3SYSiVj/TZW0xWIx895775np06ebpUuXekGEeh6Ybe7cuebFF1/c5zGbN2823/3ud733dXV1prOz08yePdtIMhMmTDDGGDN16lTvmAsuuMBks1lz9NFHW/+NlbL9+te/Ng8//HDJvl/+8pfm8ccfp64HaOsriAxEnV533XVmx44dJf9uzJ0716xdu/agy+zU0EwkEtHUqVO1ZMkSb58xRkuWLNGZZ55psWSHtsGDB0uSdu7cKUmaOnWqqqqqSur5vffe08aNG716PvPMM/Xmm29q27Zt3jHPPfecBg8erE996lNlLH3la2xs1OLFi/XCCy+U7KeeB8Yll1yiFStW6KmnnlJzc7NWrVqla665xvv8+OOP19FHH11Sz4lEQsuXLy+p5127dmnlypXeMUuWLFEul9Ppp59evh9T4V5++WVNnz5d48aNkySdfPLJOuuss/Tb3/5WEnXth4Gq0zPPPFMvvvii0um0d8xzzz2nCRMmaMiQIQdVxop/6N1AGjZsmMLhsJqbm0v2Nzc3a8KECZZKdWgLBAJ64IEH9NJLL+ntt9+WJI0YMULJZFJ79uwpOba5uVkjRozwjunrv0PxM+TNnj1bU6ZM6XMeE/U8ME444QRdf/31uv/++/X9739f06ZN049//GOlUik99thjXj31VY8967ln2JOkbDarnTt3Us893HPPPaqrq9O7776rbDarUCik22+/XU8++aQkUdc+GKg6HTFihNavX7/XdxQ/271798cuo1NBBAOvsbFREydO1FlnnWW7KIedY445Rj/60Y80Y8YMlrn2UTAY1IoVK3T77bdLklavXq2JEyfquuuu02OPPWa5dIeXWbNm6aqrrtKVV16pt99+W5MnT9YDDzygzZs3U9cOc2popqWlRZlMRvX19SX76+vrtXXrVkulOnTNnz9fX/rSl3TeeeepqanJ279161ZFo1FvyKaoZz1v3bq1z/8Oxc+QH3qpr6/XqlWrlE6nlU6nde655+of/uEflE6n1dzcTD0PgC1btuidd94p2bd27Vode+yxkrrraV//bmzdunWvu5VCoZCOOOII6rmH++67T/fcc49+/vOf66233tITTzyhefPmqaGhQRJ17YeBqlM//y1xKoik02mtXLlS06dP9/YFAgFNnz5dr7zyisWSHXrmz5+vyy+/XJ///Oe1YcOGks9WrlypVCpVUs/jx4/XmDFjvHp+5ZVXNGnSJA0fPtw7ZsaMGdqzZ89ejYKrXnjhBU2cOFGTJ0/2tj//+c9atGiRJk+erBUrVlDPA2DZsmU68cQTS/aNHz9eGzdulCStX79eW7ZsKanneDyu008/vaSehw4dqilTpnjHfP7zn1cwGNTy5cvL8CsODbW1tcrlciX7stmsgsF8U0RdD7yBqtNXXnlFZ599tsLh7oGUGTNm6N133z2oYZki67N8y7nNmjXLdHZ2mq9+9atmwoQJ5ic/+YnZuXNnyV0FbPveGhsbza5du8zZZ59t6uvrva26uto75qGHHjIbNmww5557rpkyZYpZtmyZWbZsmfd58bbS3/3ud+bkk082559/vmlubua20v1sPe+aoZ4HZjv11FNNKpUyDQ0NZuzYseaKK64wbW1t5sorr/SOueWWW8zOnTvNxRdfbCZOnGieeeaZPm9/XLlypZk2bZr5zGc+Y9577z2nbynta1u4cKHZtGmTd/vuZZddZrZt22buuece6vogtlgsZk455RRzyimnGGOMufHGG80pp5xiRo8ePWB1WldXZ7Zs2WIeffRRc9JJJ5lZs2aZtrY2bt/9uNvf//3fmw0bNpiuri7z6quvmtNOO816mQ6l7aN87Wtf846JRqPmwQcfNDt27DBtbW3m6aefNvX19SXfc+yxx5rFixeb9vZ2s23bNnPfffeZUChk/fdV8tY7iFDPA7N98YtfNGvWrDGdnZ3mnXfeMddcc81ex9x5551my5YtprOz0/z+978348aNK/l86NChZtGiRSaRSJjdu3eb//zP/zSxWMz6b6ukbdCgQWbevHlmw4YNpqOjw7z//vvm7rvv3utWcur6wLZzzjmnz3+TFy5cOKB1OmnSJPPiiy+azs5Os2nTJnPLLbcMSPkDhRcAAABl59QcEQAAUFkIIgAAwBqCCAAAsIYgAgAArCGIAAAAawgiAADAGoIIAACwhiACAACsIYgAAABrCCIAAMAagggAALCGIAIAAKz5/+r+so8y6PhtAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "iterations = 1000\n", + "nlayers = 12\n", + "loss_list = []\n", + "\n", + "\n", + "# define a callback function to recode the loss\n", + "def record_loss(loss, params):\n", + " loss_list.append(loss)\n", + "\n", + "\n", + "# apply QAOA on this portfolio optimization problem\n", + "final_params = QUBO_QAOA(Q, nlayers, iterations, callback=record_loss)\n", + "\n", + "p = plt.plot(loss_list)" + ] + }, + { + "cell_type": "markdown", + "id": "9126333d", + "metadata": {}, + "source": [ + "Create a function to visualize the results, listing all combinations in descending order of probability." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "4a2c60e4", + "metadata": {}, + "outputs": [], + "source": [ + "def print_result_prob(c, wrap=False, reverse=False):\n", + " states = []\n", + " n_qubits = c._nqubits\n", + " for i in range(2**n_qubits):\n", + " a = f\"{bin(i)[2:]:0>{n_qubits}}\"\n", + " states.append(a)\n", + " # Generate all possible binary states for the given number of qubits\n", + "\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + " # Calculate the probabilities of each state using the circuit's probability method\n", + "\n", + " sorted_indices = np.argsort(probs)[::-1]\n", + " if reverse == True:\n", + " sorted_indices = sorted_indices[::-1]\n", + " state_sorted = np.array(states)[sorted_indices]\n", + " prob_sorted = np.array(probs)[sorted_indices]\n", + " # Sort the states and probabilities in descending order based on the probabilities\n", + "\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\tprobability\")\n", + " print(\"-------------------------------------\")\n", + " if wrap == False:\n", + " for i in range(len(states)):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " # Print the sorted states and their corresponding probabilities\n", + " elif wrap == True:\n", + " for i in range(4):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\" ... ...\")\n", + " for i in range(-5, -1):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "680f52d2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 111001\t |\t 0.1169\n", + " 101101\t |\t 0.0872\n", + " 111100\t |\t 0.0823\n", + " 101011\t |\t 0.0809\n", + " ... ...\n", + " 000100\t |\t 0.0000\n", + " 010000\t |\t 0.0000\n", + " 000010\t |\t 0.0000\n", + " 000001\t |\t 0.0000\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c_final = QAOA_ansatz_for_Ising(\n", + " final_params, nlayers, portfolio_pauli_terms, portfolio_weights\n", + ")\n", + "print_result_prob(c_final, wrap=True)" + ] + }, + { + "cell_type": "markdown", + "id": "71c7a0e0", + "metadata": {}, + "source": [ + "The highest probability corresponds to the best combination, which is consistent with what we found with classical brute force search.\n", + "\n", + "## Use XY mixer to improve the performance\n", + "\n", + "In the context of QAOA, XY mixers serve as a specific type of quantum gate to augment the optimization process. XY mixers, which are quantum gates introducing qubit interactions through controlled rotations, enable modification of the quantum system's state. The utilization of XY mixers in QAOA provides several advantages. They facilitate more efficient exploration of the solution space, thereby potentially improving the algorithm's overall performance. Moreover, XY mixers can amplify gradients of the objective function during optimization and enhance quantum circuit depth. Notably, in scenarios like portfolio optimization (covered in another tutorial), where constraints exist, XY mixers preserve the constraints associated with individual combinations while allowing for smooth transitions between them.\n", + "\n", + "It is crucial to consider that the choice of mixers relies on the specific problem under consideration, its unique characteristics, and the quantum hardware available." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "3d558b9f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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VqxYoY6ODrtLGdY4zvHBcY4fjnV8cJzjYygc52E5YRcAAAxfjLwAAICEQngBAAAJhfACAAASCuEFAAAkFMJLP33lK1/RgQMH1NbWpl27dqmwsNDukhLKt771Lf3lL3+Rz+dTbW2tfvvb32rGjBk9+qSkpGj16tWqr69Xc3OzfvOb32jChAk9+kyaNEm///3v1dLSotraWn3/+9+Xy+WK51dJKA888ICMMXr00UcjyzjOsTNx4kQ9/fTTqq+vV2trq958803Nnz+/R58HH3xQR48eVWtrq/7whz9o+vTpPdZnZmZqw4YNampqktfr1bp165Senh7PrzGkOZ1OPfTQQ6qsrFRra6v279+v73znOx/px3GOzic+8Qk999xzqqqqkjFG11577Uf6xOKYzp49Wzt27FBbW5s++OADffOb34zZdzC0vttNN91k2tvbzW233WbOP/988/jjj5uGhgYzfvx422tLlLZlyxbzuc99zlxwwQVmzpw55ve//705ePCgSUtLi/T52c9+Zg4dOmSuuOIKU1BQYF577TWzc+fOyHqn02nefPNNs3XrVjN37lxz5ZVXmrq6OvMf//Eftn+/odguuugiU1lZafbs2WMeffRRjnOM29ixY82BAwfMf/7nf5rCwkJz7rnnmuLiYjN16tRIn/vvv994vV5zzTXXmNmzZ5vf/e535v333zcpKSmRPps3bzZ//etfzcUXX2wuvfRS8+6775qNGzfa/v2GSlu+fLk5duyY+dSnPmUmT55srr/+euPz+cxXv/pVjvMg2pVXXmm++93vmuuuu84YY8y1117bY30sjqnH4zHV1dXm6aefNhdccIG5+eabTUtLi/niF78Yi+9g/0Ec6m3Xrl3msccei7x3OBzmyJEj5oEHHrC9tkRt48aNM8YY84lPfMJIMhkZGaajo8Ncf/31kT4zZ840xhizYMECI3X+xxYMBs2ECRMifb70pS+ZxsZG43a7bf9OQ6mlp6ebd955xyxZssS8/PLLkfDCcY5dW7lypdmxY0effY4ePWr+5V/+JfI+IyPDtLW1mZtvvtlIMvn5+cYYY+bPnx/ps3TpUhMKhUxubq7t33EotOeff96sW7eux7Lf/OY35umnn+Y4x6j1Fl5icUzvuusuc/z48R7/bqxcudLs27dv0DVz2ugM3G635s+fr23btkWWGWO0bds2FRUV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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "loss_list = []\n", + "final_params = QUBO_QAOA(Q, nlayers, iterations, mixer=\"XY\", callback=record_loss)\n", + "\n", + "p = plt.plot(loss_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "d83fc94c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 111001\t |\t 0.1553\n", + " 001001\t |\t 0.1260\n", + " 101001\t |\t 0.1180\n", + " 111000\t |\t 0.0934\n", + " ... ...\n", + " 100110\t |\t 0.0000\n", + " 000111\t |\t 0.0000\n", + " 000101\t |\t 0.0000\n", + " 000100\t |\t 0.0000\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c_final = QAOA_ansatz_for_Ising(\n", + " final_params, nlayers, portfolio_pauli_terms, portfolio_weights, mixer=\"XY\"\n", + ")\n", + "print_result_prob(c_final, wrap=True)" + ] + }, + { + "cell_type": "markdown", + "id": "917c9415", + "metadata": {}, + "source": [ + "Compared with the standard X mixer, the XY mixer gives a higher probability of measuring the best result." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc_dev", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/qaoa.ipynb b/docs/source/tutorials/qaoa.ipynb index 647818e9..2e1f44ee 100644 --- a/docs/source/tutorials/qaoa.ipynb +++ b/docs/source/tutorials/qaoa.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "dc0db886", "metadata": {}, @@ -9,6 +10,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "aecf6615", "metadata": {}, @@ -17,28 +19,147 @@ ] }, { + "attachments": {}, "cell_type": "markdown", - "id": "ddada0ca", + "id": "eaf8cd3f", "metadata": {}, "source": [ - "QAOA is a hybrid classical-quantum algorithm that combines quantum circuits, and classical optimization of those circuits. In this tutorial, we utilize QAOA to solve the maximum cut (MAX CUT) combinatorial optimization problem: Given a graph $G=(V, E)$ with nodes $V$ and edges $E$, find a subset $S \\in V$ such that the number of edges between $S$ and $S \\backslash V$ is maximized. And this problem can be reduced to that of finding the ground state of an antiferromagnetic Ising model whose Hamiltonian reads:\n", + "QAOA is a hybrid classical-quantum algorithm that combines quantum circuits, and classical optimization of those circuits. In this tutorial, we utilize QAOA to solve the maximum cut (Max-Cut) combinatorial optimization problem, as proposed by [Farhi, Goldstone, and Gutmann (2014)](https://arxiv.org/abs/1411.4028)." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "16ad937f", + "metadata": {}, + "source": [ + "## Max-Cut Problem" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "197d6df4", + "metadata": {}, + "source": [ + "In graph theory, a graph is composed of $n$ nodes, also known as vertices, and $m$ edges that connect the nodes. Note that there is not necessarily a link between any pair of nodes. Those $n$ nodes are divided into two sets. The number of edges that are cut by a partition/partitions of the nodes is what is going to be maximized." + ] + }, + { + "attachments": { + "16c7f2fb-b981-4798-8346-da54e3bcbaeb.png": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAB6wAAAJgCAIAAACx3QrqAAAEuGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjE5NjQiCiAgIGV4aWY6UGl4ZWxZRGltZW5zaW9uPSI2MDgiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSIKICAgdGlmZjpJbWFnZVdpZHRoPSIxOTY0IgogICB0aWZmOkltYWdlTGVuZ3RoPSI2MDgiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjE0NC8xIgogICB0aWZmOllSZXNvbHV0aW9uPSIxNDQvMSIKICAgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIKICAgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9InNSR0IgSUVDNjE5NjYtMi4xIgogICB4bXA6TW9kaWZ5RGF0ZT0iMjAyMy0wNC0yMVQxMzozMDoyOSswMTowMCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMy0wNC0yMVQxMzozMDoyOSswMTowMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjUiCiAgICAgIHN0RXZ0OndoZW49IjIwMjMtMDQtMjFUMTM6MzA6MjkrMDE6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PpKdWA8AAAGAaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWR3yuDURjHP7aJmKZQLqglXG2aqcWNMmnUkmbKr5vt3S+1H2/vO0lulVtFiRu/LvgLuFWulSJScss1ccN6Pe+22pI9p+c8n/M953k65zlgCaeVjG7zQCab10IBv3N+YdHZ8IqNDux0Q0TR1bGZmSA17euBOjPeuc1atc/9a82xuK5AXaPwqKJqeeFJ4eBaXjV5V7hdSUViwufCLk0uKHxv6tESv5mcLPGPyVo4NA6WVmFnsoqjVayktIywvJzeTHpVKd/HfIk9np2bldgj3oVOiAB+nEwxwTg+BhmR2YcbLwOyoka+p5g/TU5yFZlV1tFYIUmKPC5RV6V6XGJC9LiMNOtm///2VU8MeUvV7X6ofzGMjz5o2IHCtmF8HxtG4QSsz3CVreTnjmD4U/TtitZ7CI5NuLiuaNE9uNyCzic1okWKklXckkjA+xm0LEDbLTQtlXpW3uf0EcIb8lU3sH8A/XLesfwLC4tnvJTYXoMAAAAJcEhZcwAAFiUAABYlAUlSJPAAACAASURBVHic7N15fFz1ee/x58yZfdHiRd7lBRtjjDcpGBOPgkm6xMEpThOWXMgN0NxmARK4aUmgLTi5DYSEBgLclm4hyS1pIUkDqYPTpA0mGrOYSN4QYPAi29h41zIzGs1y5tw/RpZlWbZG0jlzzpz5vP/gNTOac37Py2Dx01fPPD9F13UBAAAAAAAAAMCJXFYXAAAAAAAAAACAWQjBAQAAAAAAAACORQgOAAAAAAAAAHAsQnAAAAAAAAAAgGMRggMAAAAAAAAAHIsQHAAAAAAAAADgWITgAAAAAAAAAADHIgQHAAAAAAAAADgWITgAAAAAAAAAwLEIwQEAAAAAAAAAjkUIDgAAAAAAAABwLEJwAAAAAAAAAIBjEYIDAAAAAAAAAByLEBwAAAAAAAAA4FiE4AAAAAAAAAAAxyIEBwAAAAAAAAA4FiE4AAAAAAAAAMCxCMEBAAAAAAAAAI5FCA4AAAAAAAAAcCxCcAAAAAAAAACAYxGCAwAAAAAAAAAcixAcAAAAAAAAAOBYhOAAAAAAAAAAAMciBAcAAAAAAAAAOBYhOAAAAAAAAADAsQjBAQAAAAAAAACORQgOAAAAAAAAAHAsQnAAAAAAAAAAgGMRggMAAAAAAAAAHIsQHAAAAAAAAADgWITgAAAAAAAAAADHIgQHAAAAAAAAADgWITgAAAAAAAAAwLEIwQEAAAAAAAAAjkUIDgAAAAAAAABwLEJwAAAAAAAAAIBjEYIDAAAAAAAAAByLEBwAAAAAAAAA4FiE4AAAAAAAAAAAxyIEBwAAAAAAAAA4FiE4AAAAAAAAAMCxCMEBAAAAAAAAAI5FCA4AAAAAAAAAcCxCcAAAAAAAAACAYxGCAwAAAAAAAAAcixAcAAAAAAAAAOBYhOAAAAAAAAAAAMciBAcAAAAAAAAAOBYhOAAAAAAAAADAsQjBAQAAAAAAAACORQgOAAAAAAAAAHAsQnAAAAAAAAAAgGMRggMAAAAAAAAAHIsQHAAAAAAAAADgWITgAAAAAAAAAADHIgQHAAAAAAAAADgWITgAAAAAAAAAwLEIwQEAAAAAAAAAjkUIDgAAAAAAAABwLEJwAAAAAAAAAIBjEYIDAAAAAAAAAByLEBwAAAAAAAAA4FiE4AAAAAAAAAAAxyIEBwAAAAAAAAA4FiE4AAAAAAAAAMCxCMEBAAAAAAAAAI5FCA4AAAAAAAAAcCxCcAAAAAAAAACAYxGCAwAAAAAAAAAcixAcAAAAAAAAAOBYhOAAAAAAAAAAAMciBAcAAAAAAAAAOBYhOAAAAAAAAADAsQjBAQAAAAAAAACORQgOAAAAAAAAAHAsQnAAAAAAAAAAgGMRggMAAAAAAAAAHIsQHAAAAAAA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" + } + }, + "cell_type": "markdown", + "id": "10c267f3", + "metadata": {}, + "source": [ + "As illustrated in the graph on the left below, a graph consists of 4 nodes (or vertices) represented by grey circles, and 4 edges, which are black lines that connect the nodes. Max-Cut problem is to find the maximum number of cut when nodes are divided into two set. \n", + "\n", + "For instance, in the right graph, nodes 0 and 1 are in set 0 (light blue), and nodes 2 and 3 are in set 1 (red). If we partition the nodes between these two sets, it will cut two edges (colored pink). Therefore, the number of cut edges in this case is 2. Basically, to find the maximum cut, we need to find the maximum number of edges where the corresponding nodes belong to different sets.\n", + "\n", + "If we write down the set numbers that follow the node sequence (from 0 to 3), we can represent this instance as a bit string \"0011\". Since switching the names of the sets doesn't influence the results, the bit string \"1100\" gives the same number of edge cut. In general, we can use a binary string of length $n$ to represent a partition of $n$ nodes into two disjoint sets. This representation is commonly used in graph theory and combinatorial optimization, and it enables us to apply various computational techniques, including classical and quantum algorithms, to solve problems such as Max-Cut.\n", + "\n", + "![network1.png](attachment:16c7f2fb-b981-4798-8346-da54e3bcbaeb.png)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "2908c43d", + "metadata": {}, + "source": [ + "The Max-Cut problem is a NP-complete problem. Classically, one way to approach this problem is to brutally test every possible bit string, which takes an exponential amount of time as the number of nodes, denoted by $n$, grows. Specifically, for $n$ nodes, there are $2^n$ combinations to test. However, QAOA offers a more efficient way to solve this problem, where $n$ qubits are used to represent $n$ nodes. Nodes are divided according to the energy level of the qubits." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "4d28f719", + "metadata": {}, + "source": [ + "A cost (objective) function of the $\\alpha$-th edge (which connects $j$-th and $k$-th nodes) is defined\n", + "\n", + "$$\n", + "C_\\alpha=\\frac12(1-\\sigma_z^j\\sigma_z^k)\n", + "$$\n", + "\n", + "When $C_\\alpha = 1$, the $\\alpha$-th is accounted a cut edge. It will happen if and only if $j$-th and $k$-th nodes are in different set. The total number of edge cut is written as\n", "\n", - "$$H_C = \\frac{1}{2} \\sum_{i,j\\in E} C_{ij} \\sigma^{z}_{i} \\sigma^{z}_{j},$$\n", + "$$ \n", + "C(z)=\\sum_\\alpha^mC_\\alpha(z)\n", + "$$\n", + "\n", + "where $z = z_1z_2 . . . z_n$ is the bit string. Max-Cut asks for a string $z$ for which $C(z)$ is maximized. This problem is equivlant to finding the ground state of a cost Hamiltonian\n", "\n", - "where $\\sigma^{z}_{i}$ is the Pauli-z matrix on $i$th qubit and $C_{ij}$ is the weight of the edge between nodes $i$ and $j$. We set $C_{ij}=1$ for simplicity. If $\\sigma^{z}_{i}=\\sigma^{z}_{j}$, $i,j\\in S$ or $i,j\\in S \\backslash V$; if $\\sigma^{z}_{i}= -\\sigma^{z}_{j}$, $i\\in S, j\\in S \\backslash V$ or $i\\in S \\backslash V, j \\in S$. Obviously, the number of edges between $S$ and $S \\backslash V$ is maximized with the graph structure decoded from the ground state." + "$$\n", + "H_C = \\frac{1}{2} \\sum_{i,j} \\sigma^{j}_{z} \\sigma^{k}_{z}\n", + "$$" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "871bff2e", + "metadata": {}, + "source": [ + "## QAOA for Max-Cut" ] }, { + "attachments": {}, + "cell_type": "markdown", + "id": "598dc69e", + "metadata": {}, + "source": [ + "The Quantum Approximate Optimization Algorithm (QAOA) utilizes a parameterized quantum circuit ([PQC](https://tensorcircuit.readthedocs.io/en/latest/textbook/chap5.html?highlight=变分)) to generate a quantum state that represents a potential solution to the Max Cut problem. The initial state, denoted as $|s\\rangle$, is a uniform superposition over computational basis states.\n", + "\n", + "$$\n", + "|s\\rangle=\\frac{1}{\\sqrt{2^n}}\\sum_z|z\\rangle\n", + "$$\n", + "\n", + "This state is then evolved by a unitary operator that consists of $q$ layers, denoted as\n", + "\n", + "$$\n", + "U(\\vec{\\beta}, \\vec{\\gamma}) = V_{p}U_{p} \\cdots V_{1}U_{1},\n", + "$$\n", + "\n", + "where $U_{j}= e^{-i\\gamma_{j}H_{C}}$ and $V_{j}= e^{-i \\beta_{j} H_m}$. $H_C$ is the cost Hamiltonian introduced in previous section and the mixer Hamiltonian $H_m=\\sum_j\\sigma^j_x$ is used to mix the quantum state to explore different solutions. The unitary operator is parameterized by $2p$ angle parameters $\\gamma_1, \\gamma_2, \\dots, \\gamma_p$ and $\\beta_1, \\beta_2, \\dots ,\\beta_p$. It is worth noting that every $\\gamma$ is restricted to lie between $0$ and $2\\pi$, and every $\\beta$ is restricted to lie between $0$ and $\\pi$ due to the integer eigenvalues of $H_C$.\n", + "\n", + "It is important and also tricky to find a proper $p$. As introduced by [Farhi, Goldstone, and Gutmann (2014)](https://arxiv.org/abs/1411.4028), $p$ should be equal to the maximum steps between any pair of nodes. For example, in the graph above, the max steps are found between node 3 and node 1 or 0, and this number is 2. Therefore, a 2-layer PQC should be used.\n", + "\n", + "Begin with a set of initial parameters, the quantum state is obtained from the PQC and then the expected value of the cost Hamiltonian is calculated. A classical optimizer is then used to vary the parameters until a lower exptected value is found. This process is iterated a certain number of times, and the lowest expected value is approximated as the ground state energy of the cost Hamiltonian. By using the parameters that correspond to the lowest expected value, an approximate solution to the Max-Cut problem can be obtained.\n", + "\n", + "In summary, a general QAOA algorithm follows these steps:\n", + "\n", + "1. Define the cost fucntion according to the problem.\n", + "\n", + "2. Define the parameterized quantum circuit with cost Hamiltonian and mixer Hamiltonian.\n", + "\n", + "3. Define a group of initial parameters.\n", + "\n", + "4. calculate the cost function of this group of parameters.\n", + "\n", + "5. If a lower cost is found, accept it. Otherwise, keep the previously found cost.\n", + "\n", + "6. Find a new group of parameters with an optimizer.\n", + "\n", + "7. Repreat procedures 4-6 for given times. Then output the lowest cost and corresponding parameters." + ] + }, + { + "attachments": {}, "cell_type": "markdown", "id": "940fa22b", "metadata": {}, "source": [ - "## Setup" + "## The code" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 103, "id": "b0def04d", "metadata": {}, "outputs": [], @@ -46,32 +167,47 @@ "import tensorcircuit as tc\n", "import tensorflow as tf\n", "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from IPython.display import clear_output\n", + "import random\n", "\n", "K = tc.set_backend(\"tensorflow\")\n", "\n", "nlayers = 3 # the number of layers\n", - "ncircuits = 2 # the number of circuits with different initial parameters" + "ncircuits = 6 # six circuits with different initial parameters are going to be optimized at the same time\n", + "nnodes = 8 # the number of nodes" ] }, { + "attachments": {}, "cell_type": "markdown", "id": "6e407437", "metadata": {}, "source": [ - "## Define the Graph" + "### Define the Graph" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c82972a4", + "metadata": {}, + "source": [ + "The degree of a graph is defined as the maximum number of edges connected to single nodes. For example, the graph below has a fixed degree of 3." ] }, { "cell_type": "code", - "execution_count": 2, - "id": "14a19854", + "execution_count": 104, + "id": "f1532831", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, "metadata": {}, @@ -79,15 +215,6 @@ } ], "source": [ - "def dict2graph(d):\n", - " g = nx.to_networkx_graph(d)\n", - " for e in g.edges:\n", - " if not g[e[0]][e[1]].get(\"weight\"):\n", - " g[e[0]][e[1]][\"weight\"] = 1.0\n", - " nx.draw(g, with_labels=True)\n", - " return g\n", - "\n", - "\n", "# a graph instance\n", "# each node is connected to three nodes\n", "# for example, node 0 is connected to nodes 1,7,3\n", @@ -95,48 +222,44 @@ " 0: {1: {\"weight\": 1.0}, 7: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", " 1: {0: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", " 2: {1: {\"weight\": 1.0}, 3: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", - " 4: {7: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", - " 7: {4: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", " 3: {1: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", - " 6: {7: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", + " 4: {7: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", " 5: {6: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 2: {\"weight\": 1.0}},\n", + " 6: {7: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", + " 7: {4: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", "}\n", + "pos = nx.spring_layout(nx.to_networkx_graph(example_graph_dict))\n", + "colors = [\"c\" for key in example_graph_dict.items()]\n", "\n", - "example_graph = dict2graph(example_graph_dict)" + "# convert to a NetworkX graph\n", + "example_graph = nx.to_networkx_graph(example_graph_dict)\n", + "nx.draw_networkx(example_graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" ] }, { + "attachments": {}, "cell_type": "markdown", "id": "c944f6dd", "metadata": {}, "source": [ - "## Parameterized Quantum Circuit (PQC)" - ] - }, - { - "cell_type": "markdown", - "id": "021d2cb8", - "metadata": {}, - "source": [ - "The PQC with $p$ layers can be written as:\n", - "$$\n", - "U(\\vec{\\beta}, \\vec{\\gamma}) = V_{p}U_{p} \\cdots V_{1}U_{1},\n", - "$$\n", - "where $U_{j}= e^{-i\\gamma_{j}H_{C}}$ and $V_{j}= e^{-i \\beta_{j} \\sum_{k} \\sigma^{x}_{k}}$." + "### Parameterized Quantum Circuit (PQC)" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 105, "id": "055d1257", "metadata": {}, "outputs": [], "source": [ - "def QAOAansatz(params, g=example_graph):\n", + "def QAOAansatz(params, g=example_graph, return_circuit=False):\n", " n = len(g.nodes) # the number of nodes\n", " c = tc.Circuit(n)\n", " for i in range(n):\n", " c.H(i)\n", + "\n", " # PQC\n", " for j in range(nlayers):\n", " # U_j\n", @@ -151,106 +274,498 @@ " for i in range(n):\n", " c.rx(i, theta=params[2 * j + 1])\n", "\n", + " # whether to return the circuit\n", + " if return_circuit is True:\n", + " return c\n", + "\n", " # calculate the loss function\n", " loss = 0.0\n", " for e in g.edges:\n", - " loss += c.expectation_ps(z=[e[0], e[1]])\n", + " loss += c.expectation_ps(z=[e[0], e[1]]) * g[e[0]][e[1]].get(\"weight\", 1.0)\n", "\n", " return K.real(loss)" ] }, { + "attachments": {}, "cell_type": "markdown", "id": "5b159920", "metadata": {}, "source": [ - "## Main Optimization Loop" + "### Optimization" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "6d07ee61", + "metadata": {}, + "source": [ + "Here, several circuits with different initial parameters are optimized/trained at the same time.\n", + "\n", + "Optimizers are used to find the minimum value." ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 106, "id": "b8d63c5d", "metadata": {}, "outputs": [], "source": [ "# use vvag to get the losses and gradients with different random circuit instances\n", - "QAOA_vvag = K.jit(tc.backend.vvag(QAOAansatz, argnums=0, vectorized_argnums=0))" + "QAOA_vvag = K.jit(\n", + " tc.backend.vvag(QAOAansatz, argnums=0, vectorized_argnums=0), static_argnums=(1, 2)\n", + ")" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 107, "id": "c51b17a7", "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "params = K.implicit_randn(\n", + " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", + ") # initial parameters\n", + "opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", + "\n", + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(300):\n", + " loss, grads = QAOA_vvag(params, example_graph)\n", + " params = opt.update(grads, params) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [\"circuit %d\" % leg for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "98a6b152", + "metadata": {}, + "source": [ + "### Results" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "fc1c257d", + "metadata": {}, + "source": [ + "After inputing the optimized parameters back to the ansatz circuit, we can measure the probablitiy distribution of the quantum states. The states with highest probability are supposed to be the ones corresponding to Max Cut." + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "id": "843c0ad3", + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "[-0.23837963 -1.1651934 ]\n", - "[-0.5175445 -1.4539642]\n", - "[-0.7306818 -1.6646069]\n", - "[-0.91530037 -1.8384367 ]\n", - "[-1.0832287 -1.9884492]\n", - "[-1.2398103 -2.120449 ]\n", - "[-1.3878661 -2.2374902]\n", - "[-1.5290209 -2.341291 ]\n", - "[-1.6642232 -2.4328852]\n", - "[-1.7940071 -2.5128942]\n", - "[-1.9186544 -2.5888019]\n", - "[-2.0382538 -2.6627793]\n", - "[-2.152771 -2.735217]\n", - "[-2.2620971 -2.8060198]\n", - "[-2.3657765 -2.8749723]\n", - "[-2.4635859 -2.942443 ]\n", - "[-2.5571456 -3.0074604]\n", - "[-2.6474872 -3.071116 ]\n", - "[-2.7343643 -3.1320357]\n", - "[-2.8174913 -3.1904984]\n", - "[-2.896546 -3.2464304]\n", - "[-2.971222 -3.298626]\n", - "[-3.0411685 -3.3485155]\n", - "[-3.1060221 -3.3945203]\n", - "[-3.1671162 -3.4365993]\n", - "[-3.2244647 -3.47741 ]\n", - "[-3.2800133 -3.51378 ]\n", - "[-3.328074 -3.5467668]\n", - "[-3.3779154 -3.5716858]\n", - "[-3.42378 -3.6026983]\n", - "[-3.4665916 -3.6264663]\n", - "[-3.5065007 -3.6452012]\n", - "[-3.5436964 -3.6676104]\n", - "[-3.5783873 -3.6827888]\n", - "[-3.6107998 -3.696251 ]\n", - "[-3.6411772 -3.710956 ]\n", - "[-3.6697989 -3.725151 ]\n", - "[-3.6969085 -3.739223 ]\n", - "[-3.7227716 -3.753837 ]\n", - "[-3.747642 -3.7637105]\n", - "[-3.7717733 -3.7778597]\n", - "[-3.7953677 -3.7897499]\n", - "[-3.8185773 -3.8026254]\n", - "[-3.8415692 -3.8186839]\n", - "[-3.864397 -3.8288355]\n", - "[-3.887118 -3.8470592]\n", - "[-3.9089546 -3.8578553]\n", - "[-3.9298224 -3.8789082]\n", - "[-3.9531326 -3.898365 ]\n", - "[-3.9759274 -3.9132624]\n" + "Circuit #0\n", + "cost: -6.011465 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n", + "Circuit #1\n", + "cost: -6.0114813 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n", + "Circuit #2\n", + "cost: -6.0113897 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n", + "Circuit #3\n", + "cost: -6.001644 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n", + "Circuit #4\n", + "cost: -6.011491 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n", + "Circuit #5\n", + "cost: -5.1607475 \n", + "bit strings: ['01010101', '10101010'] \n", + "\n" ] } ], "source": [ + "# print all results\n", + "for num_circuit in range(ncircuits):\n", + " c = QAOAansatz(params=params[num_circuit], g=example_graph, return_circuit=True)\n", + " loss = QAOAansatz(params=params[num_circuit], g=example_graph)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + " index = np.where(probs == max(probs))[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + " print(\"Circuit #%d\" % num_circuit)\n", + " print(\"cost:\", K.numpy(loss), \"\\nbit strings:\", states, \"\\n\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c27fb3f6", + "metadata": {}, + "source": [ + "Based on the results, quantum states with the highest probabilities are $\\ket{01010101}$ and $\\ket{10101010}$. This outcome aligns with our intuition, as swapping the labels of the groups would have an impact on the final result.\n", + "\n", + "The network plot corresponding to $\\ket{01010101}$ is:" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "id": "fb183e97", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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qlatysqVK3P1mhs2bGD48OGMHDmSL774IlevLYTIeUOGDEGv1zN48GCMRiM//fST7CsirILd/iutVq0aV69e5eHDh7i5ueX49fbu3Uvfvn3p0aMH8+bNk0FGQtio/v37o9fr6d+/P0ajkV9++QW9Xq92WUJkyG47tZ6eUZDTTpw4QdeuXfHx8WHJkiXSdCiEjevVqxerV69m/fr19O7dm4SEBLVLEiJDdhsGqlSpApDjgwjPnTtH+/btqVGjBmvXrsXJySlHryeEsAzdunVj/fr1bN++nZ49exIfH692SUKky27DgJubG15eXjk6iPDKlSv4+vpSvHhxtmzZgqura45dSwhheTp27MimTZvYs2cP3bp149GjR2qXJESa7DYMQM7uUXDr1i3atm2Ls7MzO3bsIH829lIXQli/tm3bsnXrVg4ePEjnzp2JjY1VuyQhnmPXYSCnphfev3+fdu3aERsby65du/D09DT7NYQQ1qNly5bs2LGD48eP06FDB2JiYtQuSYhU7DoMVK1alStXrpg1qT969IjOnTsTFhbGrl27KFu2rNnOLYSwXk2bNmXXrl388ccftGvXjgcPHqhdkhAp7DoMVKtWDTDfjAKDwUCvXr04ffo0W7duTTm/EEIANG7cmD179nDhwgXatGlDVFSU2iUJAdh5GDDnjIKkpCSGDBnCnj17WL9+vWp7HgghLFv9+vUJCgri8uXLtGrVijt37qhdkhD2HQbc3d0pXbr0S4cBRVEYP348q1atYvny5bRp08ZMFQohbFHt2rXZt28fN27coGXLlty+fVvtkoSds+swAOYZRPjBBx8wf/58Fi5cSI8ePcxUmRDCllWvXp19+/Zx9+5dWrRoQUREhNolCTtm92HgZacXfvXVV3z++ed8++23DBs2zIyVCSFsnbe3N8HBwcTExODj40N4eLjaJQk7ZfdhoFq1aly+fDlbi4EsXLiQd955hw8//JDJkyfnQHVCCFtXsWJFgoODMRgM+Pj4cPXqVbVLEnbI7sOAt7c3SsGC/PjXX2y4c4etd+9yPjaWJEXJ8H2rV69m9OjRjBs3jmnTpuVStUIIW1SuXDmCg4MBaN68OaGhoSpXJOyNBsj4rodpoF10dHQulJN7TsbEMPv6dTZERnIvKem51/NotTTLm5dxJUrQqUABHLT/5qadO3fSuXNnevfuzZIlS9Bq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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "colors = [\"r\" if states[0][i] == \"0\" else \"c\" for i in range(nnodes)]\n", + "nx.draw_networkx(example_graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "4ae99ab9", + "metadata": {}, + "source": [ + "## Classical Method" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "720dd1a4", + "metadata": {}, + "source": [ + "In classial method, all situation will be checked one-by-one (brutal force). " + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "id": "2115bb6d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bit string: ['01010101', '10101010'] \n", + "max cut: 10.0\n" + ] + } + ], + "source": [ + "def classical_solver(graph):\n", + " num_nodes = len(graph)\n", + " max_cut = [0]\n", + " best_case = [0] # \"01\" series with max cut\n", + " for i in range(2**num_nodes):\n", + " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", + " cat1, cat2 = [], []\n", + " for j in range(num_nodes):\n", + " if str(case)[j] == \"0\":\n", + " cat1.append(j)\n", + " else:\n", + " cat2.append(j)\n", + "\n", + " # calculate the cost function\n", + " cost = 0\n", + " for node1 in cat1:\n", + " for node2 in cat2:\n", + " if graph[node1].get(node2):\n", + " cost += graph[node1][node2][\"weight\"]\n", + " cost = round(cost, 4) # elimate minor error\n", + " if max_cut[-1] <= cost:\n", + " max_cut.append(cost)\n", + " best_case.append(case)\n", + "\n", + " # optimal cases maybe more than 1, but they are all at the end\n", + " index = max_cut.index(max_cut[-1])\n", + "\n", + " return max_cut[-1], best_case[index:]\n", + "\n", + "\n", + "max_cut, best_case = classical_solver(example_graph_dict)\n", + "print(\"bit string:\", best_case, \"\\nmax cut:\", max_cut)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e9b8619b", + "metadata": {}, + "source": [ + "## Weighted Max-Cut Problem" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "9f8cb1da", + "metadata": {}, + "source": [ + "When an edge is cut, the total cost increase a certain number instead of 1, we say that this edge has a \"weight\".\n", + "\n", + "Let's define a graph with random weights:" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "id": "b0a1f778", + "metadata": {}, + "outputs": [], + "source": [ + "weighted_graph_dict = {\n", + " 0: {1: {\"weight\": 0.1756}, 7: {\"weight\": 2.5664}, 3: {\"weight\": 1.8383}},\n", + " 1: {0: {\"weight\": 0.1756}, 2: {\"weight\": 2.2142}, 3: {\"weight\": 4.7169}},\n", + " 2: {1: {\"weight\": 2.2142}, 3: {\"weight\": 2.0984}, 5: {\"weight\": 0.1699}},\n", + " 3: {1: {\"weight\": 4.7169}, 2: {\"weight\": 2.0984}, 0: {\"weight\": 1.8383}},\n", + " 4: {7: {\"weight\": 0.9870}, 6: {\"weight\": 0.0480}, 5: {\"weight\": 4.2509}},\n", + " 6: {7: {\"weight\": 4.7528}, 4: {\"weight\": 0.0480}, 5: {\"weight\": 2.2879}},\n", + " 5: {6: {\"weight\": 2.2879}, 4: {\"weight\": 4.2509}, 2: {\"weight\": 0.1699}},\n", + " 7: {4: {\"weight\": 0.9870}, 6: {\"weight\": 4.7528}, 0: {\"weight\": 2.5664}},\n", + "}\n", + "\n", + "weighted_graph = nx.to_networkx_graph(weighted_graph_dict)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "264289c1", + "metadata": {}, + "source": [ + "The classical algorithm is used to find the corresponding maximum cut" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "id": "f9f5ce41", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bit string: ['00010101', '11101010'] \n", + "max cut: 23.6685\n" + ] + } + ], + "source": [ + "max_cut, best_case = classical_solver(weighted_graph_dict)\n", + "print(\"bit string:\", best_case, \"\\nmax cut:\", max_cut)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "id": "35dea0fb", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "colors = [\"r\" if best_case[0][i] == \"0\" else \"c\" for i in range(nnodes)]\n", + "weighted_graph = nx.to_networkx_graph(weighted_graph_dict)\n", + "nx.draw_networkx(weighted_graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d62faa79", + "metadata": {}, + "source": [ + "The quantum algorithm is then used, and the same result is supposed to be found." + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "id": "22db40be", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "QAOA_vvag = K.jit(\n", + " tc.backend.vvag(QAOAansatz, argnums=0, vectorized_argnums=0), static_argnums=(1, 2)\n", + ")\n", "params = K.implicit_randn(\n", " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", ") # initial parameters\n", "opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", "\n", - "for i in range(50):\n", - " loss, grads = QAOA_vvag(params, example_graph)\n", - " print(K.numpy(loss))\n", - " params = opt.update(grads, params) # gradient descent" + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(300):\n", + " loss, grads = QAOA_vvag(params, weighted_graph)\n", + " params = opt.update(grads, params) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [\"circuit %d\" % leg for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "id": "d2cf1b57", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Circuit #0\n", + "cost: -15.938664 \n", + "bit strings: ['00110101', '11001010'] \n", + "\n", + "Circuit #1\n", + "cost: -17.461643 \n", + "bit strings: ['00010101', '11101010'] \n", + "\n", + "Circuit #2\n", + "cost: -16.610685 \n", + "bit strings: ['00010101', '11101010'] \n", + "\n", + "Circuit #3\n", + "cost: -16.61402 \n", + "bit strings: ['00010101', '11101010'] \n", + "\n", + "Circuit #4\n", + "cost: -14.814039 \n", + "bit strings: ['00010101', '11101010'] \n", + "\n", + "Circuit #5\n", + "cost: -14.7950735 \n", + "bit strings: ['00010101', '11101010'] \n", + "\n" + ] + } + ], + "source": [ + "# print all results\n", + "for num_circuit in range(ncircuits):\n", + " c = QAOAansatz(params=params[num_circuit], g=weighted_graph, return_circuit=True)\n", + " loss = QAOAansatz(params=params[num_circuit], g=weighted_graph)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + " index = np.where(probs == max(probs))[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + " print(\"Circuit #%d\" % num_circuit)\n", + " print(\"cost:\", K.numpy(loss), \"\\nbit strings:\", states, \"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "id": "492d215f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS info: macOS-13.3.1-arm64-arm-64bit\n", + "Python version: 3.10.10\n", + "Numpy version: 1.23.2\n", + "Scipy version: 1.10.1\n", + "Pandas version: 2.0.1\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra is not installed\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]\n", + "TensorFlow CUDA infos: {'is_cuda_build': False, 'is_rocm_build': False, 'is_tensorrt_build': False}\n", + "Jax is not installed\n", + "JaxLib is not installed\n", + "PyTorch is not installed\n", + "Cupy is not installed\n", + "Qiskit version: 0.23.3\n", + "Cirq is not installed\n" + ] + } + ], + "source": [ + "tc.about()" ] } ], @@ -270,7 +785,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.0" + "version": "3.10.10" } }, "nbformat": 4, diff --git a/docs/source/tutorials/qaoa_bo.ipynb b/docs/source/tutorials/qaoa_bo.ipynb index cd6e97e4..240bf374 100644 --- a/docs/source/tutorials/qaoa_bo.ipynb +++ b/docs/source/tutorials/qaoa_bo.ipynb @@ -3,32 +3,71 @@ { "cell_type": "markdown", "source": [ - "# Optimizing QAOA using BO" + "# Optimizing QAOA by Bayesian Optimization (BO)" ], "metadata": {} }, { "cell_type": "markdown", "source": [ - "## Setup" + "## Overview" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "In this tutorial, we show how to use Bayesian optimization to optimize QAOA. For the introduction of QAOA, please refer to the [previous tutorial](qaoa.ipynb). Bayesian optimization in this tutorial is based on $\\text{ODBO}$, please refer to [Cheng, Yang, Hsieh, Liao and Zhang](https://doi.org/10.48550/arXiv.2205.09548) for details and this [repository](https://github.com/tencent-quantum-lab/ODBO) for source code and [installation](https://github.com/tencent-quantum-lab/ODBO#installation). In this tutorial, the updated modules of BO, TuRBO and DARBO are packaged." ], "metadata": {} }, + { + "cell_type": "markdown", + "source": [ + "## Setup" + ], + "metadata": { + "collapsed": false + } + }, { "cell_type": "code", "execution_count": null, "source": [ "import tensorcircuit as tc\n", - "import tensorflow as tf\n", - "import cotengra as ctg\n", + "from jax import numpy as jnp\n", "import optax\n", + "import torch\n", "import networkx as nx\n", - "import time\n", + "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "import torch\n", - "import os\n", + "import cotengra as ctg\n", + "from typing import Union\n", + "import time\n", + "import odbo\n", + "from IPython.display import clear_output\n", + "\n", + "K = tc.set_backend(\"jax\")\n", + "tc.set_dtype(\"complex128\")\n", + "dtype = torch.float64\n", "\n", - "K = tc.set_backend(\"tensorflow\")" + "# cotengra package to speed up the calculation\n", + "opt_ctg = ctg.ReusableHyperOptimizer(\n", + " methods=[\"greedy\", \"kahypar\"],\n", + " parallel=True,\n", + " minimize=\"combo\",\n", + " max_time=20,\n", + " max_repeats=128,\n", + " progbar=True,\n", + ")\n", + "\n", + "tc.set_contractor(\"custom\", optimizer=opt_ctg, preprocessing=True)\n", + "\n", + "nlayers = 10\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "acqfn = \"ucb\"" ], "outputs": [], "metadata": {} @@ -36,257 +75,847 @@ { "cell_type": "markdown", "source": [ - "## QAOA blackbox" + "## MAX-CUT Hamiltonian" ], "metadata": {} }, + { + "cell_type": "markdown", + "source": [ + "### Define the Graph" + ], + "metadata": { + "collapsed": false + } + }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "source": [ - "# Generate a graph\n", - "def dict2graph(d):\n", - " g = nx.to_networkx_graph(d)\n", - " for e in g.edges:\n", - " if not g[e[0]][e[1]].get(\"weight\"):\n", - " g[e[0]][e[1]][\"weight\"] = 1.0\n", - " nx.draw(g, with_labels=True)\n", - " return g\n", - "\n", - "\n", "# a graph instance\n", - "example_graph_dict = {\n", - " 0: {1: {\"weight\": 0.9}, 7: {\"weight\": 0.4}, 3: {\"weight\": 0.38}},\n", - " 1: {0: {\"weight\": 0.44}, 2: {\"weight\": 0.67}, 3: {\"weight\": 0.62}},\n", - " 2: {1: {\"weight\": 0.21}, 3: {\"weight\": 0.87}, 5: {\"weight\": 0.72}},\n", - " 4: {7: {\"weight\": 0.34}, 6: {\"weight\": 0.53}, 5: {\"weight\": 0.45}},\n", - " 7: {4: {\"weight\": 0.45}, 6: {\"weight\": 0.63}, 0: {\"weight\": 0.59}},\n", - " 3: {1: {\"weight\": 0.12}, 2: {\"weight\": 0.21}, 0: {\"weight\": 0.68}},\n", - " 6: {7: {\"weight\": 0.34}, 4: {\"weight\": 0.33}, 5: {\"weight\": 0.96}},\n", - " 5: {6: {\"weight\": 0.18}, 4: {\"weight\": 0.79}, 2: {\"weight\": 0.17}},\n", + "graph_dict = {\n", + " 0: {1: {\"weight\": 1.0}, 7: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", + " 1: {0: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 3: {\"weight\": 1.0}},\n", + " 2: {1: {\"weight\": 1.0}, 3: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", + " 3: {1: {\"weight\": 1.0}, 2: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", + " 4: {7: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", + " 5: {6: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 2: {\"weight\": 1.0}},\n", + " 6: {7: {\"weight\": 1.0}, 4: {\"weight\": 1.0}, 5: {\"weight\": 1.0}},\n", + " 7: {4: {\"weight\": 1.0}, 6: {\"weight\": 1.0}, 0: {\"weight\": 1.0}},\n", "}\n", "\n", - "example_graph = dict2graph(example_graph_dict)" + "graph = nx.to_networkx_graph(graph_dict)\n", + "pos = nx.spring_layout(graph)\n", + "nx.draw_networkx(graph, with_labels=True, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" ], "outputs": [ { - "output_type": "display_data", "data": { - "text/plain": [ - "
" - ], - "image/png": "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" + "text/plain": "
", + "image/png": "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" }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } ], - "metadata": {} + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-15T07:42:26.571397400Z", + "start_time": "2023-07-15T07:42:26.444088200Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "### Brutal Force Result" + ], + "metadata": { + "collapsed": false + } }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bit string: ['01010101', '10101010'] \n", + "max cut: 10.0\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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LxUqVKB///4YjUb69u3rshcFBZGVlcWwYcPYsGEDq1evdpo7rJyRhAENOnbsGMOHD2fv3r2MGzeOadOmlakrgvj4eKKiohzhIDY2FoCGDRs6gkF4eDiNGjVyifuhhSisS5cusWzZMkwmEzt37sTb25t+/fphNBp58MEHXWLt0N3Kzs7GaDTy008/sWrVKvr27at2SU5NwoBGWSwW5syZw5QpU7jnnntYunQpnTp1UrusEnHz5s0c4WD//v0oikL9+vVzhIMmTZpIOBAuKy4ujhUrVmAymdi6dSuenp488MADGI1GBgwY4HS3GJcki8XCv//9b3788UdWrlxJ//791S7J6UkY0LhDhw4xfPhwYmNjmTBhApMnTy5TC4fuJCEhga1btzrCwb59+7DZbNStWzfHtEKzZs0kHAindu3aNVauXInJZCIyMhJ3d3f69OmD0WjkoYce0uT+IBaLhUcffZTly5ezfPlyHn74YbVLcgkSBgTZ2dm89dZbvPHGG9x7770sXbpUUz26ExMTc4SD6OhobDYbtWvXzhEOWrRoIeFAqO7GjRusXLkSs9nMr7/+ik6no1evXhgMBgYOHKjpPUCsVivDhw/n+++/x2w2M3jwYLVLchkSBoTD/v37GT58OEeOHGHy5MlMmDChTNxfXFhJSUls27bNEQ727t2L1WqlZs2aOcJBq1atJByIUpGQkMCqVaswm81s2rQJm81Gjx49MBgMDB48mOrVq6tdouqsViujRo3im2++4bvvvmPYsGFql+RSJAyIHLKyspgxYwYzZ84kICCApUuXOt3e46UtOTmZ7du3O8LBnj17sFgs1KhRg+7duzvCwb333utS/dmFc0tKSuLHH3/EZDKxceNGLBYL3bt3x2AwMGTIEGrWrKl2iU7DZrMxZswYlixZwtdff82///1vtUtyORIGxB3t3buX4cOHc/LkSaZOncrLL7/s0m1Ii1NqamqOcLB7926ys7OpXr16jnDQpk0bCQeiUFJSUlizZg0mk4n169eTmZlJ165dMRqNDBkyRLpu3oHNZuOJJ57giy++4Msvv+SRRx5RuySXJGFA5CojI4Np06bxzjvv0KlTJ5YsWUKrVq3ULsvppKWlsWPHDkc42LVrF1lZWVStWjVHOGjXrp2EA/EPqamprFu3DpPJxE8//URGRgbBwcEYjUaGDh1K/fr11S7R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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def classical_solver(graph):\n", + " num_nodes = len(graph)\n", + " max_cut = [0]\n", + " best_case = [0] # \"01\" series with max cut\n", + " for i in range(2**num_nodes):\n", + " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", + " cat1, cat2 = [], []\n", + " for j in range(num_nodes):\n", + " if str(case)[j] == \"0\":\n", + " cat1.append(j)\n", + " else:\n", + " cat2.append(j)\n", + "\n", + " # calculate the cost function\n", + " cost = 0\n", + " for node1 in cat1:\n", + " for node2 in cat2:\n", + " if graph[node1].get(node2):\n", + " cost += graph[node1][node2][\"weight\"]\n", + " cost = round(cost, 4) # elimate minor error\n", + " if max_cut[-1] <= cost:\n", + " max_cut.append(cost)\n", + " best_case.append(case)\n", + "\n", + " # optimal cases maybe more than 1, but they are all at the end\n", + " index = max_cut.index(max_cut[-1])\n", + "\n", + " return max_cut[-1], best_case[index:]\n", + "\n", + "\n", + "max_cut, best_case = classical_solver(graph_dict)\n", + "print(\"bit string:\", best_case, \"\\nmax cut:\", max_cut)\n", + "\n", + "colors = [\"r\" if best_case[0][i] == \"0\" else \"c\" for i in graph.nodes]\n", + "weighted_graph = nx.to_networkx_graph(graph_dict)\n", + "nx.draw_networkx(weighted_graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T07:42:29.489809800Z", + "start_time": "2023-07-15T07:42:29.368921400Z" + } + } + }, + { + "cell_type": "markdown", "source": [ - "def QAOAansatz(params, g=example_graph):\n", - " n = len(g.nodes) # the number of nodes\n", - " c = tc.Circuit(n)\n", + "## QAOA Ansatz" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 46, + "outputs": [], + "source": [ + "def QAOAansatz(params, each=1, return_circuit=False):\n", + " n = graph.number_of_nodes() # the number of nodes\n", + "\n", + " # PQC loop\n", + " def pqc_loop(s_, params_):\n", + " c_ = tc.Circuit(n, inputs=s_)\n", + " for j in range(each):\n", + " # driving layer\n", + " for a, b in graph.edges:\n", + " c_.RZZ(a, b, theta=graph[a][b][\"weight\"] * params_[2 * j])\n", + " # mixing layer\n", + " for i in range(n):\n", + " c_.RX(i, theta=params_[2 * j + 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(n)\n", " for i in range(n):\n", - " c.H(i)\n", - " # PQC\n", - " for j in range(nlayers):\n", - " # U_j\n", - " for e in g.edges:\n", - " c.exp1(\n", - " e[0],\n", - " e[1],\n", - " unitary=tc.gates._zz_matrix,\n", - " theta=g[e[0]][e[1]].get(\"weight\", 1.0) * params[2 * j],\n", - " )\n", - " # V_j\n", - " for i in range(n):\n", - " c.rx(i, theta=params[2 * j + 1])\n", + " c0.H(i)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, K.reshape(params, [nlayers // each, 2 * each]), s0)\n", + " c = tc.Circuit(n, inputs=s)\n", + "\n", + " # whether to return the circuit\n", + " if return_circuit is True:\n", + " return c\n", "\n", " # calculate the loss function\n", " loss = 0.0\n", - " for e in g.edges:\n", - " loss += g[e[0]][e[1]].get(\"weight\") * c.expectation_ps(z=[e[0], e[1]])\n", + " for a, b in graph.edges:\n", + " loss += c.expectation_ps(z=[a, b]) * graph[a][b][\"weight\"]\n", "\n", " return K.real(loss)" ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.534488800Z", + "start_time": "2023-07-15T05:12:41.483853500Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 47, "outputs": [], - "metadata": {} + "source": [ + "QAOA_vag = K.jit(\n", + " tc.backend.value_and_grad(QAOAansatz, argnums=0), static_argnums=(1, 2)\n", + ")\n", + "QAOA_nograd = K.jit(QAOAansatz, static_argnums=(1, 2))\n", + "\n", + "\n", + "def eval_objective(x):\n", + " \"\"\"This is a helper function we use to unnormalize and evalaute a point\"\"\"\n", + " return -torch.from_numpy(np.asarray(QAOA_nograd(jnp.asarray(x.ravel()))))" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.541255500Z", + "start_time": "2023-07-15T05:12:41.484406100Z" + } + } }, { "cell_type": "markdown", "source": [ - "## Using BO optimizer from ODBO\n" + "## Adam Optimizer" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 48, + "outputs": [], + "source": [ + "opt = K.optimizer(optax.adam(1e-2))" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.603802800Z", + "start_time": "2023-07-15T05:12:41.585764800Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## BO Optimizer" ], "metadata": {} }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 49, "source": [ - "import odbo\n", + "class BO_optimizer:\n", + " def __init__(self, eval_func, batch_size: int = 1, device=\"cpu\"):\n", + " self.eval_func = eval_func\n", + " self.device = device\n", + " self.batch_size = batch_size\n", + " self.best_dict = {\"X\": None, \"Y\": torch.tensor(-float(\"inf\"))}\n", "\n", - "# BO settings\n", - "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", - "dtype = torch.float\n", + " def compute_Y(self, X):\n", + " return torch.tensor(\n", + " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", + " ).unsqueeze(-1)\n", + "\n", + " def update_best(self, X_next, Y_next):\n", + " new_Y, new_idx = torch.max(Y_next, dim=0)\n", + " new_Y = new_Y.squeeze()\n", + " if new_Y > self.best_dict[\"Y\"]:\n", + " self.best_dict[\"Y\"] = new_Y\n", + " self.best_dict[\"X\"] = X_next[new_idx]\n", + "\n", + " def update(\n", + " self,\n", + " X,\n", + " Y=None,\n", + " acqfn: str = \"ucb\",\n", + " normalize: bool = False,\n", + " verbose: bool = False,\n", + " ):\n", + " if Y is None:\n", + " Y = self.compute_Y(X)\n", + " X_next = odbo.run_exp.bo_design(\n", + " X=X,\n", + " Y=Y,\n", + " batch_size=self.batch_size,\n", + " acqfn=acqfn,\n", + " normalize=normalize,\n", + " verbose=verbose,\n", + " )[0].reshape(self.batch_size, X.shape[-1])\n", + " Y_next = self.compute_Y(X_next)\n", + "\n", + " self.update_best(X_next, Y_next)\n", + "\n", + " # Update training set\n", + " X = torch.cat((X, X_next), dim=0)\n", + " Y = torch.cat((Y, Y_next), dim=0)\n", + "\n", + " return X, Y, Y_next.mean()" + ], + "outputs": [], + "metadata": { + "scrolled": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.603802800Z", + "start_time": "2023-07-15T05:12:41.586291Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 50, + "outputs": [], + "source": [ "batch_size = 1\n", - "acqfn = \"ucb\"\n", "\n", - "QAOA_nograd = K.jit(QAOAansatz)\n", + "bo_opt = BO_optimizer(eval_objective, batch_size, device)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.603802800Z", + "start_time": "2023-07-15T05:12:41.586291Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## TuRBO Optimizer" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 51, + "outputs": [], + "source": [ + "class TuRBO_optimizer(BO_optimizer):\n", + " def __init__(\n", + " self, eval_func, num_params, tr_length, failure_tolerance, device=\"cpu\"\n", + " ):\n", + " super(TuRBO_optimizer, self).__init__(eval_func, device=device)\n", + " self.batch_size = 1 # There is a bug in odbo.run_exp.turbo_design, batch_size can only be 1 right now.\n", + " self.tr_length = tr_length\n", + " self.state = odbo.turbo.TurboState(\n", + " dim=num_params,\n", + " batch_size=batch_size,\n", + " length=tr_length,\n", + " n_trust_regions=len(tr_length),\n", + " failure_tolerance=failure_tolerance,\n", + " )\n", "\n", + " def inverse_transform(self, X):\n", + " \"\"\"\n", + " Note TuRBO is working on only [0,1] parameter range\n", + " We need to transform parameters from [0,1] to [-pi,pi] before using eval_func\n", + " \"\"\"\n", + " return X * 2 * np.pi - np.pi\n", "\n", - "def eval_objective(x, example_graph):\n", - " \"\"\"This is a helper function we use to unnormalize and evalaute a point\"\"\"\n", - " a = tf.convert_to_tensor(np.array(x).ravel())\n", - " return -QAOA_nograd(a, example_graph).numpy()\n", + " def transform(self, X):\n", + " \"\"\"\n", + " Note TuRBO is working on only [0,1] parameter range\n", + " We need to transform parameters from [-pi,pi] to [0,1] before using odbo.run_exp.turbo_design\n", + " \"\"\"\n", + " return X / 2 / np.pi + 0.5\n", + "\n", + " def compute_Y(self, X, transformed_input: bool = True):\n", + " if transformed_input:\n", + " X = self.inverse_transform(X)\n", + " return torch.tensor(\n", + " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", + " ).unsqueeze(-1)\n", + "\n", + " def get_next(self, X, Y, acqfn, normalize, verbose):\n", + " X_next = odbo.run_exp.turbo_design(\n", + " state=self.state,\n", + " X=X,\n", + " Y=Y,\n", + " n_trust_regions=len(self.tr_length),\n", + " batch_size=self.batch_size,\n", + " acqfn=acqfn,\n", + " normalize=normalize,\n", + " verbose=verbose,\n", + " )[0].reshape(len(self.tr_length) * self.batch_size, X.shape[-1])\n", + " Y_next = self.compute_Y(X_next)\n", + " return X_next, Y_next\n", + "\n", + " def update_state(self, Y_next):\n", + " self.state = odbo.turbo.update_state(\n", + " state=self.state,\n", + " Y_next=Y_next.reshape(len(self.tr_length), self.batch_size, 1),\n", + " )\n", + "\n", + " def preprocess(self, X, Y, transformed_input):\n", + " if not transformed_input:\n", + " X = self.transform(X)\n", + " if Y is None:\n", + " Y = self.compute_Y(X)\n", + " best_Y, best_idx = torch.max(Y, dim=0)\n", + " best_Y = best_Y.squeeze()\n", + " if best_Y > self.best_dict[\"Y\"]:\n", + " self.state.best_value = best_Y.item()\n", + " self.best_dict[\"Y\"] = best_Y\n", + " self.best_dict[\"X\"] = X[best_idx]\n", + " return X, Y\n", + "\n", + " def postprocess(self, X, Y, X_next, Y_next, transformed_output):\n", + " X = torch.cat((X, X_next), dim=0)\n", + " Y = torch.cat((Y, Y_next), dim=0)\n", + " if not transformed_output:\n", + " X = self.inverse_transform(X)\n", + " return X, Y\n", + "\n", + " def update(\n", + " self,\n", + " X,\n", + " Y=None,\n", + " acqfn: str = \"ucb\",\n", + " normalize: bool = False,\n", + " verbose: bool = False,\n", + " transformed_input: bool = False,\n", + " transformed_output: bool = False,\n", + " ):\n", + " X, Y = self.preprocess(X, Y, transformed_input)\n", + "\n", + " X_next, Y_next = self.get_next(X, Y, acqfn, normalize, verbose)\n", "\n", + " self.update_best(X_next, Y_next)\n", "\n", - "X_new = np.random.uniform(low=0, high=1, size=[1, 2 * nlayers])\n", - "X_bo = torch.tensor(np.vstack([initial_X, X_new]))\n", - "Y_bo = torch.tensor(\n", - " [eval_objective(x, example_graph) for x in X_bo], dtype=dtype, device=device\n", - ").unsqueeze(-1)" + " self.update_state(Y_next)\n", + "\n", + " X, Y = self.postprocess(X, Y, X_next, Y_next, transformed_output)\n", + "\n", + " return X, Y, Y_next.mean()" ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.603802800Z", + "start_time": "2023-07-15T05:12:41.586798100Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 52, "outputs": [], + "source": [ + "failure_tolerance = 10\n", + "tr_length = [1.6]\n", + "\n", + "turbo_opt = TuRBO_optimizer(\n", + " eval_objective, 2 * nlayers, tr_length, failure_tolerance, device\n", + ")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.645737200Z", + "start_time": "2023-07-15T05:12:41.586798100Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## DARBO Optimizer" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Please refer to [Cheng, Chen, Zhang and Zhang](https://doi.org/10.48550/arXiv.2303.14877) for details." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 53, + "outputs": [], + "source": [ + "class DARBO_optimizer(TuRBO_optimizer):\n", + " def __init__(\n", + " self,\n", + " eval_func,\n", + " num_params,\n", + " tr_length,\n", + " failure_tolerance,\n", + " mode: Union[bool, str] = True,\n", + " device=\"cpu\",\n", + " ):\n", + " super(DARBO_optimizer, self).__init__(\n", + " eval_func, num_params, tr_length, failure_tolerance, device\n", + " )\n", + " self.switch_counter = 0\n", + " if mode == True or mode == \"large\":\n", + " self.mode = True\n", + " else:\n", + " self.mode = False\n", + " self.best_dict = {\n", + " \"X\": None,\n", + " \"Y\": torch.tensor(self.state.best_value),\n", + " \"mode\": self.mode,\n", + " }\n", + "\n", + " def get_mode(self):\n", + " return \"large\" if self.mode else \"small\"\n", + "\n", + " def compute_Y(self, X, transformed_input: bool = True, mode=None):\n", + " if transformed_input:\n", + " X = self.inverse_transform(X, mode)\n", + " return torch.tensor(\n", + " [self.eval_func(x) for x in X], dtype=X.dtype, device=self.device\n", + " ).unsqueeze(-1)\n", + "\n", + " def inverse_transform(self, X, mode=None):\n", + " \"\"\"\n", + " Note TuRBO is working on only [0,1] parameter range\n", + " We need to transform parameters from [0, 1] to [-pi, pi] or [-pi / 2, pi / 2] before using eval_func\n", + " \"\"\"\n", + " if mode is None:\n", + " mode = self.mode\n", + " if mode: # [0, 1] to [-pi, pi]\n", + " return X * 2 * np.pi - np.pi\n", + " else: # [0, 1] to [-pi / 2, pi / 2]\n", + " return X * np.pi - np.pi / 2\n", + "\n", + " def transform(self, X, mode=None):\n", + " \"\"\"\n", + " Note TuRBO is working on only [0,1] parameter range\n", + " We need to transform parameters from [-pi,pi] or [-pi / 2, pi / 2] to [0,1] before using odbo.run_exp.turbo_design\n", + " \"\"\"\n", + " if mode is None:\n", + " mode = self.mode\n", + " if mode: # [-pi, pi] to [0, 1]\n", + " return X / 2 / np.pi + 0.5\n", + " else: # [-pi / 2, pi / 2] to [0, 1]\n", + " return X / np.pi + 0.5\n", + "\n", + " def update_best(self, X_next, Y_next):\n", + " new_Y, new_idx = torch.max(Y_next, dim=0)\n", + " new_Y = new_Y.squeeze()\n", + " if new_Y > self.best_dict[\"Y\"]:\n", + " self.best_dict[\"Y\"] = new_Y\n", + " self.best_dict[\"X\"] = X_next[new_idx]\n", + " self.best_dict[\"mode\"] = self.mode\n", + " else:\n", + " self.switch_counter += 1\n", + "\n", + " def update(\n", + " self,\n", + " X,\n", + " Y=None,\n", + " acqfn: str = \"ucb\",\n", + " normalize: bool = False,\n", + " verbose: bool = False,\n", + " transformed_input: bool = False,\n", + " transformed_output: bool = False,\n", + " frequency: int = 4,\n", + " ):\n", + " X, Y = self.preprocess(X, Y, transformed_input)\n", + "\n", + " # check if we need to switch the searching parameter range.\n", + " if self.switch_counter >= frequency:\n", + " if self.mode:\n", + " X = X * 2 - 0.5\n", + " self.mode = False # small\n", + " else:\n", + " X = X / 2 + 0.25\n", + " self.mode = True # large\n", + " self.switch_counter = 0\n", + "\n", + " X_next, Y_next = self.get_next(X, Y, acqfn, normalize, verbose)\n", + "\n", + " self.update_best(X_next, Y_next)\n", + "\n", + " self.update_state(Y_next)\n", + "\n", + " X, Y = self.postprocess(X, Y, X_next, Y_next, transformed_output)\n", + "\n", + " return X, Y, Y_next.mean()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.645737200Z", + "start_time": "2023-07-15T05:12:41.627215300Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 54, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "initial mode: small\n" + ] + } + ], + "source": [ + "mode = \"small\"\n", + "\n", + "darbo_opt = DARBO_optimizer(\n", + " eval_objective, 2 * nlayers, tr_length, failure_tolerance, mode, device\n", + ")\n", + "print(f\"initial mode: {darbo_opt.get_mode()}\")" + ], "metadata": { - "scrolled": false + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:12:41.645737200Z", + "start_time": "2023-07-15T05:12:41.627726200Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "## Optimization" + ], + "metadata": { + "collapsed": false } }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 55, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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iDSeQo2X2W3mlroPCzWHGjIEkpIgLw++/74JCyciIhLAFGq8rErz08E+NYez2+Hss81r9asRERHxDoUaL6vS/LR7d43HnXuuWX/9dRMUSkREpBVQqPGyKjU1GRlQVFTtcUOGmPW2beZxbxEREWkchRov89TUOA7e2p07qz0uIcGsXS7IyWmKkomIiAQ2hRov89TUBB+cAH379mqPCwkxj3oD7NvXBAUTEZGAMWHCBGw2GzabjaCgIJKSkjj99NN56623cLvdRxw/duxYHA4HS5cuPeq5unTpwt13301xcXGV4yqOsdlsOJ1OOnbsyF/+8hdKSkqqHLdr1y6uueYaUlJSCA4OplOnTtx6663s37/fuzehGgo1XuZ5+inYTJfAjh01HltRW6NQIyIi9TVu3DjS0tLYvn07M2bMYOTIkdx6662cc845lJeXe47buXMnCxcuZNKkSbz11lu1nmvr1q288MIL/POf/+Shhx464ri3336btLQ0tm3bxquvvsq7777LY4895tm/detWBg8ezK+//soHH3zA5s2bef3115k9ezbDhg0jKyvL+zfiEE6fnr0V8jQ/BZl1TTU1YELN9u0KNSIiUn8hISEkJycD0L59e44//nhOPPFERo8ezdSpU/nTn/4EmCByzjnncNNNN3HiiSfy/PPPExYWVuO5UlNTGTNmDLNmzeLvf/97leNiY2OrHHfeeeexYsUKz/6JEycSHBzMt99+67lGx44dOe644+jWrRv33Xcfr732mm9uCKqp8TpP85OzbqEGFGpERJoLy7JwuQqafLG89MTIqFGjGDhwIJ999pnn+7z99ttcfvnl9O7dm+7du/PJJ5/Ueo61a9eycOFCgoODaz1u06ZNzJkzh6FDhwKQlZXFN998w80333xEaEpOTuayyy7jf//7n9e+a3VUU+NlR3QUrkPzUxM0M4qISB243YX88ENkk1/3lFPycTgivHKu3r17s3r1agC+++47CgsLGTt2LACXX345b775JldccUWVz0yfPp3IyEjKy8spKSnBbrfz8ssvH3HuSy65BIfD4TnunHPOYfLkyQD8+uuvWJZFnz59qi1Xnz59OHDgAJmZmbRt29Yr3/VwqqnxMk9NjcNmNqimRkREmpBlWdhs5nfQW2+9xUUXXYTTaeowLrnkEhYsWMCWLVuqfGbkyJGsXLmSn376iauuuoqrr76aCy644Ihzv/DCC6xcuZJVq1Yxffp0Nm3adERA8mVNzNGopsbLPB2F7QdDTVoalJSYx50Oo1AjItK82O3hnHJKvl+u6y3r16+nS5cuZGVl8fnnn1NWVlalH4vL5eKtt97i8ccf92yLiIige/fugAlCAwcO5M033+Taa6+tcu7k5GTPcb169SIvL49LLrmExx57jO7du2Oz2Vi/fj2///3vqy1XXFwciYmJXvuuh1NNjZdVjihsQViYGVlv165qj23TxqwVakREmgebzYbDEdHkS0XNSmPNmTOHNWvWcMEFF/D+++/ToUMHVq1axcqVKz3Lc889x9SpU3G5XNWew263c++993L//fdTVMMAshUcDvM7r6ioiDZt2nD66afz6quvHvG59PR03n//fS666CKvfddqy+6zM7dSnuYnt8tMzQ019qtRTY2IiDRUSUkJ6enp7N69mxUrVvDEE09w3nnncc4553DllVfy5ptv8sc//pF+/fpVWa699lr27dvHzJkzazz3hRdeiMPh4JVXXqmyPTs7m/T0dPbs2cP8+fN59NFH6dmzp6cfzcsvv0xJSQljx47l+++/Z9euXcycOZPTTz+d9u3bV6kd8gWFGi/z1NRYh4SabduqPVahRkREGmrmzJm0a9eOzp07M27cOObOncs//vEPvvzyS0+/l+r6xcTExDB69GjefPPNGs/tdDqZNGkSTz/9NAUFBZ7tV199Ne3ataNDhw5ccsklHHPMMcyYMcPTZ6dHjx4sW7aMrl27Mn78eLp168b111/PyJEjWbRoEfHx8d6/EYewWf7s0dMAr7zyCs888wzp6ekMHDiQl156iRNOOKFOn83NzSUmJoacnByio6N9Ur4tWVvo/lJ3IoIiyE+/Bl56Ce66C55++ohj166F/v1NuMnM9ElxRESkBsXFxWzbto0uXboQGhrq7+K0erX9edT193eLqqn53//+x1/+8hceeughVqxYwcCBAxk7diwZGRn+LppHlZqa3r3Nxg0bqj22oqYmKwuqGdVaRERE6qFFhZrnn3+e6667jquvvpq+ffvy+uuvEx4eXuOwz/7gefrJckOvXmbjxo3VHlvRUdjthuzsJiiciIhIAGsxoaa0tJTly5czZswYzza73c6YMWNYtGhRtZ8pKSkhNze3yuJrVToKV4SarVuhrOyIY4OCICbGvFa/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KMnJl5OUdDlBQfG4XAV+K4f61IiIiEij9ejxCi5XASEh/nuyTaFGREREGs3pjMbp9O8YcGp+EhERkYCgUCMiIiIBQaFGREREAoJCjYiIiAQEhRoREREJCAo1IiIiEhAUakRERCQgKNSIiIhIQFCoERERkYCgUCMiIiIBQaFGREREAoJCjYiIiAQEhRoREREJCK1qlm7LsgDIzc31c0lERESkrip+b1f8Hq9Jqwo1eXl5AKSmpvq5JCIiIlJfeXl5xMTE1LjfZh0t9gQQt9vNnj17iIqKwmazee28ubm5pKamsmvXLqKjo7123kCl+1V3ulf1o/tVd7pXdad7VT++uF+WZZGXl0dKSgp2e809Z1pVTY3dbqdDhw4+O390dLR+4OtB96vudK/qR/er7nSv6k73qn68fb9qq6GpoI7CIiIiEhAUakRERCQgKNR4QUhICA899BAhISH+LkqLoPtVd7pX9aP7VXe6V3Wne1U//rxfraqjsIiIiAQu1dSIiIhIQFCoERERkYCgUCMiIiIBQaFGREREAoJCjRe88sordO7cmdDQUIYOHcqSJUv8XSS/e/jhh7HZbFWW3r17e/YXFxczceJE2rRpQ2RkJBdccAF79+71Y4mb1vfff8+5555LSkoKNpuNL774osp+y7J48MEHadeuHWFhYYwZM4Zff/21yjFZWVlcdtllREdHExsby7XXXkt+fn4TfoumcbR7NWHChCN+1saNG1flmNZyr5588kmGDBlCVFQUbdu25fzzz2fjxo1VjqnL372dO3dy9tlnEx4eTtu2bbnrrrsoLy9vyq/ic3W5VyNGjDjiZ+vGG2+sckxruFcAr732GgMGDPAMqDds2DBmzJjh2d9cfq4Uahrpf//7H3/5y1946KGHWLFiBQMHDmTs2LFkZGT4u2h+d8wxx5CWluZZfvzxR8++22+/nWnTpvHxxx8zf/589uzZwx/+8Ac/lrZpFRQUMHDgQF555ZVq9z/99NP84x//4PXXX+enn34iIiKCsWPHUlxc7DnmsssuY926dcyaNYvp06fz/fffc/311zfVV2gyR7tXAOPGjavys/bBBx9U2d9a7tX8+fOZOHEiixcvZtasWZSVlXHGGWdQUFDgOeZof/dcLhdnn302paWlLFy4kP/85z9MnTqVBx980B9fyWfqcq8Arrvuuio/W08//bRnX2u5VwAdOnTgqaeeYvny5SxbtoxRo0Zx3nnnsW7dOqAZ/VxZ0ignnHCCNXHiRM97l8tlpaSkWE8++aQfS+V/Dz30kDVw4MBq92VnZ1tBQUHWxx9/7Nm2fv16C7AWLVrURCVsPgDr888/97x3u91WcnKy9cwzz3i2ZWdnWyEhIdYHH3xgWZZl/fLLLxZgLV261HPMjBkzLJvNZu3evbvJyt7UDr9XlmVZV111lXXeeefV+JnWeq8sy7IyMjIswJo/f75lWXX7u/f1119bdrvdSk9P9xzz2muvWdHR0VZJSUnTfoEmdPi9sizLOu2006xbb721xs+01ntVIS4uzvr3v//drH6uVFPTCKWlpSxfvpwxY8Z4ttntdsaMGcOiRYv8WLLm4ddffyUlJYWuXbty2WWXsXPnTgCWL19OWVlZlfvWu3dvOnbsqPsGbNu2jfT09Cr3JyYmhqFDh3ruz6JFi4iNjWXw4MGeY8aMGYPdbuenn35q8jL727x582jbti29evXipptuYv/+/Z59rfle5eTkABAfHw/U7e/eokWL6N+/P0lJSZ5jxo4dS25urud/5YHo8HtV4f333ychIYF+/foxefJkCgsLPfta671yuVx8+OGHFBQUMGzYsGb1c9WqJrT0tn379uFyuar8IQEkJSWxYcMGP5WqeRg6dChTp06lV69epKWl8cgjj3DKKaewdu1a0tPTCQ4OJjY2tspnkpKSSE9P90+Bm5GKe1Ddz1XFvvT0dNq2bVtlv9PpJD4+vtXdw3HjxvGHP/yBLl26sGXLFu69917OPPNMFi1ahMPhaLX3yu12c9ttt3HSSSfRr18/gDr93UtPT6/2Z69iXyCq7l4BXHrppXTq1ImUlBRWr17NX//6VzZu3Mhnn30GtL57tWbNGoYNG0ZxcTGRkZF8/vnn9O3bl5UrVzabnyuFGvGJM8880/N6wIABDB06lE6dOvHRRx8RFhbmx5JJoLn44os9r/v378+AAQPo1q0b8+bNY/To0X4smX9NnDiRtWvXVunLJtWr6V4d2u+qf//+tGvXjtGjR7Nlyxa6devW1MX0u169erFy5UpycnL45JNPuOqqq5g/f76/i1WFmp8aISEhAYfDcUQP771795KcnOynUjVPsbGx9OzZk82bN5OcnExpaSnZ2dlVjtF9MyruQW0/V8nJyUd0Ri8vLycrK6vV38OuXbuSkJDA5s2bgdZ5ryZNmsT06dOZO3cuHTp08Gyvy9+95OTkan/2KvYFmpruVXWGDh0KUOVnqzXdq+DgYLp3786gQYN48sknGThwIC+++GKz+rlSqGmE4OBgBg0axOzZsz3b3G43s2fPZtiwYX4sWfOTn5/Pli1baNeuHYMGDSIoKKjKfdu4cSM7d+7UfQO6dOlCcnJylfuTm5vLTz/95Lk/w4YNIzs7m+XLl3uOmTNnDm632/MPb2v122+/sX//ftq1awe0rntlWRaTJk3i888/Z86cOXTp0qXK/rr83Rs2bBhr1qypEgRnzZpFdHQ0ffv2bZov0gSOdq+qs3LlSoAqP1ut4V7VxO12U1JS0rx+rrzW5biV+vDDD62QkBBr6tSp1i+//GJdf/31VmxsbJUe3q3RHXfcYc2bN8/atm2btWDBAmvMmDFWQkKClZGRYVmWZd14441Wx44drTlz5ljLli2zhg0bZg0bNszPpW46eXl51s8//2z9/PPPFmA9//zz1s8//2zt2LHDsizLeuqpp6zY2Fjryy+/tFavXm2dd955VpcuXayioiLPOcaNG2cdd9xx1k8//WT9+OOPVo8ePaxLLrnEX1/JZ2q7V3l5edadd95pLVq0yNq2bZv13XffWccff7zVo0cPq7i42HOO1nKvbrrpJismJsaaN2+elZaW5lkKCws9xxzt7155ebnVr18/64wzzrBWrlxpzZw500pMTLQmT57sj6/kM0e7V5s3b7YeffRRa9myZda2bdusL7/80uratat16qmnes7RWu6VZVnWPffcY82fP9/atm2btXr1auuee+6xbDab9e2331qW1Xx+rhRqvOCll16yOnbsaAUHB1snnHCCtXjxYn8Xye8uuugiq127dlZwcLDVvn1766KLLrI2b97s2V9UVGTdfPPNVlxcnBUeHm79/ve/t9LS0vxY4qY1d+5cCzhiueqqqyzLMo91P/DAA1ZSUpIVEhJijR492tq4cWOVc+zfv9+65JJLrMjISCs6Otq6+uqrrby8PD98G9+q7V4VFhZaZ5xxhpWYmGgFBQVZnTp1sq677roj/lPRWu5VdfcJsN5++23PMXX5u7d9+3brzDPPtMLCwqyEhATrjjvusMrKypr42/jW0e7Vzp07rVNPPdWKj4+3QkJCrO7du1t33XWXlZOTU+U8reFeWZZlXXPNNVanTp2s4OBgKzEx0Ro9erQn0FhW8/m5slmWZXmv3kdERETEP9SnRkRERAKCQo2IiIgEBIUaERERCQgKNSIiIhIQFGpEREQkICjUiIiISEBQqBEREZGAoFAjIiIiAUGhRkRalc6dOzNlyhR/F0NEfEChRkR8ZsKECZx//vkAjBgxgttuu63Jrj116lRiY2OP2L506VKuv/76JiuHiDQdp78LICJSH6WlpQQHBzf484mJiV4sjYg0J6qpERGfmzBhAvPnz+fFF1/EZrNhs9nYvn07AGvXruXMM88kMjKSpKQkrrjiCvbt2+f57IgRI5g0aRK33XYbCQkJjB07FoDnn3+e/v37ExERQWpqKjfffDP5+fkAzJs3j6uvvpqcnBzP9R5++GHgyOannTt3ct555xEZGUl0dDTjx49n7969nv0PP/wwxx57LO+++y6dO3cmJiaGiy++mLy8PN/eNBGpN4UaEfG5F198kWHDhnHdddeRlpZGWloaqampZGdnM2rUKI477jiWLVvGzJkz2bt3L+PHj6/y+f/85z8EBwezYMECXn/9dQDsdjv/+Mc/WLduHf/5z3+YM2cOd999NwDDhw9nypQpREdHe6535513HlEut9vNeeedR1ZWFvPnz2fWrFls3bqViy66qMpxW7Zs4YsvvmD69OlMnz6d+fPn89RTT/nobolIQ6n5SUR8LiYmhuDgYMLDw0lOTvZsf/nllznuuON44oknPNveeustUlNT2bRpEz179gSgR48ePP3001XOeWj/nM6dO/PYY49x44038uqrrxIcHExMTAw2m63K9Q43e/Zs1qxZw7Zt20hNTQXgnXfe4ZhjjmHp0qUMGTIEMOFn6tSpREVFAXDFFVcwe/ZsHn/88cbdGBHxKtXUiIjfrFq1irlz5xIZGelZevfuDZjakQqDBg064rPfffcdo0ePpn379kRFRXHFFVewf/9+CgsL63z99evXk5qa6gk0AH379iU2Npb169d7tnXu3NkTaADatWtHRkZGvb6riPieampExG/y8/M599xz+fvf/37Evnbt2nleR0REVNm3fft2zjnnHG666SYef/xx4uPj+fHHH7n22mspLS0lPDzcq+UMCgqq8t5ms+F2u716DRFpPIUaEWkSwcHBuFyuKtuOP/54Pv30Uzp37ozTWfd/jpYvX47b7ea5557DbjcVzh999NFRr3e4Pn36sGvXLnbt2uWprfnll1/Izs6mb9++dS6PiDQPan4SkSbRuXNnfvrpJ7Zv386+fftwu91MnDiRrKwsLrnkEpYuXcqWLVv45ptvuPrqq2sNJN27d6esrIyXXnqJrVu38u6773o6EB96vfz8fGbPns2+ffuqbZYaM2YM/fv357LLLmPFihUsWbKEK6+8ktNOO43Bgwd7/R6IiG8p1IhIk7jzzjtxOBz07duXxMREdu7cSUpKCgsWLMDlcnHGGWfQv39/brvtNmJjYz01MNUZOHAgzz//PH//+9/p168f77//Pk8++WSVY4YPH86NN97IRRddRGJi4hEdjcE0I3355ZfExcVx6qmnMmbMGLp27cr//vc/r39/EfE9m2VZlr8LISIiItJYqqkRERGRgKBQIyIiIgFBoUZEREQCgkKNiIiIBASFGhEREQkICjUiIiISEBRqREREJCAo1IiIiEhAUKgRERGRgKBQIyIiIgFBoUZEREQCwv8DMUDZP+gMBJwAAAAASUVORK5CYII=" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 299 min loss: -5.837215998677346\t-6.87628698348999\t-6.8708058821631575\t-7.000515157123274\n", + "Epoch 299 time: 13.83302903175354\tTotal time: 2123.8649847507477\n" + ] + } + ], "source": [ - "# BO Optimizer\n", - "for i in range(100): # run 100 iter optimizations\n", - " X_next, acq_value, ids = odbo.run_exp.bo_design(\n", - " X=X_bo,\n", - " Y=Y_bo,\n", - " batch_size=batch_size,\n", - " acqfn=acqfn,\n", - " normalize=False,\n", - " verbose=False,\n", + "# initial parameters\n", + "params = K.implicit_randu(shape=(2 * nlayers,))\n", + "initial_X = torch.from_numpy(np.asarray(params)).type(dtype)\n", + "\n", + "# First point by BO is actually just a random selection, to have a better search, we pick the most distant point\n", + "X_new = []\n", + "for i in initial_X:\n", + " if i <= 0.5:\n", + " X_new.append(i + 0.5)\n", + " else:\n", + " X_new.append(i - 0.5)\n", + "X_new = torch.tensor(X_new)\n", + "\n", + "X_bo = torch.stack((initial_X, X_new), dim=0)\n", + "Y_bo = None\n", + "X_turbo = X_bo.clone()\n", + "Y_turbo = None\n", + "X_darbo = X_bo.clone()\n", + "Y_darbo = None\n", + "\n", + "losses, losses_bo, losses_turbo, losses_darbo = [], [], [], []\n", + "t0 = ts = time.time()\n", + "\n", + "for i in range(300):\n", + " loss, grads = QAOA_vag(params)\n", + " params = opt.update(grads, params) # gradient descent\n", + " losses.append(loss)\n", + "\n", + " X_bo, Y_bo, _ = bo_opt.update(X_bo, Y_bo, acqfn)\n", + " losses_bo.append(-bo_opt.best_dict[\"Y\"].item())\n", + "\n", + " X_turbo, Y_turbo, _ = turbo_opt.update(\n", + " X_turbo,\n", + " Y_turbo,\n", + " acqfn,\n", + " transformed_input=False if i == 0 else True,\n", + " transformed_output=True,\n", + " )\n", + " losses_turbo.append(-turbo_opt.best_dict[\"Y\"].item())\n", + "\n", + " X_darbo, Y_darbo, _ = darbo_opt.update(\n", + " X_darbo,\n", + " Y_darbo,\n", + " acqfn,\n", + " transformed_input=False if i == 0 else True,\n", + " transformed_output=True,\n", " )\n", - " X_next = torch.reshape(X_next, [batch_size, 2 * nlayers])\n", - " Y_next = torch.tensor(\n", - " [eval_objective(x, example_graph) for x in X_next], dtype=dtype, device=device\n", + " losses_darbo.append(-darbo_opt.best_dict[\"Y\"].item())\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " plt.figure()\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " plt.plot(range(i + 1), losses, c=\"r\", label=\"Adam\")\n", + " plt.plot(range(i + 1), losses_bo, c=\"b\", label=\"BO\")\n", + " plt.plot(range(i + 1), losses_turbo, c=\"g\", label=\"TuRBO\")\n", + " plt.plot(range(i + 1), losses_darbo, c=\"y\", label=\"DARBO\")\n", + " plt.legend()\n", + " plt.show()\n", + "\n", + " print(\n", + " f\"Epoch {i} min loss: {min(losses)}\\t{losses_bo[-1]}\\t{losses_turbo[-1]}\\t{losses_darbo[-1]}\"\n", " )\n", - " # Update training set\n", - " X_bo = torch.cat((X_bo, X_next), dim=0)\n", - " Y_bo = torch.cat((Y_bo, Y_next.unsqueeze(-1)), dim=0)\n", - " print(f\"{i+1}) New loss: {-Y_next.item(): .4e} Best loss: {-Y_bo.max():.4e}\")" + "\n", + " te = time.time()\n", + " print(f\"Epoch {i} time: {te - ts}\\tTotal time: {te - t0}\")\n", + " ts = te" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Results" ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "After inputting the optimized parameters back to the ansatz circuit, we can perform the projective measurement on the output quantum state to get the solution. Here we directly use the bit string with the maximum probability as the solution since we know all information of the probability distribution of the output quantum state, but which is not feasible in the experiment." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 56, "outputs": [ { + "name": "stdout", "output_type": "stream", + "text": [ + "Adam\n", + "loss: -5.837558827215271\tprob: 0.318607790021735\tbit strings: ['10101010']\n", + "\n", + "BO\n", + "loss: -6.876287191047742\tprob: 0.3434109359024678\tbit strings: ['10101010']\n", + "\n", + "TuRBO\n", + "loss: -6.8708058821631575\tprob: 0.3339171040448526\tbit strings: ['10101010']\n", + "\n", + "DARBO\n", + "loss: -7.000515157123274\tprob: 0.36778546095898973\tbit strings: ['01010101']\n" + ] + } + ], + "source": [ + "params_bo = jnp.asarray(bo_opt.best_dict[\"X\"])\n", + "params_turbo = jnp.asarray(turbo_opt.inverse_transform(turbo_opt.best_dict[\"X\"]))\n", + "params_darbo = jnp.asarray(\n", + " darbo_opt.inverse_transform(\n", + " darbo_opt.best_dict[\"X\"], mode=darbo_opt.best_dict[\"mode\"]\n", + " )\n", + ")\n", + "\n", + "\n", + "# find the states with max probabilities\n", + "def find_max(params):\n", + " loss = QAOA_nograd(params)\n", + " c = QAOAansatz(params, return_circuit=True)\n", + " probs = K.numpy(c.probability())\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{graph.number_of_nodes()}}\")\n", + " return loss, max_prob, states\n", + "\n", + "\n", + "loss, prob, states = find_max(params)\n", + "loss_bo, prob_bo, states_bo = find_max(params_bo)\n", + "loss_turbo, prob_turbo, states_turbo = find_max(params_turbo)\n", + "loss_darbo, prob_darbo, states_darbo = find_max(params_darbo)\n", + "print(f\"Adam\\nloss: {loss}\\tprob: {prob}\\tbit strings: {states}\\n\")\n", + "print(f\"BO\\nloss: {loss_bo}\\tprob: {prob_bo}\\tbit strings: {states_bo}\\n\")\n", + "print(f\"TuRBO\\nloss: {loss_turbo}\\tprob: {prob_turbo}\\tbit strings: {states_turbo}\\n\")\n", + "print(f\"DARBO\\nloss: {loss_darbo}\\tprob: {prob_darbo}\\tbit strings: {states_darbo}\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:48:09.478379400Z", + "start_time": "2023-07-15T05:48:05.566717500Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 57, + "outputs": [ + { "name": "stdout", + "output_type": "stream", "text": [ - "1) New loss: 1.3437e+00 Best loss: 1.2106e+00\n", - "2) New loss: 8.7936e-01 Best loss: 8.7936e-01\n", - "3) New loss: 7.1789e-01 Best loss: 7.1789e-01\n", - "4) New loss: 6.1326e-01 Best loss: 6.1326e-01\n", - "5) New loss: 5.8545e-01 Best loss: 5.8545e-01\n", - "6) New loss: 2.7606e-01 Best loss: 2.7606e-01\n", - "7) New loss: 1.7849e-02 Best loss: 1.7849e-02\n", - "8) New loss: -1.1042e-01 Best loss: -1.1042e-01\n", - "9) New loss: -1.1939e-01 Best loss: -1.1939e-01\n", - "10) New loss: -2.5096e-01 Best loss: -2.5096e-01\n", - "11) New loss: -5.6989e-01 Best loss: -5.6989e-01\n", - "12) New loss: -7.5698e-01 Best loss: -7.5698e-01\n", - "13) New loss: -8.6725e-01 Best loss: -8.6725e-01\n", - "14) New loss: -9.1735e-01 Best loss: -9.1735e-01\n", - "15) New loss: -9.2709e-01 Best loss: -9.2709e-01\n", - "16) New loss: -9.3580e-01 Best loss: -9.3580e-01\n", - "17) New loss: -9.1267e-01 Best loss: -9.3580e-01\n", - "18) New loss: -9.4420e-01 Best loss: -9.4420e-01\n", - "19) New loss: -9.4391e-01 Best loss: -9.4420e-01\n", - "20) New loss: -9.5668e-01 Best loss: -9.5668e-01\n", - "21) New loss: -9.7023e-01 Best loss: -9.7023e-01\n", - "22) New loss: -9.7753e-01 Best loss: -9.7753e-01\n", - "23) New loss: -9.7975e-01 Best loss: -9.7975e-01\n", - "24) New loss: -9.8380e-01 Best loss: -9.8380e-01\n", - "25) New loss: -9.8546e-01 Best loss: -9.8546e-01\n", - "26) New loss: -9.8754e-01 Best loss: -9.8754e-01\n", - "27) New loss: -9.8786e-01 Best loss: -9.8786e-01\n", - "28) New loss: -9.8514e-01 Best loss: -9.8786e-01\n", - "29) New loss: -9.9017e-01 Best loss: -9.9017e-01\n", - "30) New loss: -9.9235e-01 Best loss: -9.9235e-01\n", - "31) New loss: -9.9391e-01 Best loss: -9.9391e-01\n", - "32) New loss: -9.9355e-01 Best loss: -9.9391e-01\n", - "33) New loss: -9.8973e-01 Best loss: -9.9391e-01\n", - "34) New loss: -9.9798e-01 Best loss: -9.9798e-01\n", - "35) New loss: -1.0005e+00 Best loss: -1.0005e+00\n", - "36) New loss: -1.0021e+00 Best loss: -1.0021e+00\n", - "37) New loss: -1.0029e+00 Best loss: -1.0029e+00\n", - "38) New loss: -1.0029e+00 Best loss: -1.0029e+00\n", - "39) New loss: -1.0022e+00 Best loss: -1.0029e+00\n", - "40) New loss: -1.0034e+00 Best loss: -1.0034e+00\n", - "41) New loss: -1.0037e+00 Best loss: -1.0037e+00\n", - "42) New loss: -1.0035e+00 Best loss: -1.0037e+00\n", - "43) New loss: -1.0037e+00 Best loss: -1.0037e+00\n", - "44) New loss: -1.0036e+00 Best loss: -1.0037e+00\n", - "45) New loss: -1.0035e+00 Best loss: -1.0037e+00\n", - "46) New loss: -1.0033e+00 Best loss: -1.0037e+00\n", - "47) New loss: -1.0033e+00 Best loss: -1.0037e+00\n", - "48) New loss: -1.0036e+00 Best loss: -1.0037e+00\n", - "49) New loss: -1.0041e+00 Best loss: -1.0041e+00\n", - "50) New loss: -1.0035e+00 Best loss: -1.0041e+00\n", - "51) New loss: -1.0044e+00 Best loss: -1.0044e+00\n", - "52) New loss: -1.0044e+00 Best loss: -1.0044e+00\n", - "53) New loss: -1.0044e+00 Best loss: -1.0044e+00\n", - "54) New loss: -1.0045e+00 Best loss: -1.0045e+00\n", - "55) New loss: -1.0043e+00 Best loss: -1.0045e+00\n", - "56) New loss: -1.0046e+00 Best loss: -1.0046e+00\n", - "57) New loss: -1.0043e+00 Best loss: -1.0046e+00\n", - "58) New loss: -1.0045e+00 Best loss: -1.0046e+00\n", - "59) New loss: -1.0042e+00 Best loss: -1.0046e+00\n", - "60) New loss: -1.0045e+00 Best loss: -1.0046e+00\n", - "61) New loss: -1.0042e+00 Best loss: -1.0046e+00\n", - "62) New loss: -1.0047e+00 Best loss: -1.0047e+00\n", - "63) New loss: -1.0047e+00 Best loss: -1.0047e+00\n", - "64) New loss: -1.0048e+00 Best loss: -1.0048e+00\n", - "65) New loss: -1.0045e+00 Best loss: -1.0048e+00\n", - "66) New loss: -1.0047e+00 Best loss: -1.0048e+00\n", - "67) New loss: -1.0045e+00 Best loss: -1.0048e+00\n", - "68) New loss: -1.0045e+00 Best loss: -1.0048e+00\n", - "69) New loss: -1.0049e+00 Best loss: -1.0049e+00\n", - "70) New loss: -1.0049e+00 Best loss: -1.0049e+00\n", - "71) New loss: -1.0049e+00 Best loss: -1.0049e+00\n", - "72) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "73) New loss: -1.0049e+00 Best loss: -1.0050e+00\n", - "74) New loss: -1.0049e+00 Best loss: -1.0050e+00\n", - "75) New loss: -1.0049e+00 Best loss: -1.0050e+00\n", - "76) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "77) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "78) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "79) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "80) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "81) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "82) New loss: -1.0049e+00 Best loss: -1.0050e+00\n", - "83) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "84) New loss: -1.0049e+00 Best loss: -1.0050e+00\n", - "85) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "86) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "87) New loss: -1.0050e+00 Best loss: -1.0050e+00\n", - "88) New loss: -1.0051e+00 Best loss: -1.0051e+00\n", - "89) New loss: -1.0051e+00 Best loss: -1.0051e+00\n", - "90) New loss: -1.0051e+00 Best loss: -1.0051e+00\n", - "91) New loss: -1.0052e+00 Best loss: -1.0052e+00\n", - "92) New loss: -1.0050e+00 Best loss: -1.0052e+00\n", - "93) New loss: -1.0052e+00 Best loss: -1.0052e+00\n", - "94) New loss: -1.0050e+00 Best loss: -1.0052e+00\n", - "95) New loss: -1.0049e+00 Best loss: -1.0052e+00\n", - "96) New loss: -1.0051e+00 Best loss: -1.0052e+00\n", - "97) New loss: -1.0051e+00 Best loss: -1.0052e+00\n", - "98) New loss: -1.0051e+00 Best loss: -1.0052e+00\n", - "99) New loss: -1.0052e+00 Best loss: -1.0052e+00\n", - "100) New loss: -1.0051e+00 Best loss: -1.0052e+00\n" + "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", + "Python version: 3.10.11\n", + "Numpy version: 1.23.5\n", + "Scipy version: 1.11.0\n", + "Pandas version: 2.0.2\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra version: 0.2.1.dev15+g120379e\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: []\n", + "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", + "Jax version: 0.4.13\n", + "Jax installation doesn't support GPU\n", + "JaxLib version: 0.4.13\n", + "PyTorch version: 2.0.1\n", + "PyTorch GPU support: False\n", + "PyTorch GPUs: []\n", + "Cupy is not installed\n", + "Qiskit version: 0.24.1\n", + "Cirq version: 1.1.0\n", + "TensorCircuit version 0.10.0\n" ] } ], + "source": [ + "tc.about()" + ], "metadata": { - "scrolled": false + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-15T05:48:09.478379400Z", + "start_time": "2023-07-15T05:48:09.477371900Z" + } } } ], @@ -311,4 +940,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/source/tutorials/qaoa_nae3sat.ipynb b/docs/source/tutorials/qaoa_nae3sat.ipynb new file mode 100644 index 00000000..51937c93 --- /dev/null +++ b/docs/source/tutorials/qaoa_nae3sat.ipynb @@ -0,0 +1,1102 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "dc0db886", + "metadata": {}, + "source": [ + "# Quantum Approximation Optimization Algorithm (QAOA) for Not-all-equal 3-satisfiability (NAE3SAT)" + ] + }, + { + "cell_type": "markdown", + "id": "aecf6615", + "metadata": {}, + "source": [ + "## Overview" + ] + }, + { + "cell_type": "markdown", + "id": "b533d43e", + "metadata": {}, + "source": [ + "Quantum Approximation Optimization Algorithm (QAOA) is a hybrid classical-quantum algorithm used for solving the combinatorial optimization problem, which is proposed by [Farhi, Goldstone, and Gutmann (2014)](https://arxiv.org/abs/1411.4028). In QAOA, the parameterized quantum circuit is regarded as an oracle, we sample the circuit to obtain the gradient of the parameters, and update them through the classical optimizer. Before this tutorial, there was already a tutorial of [QAOA for Max-Cut](qaoa.ipynb). In this tutorial, we will focus on another combinatorial optimization problem - Not-all-equal 3-satisfiability (NAE3SAT), and discuss the performance of QAOA in different hardness cases." + ] + }, + { + "cell_type": "markdown", + "id": "16ad937f", + "metadata": {}, + "source": [ + "## Not-all-equal 3-satisfiability (NAE3SAT)" + ] + }, + { + "cell_type": "markdown", + "id": "c2321b00", + "metadata": {}, + "source": [ + "[Not-all-equal 3-satisfiability (NAE3SAT)](https://en.wikipedia.org/wiki/Not-all-equal_3-satisfiability) is a variant of 3-satisfiability (3-SAT) and 3-SAT is a subset of [Boolean satisfiability problem (SAT)](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem). SAT is, given a Boolean expression, to check whether it is satisfiable, where the Boolean expression is a disjunction of clauses (or a single clause) and each clause is a disjunction of literals (or a single literal). Here is an example of Boolean expression of SAT,\n", + "$$\n", + "(x_1\\lor x_2\\lor\\cdots\\lor x_m)\\land(\\lnot x_5\\lor x_9\\lor\\cdots\\lor x_m)\\land\\cdots\\land(x_m\\lor \\lnot x_{m+3}\\lor\\cdots\\lor \\lnot x_n),\n", + "$$\n", + "where $(x_i\\lor x_j\\lor\\cdots\\lor x_k)$ is a clause and $x_i$ is a literal. SAT with $k$ literals in each clause is called $k$-SAT, thus in 3-SAT, there are only three literals in each clause, for example\n", + "$$\n", + "(x_1\\lor x_2\\lor x_m)\\land(\\lnot x_5\\lor x_9\\lor x_m)\\land\\cdots\\land(x_m\\lor \\lnot x_{m+3}\\lor \\lnot x_n).\n", + "$$\n", + "When $k$ is not less than 3, SAT is NP-complete. On the other hand, NAE3SAT requires the three literals in each clause are not all equal to each other, in other words, at least one is true, and at least one is false. It is different from 3-SAT, which requires at least one literal is true in each clause. However, NAE3SAT is still NP-complete, [which can be proven by a reduction from 3-SAT](https://en.wikipedia.org/wiki/Not-all-equal_3-satisfiability)." + ] + }, + { + "cell_type": "markdown", + "id": "4d28f719", + "metadata": {}, + "source": [ + "Now we use the spin model to represent a NAE3SAT. Let the set of clauses in the NAE3SAT be $\\mathcal{C}$. In each clause, there are three literals and each literal is represented by a spin. Spins up ($s=1$, $\\text{bit}=0$) and down ($s=-1$, $\\text{bit}=1$) represent false and true respectively. For the clause $(s_i,\\ s_j,\\ s_k)\\in\\mathcal{C}$, $s_i,\\ s_j,\\ s_k$ cannot be 1 or -1 at the same time. The Hamiltonian of the NAE3SAT is as follows\n", + "$$\n", + "\\begin{split}\n", + " \\hat{H}_C&=\\sum_{(i,j,k)\\in\\mathcal{C}}\\left[(s_i+s_j+s_k)^2-1\\right]/2\\\\\n", + " &=\\sum_{(i,j,k)\\in\\mathcal{C}}(s_i s_j+s_j s_k+s_k s_i)+|\\mathcal{C}|,\n", + "\\end{split}\n", + "$$\n", + "where $|\\mathcal{C}|$ is the number of clauses in $\\mathcal{C}$. When all clauses are true, $\\hat{H}_C$ takes the minimum value 0, and the corresponding bit string is the solution of the NAE3SAT." + ] + }, + { + "cell_type": "markdown", + "id": "871bff2e", + "metadata": {}, + "source": [ + "## QAOA for NAE3SAT" + ] + }, + { + "cell_type": "markdown", + "id": "598dc69e", + "metadata": {}, + "source": [ + "QAOA utilizes a parameterized quantum circuit ([PQC](https://tensorcircuit.readthedocs.io/en/latest/textbook/chap5.html?highlight=变分)) to generate a quantum state that represents a potential solution. The initial state, denoted as $|s\\rangle$, is a uniform superposition over computational basis states.\n", + "$$\n", + "|s\\rangle=\\frac{1}{\\sqrt{2^n}}\\sum_z|z\\rangle\n", + "$$\n", + "This state is then evolved by a unitary operator that consists of $p$ layers, denoted as\n", + "$$\n", + "U(\\boldsymbol{\\beta}, \\boldsymbol{\\gamma}) = V_{p}U_{p} \\cdots V_{1}U_{1},\n", + "$$\n", + "where $U_{j}= e^{-\\text{i}\\gamma_{j}\\hat{H}_{C}}$ is the driving layer and $V_{j}= e^{-\\text{i}\\beta_{j} \\hat{H}_m}$ is the mixing layer. $\\hat{H}_C$ is the driving and cost Hamiltonian introduced in previous section and the mixing Hamiltonian $\\hat{H}_m=\\sum_{j=1}^{n}\\sigma_j^x$ is used to mix the quantum state to explore different solutions. The unitary operator is parameterized by $2p$ angle parameters $\\gamma_1, \\gamma_2, \\dots, \\gamma_p$ and $\\beta_1, \\beta_2, \\dots ,\\beta_p$ and each $\\gamma$ and $\\beta$ are restricted to lie between $0$ and $2\\pi$." + ] + }, + { + "cell_type": "markdown", + "id": "949be36e", + "metadata": {}, + "source": [ + "Begin with a set of initial $\\boldsymbol{\\gamma}$ and $\\boldsymbol{\\beta}$, the quantum state is obtained from the PQC and then the expectation value of $\\hat{H}_C$ is calculated. A classical optimizer is then used to vary the parameters until a lower expectation value is found. This process is iterated a certain number of times until the expectation value of $\\hat{H}_C$ is approximated to 0. Then we perform projective measurement on the quantum state output by PQC, and obtain a bit string, which is very likely to be the solution of NAE3SAT. Since NAE3SAT is an NP-complete problem, we can verify whether the solution is correct in polynomial time on classical computer. Even if this bit string is not the correct solution, we can repeat the projective measurement and verify the obtained solution until we get the correct solution.\n", + "\n", + "For other details of QAOA, such as the selection of $p$ and the overall algorithm loop, please refer to [Farhi, Goldstone, and Gutmann (2014)](https://arxiv.org/abs/1411.4028) or the tutorial of [QAOA for Max-Cut](qaoa.ipynb)." + ] + }, + { + "cell_type": "markdown", + "id": "940fa22b", + "metadata": {}, + "source": [ + "### Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b0def04d", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-03T11:21:55.043565200Z", + "start_time": "2023-07-03T11:21:54.946406500Z" + } + }, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import optax\n", + "import tensorflow as tf\n", + "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from IPython.display import clear_output\n", + "import random\n", + "\n", + "K = tc.set_backend(\"jax\")\n", + "\n", + "nlayers = 30 # the number of layers\n", + "ncircuits = 6 # six circuits with different initial parameters are going to be optimized at the same time" + ] + }, + { + "cell_type": "markdown", + "id": "6e407437", + "metadata": {}, + "source": [ + "### Define the Graph" + ] + }, + { + "cell_type": "markdown", + "id": "c82972a4", + "metadata": {}, + "source": [ + "The graph of NAE3SAT is constructed by the set $\\mathcal{C}$ of clauses. When a clause is violated, the energy will increase by 4, so the upper bound of $\\hat{H}_C$ will not exceed $4|\\mathcal{C}|$. In practice, we multiply $\\hat{H}_C$ by a normalization factor $1/(4|\\mathcal{C}|)$." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f1532831", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-03T11:21:55.148550800Z", + "start_time": "2023-07-03T11:21:54.965499300Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# an easy graph instance\n", + "easy_clauses = [\n", + " [4, 7, 6],\n", + " [0, 5, 9],\n", + " [2, 6, 9],\n", + " [2, 6, 7],\n", + " [3, 1, 9],\n", + " [5, 9, 11],\n", + " [4, 8, 9],\n", + " [5, 1, 9],\n", + " [3, 8, 6],\n", + " [2, 8, 10],\n", + " [5, 6, 8],\n", + " [2, 9, 6],\n", + " [2, 6, 8],\n", + " [5, 3, 9],\n", + " [4, 11, 7],\n", + " [3, 11, 10],\n", + " [5, 10, 7],\n", + " [3, 9, 8],\n", + " [3, 6, 9],\n", + " [2, 4, 7],\n", + " [4, 0, 6],\n", + " [3, 4, 6],\n", + " [3, 11, 6],\n", + " [4, 5, 6],\n", + " [4, 0, 10],\n", + " [5, 4, 10],\n", + " [3, 7, 9],\n", + " [0, 11, 6],\n", + " [5, 11, 9],\n", + " [3, 5, 9],\n", + " [3, 4, 7],\n", + " [3, 4, 7],\n", + " [3, 0, 7],\n", + " [1, 7, 8],\n", + " [0, 3, 10],\n", + " [0, 8, 9],\n", + " [5, 7, 8],\n", + " [2, 9, 6],\n", + " [0, 8, 6],\n", + " [4, 6, 8],\n", + " [3, 2, 9],\n", + " [4, 3, 8],\n", + " [0, 2, 8],\n", + " [4, 5, 10],\n", + " [2, 4, 8],\n", + " [5, 8, 9],\n", + " [4, 8, 9],\n", + " [3, 5, 11],\n", + " [5, 4, 10],\n", + " [2, 7, 9],\n", + " [3, 0, 7],\n", + " [2, 8, 6],\n", + " [5, 3, 6],\n", + " [0, 6, 10],\n", + " [3, 2, 8],\n", + " [4, 6, 9],\n", + " [3, 2, 6],\n", + " [1, 5, 6],\n", + " [2, 8, 11],\n", + " [2, 10, 8],\n", + " [2, 0, 6],\n", + " [2, 6, 9],\n", + " [0, 8, 7],\n", + " [0, 10, 8],\n", + " [3, 5, 7],\n", + " [2, 10, 8],\n", + " [5, 7, 9],\n", + " [0, 1, 6],\n", + " [0, 3, 8],\n", + " [0, 6, 9],\n", + " [0, 5, 11],\n", + " [1, 2, 10],\n", + "]\n", + "factor = 1 / len(easy_clauses) / 4\n", + "\n", + "# convert to a NetworkX graph\n", + "easy_graph = nx.Graph()\n", + "for i, j, k in easy_clauses:\n", + " easy_graph.add_edge(i, j, weight=0)\n", + " easy_graph.add_edge(j, k, weight=0)\n", + " easy_graph.add_edge(k, i, weight=0)\n", + "for i, j, k in easy_clauses:\n", + " easy_graph[i][j][\"weight\"] += 1\n", + " easy_graph[j][k][\"weight\"] += 1\n", + " easy_graph[k][i][\"weight\"] += 1\n", + "pos_easy = nx.spring_layout(easy_graph)\n", + "nx.draw_networkx(easy_graph, with_labels=True, pos=pos_easy)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "cell_type": "markdown", + "id": "c944f6dd", + "metadata": {}, + "source": [ + "### Parameterized Quantum Circuit (PQC)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "055d1257", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-03T11:21:55.167476700Z", + "start_time": "2023-07-03T11:21:55.166422100Z" + } + }, + "outputs": [], + "source": [ + "def QAOAansatz(params, g, each=1, return_circuit=False):\n", + " n = g.number_of_nodes() # the number of nodes\n", + "\n", + " # PQC loop\n", + " def pqc_loop(s_, params_):\n", + " c_ = tc.Circuit(n, inputs=s_)\n", + " for j in range(each):\n", + " # driving layer\n", + " for a, b in g.edges:\n", + " c_.RZZ(a, b, theta=g[a][b][\"weight\"] * params_[2 * j] * factor)\n", + " # mixing layer\n", + " for i in range(n):\n", + " c_.RX(i, theta=params_[2 * j + 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(n)\n", + " for i in range(n):\n", + " c0.H(i)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, K.reshape(params, [nlayers // each, 2 * each]), s0)\n", + " c = tc.Circuit(n, inputs=s)\n", + "\n", + " # whether to return the circuit\n", + " if return_circuit is True:\n", + " return c\n", + "\n", + " # calculate the loss function\n", + " loss = 0.25\n", + " for a, b in g.edges:\n", + " loss += c.expectation_ps(z=[a, b]) * g[a][b][\"weight\"] * factor\n", + "\n", + " return K.real(loss)" + ] + }, + { + "cell_type": "markdown", + "id": "5b159920", + "metadata": {}, + "source": [ + "### Optimization" + ] + }, + { + "cell_type": "markdown", + "id": "6d07ee61", + "metadata": {}, + "source": [ + "Here, several circuits with different initial parameters are optimized/trained at the same time.\n", + "\n", + "Optimizers are used to find the minimum value." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "690b8b67", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# use vvag to get the losses and gradients with different random circuit instances\n", + "QAOA_vvag = K.jit(\n", + " K.vvag(QAOAansatz, argnums=0, vectorized_argnums=0), static_argnums=(1, 2, 3)\n", + ")\n", + "\n", + "params_easy = K.implicit_randn(\n", + " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", + ") # initial parameters\n", + "if type(K).__name__ == \"JaxBackend\":\n", + " opt = K.optimizer(optax.adam(1e-2))\n", + "else:\n", + " opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", + "\n", + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(2000):\n", + " loss, grads = QAOA_vvag(params_easy, easy_graph)\n", + " params_easy = opt.update(grads, params_easy) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [f\"circuit {leg}\" for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "98a6b152", + "metadata": {}, + "source": [ + "### Results" + ] + }, + { + "cell_type": "markdown", + "id": "fc1c257d", + "metadata": {}, + "source": [ + "After inputting the optimized parameters back to the ansatz circuit, we can perform the projective measurement on the output quantum state to get the solution. Here we directly use the bit string with the maximum probability as the solution since we know all information of the probability distribution of the output quantum state, but which is not feasible in the experiment." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8c5df93e", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:26.692908100Z", + "start_time": "2023-07-03T11:47:45.326665300Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Circuit #0\n", + "cost: 0.014918745495378971\n", + "max prob: 0.2869008183479309\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #1\n", + "cost: 0.030193958431482315\n", + "max prob: 0.21499991416931152\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #2\n", + "cost: 0.021412445232272148\n", + "max prob: 0.24743150174617767\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #3\n", + "cost: 0.013799840584397316\n", + "max prob: 0.2941778600215912\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #4\n", + "cost: 0.014260157942771912\n", + "max prob: 0.29104718565940857\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #5\n", + "cost: 0.013322753831744194\n", + "max prob: 0.2968374788761139\n", + "bit strings: ['111111000000']\n", + "\n" + ] + } + ], + "source": [ + "# print QAOA results\n", + "for num_circuit in range(ncircuits):\n", + " print(f\"Circuit #{num_circuit}\")\n", + " c = QAOAansatz(params=params_easy[num_circuit], g=easy_graph, return_circuit=True)\n", + " loss = QAOAansatz(params=params_easy[num_circuit], g=easy_graph)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability())\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + "\n", + " print(f\"cost: {K.numpy(loss)}\\nmax prob: {max_prob}\\nbit strings: {states}\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "4ae99ab9", + "metadata": {}, + "source": [ + "## Classical Method" + ] + }, + { + "cell_type": "markdown", + "id": "720dd1a4", + "metadata": {}, + "source": [ + "Here we use two classical methods. The first is the brutal force method (BF), which is to check all bit string one-by-one and need exponential time, thus the obtained solution is guaranteed to be correct." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "2115bb6d", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-03T11:48:26.693910800Z", + "start_time": "2023-07-03T11:48:26.692908100Z" + } + }, + "outputs": [], + "source": [ + "def b2s(bit):\n", + " return 1 - 2 * int(bit)\n", + "\n", + "\n", + "def energy(cfg, graph, normalize=True):\n", + " E = 0.25\n", + " for a, b in graph.edges:\n", + " E += cfg[a] * cfg[b] * graph[a][b][\"weight\"] * factor\n", + " return E if normalize else E / factor\n", + "\n", + "\n", + "def brutal_force(graph):\n", + " num_nodes = graph.number_of_nodes()\n", + " min_cost, best_case = 1.0, []\n", + " for i in range(2**num_nodes):\n", + " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", + "\n", + " cost = energy(list(map(b2s, case)), graph)\n", + "\n", + " gap = min_cost - cost\n", + " if gap > 1e-6:\n", + " min_cost = cost\n", + " best_case = [case]\n", + " elif abs(gap) < 1e-6:\n", + " best_case.append(case)\n", + "\n", + " return best_case, min_cost" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "b0cdc04f", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:27.165348700Z", + "start_time": "2023-07-03T11:48:26.692908100Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost: 0.000\n", + "bit string: ['000000111111', '111111000000']\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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/fv3BKDSalmhUPDixYts2bKlUFEvICAgXUHi7du3nDBhAh0cHAStweLFi1XKTfAmNpbGPXuywIYNtLlwgTh8mNITJ2h14QIb3bnDiS9f8mk2tCFhYWH09PQU4vqHDRumVuHtyZMndHV1pampKc+fPy/sX7VqlVAcqnv37qmEILlczlatWlFTU5MXLlxQ23h+pFSpUmzYsGGGbRISEqihocEFCxbkyhjS4vv37zQ2Nk439Xgev5c8YeA3sWXLllzLGR8bG0uxWMzly5erve8fef/+PRs0aEAA7NKlS6YTaKtWrZg/f/5USXWUGdS2bduW6pzTqmSwGzUqWSuwbVvK/XXrElpaxJ49mfZx8xdN/j9y48YNli9fngDYvn37FBP68ePHCYCnT59O89w3b95wwYIFrFatGiUSCUUiET09PTlr1qw0axyQpIWFBUePHp3ueOLj47lx40ZB2ChQoADnz5+f5ucql8t55MgR+vj4UCKRUFtbm506deLly5ezZD569uyZUHvizJkzBMCrV6+qfH5mHDhwQEiwZGFhke7zzA6fPn2il5cXNTU1uWXLFh47doxSqZRSqZT169dPN3lUbGwsK1WqRDMzszQ1Czll8eLFlEgkmWpESpYsyS5duqj9+umxbt06AsiVe84j5+QJA78JhULBihUrsmjRompdsSgpWLAg+/Xrp/Z+f0ahUHDFihXU1dWlo6Mjz549m2a7p0+fUiwWc+HChSn2JyQk0M3NjVWqVElzErn27VvmwkCxYkSRIqn3/5MWFjNnZtpHSDZTz2aHL1++0N/fX6gyeObMmVRtFAoFCxUqxKZNm2baX3h4OFevXs2GDRumqLI4btw43r17V3iutWvXTlMb9fHjR06cOFGwt9esWZMHDhxI07/g/fv3nDRpEvPnz08ALFq0KBcuXJjtDIXLly+nWCzm169fOWTIEFpaWqq9tHZCQgL9/f0FM1CdOnWyZGLJiLi4OLZt21YoYKWhocGSJUtmmsHz06dPdHV1ZYECBdReUfLr16/U0tLilClTMmzXuXNnlipVSq3XzogKFSqwVq1av+x6eWSNPGHgN3L16lXBNqxumjVr9kvzjz99+pSenp4UiUQcMmRIKptgjx49aG5unsoBbs6cORSLxenWk49KTMw8/bCdHVGoUOr9o0cnCwPTpmV4vvjECS5etox3795V+0T0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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# print BF results\n", + "bf_best_cases, bf_best = brutal_force(easy_graph)\n", + "print(f\"cost: {bf_best:.3f}\\nbit string: {bf_best_cases}\")\n", + "\n", + "# plot NetworkX graph\n", + "colors = [\"r\" if bf_best_cases[0][i] == \"0\" else \"c\" for i in easy_graph.nodes]\n", + "nx.draw_networkx(easy_graph, with_labels=True, node_color=colors, pos=pos_easy)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "cell_type": "markdown", + "id": "20324164", + "metadata": {}, + "source": [ + "Another method is the simulated annealing method (SA), which is an approximation method that can be done in polynomial time, so the obtained solution has only a certain probability of being correct." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e1551fb4", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:27.165348700Z", + "start_time": "2023-07-03T11:48:27.164345100Z" + } + }, + "outputs": [], + "source": [ + "def sim_annealing(graph, t_max: int, T: float):\n", + " num_nodes = graph.number_of_nodes()\n", + " state = np.random.randint(0, 2, num_nodes)\n", + " next_state = state.copy()\n", + " E = energy(1 - 2 * state, graph, normalize=False)\n", + " t = 0\n", + " while t < t_max:\n", + " temper = (1 - t / t_max) * T\n", + " flip_idx = np.random.randint(num_nodes)\n", + " next_state[flip_idx] = 1 - next_state[flip_idx]\n", + " next_E = energy(1 - 2 * next_state, graph, normalize=False)\n", + " if next_E <= E or np.exp(-(next_E - E) / temper) > np.random.rand():\n", + " state[flip_idx] = 1 - state[flip_idx]\n", + " E = next_E\n", + " else:\n", + " next_state[flip_idx] = 1 - next_state[flip_idx]\n", + " t += 1\n", + " return \"\".join(map(str, state.tolist())), E" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "04596ec1", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:31.015863400Z", + "start_time": "2023-07-03T11:48:27.165348700Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost: 0.000\n", + "prob: 0.910\n", + "bit string: ['000000111111', '111111000000']\n" + ] + } + ], + "source": [ + "# print SA results\n", + "sa_best_cases, sa_best, n_exp = [], float(\"inf\"), 100\n", + "for _ in range(n_exp):\n", + " sa_case, sa_cost = sim_annealing(easy_graph, 200, 1)\n", + " gap = sa_best - sa_cost\n", + " if gap > 1e-6:\n", + " sa_best = sa_cost\n", + " sa_best_cases = [sa_case]\n", + " elif abs(gap) < 1e-6:\n", + " sa_best_cases.append(sa_case)\n", + "sa_prob = len(sa_best_cases) / n_exp\n", + "sa_best_cases = list(set(sa_best_cases))\n", + "print(f\"cost: {sa_best:.3f}\\nprob: {sa_prob:.3f}\\nbit string: {sa_best_cases}\")" + ] + }, + { + "cell_type": "markdown", + "id": "e9b8619b", + "metadata": {}, + "source": [ + "## Hard Problem" + ] + }, + { + "cell_type": "markdown", + "id": "9f8cb1da", + "metadata": {}, + "source": [ + "We call the above problem an easy problem, because the classical simulated annealing method has a high probability to obtain the correct solution. Now let's define another relatively hard problem." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b0a1f778", + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-03T11:48:31.522735600Z", + "start_time": "2023-07-03T11:48:30.976530700Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# a hard graph instance\n", + "hard_clauses = [\n", + " [4, 1, 7],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [4, 11, 8],\n", + " [4, 1, 10],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [1, 11, 8],\n", + " [4, 1, 7],\n", + " [0, 11, 8],\n", + " [4, 1, 10],\n", + " [4, 11, 8],\n", + " [5, 0, 10],\n", + " [0, 6, 7],\n", + " [5, 0, 11],\n", + " [0, 6, 7],\n", + " [5, 0, 9],\n", + " [3, 6, 7],\n", + " [5, 0, 8],\n", + " [5, 6, 7],\n", + " [5, 0, 10],\n", + " [3, 6, 7],\n", + " [5, 0, 10],\n", + " [1, 6, 7],\n", + " [2, 4, 6],\n", + " [1, 8, 11],\n", + " [2, 4, 6],\n", + " [2, 8, 11],\n", + " [2, 4, 9],\n", + " [5, 8, 11],\n", + " [2, 4, 10],\n", + " [2, 8, 11],\n", + " [2, 4, 10],\n", + " [4, 8, 11],\n", + " [2, 4, 8],\n", + " [4, 8, 11],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [2, 11, 7],\n", + " [3, 0, 9],\n", + " [0, 11, 7],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [3, 11, 7],\n", + " [3, 0, 7],\n", + " [4, 11, 7],\n", + " [5, 0, 10],\n", + " [4, 0, 10],\n", + " [2, 5, 6],\n", + " [2, 11, 10],\n", + " [2, 6, 10],\n", + " [2, 4, 9],\n", + " [0, 9, 10],\n", + " [3, 0, 7],\n", + " [2, 5, 6],\n", + " [1, 10, 9],\n", + " [1, 4, 11],\n", + " [5, 10, 11],\n", + " [0, 4, 8],\n", + " [0, 9, 8],\n", + " [2, 11, 10],\n", + " [2, 8, 6],\n", + " [3, 6, 7],\n", + " [0, 8, 10],\n", + " [4, 0, 9],\n", + " [3, 5, 8],\n", + " [5, 11, 10],\n", + " [2, 11, 10],\n", + " [4, 11, 8],\n", + " [1, 3, 11],\n", + "]\n", + "factor = 1 / len(hard_clauses) / 4\n", + "\n", + "# convert to a NetworkX graph\n", + "hard_graph = nx.Graph()\n", + "for i, j, k in hard_clauses:\n", + " hard_graph.add_edge(i, j, weight=0)\n", + " hard_graph.add_edge(j, k, weight=0)\n", + " hard_graph.add_edge(k, i, weight=0)\n", + "for i, j, k in hard_clauses:\n", + " hard_graph[i][j][\"weight\"] += 1\n", + " hard_graph[j][k][\"weight\"] += 1\n", + " hard_graph[k][i][\"weight\"] += 1\n", + "pos_hard = nx.spring_layout(hard_graph)\n", + "nx.draw_networkx(hard_graph, with_labels=True, pos=pos_hard)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "cell_type": "markdown", + "id": "d37be898", + "metadata": {}, + "source": [ + "We first solve this problem by two classical methods." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f22b5956", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:31.523763100Z", + "start_time": "2023-07-03T11:48:31.070473700Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost: 0.000\n", + "bit string: ['000000111111', '111111000000']\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# print BF results\n", + "bf_best_cases, bf_best = brutal_force(hard_graph)\n", + "print(f\"cost: {bf_best:.3f}\\nbit string: {bf_best_cases}\")\n", + "\n", + "# plot NetworkX graph\n", + "colors = [\"r\" if bf_best_cases[0][i] == \"0\" else \"c\" for i in hard_graph.nodes]\n", + "nx.draw_networkx(hard_graph, with_labels=True, node_color=colors, pos=pos_hard)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9df75fbc", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T11:48:35.050434800Z", + "start_time": "2023-07-03T11:48:31.518734800Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost: 0.000\n", + "prob: 0.070\n", + "bit string: ['000000111111', '111111000000']\n" + ] + } + ], + "source": [ + "# print SA results\n", + "sa_best_cases, sa_best, n_exp = [], float(\"inf\"), 100\n", + "for _ in range(n_exp):\n", + " sa_case, sa_cost = sim_annealing(hard_graph, 200, 1)\n", + " gap = sa_best - sa_cost\n", + " if gap > 1e-6:\n", + " sa_best = sa_cost\n", + " sa_best_cases = [sa_case]\n", + " elif abs(gap) < 1e-6:\n", + " sa_best_cases.append(sa_case)\n", + "sa_prob = len(sa_best_cases) / n_exp\n", + "sa_best_cases = list(set(sa_best_cases))\n", + "print(f\"cost: {sa_best:.3f}\\nprob: {sa_prob:.3f}\\nbit string: {sa_best_cases}\")" + ] + }, + { + "cell_type": "markdown", + "id": "c4f3a812", + "metadata": {}, + "source": [ + "We found that the probability of SA getting the correct solution on the hard problem is much lower than that on the easy problem. This is because the energy landscape is different for the easy and hard problem, as shown in the following figure.\n", + "\n", + "\n", + "\n", + "The global minimum is located in a large and smooth neighborhood for a simpler problem and a narrow region for a harder problem. It is worth noting that when the system size is relatively small, most of the randomly generated problems are easy, and hard problems need to be constructed with special methods, please refer to [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171)." + ] + }, + { + "cell_type": "markdown", + "id": "99ee9bf8", + "metadata": {}, + "source": [ + "Now we use QAOA to solve this hard problem." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "1f6ba479", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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upnVaqx/FaSiriaqdRFCCCH6KglA3cwaE56zQKkAVd7qKNdGCCGE6JskAHUzq6PhhnMBqjwSgIQQQohokADUzWxOe+R1da2MARJCCNG18vLy0DTtlDcv7ahVq1YRFxfXpfvoTBKAupk17tjU3J5aaQESQgjRtTIyMigoKGD06NFdup958+axZ8+eyPtFixYxfvz4U2737LPPcs455xAfH098fDyzZs3iiy++6MKahkkA6mbmhDggfCm8v642qnURQghx+tPr9aSlpWEwGJr8XClFINDxOxNYrVZSUlLavN369eu54oor+PDDD9m0aRMZGRlcfPHFHD16tMN1aokEoG5mcDhBC18JFqiri3JthBBCnA5CoRAPPfQQ2dnZmM1mBg4cyNKlS4GTu8DWr1+Ppmm88847TJo0CbPZzMaNG1sso2GbysrKyD5zcnLQNI28vDygcRfYqlWrWLx4MVu3bkXTNDRNY9WqVU3W/Z///Cc333wz48ePZ/jw4fzlL38hFAqxbt26rvhRRTQdB0WX0cXGoWFAAarOHe3qCCGEaIFSirpA9/9n1Wqwomlaq9dfsGABzz77LI899hgzZsygoKCAXbt2tbjNvffey4oVK8jKyiI+Pr5dZTRn3rx5bNu2jTVr1rB27VoAnE5nq7Z1u934/X4SEhLate/WkgDUzXSOxEgA0rvlVhhCCNGT1QXqmPbitG7f7+c/+xyb0daqdaurq3n88cd58sknmT9/PgBDhgxhxowZLW63ZMkSLrroog6V0Ryr1YrdbsdgMJCWltambe+55x769evHrFmz2rXv1pIA1N2ssWiEZ4M21kkAEkII0TE7d+7E6/Uyc+bMNm03efLkDpfR2ZYvX85LL73E+vXrsVgsXbovCUDdTDPZIgHI5O34oDMhhBBdx2qw8vnPPo/Kflu9rrX16x4vJiam1WXodOEhw0qpyDK/39+u/TZnxYoVLF++nLVr1zJ27NhOLbspEoC6m06Prn7sucEvAUgIIXoyTdNa3RUVLUOHDsVqtbJu3Tquu+66LikjOTkZgIKCAuLj4wFOOa+QyWQiGAy2av8PPfQQS5cu5d13323UMtWVJABFgVYfgIyBUJRrIoQQorezWCzcc8893H333ZhMJs4++2xKSkrYvn071157baeUkZ2dTUZGBosWLWLp0qXs2bOHRx55pMUyMzMzyc3NJScnhwEDBhAbG4vZbD5pvQcffJCFCxfy4osvkpmZSWFhIQB2ux273X7S+p1FLoOPAh3hkf2GoDrFmkIIIcSp3Xfffdxxxx0sXLiQESNGMG/ePIqLizutDKPRyOrVq9m1axdjx47lwQcf5IEHHmixvLlz5zJnzhwuuOACkpOTWb16dZPrPf300/h8Pn784x+Tnp4eeaxYsaJN9W8rTR3foScAcLlcOJ1OqqqqcDgcp96gjZ65/GZq1SHc9lju+2vTvxBCCCG6l8fjITc3l8GDB3f5AFzRfi2dp7Z8f0sLUBTo66d20Leua1QIIYQQnUwCUBTo67vAdNL2JoQQQkSFBKAoMOjqA1AIPH5vlGsjhBBC9D0SgKLAqIV/7LoQVHjkjvBCCCFEd5MAFAVGffjHrilFeZ0EICGEEKK7SQCKApOh/seuQlR4aqJbGSGEEKIPkgAUBUbDsRagSmkBEkIIIbqdBKAoMBvD9wJTBKnySguQEEII0d0kAEWBxRIOQKgQVdIFJoQQQnQ7CUBRYLU13IItgMsrXWBCCCG6Tl5eHpqmnfLmpR21atUq4uLiunQfnUkCUBRYY45N3V3jlhYgIYQQXScjI4OCggJGjx7dpfuZN28ee/bsibxftGgR48ePP+V2r732GpMnTyYuLo6YmBjGjx/P3//+9y6saZjcDT4KrLHWyOu6OlcUayKEEOJ0p9frSUtLa/ZzpRTBYBCDoWORwGq1YrVaT73iCRISEvjNb37D8OHDMZlMvPXWW1xzzTWkpKQwe/bsDtWpJdICFAUWhwUwAuCRq8CEEEJ0UCgU4qGHHiI7Oxuz2czAgQNZunQpcHIX2Pr169E0jXfeeYdJkyZhNpvZuHFji2U0bFNZWRnZZ05ODpqmkZeXBzTuAlu1ahWLFy9m69ataJqGpmmsWrWqybqff/75/PCHP2TEiBEMGTKE2267jbFjx7Jx48au+FFFSAtQFJhiY0AzgfLjc9dGuzpCCCGaoZRC1dV1+341qxVN01q9/oIFC3j22Wd57LHHmDFjBgUFBezatavFbe69915WrFhBVlYW8fHx7SqjOfPmzWPbtm2sWbOGtWvXAuB0Ok+5nVKKDz74gN27d/Pggw+2a9+tJQEoCsxxsWiaEaUgVOeLdnWEEEI0Q9XVsXvipG7f77Atm9FstlatW11dzeOPP86TTz7J/PnzARgyZAgzZsxocbslS5Zw0UUXdaiM5litVux2OwaDocXutwZVVVX0798fr9eLXq/nj3/8Y6RuXUUCUBQY4xw0dIFR549qXYQQQvRuO3fuxOv1MnPmzDZtN3ny5A6X0VliY2PJycmhpqaGdevWcfvtt5OVlcX555/fZfuUABQFuth4dOgJAvq6QLSrI4QQohma1cqwLZujst/Was/AY4CYmJhWl6HThYcMK6Uiy/z+zvsPvE6nIzs7G4Dx48ezc+dOli1b1qUBSAZBR4Fmj0cjPBmiUQKQEEL0WJqmobPZuv3RlvE/Q4cOxWq1sm7dunYf56nKSE5OBqCgoCCy7FTzCplMJoLBYLvqEwqF8Hq97dq2taQFKAq0GAc6Ff7lNnlDUa6NEEKI3sxisXDPPfdw9913YzKZOPvssykpKWH79u1ce+21nVJGdnY2GRkZLFq0iKVLl7Jnzx4eeeSRFsvMzMwkNzeXnJwcBgwYQGxsLGaz+aT1li1bxuTJkxkyZAher5e3336bv//97zz99NPt+nm0lgSgKNDMdnSEA5DRr06xthBCCNGy++67D4PBwMKFC8nPzyc9PZ0bb7yx08owGo2sXr2am266ibFjxzJlyhQeeOABfvKTnzRb3ty5c3nttde44IILqKys5Pnnn+fqq68+ab3a2lpuvvlmjhw5gtVqZfjw4fzjH/9g3rx5bap/W2nq+A49AYDL5cLpdFJVVYXD4ej8HSjFM5ffQi2HKI+PZekzqzt/H0IIIdrE4/GQm5vL4MGDsVgsp95AREVL56kt398yBigaNA19fe40tq97VAghhBAdIAEoShoCkCGo4QvKXEBCCCFEd5IAFCVGwgFIH9Rw+91Rro0QQgjRt0gAihKjFg5AuhDUBuR2GEIIIUR3kgAUJcbwNEDoQooab010KyOEEEL0MT0iAD311FNkZmZisViYNm0aX3zxRbPrPvvss5xzzjnEx8cTHx/PrFmzTlpfKcXChQtJT0/HarUya9Ys9u7d29WH0SYmffgyeE2FKJM7wgshhBDdKuoB6OWXX+b222/n/vvvZ8uWLYwbN47Zs2dTXFzc5Prr16/niiuu4MMPP2TTpk1kZGRw8cUXc/To0cg6Dz30EH/4wx945pln+Pzzz4mJiWH27Nl4PJ7uOqxTMhsaAlCQMndVlGsjhBBC9C1RD0CPPvoo119/Pddccw0jR47kmWeewWaz8dxzzzW5/j//+U9uvvlmxo8fz/Dhw/nLX/5CKBSKTN+tlGLlypX89re/5dJLL2Xs2LH87W9/Iz8/nzfeeKPJMr1eLy6Xq9Gjq5lN9XNQqiBldV2/PyGEEEIcE9UA5PP52Lx5M7NmzYos0+l0zJo1i02bNrWqDLfbjd/vJyEhAYDc3FwKCwsblel0Opk2bVqzZS5btgyn0xl5ZGRkdOCoWsdqbQhAASokAAkhhBDdKqoBqLS0lGAwSGpqaqPlqampFBYWtqqMe+65h379+kUCT8N2bSlzwYIFVFVVRR6HDx9u66G0mc1mqn8VolK6wIQQQnSRvLw8NE075c1LO2rVqlXExcV16T46U9S7wDpi+fLlvPTSS7z++usdmrbcbDbjcDgaPbqa1WGLvK6pruzy/QkhhOibMjIyKCgoYPTo0V26n3nz5rFnz57I+0WLFjF+/Pg2lfHSSy+haRqXXXZZ51auCVENQElJSej1eoqKihotLyoqIi0trcVtV6xYwfLly3nvvfcYO3ZsZHnDdu0pszuZHTGAEQC3tAAJIYToInq9nrS0NAyGpu9/rpQiEAh0eD9Wq5WUlJR2b5+Xl8edd97JOeec0+G6tEZUA5DJZGLSpEmRAcxAZEDz9OnTm93uoYce4ne/+x1r1qxh8uTJjT4bPHgwaWlpjcp0uVx8/vnnLZbZ3UwOG2jhbjBvncwDJIQQov1CoRAPPfQQ2dnZmM1mBg4cyNKlS4GTu8DWr1+Ppmm88847TJo0CbPZzMaNG1sso2GbysrKyD5zcnLQNI28vDygcRfYqlWrWLx4MVu3bkXTNDRNY9WqVc3WPxgMcuWVV7J48WKysrI6+8fTpKbjYDe6/fbbmT9/PpMnT2bq1KmsXLmS2tparrnmGgCuuuoq+vfvz7JlywB48MEHWbhwIS+++CKZmZmRcT12ux273Y6mafz617/mgQceYOjQoQwePJj77ruPfv36dUuTWmuZE5xomgmlagm466JdHSGEEE1QShHwhbp9vwaTDk3TWr3+ggULePbZZ3nssceYMWMGBQUF7Nq1q8Vt7r33XlasWEFWVhbx8fHtKqM58+bNY9u2baxZs4a1a9cC4QuSmrNkyRJSUlK49tpr+fjjj9u1z7aKegCaN28eJSUlLFy4kMLCQsaPH8+aNWsig5gPHTqETnesoerpp5/G5/Px4x//uFE5999/P4sWLQLg7rvvpra2lhtuuIHKykpmzJjBmjVrOjROqLNZkhMiLUC4/dGtjBBCiCYFfCH+fNuGbt/vDY+fh9Gsb9W61dXVPP744zz55JPMnz8fgCFDhjBjxowWt1uyZAkXXXRRh8pojtVqxW63YzAYTjn8ZOPGjfz1r3/t8kHaJ4p6AAK49dZbufXWW5v8bP369Y3eNzS1tUTTNJYsWcKSJUs6oXZdQx+XjIYBBejrOt73KoQQom/auXMnXq+XmTNntmm744eQtLeMjqqurubnP/85zz77LElJSd267x4RgPoiXUIKOqUnBJjrVLSrI4QQogkGk44bHj8vKvttLavV2q59xMTEtLqMhp4YpY59X/n9He+92L9/P3l5eXz/+9+PLAuFwl2OBoOB3bt3M2TIkA7vpykSgKJEF5uAHh0BwOLp/v5lIYQQp6ZpWqu7oqJl6NChWK1W1q1bx3XXXdclZSQnJwNQUFBAfHw8wCm7rEwmE8FgsMV1hg8fzrffftto2W9/+9tIl1xXTkwsAShajDHoVHiAm9mnoZRq04A3IYQQAsBisXDPPfdw9913YzKZOPvssykpKWH79u1ce+21nVJGdnY2GRkZLFq0iKVLl7Jnzx4eeeSRFsvMzMwkNzeXnJwcBgwYQGxsLGaz+aT9njg/UcOVZF09b5EEoGjR6TDUtySaA3rqAnXYjLaWtxFCCCGacN9992EwGFi4cCH5+fmkp6dz4403dloZRqOR1atXc9NNNzF27FimTJnCAw88wE9+8pNmy5s7dy6vvfYaF1xwAZWVlTz//PNcffXVHTnMTqWp4zv0BBCeN8jpdFJVVdWls0I/N+9WKsjDbYvhhif/QGpM6qk3EkII0SU8Hg+5ubkMHjy4R101LBpr6Ty15fu7V98Ko7czUj/QK6ijxi+TIQohhBDdRQJQFBkJN77pQ4pqX3WUayOEEEL0HRKAosisCwcgXQhpARJCCCG6kQSgKDLVj4LWVIhqr7QACSGEEN1FAlAUWY31L1SQco8rqnURQggh+hIJQFFkbZhcSwUor5MAJIQQQnQXCUBRZLM1zC4apNJdFdW6CCGEEH2JBKAostmPzYhZVV0ZvYoIIYQQfYwEoCiKiYsBwq1AtbXSAiSEEEJ0FwlAUWSKs4FmAsBTWxvl2gghhDgd5eXloWnaKW9e2lGrVq2K3MerN5AAFEWWRCdafQAK1nqiXBshhBCno4yMDAoKCrr85qLz5s1jz549kfeLFi1i/Pjxp9xu1apVaJrW6NEdtyKRm6FGkTExEai/Ft4diGpdhBBCnJ70ej1paWnNfq6UIhgMYjB0LBJYrVasVmu7tnU4HOzevTvyXtO0DtWlNaQFKIoMCcno6gOQ3u2Pcm2EEEKcSCmF3+Pp9kdb71MeCoV46KGHyM7Oxmw2M3DgQJYuXQqc3AW2fv16NE3jnXfeYdKkSZjNZjZu3NhiGQ3bVFZWRvaZk5ODpmnk5eUBjbvAVq1axeLFi9m6dWukVWfVqlXN1l/TNNLS0iKP1NSuvzm4tABFkS4+Ba1+ELTFHYpybYQQQpwo4PXyh/k/7vb9/vcLr2JsQzfQggULePbZZ3nssceYMWMGBQUF7Nq1q8Vt7r33XlasWEFWVhbx8fHtKqM58+bNY9u2baxZs4a1a9cC4HQ6m12/pqaGQYMGEQqFmDhxIr///e8ZNWpUu/bdWhKAokizxaNHRwCweDT8QT9GvfGU2wkhhBANqqurefzxx3nyySeZP38+AEOGDGHGjBktbrdkyRIuuuiiDpXRHKvVit1ux2AwtNj9BjBs2DCee+45xo4dS1VVFStWrOCss85i+/btDBgwoF37bw0JQNFkcaBT4X5Oi09Pla+KJGtSlCslhBCigcFs5r9feDUq+22tnTt34vV6mTlzZpv2MXny5A6X0RmmT5/O9OnTI+/POussRowYwZ/+9Cd+97vfddl+JQBFk9FG/f1QMfv1uLwuCUBCCNGDaJrWpq6oaGjvwOOYmJhWl6HThYcMHz82ye/vmrGrRqORCRMmsG/fvi4pv4EMgo4mTcOghX+ZjAEdLp/cD0wIIUTbDB06FKvVyrp167qsjOTkZAAKCgoiy041r5DJZCIYDLa5LsFgkG+//Zb09PQ2b9sW0gIUZUbCAcgQ1FHlldmghRBCtI3FYuGee+7h7rvvxmQycfbZZ1NSUsL27du59tprO6WM7OxsMjIyWLRoEUuXLmXPnj088sgjLZaZmZlJbm4uOTk5DBgwgNjYWMxNdO0tWbKEM888k+zsbCorK3n44Yc5ePAg1113Xbt+Hq0lASjKTFoIFOhDUOWTACSEEKLt7rvvPgwGAwsXLiQ/P5/09HRuvPHGTivDaDSyevVqbrrpJsaOHcuUKVN44IEH+MlPftJseXPnzuW1117jggsuoLKykueff56rr776pPUqKiq4/vrrKSwsJD4+nkmTJvHpp58ycuTINtW/rTTV1skG+gCXy4XT6aSqqgqHw9Gl+3r9v27ggD8f9LGk/PY7/Hzkz7t0f0IIIZrm8XjIzc1l8ODB3TITsWifls5TW76/ZQxQlFnqr3rXVEi6wIQQQohuIgEoyiyW+lOgQlR5ZRC0EEII0R0kAEVZTEy4CUipAGV1FVGujRBCCNE3SACKslhnQ/9lgDK3BCAhhBCiO0gAirLYhIaJqBTVNTIGSAghok2uDerZOuv8SACKMntKHNTfENVX7Y5qXYQQoi8zGsNDEtxu+VvckzWcn4bz1V4yD1CU2ZITQTODcqOrCUS7OkII0Wfp9Xri4uIoLi4GwGazoWlalGslGiilcLvdFBcXExcXh16v71B5EoCiTJ+Ugg4TIdyYayCkQug0aZgTQohoaLhzeUMIEj1PXFzcKe8w3xoSgKJMl5CKVn8a4mrM1PhrcJi6dvJFIYQQTdM0jfT0dFJSUrrsZp+i/YxGY4dbfhpIAIoyzRqHHj1BILbOSJWnSgKQEEJEmV6v77QvWtEzSV9LtJkdGFT4NMR4jVR6K6NbHyGEEKIPkAAUbRZn5I7wZp+BCq/MBSSEEEJ0NQlA0abTY6oPQMaAjnJPeZQrJIQQQpz+JAD1AGZdEABDSEeFR1qAhBBCiK4mAagHsBrCAUgLhSQACSGEEN1AAlAPEGupn2hLBSmrK4tuZYQQQog+QAJQD+CMDV9qqZSPYreMARJCCCG6mgSgHiAxyRp+oTyUyx3hhRBCiC4nAagHiO8fV/9K4S/3RLMqQgghRJ8gAagHsKSmAyYAdJWh6FZGCCGE6AMkAPUA+tQB6OoDkN1lwBf0RblGQgghxOlNAlAPoEvsh77+tmzxtRaZDFEIIYToYhKAegDNloix/n5gjjqTzAUkhBBCdDEJQD2BLQGTCt8Ow+oxSAASQgghupgEoJ7AEoeZAACmgEa5V7rAhBBCiK4kAagn0OmwauEApA9CpacyuvURQgghTnMSgHqIGGM4AGmhIGUeuR2GEEII0ZUkAPUQDmv9/D/KR1FtcXQrI4QQQpzmJAD1EInx4cvglaojv6okyrURQgghTm8SgHqI5AHO8AvlxVXmim5lhBBCiNOcBKAewp4xADCG35R6o1oXIYQQ4nQnAaiHMPQfjB4LAHEVOrkdhhBCCNGFJAD1ELqEARiUHoBEl52SOhkHJIQQQnQVCUA9RWwallB4NmhHnYUStwQgIYQQoqtIAOop7GnYVHjsj8Wnp9gtl8ILIYQQXUUCUE9hS8Sp1QCgDyrpAhNCCCG6kASgnkKnI8HiDr8OeSl2lUa3PkIIIcRpTAJQD5KWEJ4NWoWqKCiUO8ILIYQQXSXqAeipp54iMzMTi8XCtGnT+OKLL5pdd/v27cydO5fMzEw0TWPlypUnrbNo0SI0TWv0GD58eBceQedJHJQWfqG8VB+pjW5lhBBCiNNYVAPQyy+/zO23387999/Pli1bGDduHLNnz6a4uOkBwG63m6ysLJYvX05aWlqz5Y4aNYqCgoLIY+PGjV11CJ0qZkg2OmUCwFAkkyEKIYQQXSWqAejRRx/l+uuv55prrmHkyJE888wz2Gw2nnvuuSbXnzJlCg8//DCXX345ZrO52XINBgNpaWmRR1JSUlcdQqfS9cvGFArPBeQs1/CH/FGukRBCCHF6iloA8vl8bN68mVmzZh2rjE7HrFmz2LRpU4fK3rt3L/369SMrK4srr7ySQ4cOtbi+1+vF5XI1ekSDFp9JTCgIQKxbT1FtUVTqIYQQQpzu2hWAlixZgtvtPml5XV0dS5YsaVUZpaWlBINBUlNTGy1PTU2lsLCwPdUCYNq0aaxatYo1a9bw9NNPk5ubyznnnEN1dXWz2yxbtgyn0xl5ZGRktHv/HRI3EKcW/rka/Yr8mvzo1EMIIYQ4zbUrAC1evJiampqTlrvdbhYvXtzhSnXEJZdcwk9+8hPGjh3L7Nmzefvtt6msrORf//pXs9ssWLCAqqqqyOPw4cPdWOPjxGWQYigLvw7WcqTyaHTqIYQQQpzmDO3ZSCmFpmknLd+6dSsJCQmtKiMpKQm9Xk9RUeNunqKiohYHOLdVXFwcZ5xxBvv27Wt2HbPZ3OKYom5jtNIvvg4qQIXKOLC/CEZEu1JCCCHE6adNLUDx8fEkJCSgaRpnnHEGCQkJkYfT6eSiiy7ipz/9aavKMplMTJo0iXXr1kWWhUIh1q1bx/Tp09t2FC2oqalh//79pKend1qZXSktKwmUBspL2e7KaFdHCCGEOC21qQVo5cqVKKX4xS9+weLFi3E6nZHPTCYTmZmZbQovt99+O/Pnz2fy5MlMnTqVlStXUltbyzXXXAPAVVddRf/+/Vm2bBkQHji9Y8eOyOujR4+Sk5OD3W4nOzsbgDvvvJPvf//7DBo0iPz8fO6//370ej1XXHFFWw41aiyDh2D6ogKf3of1UF20qyOEEEKcltoUgObPnw/A4MGDOfvsszEY2tWDFjFv3jxKSkpYuHAhhYWFjB8/njVr1kQGRh86dAid7lgjVX5+PhMmTIi8X7FiBStWrOC8885j/fr1ABw5coQrrriCsrIykpOTmTFjBp999hnJyckdqmt30ZKHEhP6FJ8ebNWhaFdHCCGEOC1pSinV1o22bNmC0WhkzJgxALz55ps8//zzjBw5kkWLFmEymTq9ot3J5XLhdDqpqqrC4XB0786/fZW3Fj7ObpMTnWkkVz11L4mO1o2rEkIIIfqytnx/t+sqsF/+8pfs2bMHgAMHDjBv3jxsNhuvvPIKd999d3uKFA2ShtLfFr4RqgqW8vX2PVGukBBCCHH6aVcA2rNnD+PHjwfglVde4bzzzuPFF19k1apV/Pvf/+7M+vU9idn0j68EwgFo29aD0a2PEEIIcRpqVwBSShEKhcenrF27lu985zsAZGRkUFpa2nm164tMMSQNikMf0gMhvLtkMkQhhBCis7UrAE2ePJkHHniAv//972zYsIHvfve7AOTm5p40s7NoO13qMGz1t8QwVcld4YUQQojO1q4AtHLlSrZs2cKtt97Kb37zm8gl6K+++ipnnXVWp1awT0ofS6K+viUtUEl50cm3HRFCCCFE+7XrOvaxY8fy7bffnrT84YcfRq/Xd7hSfV7aWLKcL5LnSiLkP8ynGw/wvbmjo10rIYQQ4rTRoYl8Nm/ezM6dOwEYOXIkEydO7JRK9Xnp4xiVUsqHVRqKWg5s2gISgIQQQohO064AVFxczLx589iwYQNxcXEAVFZWcsEFF/DSSy/1mkkHe6yEIZhsNiyhIHV6Haq0iGAwhF7frh5LIYQQQpygXd+ov/rVr6ipqWH79u2Ul5dTXl7Otm3bcLlc/Pd//3dn17Hv0ekgbTQWS3gcUChwlP3b5eo6IYQQorO0KwCtWbOGP/7xj4wYcexW5SNHjuSpp57inXfe6bTK9Wn9JpKUVg5AyH+IT9/ZHeUKCSGEEKePdgWgUCiE0Wg8abnRaIzMDyQ6aNB0xjkr0IcAfLj27CLol5+tEEII0RnaFYAuvPBCbrvtNvLzj03Sd/ToUf7f//t/zJw5s9Mq16cNnM7AYACf2QVAyJ/Hvm9KolwpIYQQ4vTQrgD05JNP4nK5yMzMZMiQIQwZMoTBgwfjcrl44oknOruOfZM9BS1xKO7+VQAEffv4dM3eKFdKCCGEOD206yqwjIwMtmzZwtq1a9m1axcAI0aMYNasWZ1auT5v0HT6+96kJncAIWqpPrCH2sopxMSZo10zIYQQoldrUwvQBx98wMiRI3G5XGiaxkUXXcSvfvUrfvWrXzFlyhRGjRrFxx9/3FV17XuyLmC830O1rRqAoG8Xn7ybF906CSGEEKeBNgWglStXcv311+NwOE76zOl08stf/pJHH3200yrX52XPZLQ/xJfDawAI+fay56NcAv5glCsmhBBC9G5tCkBbt25lzpw5zX5+8cUXs3nz5g5XStSzOLEOOht7fA2a8gN+Qu597PisMNo1E0IIIXq1NgWgoqKiJi9/b2AwGCgpkSuVOtWw7zDF4+VgWrgVKODdyqf/u49QSEW5YkIIIUTv1aYA1L9/f7Zt29bs59988w3p6ekdrpQ4zrBLOLuujk9HVYNSqGAB/ooj7P5CWoGEEEKI9mpTAPrOd77Dfffdh8fjOemzuro67r//fr73ve91WuUEEDeQCamT0UxBXPaGVqCv+ej1fYSCMjGiEEII0R6aUqrVfSlFRUVMnDgRvV7PrbfeyrBhwwDYtWsXTz31FMFgkC1btpCamtplFe4OLpcLp9NJVVVVkwO+u13Oi9y6aSE7PA6++1k/QIfZeS0XXDWZUTP6R7t2QgghRI/Qlu/vNs0DlJqayqeffspNN93EggULaMhOmqYxe/ZsnnrqqV4ffnqkET/grPW/ZUOCHywB8BgIeL7go9fiOGNKGkazPto1FEIIIXqVNs8EPWjQIN5++21KS0v5/PPP+eyzzygtLeXtt99m8ODBXVFHYbZzYebFALw/JnxX+KD3W4I1lWx+72A0ayaEEEL0Su26FQZAfHw8U6ZMYerUqcTHx3dmnUQT0mbcwXiPl6PJXqx2ExAi4PmCzWsOUlPhjXb1hBBCiF6l3QFIdLOkocyxDQJg+8hjrUDKX8WGV/dEs2ZCCCFEryMBqBe5aPqdaErxUWIFSfFOIITf/Ql5m0s4srsi2tUTQggheg0JQL1ISvZspuvsoEHF6GIAQr6dhALFvP+3nQT9clm8EEII0RoSgHqZn4y7AYA3rEfJGjQANAi6P8Rd5mHL+zIgWgghhGgNCUC9zHljfk6SZqTMoMeQ+jkaEAweJejP48v/5FFV4o52FYUQQogeTwJQL2PUGZk7/AoAVttrGTsoBgBV8z6hQJAPX9xNG+a2FEIIIfokCUC90M/GXotFZ+RbixmrcyNGTUeAaoLebzm6s4J9m4ujXUUhhBCiR5MA1AslWBL44dAfA/BCopUzM6oBULXrUcrH+tW78dT6o1lFIYQQokeTANRLzR89H72mY5PViha3g1ijjqAuCNXr8dUG+PS1fdGuohBCCNFjSQDqpfrb+zO3vhVoZZKT85K3A+ALbEMFXez8pICje2RuICGEEKIpEoB6sZvG34TVYOUbi5lPB3hJN9ahNDCUvw7Aur/vIuAPRrmWQgghRM8jAagXS7ImcdeUuwD4U2I8kwbsBqWoNZQR8uZSXVLH5jUyN5AQQghxIglAvdzcoXPJcmZRq8FfB1oZbisBwFj5vyil2PzOQcrya6JcSyGEEKJnkQDUy+k0HUtnLEWn6XgnxoI1Ox+DClJrCqKv2oAKKT78xy5USOYGEkIIIRpIADoNjE4azc+G/wyABwelMz7+KABB35cEQh6KDrjYvjE/mlUUQgghehQJQKeJX034Ff1i+pEf8vD2VCs25cNr1BNb+BIAn/x7H7WV3ijXUgghhOgZJACdJmxGG8vPXY5e0/O2wU3MMBcALlMpXs8RAt4gH7+8J8q1FEIIIXoGCUCnkQkpE7h1wq0ArMz24jDUEdTrSCl6kRCK/V+XcCCnJMq1FEIIIaJPAtBp5hejf8HMgTPxE2DNmeHbYRTF6nFUvAfAhpd246sLRLOKQgghRNRJADrNNFwVlh2XzR5HBe4EP2gaoZrNBFQ17kofn715INrVFEIIIaJKAtBpKMYYwx8u+ANOs5O3xxahoSi3WzjjyLMAfLvhCIUHqqJcSyGEECJ6JACdpjIcGfzhgj/gs+vZPSAcdvKMPgYEPgIFH/5jF8FgKMq1FEIIIaJDAtBpbGLqRJaes5QvR7gIaUHcZhPGvLUYtWrK82vJef9QtKsohBBCRIUEoNPcnMw5/OrM/8eXw8N3ht/njGWM6+8AfPV2HtXlnmhWTwghhIgKCUB9wNWjrmb87O/jNfrwG/QcKSokTb+DgC/Eptf2Rbt6QgghRLeTANQHaJrGvWcuwD0nG4DDCU7i819FI8jer4rJ31sR5RoKIYQQ3UsCUB+h03Tcf8XjBBL1KE3jSJ1Gf8OHAHy06itCMiBaCCFEHyIBqA8x6o381z0rAEWJMwZX7gaMWjVlZXq2/99n0a6eEEII0W0kAPUx/QcNZcRZ5wBQp7dx1PQOAJ+/V4bniEyQKIQQom+QANQHXfCLmzHq9VRbzYzankO15SjeUAyf/fEl8MgEiUIIIU5/EoD6IGusg7N+ciUAxY44PJ5XANhePpWS5+6EoD+a1RNCCCG6nASgPmrC939IbEwsXqOBMXtKyIvbDOj4eOdY1H/uBKWiXUUhhBCiy0gA6qP0BiMzrr4egCMJ8SQW/B8BzUeBfxT7Pt0Fm56Mcg2FEEKIriMBqA8bMeN8EpNSCOh1DDmi2J0Yvix+Te0v8L+7BHa+FeUaCiGEEF1DAlAfpul0nHf9LQAcSXBwxre7qDVWovMn85fgj+Hf18HRLVGupRBCCNH5JAD1cZnjJtJ/UBYhnUaqu5Ltxr0AeMq/z2pjAqy+HCoPR7mWQgghROeSANTHaZrG+TfcCkB+vJ2zvvmCQnMFppCFT2v+i/dCLnhxHnhcUa6pEEII0XkkAAnSss8ge/R40DSsxnL2uSsBGFYylRW2CXzp2gev/gKCgajWUwghhOgsEoAEAOdcexMaUOKI4Tv7/s0Oox8NHVMPzuXXyckcOPghrLk32tUUQgghOoUEIAFAQr/+jD77fAB8MT5crh0ENUivziK5ciI3paZQsuWv8OVfoltRIYQQohNEPQA99dRTZGZmYrFYmDZtGl988UWz627fvp25c+eSmZmJpmmsXLmyw2WKY876+S/Q63RUxlj4/sH/8LnJB8CMw3Mp0lm5JTWF2jX3wsFNUa6pEEII0TFRDUAvv/wyt99+O/fffz9btmxh3LhxzJ49m+Li4ibXd7vdZGVlsXz5ctLS0jqlTHGMPT6BSXO+D0C5U4et+HPcBrB6HJxZ8h12mk3ckRSH/19XgSs/yrUVQggh2i+qAejRRx/l+uuv55prrmHkyJE888wz2Gw2nnvuuSbXnzJlCg8//DCXX345ZrO5U8oUjU39yc8wG03UWkzMKVjPBoMbgHFHLiQhkMwnNiuLrQHUy/8FAW+UayuEEEK0T9QCkM/nY/PmzcyaNetYZXQ6Zs2axaZN7etiaW+ZXq8Xl8vV6NFXmW0xnPmTnwFQGG/mjCPrKTIqQn64wXMfek3Hm7F2nqzdB2/fFeXaCiGEEO0TtQBUWlpKMBgkNTW10fLU1FQKCwu7tcxly5bhdDojj4yMjHbt/3Qx/juXYrfZ8ZgMzCj7ko914UBY+a3inkGLAfhzvJN/7f03fCUta0IIIXqfqA+C7gkWLFhAVVVV5HH4cN+e+dhgNDLjqmsBOJxg49zcd9lhDgJg+nwAN469CYClifF8+OF9cOjzqNVVCCGEaI+oBaCkpCT0ej1FRUWNlhcVFTU7wLmryjSbzTgcjkaPvm7EeReSkJBEwKBnTO0OtqoyQjooPODiIv+P+FH2DwlpGncnxZHz2lXgKoh2lYUQQohWi1oAMplMTJo0iXXr1kWWhUIh1q1bx/Tp03tMmX2VTqfn3OtuBuBwgp0f7n2bT0x+ADa9vp97J/2Gc9LPwqPT8SuHnrx//QwCvmhWWQghhGi1qHaB3X777Tz77LO88MIL7Ny5k5tuuona2lquueYaAK666ioWLFgQWd/n85GTk0NOTg4+n4+jR4+Sk5PDvn37Wl2maL2siVNIzxhESKejf+Ag+b4C3EaoqfDy7dp8VlzwGKOdQ6nU67mRQkr/c1u0qyyEEEK0SlQD0Lx581ixYgULFy5k/Pjx5OTksGbNmsgg5kOHDlFQcKxrJT8/nwkTJjBhwgQKCgpYsWIFEyZM4Lrrrmt1maL1wjdK/RUAR+PtXLX/bdYaw608X797kFCNjidnP0uGJZGjRgM3F31A7Rd/jmaVhRBCiFbRlFIq2pXoaVwuF06nk6qqKhkPBLy+eAEHdnxLalUtfx/4E6ZahpHm0zhjaioX/WIUh1yH+PmbcykPeTi7zssTl7yAcZB0OQohhOhebfn+lqvAxCmde+3NaECRM4ZrD7zNeyYPCtjzRREF+yoZ6BjIU3Oew4qOT6xmFq25DuVq31QGQgghRHeQACROKXFABiOnnwNAldXLqKNf8a0pAMCH/9hF0B9idPIYVpz7EHoF/2vR8cS/fyiDooUQQvRYEoBEq5xz9Q0YDQZcNjOXFX3Al/pqvHqoKHSz+d2DAJw7eDYLx90CwLO6Gv75xpXRrLIQQgjRLAlAolVi4uI558rwlXS5CTau3Pc275rDLTyb38mjLL8GgB9NuJFbMmYDsLx2F/+77p7oVFgIIYRogQQg0Wrj5nyP5JQ0Ano9/bz78LsPkWcKEQoqPvz7LkKh8Hj6X17wMP/lGA7AwsP/Yd3XcmWYEEKInkUCkGg1nU7PRbeFb4CaHx/LrQf+l3fNHoI6KMp1sW3DESB8+fxdP1jNZbp4gprGXVv/wGcH1kSz6kIIIUQjEoBEm6RnD2PM2ecBUGz1MevQx3xQ3xW26bX9VBTWAqDTG7h/7htc5Nfh1zT++6O72Vq4OWr1FkIIIY4nAUi02bm/uAmrxUqtxcTZZZ9R6C/miClEwB/i/ed2EAyGADDYElj+/dWc5fFTpylueu86dpbtjHLthRBCCAlAoh0sdjsX33oHAHkJdu7Y+2/+z+wloIeSQ9V8+VZuZF1T6kgem7Gc8R4v1SrAde9cJSFICCFE1EkAEu2SPeVMhk2cCppGuaWOC498yn/MXgC2rDlI/r7KyLq2UZfxx+wrGevx4gp6uG7NNewo2xGlmgshhBASgEQHzLzl/2E1mamxmDi39BNqfUXsMAdRCt5/bjueGn9k3dgL7uNP9nHhEBSo5fp3r5MQJIQQImokAIl2s9pjmX3b3QAcTLBz156X+dDkpsYINeVe3n9+B6r+0nh0Ouxz/8KffHbGeby4/NVc99515BTnRO8AhBBC9FkSgESHDJk8jfHnzQLgcCxcu/8dXrV4COng0PYyvnon79jKFif2y1fzTHlteEyQr5ob3r+BjUc3RqfyQggh+iwJQKLDzrv+FhITk/EZ9CR69pJRupM1lvCl8V+8lcuhHWXHVk4ehv2yZ/hTYTEz3HXUBer41bpf8daBt6JUeyGEEH2RBCDRYQajkR/89ncYNB1lsVb+68hbFAdK+dYcAAXv/XU7lcXuYxuM+D62c+7kD0UlfKfWQ0AFWPDxAp7e+jRKqegdiBBCiD5DApDoFAn9BjDzupsByE2I4Te7/8kGo5sSk8JbG+A/T32Dp/bYoGjOX4Bx6MUsKy7m6rrwoj/m/JFlXywjGApG4QiEEEL0JRKARKcZPWsO42ZcAEBerMade17lFXMddUaoLHLzzjPfEgyEJ0lEp4cfPYsuIYs7Cg/xGxIAWL1rNb9e/2vcfndzuxFCCCE6TAKQ6FQX3HQb/TIyCep1+HQl/ODIR7xk8RDUQ/7eSj78x65j3VzWOJj3TzDGcHluDg87J2HSmVh/eD1XvXMVBTUF0TwUIYQQpzEJQKJT6Q0GLl24FLvVhtts5AzXZkaUfMtrFi9Kg92fFfLZmweObZA6Ei77IwBzcl7nr9n/RYIlgd0Vu5n31jw+L/g8SkcihBDidCYBSHQ6m8PJDxctx6DTUW63MqfoXSyuA7xXf2XYljUH2bwm79gGoy6DGbcDMH7dg7w0dREjEkZQ4a3ghvdv4IXtL8jgaCGEEJ1KApDoEimZWVx690I0oNBh4xeH/k2pr4ANlvBA6M/eOMC3648c2+DC38KQmRCoI/3N2/jb+Y/zgyE/IKRCrPhqBXd9dBc1vproHIwQQojTjgQg0WUyJ0xmzg3/DcDhOBt37HuR3FAJn5rDIeijl/aw/eOj4ZV1epj7F4jPhMqDWP59PQ9Mu48FUxdg0Ay8m/cuP/m/n/BNyTdROhohhBCnEwlAokuNnHkx58y9AoC8ODMLdr/AblXKV+YAAOv/uZut6w6HV7YlwOUvgskOeR+jvXkLPxt2Oc/PeZ70mHSO1Bxh/jvz+cu3fyGkQtE6JCGEEKcBCUCiy0396ZVM/+5lAOTWh6CtqpQv6luCNr6y99iYoNRR8NO/gc4A216FdYsZnzKeV3/wKrMzZxNQAR7f8jg3vHcDhbWF0TkgIYQQvZ4EINEtzrrqOs685AcA5MWZ+M2eVewIlfDJcWOCPvn3vvDNU7Nnwg+eCG/4yUr44lkcJgcPn/swS85agtVg5fPCz/nhmz/k33v+LQOkhRBCtJkEINFtzr76BqZe/D0A8pwm7tq3isO+I6yvD0E57x/ivb9uJ+APwvifwQW/DW/49l2w4000TeOHQ3/Iy997mbHJY6nx17Bo0yJ++f4vya/Jj9ZhCSGE6IUkAIludc61NzLjBz8G4LDDwo15q3G59/Efmw+lwb7Nxfzv4zl4avxw7p0wcT6g4NVrYfcaAAY7B/O3OX/jzsl3Ytab2VSwiR+++UNe2vWS3EZDCCFEq2hK+g9O4nK5cDqdVFVV4XA4ol2d09K2NW/x3nPPoDRIrPWwPvF89idNYm6dGWMIHEkW5vxyDMn9bfDa9bDt36A3wRUvhbvI6uVV5bHw04V8Xfw1AKMSR3HfmfcxKmlUtA5NCCFElLTl+1sCUBMkAHWP/Z99wv89tpwgihiPj1LTUN4YdAk/9liJDWjojTouuHIYw6YkwStXw663wGCBK1+BwedGygmGgry0+yWe/PpJavw1aGj8dNhP+dWEX+E0O6N3gEIIIbqVBKAOkgDUfQr37uL1xf+D2+/DEAwS641l5RlXMNtnJ9OvB2DMef05+7JB6F+fD3vWhEPQT/8GZ8xuVFaJu4RHNj/Cfw78B4AESwI3j7uZuWfMxaAzdPuxCSGE6F4SgDpIAlD3qq2s4PX/uYOismJQin7VQZ7M/CmZpv6c5TUCkDjAzkVXZZO48aZwCNL0cNnTMG7eSeV9UfAFSz9fyoGq8D3HBjsHc/uk2zlvwHlomtatxyaEEKL7SADqIAlA3S8Y8PPeQw+wY+tmAOJrvXzlmMKutBl8z2PBHAK9UcdZl2UypvL3aN++HN5wznI486aTyvOH/Lyy+xWe3vo0ld5KAKakTeGOyXcwKlHGBwkhxOlIAlAHSQCKnm/+93U++OdfCQLGQBCzz8Gz2fM4PxDL4PousYEjE7hgwOvYv1kZ3mjyL2DOg2AwnVReta+av3z7F/6x4x/4QuGbsV6YcSE3jruREYkjuumohBBCdAcJQB0kASi6yo8c4s37F1BeUwVASo2P11MvQjnHcIHHhF6B0aJn+phDjD7032haCAadHR4XFJPUZJn5Nfn84es/8PaBt1GEf+XPzzifG8fdKC1CQghxmpAA1EESgKIv4Pez/vGH2frlpwCY/QFCgUReHjKX830O+gXDU1ilpYc4X/2GRHaBMwPm/hUGTmu23P2V+/nzN39mTd6ayP3EzhtwHjeNu0kunRdCiF5OAlAHSQDqOQ5t+ZI1jy2n2ucFILnay3tJ51KbOIXzPCaMCjQdjI77mKmGP2PR18F5d8M5d4K++Su/cqty+fM3f+bt3LcjQWha2jT+a+R/ce6Ac9FpMkeoEEL0NhKAOkgCUM/i93rY8IdHwq1BmoY+GMLuMfKvjMsYaRjA0PqxQWajl2mWFxhlexfdwCnwoz9DfGaLZR90HeTP3/yZ/xz4D0EVnkU6IzaDK0dcyWXZlxFjjOnqwxNCCNFJJAB1kASgnqlg1w7ef/gBSmpcANi8fipVOh8Ovoyz/XaS6rvFEoxHODPmb2Tat6NdcC+ceTPojS2WXVhbyOpdq3l1z6u4fOHy7UY7l2Vfxo+G/oih8UO79uCEEEJ0mASgDpIA1HOpUIitr/2Lja++iLe+6yq+1sfWmLEcSr+QGV4zFhWe6yfFuIcz7f8gY6CC7z0GGVNPWb7b7+atA2/xj53/ILcqN7J8VOIofpj9Q+YMniOzSwshRA8lAaiDJAD1fF53LRtWPsy2nC9R9ZMbxtf6+dIxlZrks5nkM2KsD0L9Td8wxf4v+o0fhnbR/afsFgMIqRCb8jfx6p5XWX9kPYFQAACTzsTMgTP5QfYPmJY+DaOu5ZYlIYQQ3UcCUAdJAOo9Ko4eZv2KZRw4ehA0DU0p4muDfJowg2D8FMb7DOgJB6E04y4mxv4vmedMQJtxG8SmtWof5Z5y/nPgP7y+73X2VuyNLHeYHFw48EIuGnQR09KnYdabu+QYhRBCtI4EoA6SANT7FO3czod/eISj5cXhBUrhdIfY4pyGP3E6Y316dITHCMUbDjEx9v8YelYW+nP+G+IyWrUPpRQ7ynfw+t7Xef/g+5R7yiOfmfVmzkw/k8uyL2Na+jRiTbGdfoxCCCFaJgGogyQA9V6Ht3zJxj89SX5lWWRZXK2fHfYJlKWcx0S/Hr0KXx5v1xUzzv4Ow6cmYDnnOkht/TxAwVCQLcVbeDfvXT449AEldSWRz/SangkpEzg/43zOTD+TofFD5bJ6IYToBhKAOkgCUO93NGcLnz77FIdKiyLLHG4/B81DOJg2m4lBCyYVHr9j0DycYdnAmOxCki74EQz7botzCJ1IKcXeyr28vvd1Nh7dSJ4rr9HnscZYxqeMZ2LqRCamTGRU0ijpLhNCiC4gAaiDJACdPkr27uGTpx/nwJG8yGBpiy+AJxjHzrRLGGpIwh6yRtZPN25nTOImss4ahn7izyCp7Ze/H6k+woYjG/joyEfkFOfgDrgbfW7UGRmdNJoJKROYlDqJccnj5MoyIYToBBKAOkgC0OnHVZjPF888xc4dW/GFcxC6UAhbncaO+LMxO8cwKGCF+nFCNl05w60fMqLfAeIGZ8BZv4K0MW3ebyAUYHfFbr4u+potxVvYUrSFMk9Zo3U0NLLjs5mYMpEJKRMYlTiKgY6B0m0mhBBtJAGogyQAnb58Xg/bXvw7X699h8qAL7I8ts5PoTGT/NRZDFexGNWxO8unGXcywvoB2VluTBN+CKN/1OxNV09FKcXh6sORMPR18dcndZkBWA1Wzog/g+EJwyPPQ+OHYjVYTy5UCCEEIAGowyQAnf6UUhzctJGv/rGKg6WFUN89ZggEMXiNHEg4B6NjFAMCZrT6y+gNmoch5k0Mt35I/0F6tKEzYciFMGAqGEwt7a5FZXVlfF0cbiHKKc5hT8UevEHvSevpNB0DYweS5cxiSNwQsuKyyHJmMdg5WIKREEIgAajDJAD1La7CArY892d2bt2Mm1Bkud3jp0KXzsGUC8nQp+IMHZv00KEv5AzLR2RbNpIYUwGZ54TDUPZMSMiKBKr2CIQCHHIdYlf5LnZV7GJ3+W52le9qdNn98TQ0+tn7MSRuCIMdgxnoGMiA2AEMjB1IWkwaBl3rB3QLIURvJgGogyQA9U2hUJD9779LzuuvcLi8ODJoGqWI8YQotJ5BRcJ5ZCoHJo6Nz4nXHybb8glDLJ+SaDwMcQNhSH3r0OBzwRrX4boppSitK2Vv5V5yq3LZX7mf/ZX7OVB1gEpvZbPbGTQD/ez9yHBkkGHPYKBjIBmxGQyMHUj/2P5yNZoQ4rQiAaiDJACJ2rJSvvnn39j9+SeUBY51R+lCIcxePQWxE6hzTiMjZMHAsdaeeMNhss2fkG39hATDEdD0MGByOAwNmQn9JrTpEvvWKPeUh8NQ5QHyXHkcrj7M4erDHKk+gi/ka3Y7DY3UmFRSrClU+6uZmDKREQkjyI7PJsuZRZw5Dq0DLVlCCNHdJAB1kAQgcbzS3bv4ZvXf2bvzW2qO6yIzBoLgt3IkbhpB+zgGhYyR224AxJsLyTZ+SLbl03AYAjDGwIBJkHEmDJwGA6aApWsugQ+pEMXuYg65DnG4+jCHqg9FgtGh6kPU+mtb3N5qsJIRm0F/e3/SY9LDD3t65HWiNVGuVBNC9CgSgDpIApBoilKKo599yjf/fpkDhw7gPa5xxOIL4A05ORI3Fc0+mkFBQ6MwlBBTQbbxQ4YYPjwWhgDQIGVkuJWo34TwI2VkhwZVt/ZYKrwVHHIdorSulApvBdtKt3HIdYhDrkMU1xWfsgyDzkCaLY1+9n6kxaQdC0kx6aTGpJJqS8VusnfpcQghxPEkAHWQBCBxKqFgkH1r/sP2/7zJwZJCgrpjYcfiC+ALxZIfNxkVM46BJ7QMJcT7yErYS2bwPVLqPkbTTvgnqDeFb8vREIjSx0PKCNB3353nfUEfR2uOcrj6MAU1BeTX5lNQW0BhbSEFtQUUu4sJqdApy4kxxpBiSyHVFg5EDcEoLSYtssxpdkpXmxCiU0gA6iAJQKItfHV17HxlNbs//pCjleWEjgtDJn+QYNBGoXMSQfsEMkKmRmHIFmtg0MA6Mh17GRDagKnoC/BUnrwTvTk8EWNDKOo3HpKGdfp4otYKhAIUu4spqC04Fozqg1KRu4ii2iJcPleryjLrzZFwlGJLCT+sKSTbkkmxpZBsTSbZliwDtoUQpyQBqIMkAIn28tXVseeNV9m9YR1HykoIHBeGjIEgOr+ZktgxuB2T6KdiMR0XhnQGjQFnxDNoiEZmQi6Omi2Q/zXkbwVv1ck7M1jDoSh1JKSMCrcSpY4CW0J3HOopuf1uit3F4UBUH4oaPbuLmr20vylOs5NkazgUJVmTSLQmkmRJIsl67JFoTcRhckiLkhB9lASgDpIAJDqD3+tl/1tvsuuD9zhcXIDvuDCkCynMXii3DqbcMYVEY3/iQo0HFCf0iyFzTCKDRiWQFleOriinPhDlQMFW8FU3vWN7angcUcrI+nA0Ijw3kSWuQ/MTdQVf0HcsJNUHo2J3MSV1JZS4SyKvm5oYsjlGnbFRIIoEJEvjZYnWRKwGK8FQEL1O34VHKYToLhKAOkgCkOhswUCAvLXvsWftGg4ezqWWxv/srN4gtbokyh3j0ayjSFdGdMe1DpltBgYMT2DgyAQyRiYQG2eC8v3hIFS8A4p2hJ8rDzZfCccAGHQW9J8IqaN7VGtRS5RSuHyucCCqK6bYXUxZXRmldaXhZ08ppXXhR3VzobAZRp2RoAoyPnk8A2IHkGxNpp+9X6QrLsmaRIIlQSaTFKKXkADUQRKARFdSSlG6/Vt2vfkauTu+pdTvOTbpIuGuMr3fSLntDGodE0nSp2JVjVtu4lJtZIxMYOCIBPqdEYfJUv8F7a2Gkt1QtB2Kd0Lx9nA4cpc2XRl7GqQMD7cWJQ8PtxYlDwdL7/y99wa9kXDU8Gj03nPsfWtblTQ04i3xJFuTSbIlkWINB6OG8UnHLzN240B1IcTJJAB1kAQg0Z3cpSXsfu0VDnz1OUcrSvHrGocdqzeAR5dMpX0UKmYUKcrWqHVIp9dIy3KSMSKe/mfEk5LpQG84YX4eXy3kfgSF2yB/S7i1qCKv+Uo5+h8LQykjIHkEJA8D8+lxWbtSilp/LdW+aiq8Fewu302Ru4iyujIK3YXhrjd3CeWecoIq2Opy483xJNmSwgO36wdvn/icZE2SAd1CdBEJQB0kAUhESzAQ4NBH69n3wfscObCH8oCv0bgdLaQw+TWqTQNxxY7FbswijsbdM3qTjn7ZcfQ/I47+w+JJGRiLTt/EhIUNrUXFO+pbi3ZCyS6oLmi+go7+kHRGOAw1PCcPh5ikzvoR9CjBUJAKbwVldWUUu4sprSuNjEsqrSulxF0SHq9UV0IgFGh1uQ0DuhtakpKsSU0GJovB0oVHJ8TpRwJQB0kAEj2Fu6yUfW+9Se4Xm8gvLsR9Qo4xBENoAQsu21DqYsYQZ0jHdkJ3mcGsDweiYXEMGBZPUkYsOl0Lg6HrKqB4F5TsbPxc28LkiNaExqEoaRgknxEed6Q7/WeLDqkQVd6qyODthoB0fGhqCEwt3Z7kRLHG2JNCUaPQVL/MZrR14dEJ0XtIAOogCUCiJ1JKUbrtG/a9/X8c3P4tRXXVBE4IF2Z/kKCKxWUdgidmJPH6dKw0Xsdo0dNvaBz9suNIz44jZVDsyV1mTXGXQ+mecKtR5Hk3VB5qfhujDZKGHgtEScPCASkhq1snduwpThzQ3agVyd04NHmCnlaXG2OMIdmaTIIlPKh9fMp4zog/gxGJIxhgH4BJ37UziwvRU0gA6iAJQKI3CPp8HPzgfXI/+pDDefspD/gaDaaG8IBqFbJTYxmM1z4Sp24AlhPu36U36Egd7CA920m/7DjSspyYrG246snnhrK9ULInHIgaAlLZfgj5m95GZwiHoBNbjJLOAFNMW38Upx2lFNX+akrdpZTUlZzcknRcS1NdoO6U5SVYEhrNwJ0Wk0ZqTCpptrTI7NwSksTpQAJQB0kAEr2R11VF3ntrOPTFJvIPH6Q84Gs0KzXUd5mFbNSYB+G1jcBuHIjthDFEaJCQFkNqloPUTAdpWU7i02Na7jZrStAfHmjd0FLUEJBK94KvpvntnBknjzNKGgYxiW3bfx9R66+NBKPSulKO1hxld/luCmoL2F2+u9UtSQmWhEa3KJGQJHqjXheAnnrqKR5++GEKCwsZN24cTzzxBFOnTm12/VdeeYX77ruPvLw8hg4dyoMPPsh3vvOdyOdXX301L7zwQqNtZs+ezZo1a1pVHwlA4nTgr63l0Lr3yNv0CQWHcin11RE8octMHwxhCBipM/WnznoGJssQYrWTW2CMZj0pmbGkDnaSmukgdbCDGGc7r2RSClxHT+hKq39u7nJ9AFsiJGaHHwlZjV+bZAxMU5RSVHorKawNX9lWWFtIkbvopOfWTgmQYEmIjEdqmAagYTxSw/tEa6LMmySiplcFoJdffpmrrrqKZ555hmnTprFy5UpeeeUVdu/eTUpKyknrf/rpp5x77rksW7aM733ve7z44os8+OCDbNmyhdGjRwPhAFRUVMTzzz8f2c5sNhMfH9+qOkkAEqejgMfDkQ3rOfjJBvIP7KPEU4v/xKvDlMLiUwR0idRaB+O3nkGsPg2zdvIYodhEC6mDHaQNdpI62EFShh2DsYMzKrvLT24xKtkDVS2MM4Lw1WmJQ+oD0ZBj4Sh+UJ8ca9QWDSGpYTbujoYkDY1Ea2Kjgdsptvp7u1lTIvMmJVgSZAZu0el6VQCaNm0aU6ZM4cknnwQgFAqRkZHBr371K+69996T1p83bx61tbW89dZbkWVnnnkm48eP55lnngHCAaiyspI33nijVXXwer14vcf+cbtcLjIyMiQAidNaKBik4PNNHNz4EQV7d1FcVY67iV4uYyCILmimzpROnXUIOksWcZoTjcYra3qN5AF2UrOcpA0OtxI5kqydc18uXy2U7QuPKyrbH54Fu2xfuDutqZvHHqtUOAQ1BKLEIccCkqN/n7hCrTMopajyVlHkLjrpNiUnjk9q7bxJOk1HkiWp8VVu9SHp+GXx5vhIUFJKyX3eRIt6TQDy+XzYbDZeffVVLrvsssjy+fPnU1lZyZtvvnnSNgMHDuT222/n17/+dWTZ/fffzxtvvMHWrVuBcAB64403MJlMxMfHc+GFF/LAAw+QmNj0GIJFixaxePHik5ZLABJ9jevoEQ5+sJYjW7dQlH+EioCXUBNfOEZ/iJDmwG0egN+Shc04CJtmPXk9i56UQbGkDHSQPCiW5IGxOJM7KRQ1cJfXB6N9xx7l9UHJ725+O4OlPgwd153W0IIUk9Tj7pvWG4RUiHJPeaMr24rrwpNKNrrazVNKSIVaXa5RZ8Sit+AOuBmRMIIhcUNIsaWQFpNGsjWZeEs8CZYE4i3x2I12CUl9WK8JQPn5+fTv359PP/2U6dOnR5bffffdbNiwgc8///ykbUwmEy+88AJXXHFFZNkf//hHFi9eTFFREQAvvfQSNpuNwYMHs3//fv7nf/4Hu93Opk2b0OtPbnKVFiAhmub3+Sj84jOObPqEwr27Kakoo1oLnRwOlMIY0AjoEvFYMlDmLGIM/TFqJ3c/GSx6UgbGkjLIQcrA40JRWwdZn4pS4UkdIy1Hxz1X5DV/hRqA2XmsS+3454QhvfY2IT1JMBSk3FMengrAXRoJScffCLekroSyujIUbfuKMugMxJvjibeEH06TkzhzHE6zM/Jo9N4UfpZxS6eHtgSg0/KMX3755ZHXY8aMYezYsQwZMoT169czc+bMk9Y3m82YzTI1vRAnMppMZMw4l4wZ50aWeUpLObz+A45u+Yqiw3mUuWuoM+jwGwHKMPvLwJ9DKKQIBQ349UnhUGTKJMbQDzyQv6eS/D2VkTL1Zj3J/WNIGhBL4gA7if3tJPaPOXaPs/bQNHD0Cz8Gn9v4s2AgPK7oxGBUth+qDoO3KnzLkPwtJ5cbkxIOQ/GZED+4/rn+YU+RlqNW0Ov0kS4vWri4LxAKUOOrwRP0UBeowxf08XXx15R5yqjwVFBQW0BZXRmV3krKPeXUBeoIhAKR2bnbwm60NwpFceY4HGYHDlP4YTfZiTXFhh/G2GOvTbFydVwvFdUAlJSUhF6vj7TcNCgqKiItLa3JbdLS0tq0PkBWVhZJSUns27evyQAkhGg9S1ISQ3/8U4b++KdA/eR++/dx5OMN5G/bSnFBPuW+Onx6HT5dECjC7CsC31f1oUhPQJ+AxzwAZR6EzTAAvGYKD7goPOBqtK/YRAtJkUBkJ2mAHUeyte2X5J9IXz8PUUIWDL2o8Wd+D1TkHteltv9YQKotPvY4tOnkco02iBsECScEo/hMiBsIxpO7CUXzDDoDcZa4RsuGJQxrdn1PwBMJQxWeCiq8FVR5q3B5XVR6K6nyVVHprTz23ltFta8ahaLGX0ONv4ajNUfbXE+z3kysKRa70Y7D5Ai/bghMxlhijDGRh91kP/baaMdisGDUGTHpTBj1RgKhAKV1pQx2DkbXxMUHovNENQCZTCYmTZrEunXrImOAQqEQ69at49Zbb21ym+nTp7Nu3bpGY4Def//9Rl1oJzpy5AhlZWWkp6d3ZvWFEICmaTizh+LMHsqo+mWhUIjybd9w5JONFOzaQUlJIZV+D36dDp8uBJRi8peCP4egUuiCOkKaE48pnYB5ECZjBjG6WKrLPFSXecjdeuzyeL1RR2K/mEhLUVJ9OLLYO+lqL6MlfAPYlBEnf+ZxHRtfVHkQynPD3WkVB8F1JDzmqGRn+NGU2PSTW42k9ajTWAwW0gxppMU0/x/iEwVDQap91ZGAVOUNPyq9lVR6K6n2VVPjq6HaV43L56LGX3Nsmb8aAG/Qi7fOS2ldC9M4tJHNYCPJmoTT7CTRmkiMMQabwYbVYMVqsGIzHve6fvlJy4zh10adXAnZlKhfBfbyyy8zf/58/vSnPzF16lRWrlzJv/71L3bt2kVqaipXXXUV/fv3Z9myZUD4MvjzzjuP5cuX893vfpeXXnqJ3//+95HL4Gtqali8eDFz584lLS2N/fv3c/fdd1NdXc23337bqq4uuQxeiM4XCoWo2LmDo599QtHOHZQUHqXC48bT1I1aAWMghKZs+AxJeM39wZSB1ZCOqYlxRQAxceb6VqKYSItRXJoNfTPld7qAL9x9VpEXbkGqyDv2KM8DX3XL2xttTQcjaT3qsYKhILWB2sYBqT4YVfuOPWr9tbj9bmr8NdT6axs9ewNe/CF/q6+eaw+jzthkQLIYLFgNVix6CxZD/UNfv6yJ92a9ObK+2RB+bdabI61YzVFK4Ql6sBq6/ne41wyCbvDkk09GJkIcP348f/jDH5g2bRoA559/PpmZmaxatSqy/iuvvMJvf/vbyESIDz30UGQixLq6Oi677DK+/vprKisr6devHxdffDG/+93vSE1NbVV9JAAJ0X1cebkc/WQjhdu/oeTIYSrc1dToaLo1RCnMAY2QFovXmErAPAC9aQA2XRJaE90FOr1GfHpMpJUosT4c2Rym7r1SSKnwTWYbglH58QGpvvXoVFdFxfZrPiBJ61GvFwwF8Yf8kavj9lfup9pfTV2gjrK6MuoCdbj97vBzIPwcee2vO/b+uHW6MlSdSK/pMeqMGHQG9Do9Bi38bNQZqQvUUe4pJy0mjUxHJim2FGJNsUxPn855Ged1aj16XQDqaSQACRFdnooK8j/7lKJt31B6MJfy8lKq/F78zYz90YUUxqCeoC4enymNoGkAZtMAjJqjyaBjijGQPMBOQj87CekxJKTbiE+LwRobpcGskdajE1qOOtx6NLi+9cjSlbUXPZBSCn/I32QwanjvCXrwBMKPumBd5HXDoPPj3zd6Pu51W6/SO951Y67jtom3deJRSwDqMAlAQvQ8SimqDx2k4MvPKd65ndIjh6moKqcqGDjpnmcN9EGFPmQmYEjEb+qPZhqA2ZCOXtd0U7zRZiAhPYakfjHEp8eQkB5DXKoNe5y58y/Tb62G1qPy3CYCUgdajxoGasckS+uRaJfjQ5Yn4CGgAgRCAYKhYKPXADGmGPZX7qfGV0NJXQmegIfJqZM5q/9ZnVonCUAdJAFIiN4jGAxQvmsnhV99RcneXZTlH6GixkUNIVQzX+zGAGjE4DckEjClo5n6YdWnoumavqeYzqARm2wlqZ+d+FQbcfWP+FQbJmuUZxPp9NajwSeMPZLWI9F7SADqIAlAQvR+fq+Xkq83U7T1a4r37aG8uJBKdy3uFsZE64OgYSWoTyBgSgVDGhZDKjqds8kxRgAmu5GENBsJaTGNglFskqX7BmA3R6nwTNlNDcyuyIOqI3CqLoxI69EgcGaAc0D9IwOc/cF08s1zhYgWCUAdJAFIiNOXp6qSwi+/oOjbrZQdzKWitBiXpy4cjJppMdKUQh8yEtJiCRqTCRpSMBjTMOuTQGv61h6aDmKTrJFgFG45shKXGoM11tgzbtfQVOtReW64a60iF3w1py7DmnBcIBpwQkAaAPZUueea6DYSgDpIApAQfY+3vJzir76geMd2yg7lhYORu5YaLUSohS9wfQg0ZSGojyNoSEQZUzAZkjHo4kCLaTLo6E06HElW4pKtOJOtOJKsOJKtOJOsxCZY0Bt7QGBoqvXIdTTcalR1BCoPn7p7DUBnDM/GfVJAOu5hju3qoxF9hASgDpIAJIRoEPL5KN+xjZJvtlK2fx8VhflUVVXg8vuo02stDiDWFOiUmZDOiTIkgCEZgz4RnT4OTedA05oeP2RxmohPsRKXbKsPRxYcSeGAZLH3kNYjAE/VsUBUdfi41/UPVz605lJsi7P5FiTnALCnhWfvFuIUJAB1kAQgIURreMvLKfl6C6W7dlB+KI+qkiKqa6qpCfipM+havrpKgU4ZQWcnpI9DGRLR65Mw6OPRdHGgWZoMOjqTDnuihYQUG3E9tfWoQTAANYUnB6PjQ5On8tTlaPpj93WLTQvPqN3Us9khV7T1cRKAOkgCkBCio3xlZZRv+5ayPbuoOJRHVVERLlclNT4PtTqN4CkGSGshDZ1mjbQeafokDIYkNJ0TTReLpumb3M7kMOJIspKUaiM2MRyKYhMtxCZYsMeb0Rt6UEAC8FZD1dFmWpEOh7vdQoHWlWWMOSEY1T/sqeHJImNSwq+t8TIu6TQlAaiDJAAJIbpS0O3GtXsXZTt3UHFgPxWF+VRXlFFd56aWEB7jKbp7FOiVEbQYQnoHyhCPTh+PXucIhyOdHTRb05NAxhqJTbSQkGQNB6TEcDBqCEgmq6HndLEBhIJQUxwOQ9UFUF148rOrALxVrS9TZ6gPQ8knhKOU8KBuW0L9c3z42eKUlqVeQgJQB0kAEkJEiwoEqDt8mPKdOyjfv5fKo4epKi3BVeOi1u+jVkeLg7KPFaShwww6O0rvQNPHoTsuIGm62PqQ1LgsnUmH1WnGmWghLsmKPd6MPd6CPcGMPc5MjNOM0aLvWSEJwFdbH4pOCEg1RfWP4vCjrrztZWv6cKtRJBglHgtHkWVNPOvlJqTdTQJQB0kAEkL0VEGPh6o9uynbvRPXwYO4CguoqSyntqaaWr+XOhXCa9C3rsVCgaZZQBcbHpStj4uEo2MhKeakkKQZNSyxJuxxZpwJlnAwijNjc5qIcYZDUkycGaO56W66qAr4oLbkWCiqLT7udUn4yre6cnBXhJ/97vbvyxQbDkIthSRrfH2gql9mipHWpg6QANRBEoCEEL2VCoXwlRRTtXcfroMHqDpyBFdxIbUVFdS4a3D7PNQphdeob3am7MYFHgtJ6Bzo9Ce2ItnDr5sYk6Qz6bA5TcTGW4iNN0fCkc1pIiau4b0Jg6kHBqUGfk99IGoIRmUnh6TI+/rnukpOOcFkc/SmprvhGrU+1b+2xoPFER78bbRKcEICUIdJABJCnM5UMIivuITqA/uozD2A68hhqouLqK4sp7a2BrfPSx0hPAYDqjX3QFOgaSY0LQalc6DpneGgpNWPR2oITM1c9q+36LE5TMQmWHDEmbHFhYNRQ0uSzWkixmHuWVe4tSQUDE8R4K4PTE2FJHd5+B5vx78Petu/T50xPJ9SQyCyOOufHS08Oxu/N9p6fYiSANRBEoCEEH2dCgTwFxfj2r+Pqrxcqo4cpqakmOqKcmprq+tDksJjNDR7M9oT6ZQeDQtKFwP6WDS9oz4YxYAuBk2zhe/HplmbvPWI3qLH7DAS4wx3vTnizNgcZqyxRqyxpvqHEavdiC7atyFpK6XC3W2NWpiaCEmNWpoqwlfRnepmuK2l6VsOSKcKUGZH1LvwJAB1kAQgIYQ4NeX34y8qoubQQaoOHcSVf5TqkmJqKsupqanG7fXgDgaoa+3A7UjBoGFC01lBqw9LOnt9V5w1/KxZ0Y5/fUIXnGbWYYoxYok1YneYccabsTvNx0JSrAlb/esed+VbWygVvmWJxwVe13HPVSe8b+q56tj7TgtRunBL1EnhKLbxwxQL/SdBxpTO2W89CUAdJAFICCE6TygYxJ1/FFdeLtVHjlBTWEBNWQm1lRW4a6qp89RRF/DjVSF8+lNMINksA5pmrQ9I1khQ0jRrfVhqCErHv66/SksHeqsBU4wBi92IzW7C7jTjcIRblSx2I5YYY+TZajf27HFLbaVU+Cq6lgJSo+fqpkNWa+drajDj/8GsRZ16KG35/pa5xYUQQnQpnV6PPWMg9oyBp1w34HJRfSiP6iNHqC0soKakmNqKCtyuSjzuWrweDx6/D18ogA+OC0wBlKqGYHUbhh/rj7UkVVmo06y4dNb6WbitTbY4gQlN01B6Dc2sw2A1YLQZsMYYsTlM2B0mnA4zMbEmLDFGzDYDZpsBi82IOcaAwdgDg5Omgdkefjj6ta8MpcBf13QrlLf6hEf9srQxnXscbSQtQE2QFiAhhOj5lFIEXS7c+fnU5B/FXVyIu7QEd1kZdVVVeGqq8dS58Xg9eAN+vKEgfr0Ov17f6nFLJ9NFAhI6SytamaygmSNjmpQOMOnQmfUYLHpMDeHJbsQea8bpNBNjN2K2NYSncHAy23poeOphpAVICCHEaU/TNAxOJw6nE8eIEadcXylFqNZNoLwMT2EhtYUFuIuLcZeVUFdZQZ2rirraWjyeOrw+L95gAF99t5xfr6+/fUkIlBul3OGXra6s5bjxSmbQzPg0E27NRJVmAs0MmglNMx33bI68BxPoNTDp0Fv0GCz1LUsxRmLsJmJjTcQ6TJitBkwWAyaLHpPVgNGiD7+3GjCa9ejaHfxOPxKAhBBC9AmapqG3x6C3x2AeOBBnK7ZRShGqqSFYWYm3tAR3YRHu8lLc5eV4XFW4XS487ho8de5w91zAhzdQH5w0CDRcjaY8KOUBKts7QxBgahSSak4ITeHXJwYp83HbmVFGM3qTAZ1Jh8Gsx2gxYLLqsViNWG0GbHYjMTH1QcpaH54sxwep8HOPu6dcO0gAEkIIIZqhaRr62Fj0sbGYMjKIbeP2AY8Hd3FR+FFSgrusFI+rEq+rGm9tNT63G1+dG5/Hi8/vxef34w8G8KsQASCg046bsNIHykfDwJX2BylDo9alYwHqxGVmNBq/b3it9CY0kwmdSYfepK8PU3rMVgMWmwFbjBFbjBF7jAmz7YRWKXP4OdrdehKAhBBCiC5isFhwDByEY+Cgdm0fCoUIuKqoKynBU1aKp7wcT0U53ioX3uoqvDU1+Nw1eNxuvHV1eL1e/PUhKqBCBFEEdBoBve64qQgCoAIoVQt0JEjpm2+BoukWqXDIMoJmwj48mWvuOL/de+8oCUBCCCFED6XT6TDFxWOKi8c59Ix2lRHy+QhVV+MrL8dbXkZdWRneygo8lZV4XVV4a6rx1dTg89Th8Xjw+Xz4/L5wiAoFCSgVbo3SawR0uvqxUABBUHUoVRfZV1vClGfrEOD8dh1TZ5AAJIQQQpzGdCYTusREDImJ2BhKfDvLCfl8hGprCVTX4K0obxyiqqvx1lTjra0Jd+nV1eH1hFukfH4//oCfQCiEv75VKqhBemonTb7YThKAhBBCCHFKOpMJncmEIT4ey8CMDpcX7Vl4ev8wbiGEEEL0OtG+/YgEICGEEEL0ORKAhBBCCNHnSAASQgghRJ8jAUgIIYQQfY4EICGEEEL0ORKAhBBCCNHnSAASQgghRJ8jAUgIIYQQfY4EICGEEEL0ORKAhBBCCNHnSAASQgghRJ8jAUgIIYQQfY4EICGEEEL0OYZoV6AnUkoB4HK5olwTIYQQQrRWw/d2w/d4SyQANaG6uhqAjIyMKNdECCGEEG1VXV2N0+lscR1NtSYm9TGhUIj8/HxiY2PRNK1Ty3a5XGRkZHD48GEcDkenlt0TyPH1fqf7MZ7uxwen/zHK8fV+XXWMSimqq6vp168fOl3Lo3ykBagJOp2OAQMGdOk+HA7HafuLDXJ8p4PT/RhP9+OD0/8Y5fh6v644xlO1/DSQQdBCCCGE6HMkAAkhhBCiz5EA1M3MZjP3338/ZrM52lXpEnJ8vd/pfoyn+/HB6X+Mcny9X084RhkELYQQQog+R1qAhBBCCNHnSAASQgghRJ8jAUgIIYQQfY4EICGEEEL0ORKAutFTTz1FZmYmFouFadOm8cUXX0S7Sq2ybNkypkyZQmxsLCkpKVx22WXs3r270Trnn38+mqY1etx4442N1jl06BDf/e53sdlspKSkcNdddxEIBLrzUJq0aNGik+o+fPjwyOcej4dbbrmFxMRE7HY7c+fOpaioqFEZPfXYGmRmZp50jJqmccsttwC97/x99NFHfP/736dfv35omsYbb7zR6HOlFAsXLiQ9PR2r1cqsWbPYu3dvo3XKy8u58sorcTgcxMXFce2111JTU9NonW+++YZzzjkHi8VCRkYGDz30UFcfWkRLx+j3+7nnnnsYM2YMMTEx9OvXj6uuuor8/PxGZTR13pcvX95onWgd46nO4dVXX31S3efMmdNonZ58Dk91fE39e9Q0jYcffjiyTk8+f635Xuisv53r169n4sSJmM1msrOzWbVqVecchBLd4qWXXlImk0k999xzavv27er6669XcXFxqqioKNpVO6XZs2er559/Xm3btk3l5OSo73znO2rgwIGqpqYmss55552nrr/+elVQUBB5VFVVRT4PBAJq9OjRatasWerrr79Wb7/9tkpKSlILFiyIxiE1cv/996tRo0Y1qntJSUnk8xtvvFFlZGSodevWqa+++kqdeeaZ6qyzzop83pOPrUFxcXGj43v//fcVoD788EOlVO87f2+//bb6zW9+o1577TUFqNdff73R58uXL1dOp1O98cYbauvWreoHP/iBGjx4sKqrq4usM2fOHDVu3Dj12WefqY8//lhlZ2erK664IvJ5VVWVSk1NVVdeeaXatm2bWr16tbJarepPf/pT1I+xsrJSzZo1S7388stq165datOmTWrq1Klq0qRJjcoYNGiQWrJkSaPzevy/22ge46nO4fz589WcOXMa1b28vLzROj35HJ7q+I4/roKCAvXcc88pTdPU/v37I+v05PPXmu+FzvjbeeDAAWWz2dTtt9+uduzYoZ544gml1+vVmjVrOnwMEoC6ydSpU9Utt9wSeR8MBlW/fv3UsmXLolir9ikuLlaA2rBhQ2TZeeedp2677bZmt3n77beVTqdThYWFkWVPP/20cjgcyuv1dmV1T+n+++9X48aNa/KzyspKZTQa1SuvvBJZtnPnTgWoTZs2KaV69rE157bbblNDhgxRoVBIKdW7z9+JXy6hUEilpaWphx9+OLKssrJSmc1mtXr1aqWUUjt27FCA+vLLLyPrvPPOO0rTNHX06FGllFJ//OMfVXx8fKPju+eee9SwYcO6+IhO1tQX6Im++OILBaiDBw9Glg0aNEg99thjzW7TU46xuQB06aWXNrtNbzqHrTl/l156qbrwwgsbLest50+pk78XOutv5913361GjRrVaF/z5s1Ts2fP7nCdpQusG/h8PjZv3sysWbMiy3Q6HbNmzWLTpk1RrFn7VFVVAZCQkNBo+T//+U+SkpIYPXo0CxYswO12Rz7btGkTY8aMITU1NbJs9uzZuFwutm/f3j0Vb8HevXvp168fWVlZXHnllRw6dAiAzZs34/f7G5274cOHM3DgwMi56+nHdiKfz8c//vEPfvGLXzS62W9vPn/Hy83NpbCwsNE5czqdTJs2rdE5i4uLY/LkyZF1Zs2ahU6n4/PPP4+sc+6552IymSLrzJ49m927d1NRUdFNR9N6VVVVaJpGXFxco+XLly8nMTGRCRMm8PDDDzfqXujpx7h+/XpSUlIYNmwYN910E2VlZZHPTqdzWFRUxH/+8x+uvfbakz7rLefvxO+FzvrbuWnTpkZlNKzTGd+dcjPUblBaWkowGGx0kgFSU1PZtWtXlGrVPqFQiF//+tecffbZjB49OrL8Zz/7GYMGDaJfv35888033HPPPezevZvXXnsNgMLCwiaPv+GzaJo2bRqrVq1i2LBhFBQUsHjxYs455xy2bdtGYWEhJpPppC+V1NTUSL178rE15Y033qCyspKrr746sqw3n78TNdSnqfoef85SUlIafW4wGEhISGi0zuDBg08qo+Gz+Pj4Lql/e3g8Hu655x6uuOKKRjeW/O///m8mTpxIQkICn376KQsWLKCgoIBHH30U6NnHOGfOHH70ox8xePBg9u/fz//8z/9wySWXsGnTJvR6/Wl1Dl944QViY2P50Y9+1Gh5bzl/TX0vdNbfzubWcblc1NXVYbVa211vCUCiTW655Ra2bdvGxo0bGy2/4YYbIq/HjBlDeno6M2fOZP/+/QwZMqS7q9kml1xySeT12LFjmTZtGoMGDeJf//pXh/5x9VR//etfueSSS+jXr19kWW8+f32d3+/npz/9KUopnn766Uaf3X777ZHXY8eOxWQy8ctf/pJly5b1+NssXH755ZHXY8aMYezYsQwZMoT169czc+bMKNas8z333HNceeWVWCyWRst7y/lr7nuhp5MusG6QlJSEXq8/afR7UVERaWlpUapV291666289dZbfPjhhwwYMKDFdadNmwbAvn37AEhLS2vy+Bs+60ni4uI444wz2LdvH2lpafh8PiorKxutc/y5603HdvDgQdauXct1113X4nq9+fw11Kelf29paWkUFxc3+jwQCFBeXt6rzmtD+Dl48CDvv/9+o9afpkybNo1AIEBeXh7QO46xQVZWFklJSY1+J0+Hc/jxxx+ze/fuU/6bhJ55/pr7Xuisv53NreNwODr8H1QJQN3AZDIxadIk1q1bF1kWCoVYt24d06dPj2LNWkcpxa233srrr7/OBx98cFKTa1NycnIASE9PB2D69Ol8++23jf5gNfzBHjlyZJfUu71qamrYv38/6enpTJo0CaPR2Ojc7d69m0OHDkXOXW86tueff56UlBS++93vtrhebz5/gwcPJi0trdE5c7lcfP75543OWWVlJZs3b46s88EHHxAKhSLhb/r06Xz00Uf4/f7IOu+//z7Dhg3rEV0nDeFn7969rF27lsTExFNuk5OTg06ni3Qd9fRjPN6RI0coKytr9DvZ288hhFtkJ02axLhx4065bk86f6f6Xuisv53Tp09vVEbDOp3y3dnhYdSiVV566SVlNpvVqlWr1I4dO9QNN9yg4uLiGo1+76luuukm5XQ61fr16xtdjul2u5VSSu3bt08tWbJEffXVVyo3N1e9+eabKisrS5177rmRMhoud7z44otVTk6OWrNmjUpOTu4Rl4rfcccdav369So3N1d98sknatasWSopKUkVFxcrpcKXcg4cOFB98MEH6quvvlLTp09X06dPj2zfk4/teMFgUA0cOFDdc889jZb3xvNXXV2tvv76a/X1118rQD366KPq66+/jlwBtXz5chUXF6fefPNN9c0336hLL720ycvgJ0yYoD7//HO1ceNGNXTo0EaXUFdWVqrU1FT185//XG3btk299NJLymazddtl8C0do8/nUz/4wQ/UgAEDVE5OTqN/lw1Xz3z66afqscceUzk5OWr//v3qH//4h0pOTlZXXXVVjzjGlo6vurpa3XnnnWrTpk0qNzdXrV27Vk2cOFENHTpUeTyeSBk9+Rye6ndUqfBl7DabTT399NMnbd/Tz9+pvheU6py/nQ2Xwd91111q586d6qmnnpLL4HujJ554Qg0cOFCZTCY1depU9dlnn0W7Sq0CNPl4/vnnlVJKHTp0SJ177rkqISFBmc1mlZ2dre66665G88gopVReXp665JJLlNVqVUlJSeqOO+5Qfr8/CkfU2Lx581R6eroymUyqf//+at68eWrfvn2Rz+vq6tTNN9+s4uPjlc1mUz/84Q9VQUFBozJ66rEd791331WA2r17d6PlvfH8ffjhh03+Ts6fP18pFb4U/r777lOpqanKbDarmTNnnnTcZWVl6oorrlB2u105HA51zTXXqOrq6kbrbN26Vc2YMUOZzWbVv39/tXz58u46xBaPMTc3t9l/lw1zO23evFlNmzZNOZ1OZbFY1IgRI9Tvf//7RgEimsfY0vG53W518cUXq+TkZGU0GtWgQYPU9ddff9J/GHvyOTzV76hSSv3pT39SVqtVVVZWnrR9Tz9/p/peUKrz/nZ++OGHavz48cpkMqmsrKxG++gIrf5AhBBCCCH6DBkDJIQQQog+RwKQEEIIIfocCUBCCCGE6HMkAAkhhBCiz5EAJIQQQog+RwKQEEIIIfocCUBCCCGE6HMkAAkhhBCiz5EAJIQQTcjMzGTlypXRroYQootIABJCRN3VV1/NZZddBsD555/Pr3/9627b96pVq4iLiztp+ZdffskNN9zQbfUQQnQvQ7QrIIQQXcHn82Eymdq9fXJycifWRgjR00gLkBCix7j66qvZsGEDjz/+OJqmoWkaeXl5AGzbto1LLrkEu91OamoqP//5zyktLY1se/7553Prrbfy61//mqSkJGbPng3Ao48+ypgxY4iJiSEjI4Obb76ZmpoaANavX88111xDVVVVZH+LFi0CTu4CO3ToEJdeeil2ux2Hw8FPf/pTioqKIp8vWrSI8ePH8/e//53MzEycTieXX3451dXVXftDE0K0iwQgIUSP8fjjjzN9+nSuv/56CgoKKCgoICMjg8rKSi688EImTJjAV199xZo1aygqKuKnP/1po+1feOEFTCYTn3zyCc888wwAOp2OP/zhD2zfvp0XXniBDz74gLvvvhuAs846i5UrV+JwOCL7u/POO0+qVygU4tJLL6W8vJwNGzbw/vvvc+DAAebNm9dovf379/PGG2/w1ltv8dZbb7FhwwaWL1/eRT8tIURHSBeYEKLHcDqdmEwmbDYbaWlpkeVPPvkkEyZM4Pe//31k2XPPPUdGRgZ79uzhjDPOAGDo0KE89NBDjco8fjxRZmYmDzzwADfeeCN//OMfMZlMOJ1ONE1rtL8TrVu3jm+//Zbc3FwyMjIA+Nvf/saoUaP48ssvmTJlChAOSqtWrSI2NhaAn//856xbt46lS5d27AcjhOh00gIkhOjxtm7dyocffojdbo88hg8fDoRbXRpMmjTppG3Xrl3LzJkz6d+/P7Gxsfz85z+nrKwMt9vd6v3v3LmTjIyMSPgBGDlyJHFxcezcuTOyLDMzMxJ+ANLT0ykuLm7TsQohuoe0AAkheryamhq+//3v8+CDD570WXp6euR1TExMo8/y8vL43ve+x0033cTSpUtJSEhg48aNXHvttfh8Pmw2W6fW02g0NnqvaRqhUKhT9yGE6BwSgIQQPYrJZCIYDDZaNnHiRP7973+TmZmJwdD6P1ubN28mFArxyCOPoNOFG7z/9a9/nXJ/JxoxYgSHDx/m8OHDkVagHTt2UFlZyciRI1tdHyFEzyFdYEKIHiUzM5PPP/+cvLw8SktLCYVC3HLLLZSXl3PFFVfw5Zdfsn//ft59912uueaaFsNLdnY2fr+fJ554ggMHDvD3v/89Mjj6+P3V1NSwbt06SktLm+wamzVrFmPGjOHKK69ky5YtfPHFF1x11VWcd955TJ48udN/BkKIricBSAjRo9x5553o9XpGjhxJcnIyhw4dol+/fnzyyScEg0EuvvhixowZw69//Wvi4uIiLTtNGTduHI8++igPPvggo0eP5p///CfLli1rtM5ZZ53FjTfeyLx580hOTj5pEDWEu7LefPNN4uPjOffcc5k1axZZWVm8/PLLnX78QojuoSmlVLQrIYQQQgjRnaQFSAghhBB9jgQgIYQQQvQ5EoCEEEII0edIABJCCCFEnyMBSAghhBB9jgQgIYQQQvQ5EoCEEEII0edIABJCCCFEnyMBSAghhBB9jgQgIYQQQvQ5EoCEEEII0ef8f9CiVOYDEPM5AAAAAElFTkSuQmCC" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# use vvag to get the losses and gradients with different random circuit instances\n", + "QAOA_vvag = K.jit(\n", + " K.vvag(QAOAansatz, argnums=0, vectorized_argnums=0), static_argnums=(1, 2, 3)\n", + ")\n", + "\n", + "params_hard = K.implicit_randn(\n", + " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", + ") # initial parameters\n", + "if type(K).__name__ == \"JaxBackend\":\n", + " opt = K.optimizer(optax.adam(1e-2))\n", + "else:\n", + " opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", + "\n", + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(2000):\n", + " loss, grads = QAOA_vvag(params_hard, hard_graph)\n", + " params_hard = opt.update(grads, params_hard) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [f\"circuit {leg}\" for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "a6b7606f", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T14:01:09.731783100Z", + "start_time": "2023-07-03T14:00:36.495805100Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Circuit #0\n", + "cost: 0.02998761646449566\n", + "max prob: 0.04241819679737091\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #1\n", + "cost: 0.034460458904504776\n", + "max prob: 0.03702807426452637\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #2\n", + "cost: 0.04517427086830139\n", + "max prob: 0.027316443622112274\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #3\n", + "cost: 0.02961093559861183\n", + "max prob: 0.04281751438975334\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #4\n", + "cost: 0.030255526304244995\n", + "max prob: 0.042135994881391525\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #5\n", + "cost: 0.029639022424817085\n", + "max prob: 0.04278436675667763\n", + "bit strings: ['000000111111']\n", + "\n" + ] + } + ], + "source": [ + "# print QAOA results\n", + "for num_circuit in range(ncircuits):\n", + " print(f\"Circuit #{num_circuit}\")\n", + " c = QAOAansatz(params=params_hard[num_circuit], g=hard_graph, return_circuit=True)\n", + " loss = QAOAansatz(params=params_hard[num_circuit], g=hard_graph)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability())\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + " print(f\"cost: {K.numpy(loss)}\\nmax prob: {max_prob}\\nbit strings: {states}\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "565dd4a7", + "metadata": {}, + "source": [ + "The probability of QAOA getting the correct solution is also very low. A very simple trick can be adopted to improve the performance of QAOA, namely quantum dropout, please refer to [following tutorials](qaoa_quantum_dropout.ipynb) or [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171)." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "89ed16e3", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2023-07-03T14:02:46.556219900Z", + "start_time": "2023-07-03T14:02:46.519177800Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", + "Python version: 3.10.11\n", + "Numpy version: 1.23.5\n", + "Scipy version: 1.11.0\n", + "Pandas version: 2.0.2\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra is not installed\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: []\n", + "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", + "Jax version: 0.4.13\n", + "Jax installation doesn't support GPU\n", + "JaxLib version: 0.4.13\n", + "PyTorch version: 2.0.1\n", + "PyTorch GPU support: False\n", + "PyTorch GPUs: []\n", + "Cupy is not installed\n", + "Qiskit version: 0.24.1\n", + "Cirq version: 1.1.0\n", + "TensorCircuit version 0.10.0\n" + ] + } + ], + "source": [ + "tc.about()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/qaoa_portfolio_optimization.ipynb b/docs/source/tutorials/qaoa_portfolio_optimization.ipynb deleted file mode 100644 index 7f390853..00000000 --- a/docs/source/tutorials/qaoa_portfolio_optimization.ipynb +++ /dev/null @@ -1,602 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", - "metadata": {}, - "source": [ - "# Solving QUBO problems using QAOA\n", - "\n", - "## Overview\n", - "\n", - "Here we show how to solve a quadratic unconstrained binary optimization (QUBO) problem using QAOA. Later on below we will extend this to show how to solve binary Markowitz portfolio optimization problems.\n", - "\n", - "Consider minimizing the following 2x2 QUBO objective function:\n", - "\n", - "$\\begin{pmatrix}x_1 & x_2\\end{pmatrix}\\begin{pmatrix}-5& -2 \\\\-2 & 6\\end{pmatrix}\\begin{pmatrix}x_1\\\\x_2\\end{pmatrix} = -5x_1^2 -4x_1x_2 +6x_2^2$\n", - "\n", - "Clearly this is minimized at $(x_1,x_2) = (1,0)$, with corresponding objective function value of $-5$\n", - "\n", - "We first convert this to an Ising Hamiltonian by mapping $x_i\\rightarrow \\frac{I-Z_i}{2}$\n", - "\n", - "This gives\n", - "\n", - "$$-\\frac{5}{4}(I-Z_1)^2 -\\frac{4}{4}(I-Z_1)(I-Z_2) + \\frac{6}{4}(I-Z_2)^2 $$\n", - "\n", - "which simplifies to\n", - "\n", - "$$-\\frac{1}{2}I +\\frac{7}{2}Z_1 -2Z_2 -Z_1Z_2$$ \n", - "\n", - "The $-I/2$ term is simply a constant offset, so we can solve the problem by finding the minimum of \n", - "\n", - "$$\\langle \\psi | \\frac{7}{2}Z_1 -2Z_2 -Z_1Z_2 |\\psi\\rangle$$ \n", - "\n", - "Note that the minimum should correspond to the computational basis state $|10\\rangle$, and the corresponding true objective function value should be $-4.5$ (ignoring the offset value of $-1/2$)" - ] - }, - { - "cell_type": "markdown", - "id": "8176aa81", - "metadata": {}, - "source": [ - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "45964c1f", - "metadata": {}, - "outputs": [], - "source": [ - "import tensorcircuit as tc\n", - "import numpy as np\n", - "import tensorflow as tf\n", - "import matplotlib.pyplot as plt\n", - "from functools import partial" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "4006848a-1a2f-407a-9f80-63e75ea0d3a4", - "metadata": {}, - "outputs": [], - "source": [ - "# we first manually encode the terms (-7/2) Z_1 - 2 Z_2 - Z_1Z_2 as:\n", - "pauli_terms = [\n", - " [1, 0],\n", - " [0, 1],\n", - " [1, 1],\n", - "] # see the TensorCircuit whitepaper for 'pauli structures'\n", - "weights = [7 / 2, -2, -1]\n", - "\n", - "# see below for a function to generate the pauli terms and weights from the QUBO matrix" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d197cf4a-1bad-4470-a846-998bfe68ba3c", - "metadata": {}, - "outputs": [], - "source": [ - "# Now we define the QAOA ansatz of depth nlayers\n", - "def QAOA_from_Ising(params, nlayers, pauli_terms, weights):\n", - " nqubits = len(pauli_terms[0])\n", - " c = tc.Circuit(nqubits)\n", - " for i in range(nqubits):\n", - " c.h(i)\n", - " for j in range(nlayers):\n", - " for k in range(len(pauli_terms)):\n", - " term = pauli_terms[k]\n", - " index_of_ones = []\n", - " for l in range(len(term)):\n", - " if term[l] == 1:\n", - " index_of_ones.append(l)\n", - " if len(index_of_ones) == 1:\n", - " c.rz(index_of_ones[0], theta=2 * weights[k] * params[2 * j])\n", - " elif len(index_of_ones) == 2:\n", - " c.exp1(\n", - " index_of_ones[0],\n", - " index_of_ones[1],\n", - " unitary=tc.gates._zz_matrix,\n", - " theta=weights[k] * params[2 * j],\n", - " )\n", - " else:\n", - " raise ValueError(\"Invalid number of Z terms\")\n", - "\n", - " for i in range(nqubits):\n", - " c.rx(i, theta=params[2 * j + 1]) # mixing terms\n", - " return c" - ] - }, - { - "cell_type": "markdown", - "id": "cb38c120-500a-44cc-96ec-fb5ceb11032d", - "metadata": {}, - "source": [ - "For a general state that is the output of a quantum circuit c, we first define the corresponding loss with respect to the Ising Hamiltonian." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "88cec9cf-3ab6-4a4c-b743-ed95ee8c3817", - "metadata": {}, - "outputs": [], - "source": [ - "def Ising_loss(c, pauli_terms, weights):\n", - " loss = 0.0\n", - " for k in range(len(pauli_terms)):\n", - " term = pauli_terms[k]\n", - " index_of_ones = []\n", - "\n", - " for l in range(len(term)):\n", - " if term[l] == 1:\n", - " index_of_ones.append(l)\n", - "\n", - " if len(index_of_ones) == 1:\n", - " delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]])\n", - "\n", - " else:\n", - " delta_loss = weights[k] * c.expectation_ps(\n", - " z=[index_of_ones[0], index_of_ones[1]]\n", - " )\n", - "\n", - " loss += delta_loss\n", - "\n", - " return K.real(loss)" - ] - }, - { - "cell_type": "markdown", - "id": "30a3aa96-7823-4337-9b2f-5170502bb893", - "metadata": {}, - "source": [ - "For the particular case of a circuit corresponding to a QAOA ansatz this is:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "26e4bec2-ce5b-4d0d-9e06-c80fda20619f", - "metadata": {}, - "outputs": [], - "source": [ - "def QAOA_loss(nlayers, pauli_terms, weights, params):\n", - " c = QAOA_from_Ising(params, nlayers, pauli_terms, weights)\n", - " return Ising_loss(c, pauli_terms, weights)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ca8b7a76-5c4f-4ad8-9173-90126b8bb93b", - "metadata": {}, - "outputs": [], - "source": [ - "K = tc.set_backend(\"tensorflow\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d5b1897f-cd77-4cd3-bd3b-ece64e6004fc", - "metadata": {}, - "outputs": [], - "source": [ - "def QAOA_solve(pauli_terms, weights, nlayers, iterations):\n", - " print_every = 100\n", - " learning_rate = 1e-2\n", - "\n", - " loss_val_grad = K.value_and_grad(partial(QAOA_loss, nlayers, pauli_terms, weights))\n", - " loss_val_grad_jit = K.jit(loss_val_grad)\n", - "\n", - " opt = K.optimizer(tf.keras.optimizers.Adam(learning_rate))\n", - "\n", - " params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5)\n", - " print(f\"initial params: {params}\")\n", - " for i in range(iterations):\n", - " loss, grads = loss_val_grad_jit(params)\n", - " if i % print_every == 0:\n", - " print(K.numpy(loss))\n", - " params = opt.update(grads, params)\n", - "\n", - " return params" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "2bc533da-b4f2-4ffb-b486-c65880a30a6d", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "initial params: [ 0.39931756 -0.49578992 -0.22545011 -0.40585193]\n", - "-2.1728685\n", - "-4.177884\n", - "-4.2291102\n", - "-4.2291365\n", - "-4.229136\n" - ] - } - ], - "source": [ - "iterations = 500\n", - "nlayers = 2\n", - "final_params = QAOA_solve(pauli_terms, weights, nlayers, iterations)" - ] - }, - { - "cell_type": "markdown", - "id": "e93d8cbe-2884-4f0a-80f8-3b600194927b", - "metadata": {}, - "source": [ - "We note that for nlayers=2 and 500 iterations, the objective function does not in this case (although it depends on the initial parameters)converge to the true value of $-4.5$. However, the we see below that the final wavefunction does have large overlap with the desired state $|10\\rangle$, so measuring the output of the QAOA algorithm will, with high probability, output the correct answer." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "294ea9ce-5064-4176-94d0-8dbb7d1707f8", - "metadata": {}, - "outputs": [], - "source": [ - "def print_output(c):\n", - " n = c._nqubits\n", - " N = 2**n\n", - " x_label = r\"$\\left|{0:0\" + str(n) + r\"b}\\right>$\"\n", - " labels = [x_label.format(i) for i in range(N)]\n", - " plt.bar(range(N), c.probability())\n", - " plt.xticks(range(N), labels, rotation=70);" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "fc1353ab-7a7a-4cdc-931c-3b90417c4961", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGwCAYAAAB7MGXBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAdrklEQVR4nO3df3DX9X3A8VcSIAEx0UpJhKamFVv1kGChpqCt/SMVN0bLRk/OUqGs02urzhrdlVgkqB3RbuXoTVqunuy6cx70x3Q/YNQay7UrdMzgDp2KqxaJ2oSgZxLiSJZ8v/ujIy4jKF8E33y/PB53+YNPPp/knXvlQ575fD/fb4qy2Ww2AAASKU69AADg1CZGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgqVGpF3A0MplMvPLKK3H66adHUVFR6uUAAEchm81GT09PTJo0KYqLj3z9Iy9i5JVXXonq6urUywAAjkFbW1u8733vO+L78yJGTj/99Ij43RdTXl6eeDUAwNHo7u6O6urqoZ/jR5IXMXLooZny8nIxAgB55u1usXADKwCQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgqVGpFwCQq5plm1Iv4ZS15+65qZdAAXJlBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFLHFCNr166NmpqaKCsri7q6utixY8db7r9mzZr48Ic/HGPHjo3q6uq4+eab4+DBg8e0YACgsOQcIxs3boyGhoZoamqKnTt3Rm1tbcyZMyf27ds34v4PPvhgLFu2LJqamuKZZ56J+++/PzZu3Bi33XbbO148AJD/co6R1atXx7XXXhtLly6NCy+8MNatWxfjxo2L9evXj7j/tm3b4tJLL43Pfe5zUVNTE1dccUVcffXVb3s1BQA4NeQUI/39/dHa2hr19fVvfoDi4qivr4/t27ePeMzs2bOjtbV1KD5eeOGF2Lx5c/z+7//+ET9PX19fdHd3D3sDAArTqFx23r9/fwwODkZlZeWw7ZWVlfHss8+OeMznPve52L9/f1x22WWRzWZjYGAgvvSlL73lwzTNzc1xxx135LI0ACBPnfBn02zdujVWrVoV3/nOd2Lnzp3xd3/3d7Fp06a46667jnhMY2NjdHV1Db21tbWd6GUCAInkdGVkwoQJUVJSEh0dHcO2d3R0RFVV1YjH3H777XHNNdfEn/zJn0RExEUXXRS9vb1x3XXXxde//vUoLj68h0pLS6O0tDSXpQEAeSqnKyNjxoyJGTNmREtLy9C2TCYTLS0tMWvWrBGPeeONNw4LjpKSkoiIyGazua4XACgwOV0ZiYhoaGiIJUuWxMyZM+OSSy6JNWvWRG9vbyxdujQiIhYvXhyTJ0+O5ubmiIiYN29erF69Oi6++OKoq6uLX//613H77bfHvHnzhqIEADh15RwjCxcujM7OzlixYkW0t7fH9OnTY8uWLUM3te7du3fYlZDly5dHUVFRLF++PF5++eV473vfG/PmzYs///M/P35fBQCQt4qyefBYSXd3d1RUVERXV1eUl5enXg6QWM2yTamXcMrac/fc1Esgjxztz29/mwYASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJDUMcXI2rVro6amJsrKyqKuri527Njxlvu//vrrcf3118fZZ58dpaWl8aEPfSg2b958TAsGAArLqFwP2LhxYzQ0NMS6deuirq4u1qxZE3PmzIndu3fHxIkTD9u/v78/PvWpT8XEiRPjRz/6UUyePDlefPHFOOOMM47H+gGAPJdzjKxevTquvfbaWLp0aURErFu3LjZt2hTr16+PZcuWHbb/+vXr47XXXott27bF6NGjIyKipqbmna0aACgYOT1M09/fH62trVFfX//mBygujvr6+ti+ffuIx/zDP/xDzJo1K66//vqorKyMqVOnxqpVq2JwcPCIn6evry+6u7uHvQEAhSmnGNm/f38MDg5GZWXlsO2VlZXR3t4+4jEvvPBC/OhHP4rBwcHYvHlz3H777fGtb30rvvGNbxzx8zQ3N0dFRcXQW3V1dS7LBADyyAl/Nk0mk4mJEyfG9773vZgxY0YsXLgwvv71r8e6deuOeExjY2N0dXUNvbW1tZ3oZQIAieR0z8iECROipKQkOjo6hm3v6OiIqqqqEY85++yzY/To0VFSUjK07YILLoj29vbo7++PMWPGHHZMaWlplJaW5rI0ACBP5XRlZMyYMTFjxoxoaWkZ2pbJZKKlpSVmzZo14jGXXnpp/PrXv45MJjO07bnnnouzzz57xBABAE4tOT9M09DQEPfdd198//vfj2eeeSa+/OUvR29v79CzaxYvXhyNjY1D+3/5y1+O1157LW666aZ47rnnYtOmTbFq1aq4/vrrj99XAQDkrZyf2rtw4cLo7OyMFStWRHt7e0yfPj22bNkydFPr3r17o7j4zcaprq6On/zkJ3HzzTfHtGnTYvLkyXHTTTfF1772teP3VQAAeasom81mUy/i7XR3d0dFRUV0dXVFeXl56uUAidUs25R6CaesPXfPTb0E8sjR/vz2t2kAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASOqYYmTt2rVRU1MTZWVlUVdXFzt27Diq4zZs2BBFRUUxf/78Y/m0AEAByjlGNm7cGA0NDdHU1BQ7d+6M2tramDNnTuzbt+8tj9uzZ0/ceuut8fGPf/yYFwsAFJ6cY2T16tVx7bXXxtKlS+PCCy+MdevWxbhx42L9+vVHPGZwcDAWLVoUd9xxR3zwgx98RwsGAApLTjHS398fra2tUV9f/+YHKC6O+vr62L59+xGPu/POO2PixInxxS9+8dhXCgAUpFG57Lx///4YHByMysrKYdsrKyvj2WefHfGYf/mXf4n7778//v3f//2oP09fX1/09fUN/bu7uzuXZQIAeeSEPpump6cnrrnmmrjvvvtiwoQJR31cc3NzVFRUDL1VV1efwFUCACnldGVkwoQJUVJSEh0dHcO2d3R0RFVV1WH7P//887Fnz56YN2/e0LZMJvO7TzxqVOzevTvOPffcw45rbGyMhoaGoX93d3cLEgAoUDnFyJgxY2LGjBnR0tIy9PTcTCYTLS0tccMNNxy2//nnnx9PPvnksG3Lly+Pnp6e+Pa3v33EwCgtLY3S0tJclgYA5KmcYiQioqGhIZYsWRIzZ86MSy65JNasWRO9vb2xdOnSiIhYvHhxTJ48OZqbm6OsrCymTp067PgzzjgjIuKw7QDAqSnnGFm4cGF0dnbGihUror29PaZPnx5btmwZuql17969UVzshV0BgKNTlM1ms6kX8Xa6u7ujoqIiurq6ory8PPVygMRqlm1KvYRT1p6756ZeAnnkaH9+u4QBACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABI6phiZO3atVFTUxNlZWVRV1cXO3bsOOK+9913X3z84x+PM888M84888yor69/y/0BgFNLzjGycePGaGhoiKampti5c2fU1tbGnDlzYt++fSPuv3Xr1rj66qvjZz/7WWzfvj2qq6vjiiuuiJdffvkdLx4AyH9F2Ww2m8sBdXV18dGPfjTuvffeiIjIZDJRXV0dN954Yyxbtuxtjx8cHIwzzzwz7r333li8ePFRfc7u7u6oqKiIrq6uKC8vz2W5QAGqWbYp9RJOWXvunpt6CeSRo/35ndOVkf7+/mhtbY36+vo3P0BxcdTX18f27duP6mO88cYb8d///d/xnve854j79PX1RXd397A3AKAw5RQj+/fvj8HBwaisrBy2vbKyMtrb24/qY3zta1+LSZMmDQua/6+5uTkqKiqG3qqrq3NZJgCQR97VZ9PcfffdsWHDhnjooYeirKzsiPs1NjZGV1fX0FtbW9u7uEoA4N00KpedJ0yYECUlJdHR0TFse0dHR1RVVb3lsX/5l38Zd999dzz66KMxbdq0t9y3tLQ0SktLc1kaAJCncroyMmbMmJgxY0a0tLQMbctkMtHS0hKzZs064nHf/OY346677ootW7bEzJkzj321AEDByenKSEREQ0NDLFmyJGbOnBmXXHJJrFmzJnp7e2Pp0qUREbF48eKYPHlyNDc3R0TEPffcEytWrIgHH3wwampqhu4tGT9+fIwfP/44fikAQD7KOUYWLlwYnZ2dsWLFimhvb4/p06fHli1bhm5q3bt3bxQXv3nB5bvf/W709/fHZz/72WEfp6mpKVauXPnOVg8A5L2cX2ckBa8zAvxfXmckHa8zQi5OyOuMAAAcb2IEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJIalXoBABARUbNsU+olnLL23D036ed3ZQQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApMQIAJCUGAEAkhIjAEBSYgQASEqMAABJiREAICkxAgAkJUYAgKTECACQlBgBAJISIwBAUmIEAEhKjAAASYkRACApMQIAJCVGAICk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mUwmRo363ZPdqqqq4p577oklS5aYbR762c9+FitXroxf/OIXztsC5Zx958RIHvqP//iP+Nu//dvYvHlzlJeXxznnnBOLFy+OT33qU6mXxnHwf//zevLJJ2PBggWxe/duv13luaeffjo2bNgQ//RP/xTjx4933uap7NvcjOqcPTZi5CT3+uuvxxNPPBG//e1vo7+/P2bPnh0f+tCHht7f09MT48eP902fhw7Ntr29PTKZTHzsYx+Lc889d9g+fX190dnZGe973/v8fYs8NTAwECUlJcPO0Z6enhg3bpzfmAvQf/3Xf8X+/fujurraOZsDMXISOvQN/Nhjj8Xq1atj8+bN8f73vz+qqqriwIEDcf7558fChQtj7ty5MW7cON/weeStZtvb2xvnn39+LFq0KH7v934vSktLUy+XHBz6jbmzszMGBwdj4sSJw87LbDYbg4ODUVxc7HzNI283V44PMXISOvQD6yMf+UhMnz49Vq5cGaWlpdHa2hq7du2Kf/3Xf42XX345vvCFL8RXvvKV1MslB2ZbuA7N9g//8A+jq6srFi5cGJdddlmcc845MX78+GH7Pv300zEwMDDsab+cnHKZ6zPPPBP9/f1RW1ubaLV5LMEzeDgKr7zySvaMM87I/uY3vznsfc8991y2sbExW1RUlH3ggQfe/cXxjpht4XrppZeyo0ePzs6ePTtbWlqaraioyF511VXZH/zgB9nnn38+e/DgwWwmk8nOnz8/+41vfCObzXraZz4w1xPPtaaT1MGDB+ODH/xg/PjHPz7sfeedd16sWrUqrrvuunjkkUeiv78/wQo5VmZbeLL/e4F527ZtMWvWrHj44Yfj4MGDce+998ZLL70UCxcujE9+8pNx6623xt/8zd/E3//938dnPvOZxKvm7Zjru0eMnIQymUx84AMfiCuvvDK+//3vx49//OM4cODAYftNmTIldu3adcS/AsrJx2wL06GbU2tqauLKK68cmunnP//5+OUvfxn79++PG2+8MR599NFYunRp1NbWxtSpU71M+EnOXN897hk5ibW1tcUtt9wSDz30UMyePTuuueaa+OhHPxqjR4+O3bt3x5133hlXXXVVNDY2Dv0RJvKD2RamgYGB2LdvX0yaNGno30VFRcOeNTNlypS44YYb4qtf/arZ5glzfRekfIyIw23cuDH79NNPD9v2y1/+MrtgwYLsaaedlj3ttNOyF198cfb000/P3nTTTdkDBw5ks1mPT+YDsy1cI812cHAwOzAwkM1mfzfDgYGB7L/9279li4qKsvv27RvazsnLXN89roycRLLZbCxYsCAef/zxOOecc2LBggWxaNGieO973zu0z2OPPRa//e1vY+bMmTFlyhSvU5AnzLZw/f/ZXnXVVbFo0aJ4z3veM7TPoZcEb2tri61bt3plzjxgru8uMXKSee211+I3v/lNPPLII7Fly5Z48cUXY9q0afH5z38+PvvZzx72/Hbf+PnDbAvXSLOtra2Na665JhYsWDDs/oH+/n73AuUJc333iJGT1MDAQLz66qvx1FNPxebNm6OlpSUOHDgQn/jEJ+KP//iP47LLLhva99AI3TCVH8y2cP3/2T722GNx4MCB+OQnPxlf+MIX4tJLLx3a12zzh7meeGIkD/T19UV7e3s8/vjj8Y//+I+xffv2KCsri3nz5sXixYuHvTw8+cVsC5fZFiZzPTHESJ7p7e2NvXv3xs9//vP453/+5/jVr34VCxYsiJUrVw67/4D8Y7aFy2wLk7keP2IkT2Uymeju7o7//M//jK6urrjsssuirKws9bI4Dsy2cJltYTLXd06MAABJeQVWACApMQIAJCVGAICkxAgAkJQYAQCSEiMAQFJiBABISowAAEmJEQAgKTECACQlRgCApP4H157oSnD133MAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "c = QAOA_from_Ising(final_params, nlayers, pauli_terms, weights)\n", - "\n", - "print_output(c)" - ] - }, - { - "cell_type": "markdown", - "id": "d155c5e5-5843-4bba-9edc-595a18cb0c9a", - "metadata": {}, - "source": [ - "## General Case\n", - "\n", - "For the general QUBO case, we wish to minimize\n", - "\n", - "$$ x^T Q x$$\n", - "\n", - "where $x\\in\\{0,1\\}^n$ and $Q\\in\\mathbb{R}^{n\\times n}$ is a real symmetric matrix.\n", - "\n", - "This maps to an Ising Hamiltonian \n", - "\n", - "$$\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i 0 $: risk-appetite\n", - "* $\\Sigma \\in \\mathbb{R}^{n\\times n}$: covariance matrix of the assets\n", - "* $\\mu\\in\\mathbb{R}^n$: mean return of the assets\n", - "* $B$: budget (i.e., total number of assets out of $n$ that can be selected)\n", - "\n", - "Our first step is to convert this constrained quadratic programming problem into a QUBO. We do this by adding a penalty factor $t$ and consider the alternative problem:\n", - "\n", - "$$ \\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\mu^Tx + t(1^Tx-B)^2$$\n", - "\n", - "The variables in the linear terms $\\mu^Tx = \\mu_1 x_1 + \\mu_2 x_2+\\ldots$ can all be squared (since they are boolean variables), i.e. we can consider\n", - "\n", - "$$\\min_{x\\in\\{0,1\\}^n}\\quad q x^T \\Sigma x - \\sum_{i=1}^n\\mu_i x_i^2 + t(1^Tx-B)^2$$\n", - "\n", - "which is a QUBO defined by the matrix $Q$ \n", - "\n", - "$$ Q = q\\Sigma -\\mu\\begin{pmatrix}1 & \\\\ & 1\\\\ & & \\ddots\\end{pmatrix} + t\\begin{pmatrix}1 -2B & 1 & \\ldots & 1 \\\\\n", - "1 & 1-2B & 1 & \\ldots \\\\1 & 1 & 1-2B \\\\\n", - "\\vdots\\end{pmatrix}$$\n", - "\n", - "i.e., we wish to mimimize\n", - "\n", - "$$ x^T Q X + tB$$\n", - "\n", - "and we ignore the constant term $t B$.\n", - "We can now solve this by QAOA as above.\n", - "\n", - "Let us first define a function to convert portfolio data into a QUBO matrix:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "3080b901-fb6c-4bda-8348-c96540cbc39a", - "metadata": {}, - "outputs": [], - "source": [ - "def QUBO_from_portfolio(cov, mean, q, B, t):\n", - " # cov: n x n covariance numpy array\n", - " # mean: numpy array of means\n", - " n = cov.shape[0]\n", - " R = np.diag(mean)\n", - " S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n))\n", - "\n", - " Q = q * cov - R + t * S\n", - " return Q" - ] - }, - { - "cell_type": "markdown", - "id": "b4cdcb0e-15a2-461c-b487-084488486c67", - "metadata": {}, - "source": [ - "We can test this using the qiskit_finance package to generate some stock covariance and mean data:\n", - "\n", - "*Note that this was tested with qiskit version 0.39.3 and qiskit-finance version 0.3.4.*" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "2168c69e-73ce-4306-8a39-4ddc475acc8f", - "metadata": {}, - "outputs": [], - "source": [ - "import datetime\n", - "from qiskit_finance.data_providers import RandomDataProvider" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "6a7bc671-a496-4cd8-b954-50a280b5dd85", - "metadata": {}, - "outputs": [], - "source": [ - "num_assets = 4\n", - "seed = 123\n", - "\n", - "# Generate expected return and covariance matrix from (random) time-series\n", - "stocks = [(\"TICKER%s\" % i) for i in range(num_assets)]\n", - "data = RandomDataProvider(\n", - " tickers=stocks,\n", - " start=datetime.datetime(2016, 1, 1),\n", - " end=datetime.datetime(2016, 1, 30),\n", - " seed=seed,\n", - ")\n", - "data.run()\n", - "\n", - "mu = data.get_period_return_mean_vector()\n", - "sigma = data.get_period_return_covariance_matrix()" - ] - }, - { - "cell_type": "markdown", - "id": "f6dc53d4-7ed0-436d-aa1f-8674c56e756e", - "metadata": {}, - "source": [ - "Using this mean and covariance data, we can now define our portfolio optimization problem, convert it to a QUBO matrix, and then extract the pauli terms and weights" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "3f6edcd5-3c10-49fc-86ea-160fc6d3187e", - "metadata": {}, - "outputs": [], - "source": [ - "q = 0.5\n", - "budget = 3 # Note that in this example, there are 4 assets, but a budget of only 3\n", - "penalty = 3\n", - "\n", - "Q = QUBO_from_portfolio(sigma, mu, q, budget, penalty)\n", - "portfolio_pauli_terms, portfolio_weights, portfolio_offset = QUBO_to_Ising(Q)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "809b90fa-7047-4c88-b862-355da4f58a50", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0000: 21.006979417669037\n", - "0001: 6.006208358124514\n", - "0010: 6.006857249462996\n", - "0011: -2.994037697463167\n", - "0100: 6.007889613170697\n", - "0101: -2.992836964752989\n", - "0110: -2.992179512275861\n", - "0111: -5.9930299775811875\n", - "1000: 5.992965725313347\n", - "1001: -3.007905195444355\n", - "1010: -3.0070278423618397\n", - "1011: -6.008022650501182\n", - "1100: -3.0060506769683\n", - "1101: -6.006877116105166\n", - "1110: -6.005991201884008\n", - "1111: -3.006941528402507\n" - ] - } - ], - "source": [ - "# Brute force search over classical results for comparison before we run QAOA\n", - "for i in range(2):\n", - " for j in range(2):\n", - " for k in range(2):\n", - " for l in range(2):\n", - " x = np.array([i, j, k, l])\n", - " print(f\"{i}{j}{k}{l}: {np.dot(x,np.dot(Q,x))- portfolio_offset}\")" - ] - }, - { - "cell_type": "markdown", - "id": "b5e69a34-87dc-47b4-aeb2-3b9a03fd0974", - "metadata": {}, - "source": [ - "We see that, due to the penalty, the lowest energy solutions correspond to 0111, 1011, 1101, 1110, i.e. the portfolios with only 3 assets." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "80c1de6c-d3a4-4ea5-922a-bffb59dd1ea3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "initial params: [ 0.13778198 -0.75357753 -0.01271329 -0.5461785 -0.1501883 0.36323363]\n", - "-4.204754\n", - "-5.681799\n", - "-5.6837077\n", - "-5.6837044\n", - "-5.6837053\n", - "-5.683704\n", - "-5.6837063\n", - "-5.683709\n", - "-5.6837063\n", - "-5.683705\n" - ] - } - ], - "source": [ - "iterations = 1000\n", - "nlayers = 3\n", - "final_params = QAOA_solve(portfolio_pauli_terms, portfolio_weights, nlayers, iterations)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "8a9064e3-0c61-4d2d-baf9-bdf120c0331d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "c_final = QAOA_from_Ising(\n", - " final_params, nlayers, portfolio_pauli_terms, portfolio_weights\n", - ")\n", - "print_output(c_final)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.0" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/source/tutorials/qaoa_quantum_dropout.ipynb b/docs/source/tutorials/qaoa_quantum_dropout.ipynb new file mode 100644 index 00000000..e856d151 --- /dev/null +++ b/docs/source/tutorials/qaoa_quantum_dropout.ipynb @@ -0,0 +1,1064 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Quantum Dropout for QAOA" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Overview" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Quantum Approximation Optimization Algorithm (QAOA) is a hybrid classical-quantum algorithm used for solving the combinatorial optimization problem, which is proposed by [Farhi, Goldstone, and Gutmann (2014)](https://arxiv.org/abs/1411.4028). In the [previous tutorial](qaoa_nae3sat.ipynb), we introduced solving the [Not-all-equal 3-satisfiability (NAE3SAT)](https://en.wikipedia.org/wiki/Not-all-equal_3-satisfiability) by QAOA and the dilemma of QAOA on the hard problem. In this tutorial, we will introduce a simple trick to alleviate this dilemma, namely quantum dropout, please refer to [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171) for more details." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## NAE3SAT and Hard Problem" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Let's briefly review the NAE3SAT and the difference between the easy and hard problem.\n", + "\n", + "Let the set of clauses in the NAE3SAT be $\\mathcal{C}$. In each clause, there are three literals and each literal is represented by a spin. Spins up ($s=1$, $\\text{bit}=0$) and down ($s=-1$, $\\text{bit}=1$) represent false and true respectively. NAE3SAT requires the three spins in each clause are not all equal to each other, in other words, at least one is up, and at least one is down. The Hamiltonian of the NAE3SAT is as follows\n", + "$$\n", + "\\begin{split}\n", + " \\hat{H}_C&=\\sum_{(i,j,k)\\in\\mathcal{C}}\\left[(s_i+s_j+s_k)^2-1\\right]/2\\\\\n", + " &=\\sum_{(i,j,k)\\in\\mathcal{C}}(s_i s_j+s_j s_k+s_k s_i)+|\\mathcal{C}|,\n", + "\\end{split}\n", + "$$\n", + "where $|\\mathcal{C}|$ is the number of clauses in $\\mathcal{C}$. When all clauses are true, $\\hat{H}_C$ takes the minimum value 0, and the corresponding bit string is the solution of the NAE3SAT.\n", + "\n", + "The difference between the easy and hard problem is the energy landscape, as shown in the following figure.\n", + "\n", + "\n", + "\n", + "The global minimum is located in a large and smooth neighborhood for a simpler problem and a narrow region for a harder problem. It is worth noting that when the system size is relatively small, most of the randomly generated problems are easy, and hard problems need to be constructed with special methods, please refer to [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171)." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Quantum Dropout" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "The algorithm is shown in the following figure.\n", + "\n", + "\n", + "\n", + "We first implement the classical algorithm that can be done in polynomial time, such as simulated annealing method (SA). If the result is satisfactory, we stop the procedure since there is no point in a quantum solver. Otherwise, these failed classical results, typically low-lying excited states (local minima), offer insights as we prepare quantum dropout for QAOA: whether a clause should be kept or available for quantum dropout to underweight the distracting local minima and enhance the chances to locate the true ground state. Specifically, the clauses violated by low-lying excited states should be all kept, and the other clauses can be randomly discarded at the ratio $R$.\n", + "\n", + "Finally, we optimize the PQC with respect to the original cost function $H_C$ with a complete set of clauses to ensure the uniqueness of the global minimum. The current procedure does not incur obvious overhead to the conventional QAOA since the preliminary approaches and the quantum-dropout controls are both inexpensive on a classical computer." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Setup" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import optax\n", + "import jax.numpy as jnp\n", + "import tensorflow as tf\n", + "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from functools import partial\n", + "from IPython.display import clear_output\n", + "import random\n", + "\n", + "K = tc.set_backend(\"jax\")\n", + "\n", + "nlayers = 30 # the number of layers\n", + "ncircuits = 6 # six circuits with different initial parameters are going to be optimized at the same time\n", + "R = 0.5 # dropout ratio, 0 means no dropout, 1 means all dropout" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "We use the same NAE3SAT as the [previous tutorial](qaoa_nae3sat.ipynb)." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 2, + "outputs": [], + "source": [ + "# a hard graph instance\n", + "hard_clauses = [\n", + " [4, 1, 7],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [4, 11, 8],\n", + " [4, 1, 10],\n", + " [5, 11, 8],\n", + " [4, 1, 8],\n", + " [1, 11, 8],\n", + " [4, 1, 7],\n", + " [0, 11, 8],\n", + " [4, 1, 10],\n", + " [4, 11, 8],\n", + " [5, 0, 10],\n", + " [0, 6, 7],\n", + " [5, 0, 11],\n", + " [0, 6, 7],\n", + " [5, 0, 9],\n", + " [3, 6, 7],\n", + " [5, 0, 8],\n", + " [5, 6, 7],\n", + " [5, 0, 10],\n", + " [3, 6, 7],\n", + " [5, 0, 10],\n", + " [1, 6, 7],\n", + " [2, 4, 6],\n", + " [1, 8, 11],\n", + " [2, 4, 6],\n", + " [2, 8, 11],\n", + " [2, 4, 9],\n", + " [5, 8, 11],\n", + " [2, 4, 10],\n", + " [2, 8, 11],\n", + " [2, 4, 10],\n", + " [4, 8, 11],\n", + " [2, 4, 8],\n", + " [4, 8, 11],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [2, 11, 7],\n", + " [3, 0, 9],\n", + " [0, 11, 7],\n", + " [3, 0, 9],\n", + " [5, 11, 7],\n", + " [3, 0, 10],\n", + " [3, 11, 7],\n", + " [3, 0, 7],\n", + " [4, 11, 7],\n", + " [5, 0, 10],\n", + " [4, 0, 10],\n", + " [2, 5, 6],\n", + " [2, 11, 10],\n", + " [2, 6, 10],\n", + " [2, 4, 9],\n", + " [0, 9, 10],\n", + " [3, 0, 7],\n", + " [2, 5, 6],\n", + " [1, 10, 9],\n", + " [1, 4, 11],\n", + " [5, 10, 11],\n", + " [0, 4, 8],\n", + " [0, 9, 8],\n", + " [2, 11, 10],\n", + " [2, 8, 6],\n", + " [3, 6, 7],\n", + " [0, 8, 10],\n", + " [4, 0, 9],\n", + " [3, 5, 8],\n", + " [5, 11, 10],\n", + " [2, 11, 10],\n", + " [4, 11, 8],\n", + " [1, 3, 11],\n", + "]\n", + "cost_factor = 1 / len(hard_clauses) / 4" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.202605500Z", + "start_time": "2023-07-03T11:45:08.202029100Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 3, + "outputs": [], + "source": [ + "# convert to a NetworkX graph\n", + "def construct_graph(clauses):\n", + " graph = nx.Graph()\n", + " for i, j, k in clauses:\n", + " graph.add_edge(i, j, weight=0)\n", + " graph.add_edge(j, k, weight=0)\n", + " graph.add_edge(k, i, weight=0)\n", + " for i, j, k in clauses:\n", + " graph[i][j][\"weight\"] += 1\n", + " graph[j][k][\"weight\"] += 1\n", + " graph[k][i][\"weight\"] += 1\n", + " return graph" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.206621400Z", + "start_time": "2023-07-03T11:45:08.203172500Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 4, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot original hard graph\n", + "hard_graph = construct_graph(hard_clauses)\n", + "pos = nx.spring_layout(hard_graph)\n", + "nx.draw_networkx(hard_graph, with_labels=True, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.390560600Z", + "start_time": "2023-07-03T11:45:08.210412300Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "We first use the brutal force method (BF) to obtain the true solution." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 5, + "outputs": [], + "source": [ + "def b2s(bit):\n", + " return 1 - 2 * int(bit)\n", + "\n", + "\n", + "def energy(cfg, graph, n_cls, normalize=True):\n", + " factor = 1 / n_cls / 4\n", + " E = 0.25\n", + " for a, b in graph.edges:\n", + " E += cfg[a] * cfg[b] * graph[a][b][\"weight\"] * factor\n", + " return E if normalize else E / factor\n", + "\n", + "\n", + "def brutal_force(graph):\n", + " num_nodes, n_cls = graph.number_of_nodes(), len(hard_clauses)\n", + " min_cost, best_case = 1.0, []\n", + " for i in range(2**num_nodes):\n", + " case = f\"{bin(i)[2:]:0>{num_nodes}}\"\n", + "\n", + " cost = energy(list(map(b2s, case)), graph, n_cls)\n", + "\n", + " gap = min_cost - cost\n", + " if gap > 1e-6:\n", + " min_cost = cost\n", + " best_case = [case]\n", + " elif abs(gap) < 1e-6:\n", + " best_case.append(case)\n", + "\n", + " return best_case, min_cost" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.390560600Z", + "start_time": "2023-07-03T11:45:08.390046300Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 6, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost: 0.000\n", + "bit string: ['000000111111', '111111000000']\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# print BF results\n", + "bf_best_cases, bf_best = brutal_force(hard_graph)\n", + "print(f\"cost: {bf_best:.3f}\\nbit string: {bf_best_cases}\")\n", + "\n", + "# plot NetworkX graph\n", + "colors = [\"r\" if bf_best_cases[0][i] == \"0\" else \"c\" for i in hard_graph.nodes]\n", + "nx.draw_networkx(hard_graph, with_labels=True, node_color=colors, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.708112400Z", + "start_time": "2023-07-03T11:45:08.390560600Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then we start to execute the algorithm loop shown in the figure above. The algorithm starts from the classical method - SA." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 7, + "outputs": [], + "source": [ + "def sim_annealing(graph, t_max: int, T: float):\n", + " num_nodes, num_cls = graph.number_of_nodes(), len(hard_clauses)\n", + " state = np.random.randint(0, 2, num_nodes)\n", + " next_state = state.copy()\n", + " E = energy(1 - 2 * state, graph, num_cls, normalize=False)\n", + " t = 0\n", + " while t < t_max:\n", + " temper = (1 - t / t_max) * T\n", + " flip_idx = np.random.randint(num_nodes)\n", + " next_state[flip_idx] = 1 - next_state[flip_idx]\n", + " next_E = energy(1 - 2 * next_state, graph, num_cls, normalize=False)\n", + " if next_E <= E or np.exp(-(next_E - E) / temper) > np.random.rand():\n", + " state[flip_idx] = 1 - state[flip_idx]\n", + " E = next_E\n", + " else:\n", + " next_state[flip_idx] = 1 - next_state[flip_idx]\n", + " t += 1\n", + " return tuple(state), E" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:08.711814200Z", + "start_time": "2023-07-03T11:45:08.709702400Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 8, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "number of low-lying excited states: 23\n" + ] + } + ], + "source": [ + "# obtain the low-lying excited states\n", + "ll_excited, n_exp = set(), 100\n", + "for _ in range(n_exp):\n", + " sa_case, sa_cost = sim_annealing(hard_graph, 200, 1)\n", + " if sa_cost > 1e-6:\n", + " ll_excited.add(sa_case)\n", + "print(f\"number of low-lying excited states: {len(ll_excited)}\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:12.123684300Z", + "start_time": "2023-07-03T11:45:08.709702400Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 9, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "number of clauses should be kept: 12\n", + "number of clauses can be discarded: 60\n", + "number of clauses after dropout: 42\n" + ] + } + ], + "source": [ + "# obtain the clauses violated by low-lying excited states and the clauses can be discarded\n", + "def get_clauses(ll_exc_st, clauses):\n", + " kept, drop = [], []\n", + " for cls in clauses:\n", + " violated = False\n", + " for state in ll_exc_st:\n", + " if sum(state[i] for i in cls) in [0, 3]:\n", + " kept.append(cls)\n", + " violated = True\n", + " break\n", + " if not violated:\n", + " drop.append(cls)\n", + " return kept, drop\n", + "\n", + "\n", + "kept_clauses, drop_clauses = get_clauses(ll_excited, hard_clauses)\n", + "num_selected = int((1 - R) * len(drop_clauses))\n", + "num_after_drop = len(kept_clauses) + num_selected\n", + "driving_factor = 1 / num_after_drop / 4\n", + "print(f\"number of clauses should be kept: {len(kept_clauses)}\")\n", + "print(f\"number of clauses can be discarded: {len(drop_clauses)}\")\n", + "print(f\"number of clauses after dropout: {num_after_drop}\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:12.128858800Z", + "start_time": "2023-07-03T11:45:12.128083Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "There are two ways of quantum dropout. One isotropic or uniform, i.e., $\\hat H_{C_1} = \\hat H_{C_2} = \\cdots = \\hat H_{C_p}$. The other is random or different, i.e., $\\hat H_{C_i}\\neq\\hat H_{C_j}$ if $i\\neq j$." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Isotropic Quantum Dropout" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 10, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOyddVyU2ffHPzOkpAKKCaiASqi4u3auSAn22oWBgYW9ayc2BnaA2K2AoqIoBrZioYRBCSgg0jVzfn/4m/kyMsAAQ8l9v1683J3nPveeB2bmfu6555zLISICg8FgMBiMagu3og1gMBgMBoNRsTAxwGAwGAxGNYeJAQaDwWAwqjlMDDAYDAaDUc1hYoDBYDAYjGoOEwMMBoPBYFRzmBhgMBgMBqOaIytJIz6fjy9fvkBVVRUcDqesbWIwGAwGgyEFiAgpKSmoX78+uNyC1/8SiYEvX76gUaNGUjOOwWAwGAxG+REZGYmGDRsWeF0iMaCqqirsTE1NTTqWMRgMBoPBKFOSk5PRqFEj4TxeEBKJAcHWgJqaGhMDDAaDwWBUMYra4mcBhAwGg8FgVHOYGGAwGAwGo5rDxACDwWAwGNUcJgYYDAaDwajmMDHAYDAYDEY1h4kBBoPBYDCqOUwMMBgMBoNRzWFigMFgMBiMag4TAwwGg8FgVHOYGGAwGAwGo5rDxACDwWAwGNUcJgYYDAaDwajmMDHAYDAYDEY1h4kBBoPBYDCqOUwMMBgMBoNRzWFigMFgMBiMao5sRRvAYDAYjLIhLSsXnxPSkJ3Lh7wsF3qaylBWYF/7jPywdwWDwWD8RoTGpeDYowjcCv6KiMR0UJ5rHAA6Gkro0awORrTTgYG2akWZyahkcIiIimqUnJwMdXV1/PjxA2pqauVhF4PBYDCKQWRiOv678Bp3w+Ihw+WAxy/4q11wvYu+Ftb2N0UjDaVytJRRnkg6f7OYAQaDwajinHwSAXMXfwR8TACAQoVA3usBHxNg7uKPk08iytxGRuWGbRMwGAxGFcb1Vig2XQ8p0b08PoHHJyw8/xrxqVmY1sNAytYxqgrMM8BgMBhVlJNPIkosBH5l0/UQnGIegmoL8wwwGAxGFSQyMR3LPN8WeD0rNgxJ/h7Iin4HAFCo3xy1ethDXrtJgfcs9XyLjk21WAxBNYR5BhgMBqMK8t+F18gtIDYgKzYMcUfnIzcpFjU7DYN6p6HI+f4FsccXIichqsA+c/mE/y68LiuTGZUYJgYYDAajihEal4K7YfEFBgr+uHsUHFl51B29CWrtBkC93UDUHbURIEKSv0eB/fL4hLth8Qj7mlJWpjMqKUwMMBgMRhXj2KMIyHA5BV7PjHwLRb3WkKnxv1QyWRUNKDYyQfqHx+BnZxR4rwyXg6MPWexAdYOJAQaDwahi3Ar+Wmj6IPFywJGVz/c6R04B4OUi51t4gffy+IRbIV+lYiej6sDEAIPBYFQhUrNyEZGYXmgbOY2GyPoSDOLzhK8RLwdZX4IBALkpCYXeH5GQjrSs3NIby6gyMDHAYDAYVYjwhDQUVTZWtY0NchOjkXBlO7LjI5D97TPivbeAl/odAEC52YXeTwA+J6RJx2BGlYClFjIYDEYVIjuXX2QbVTMb5CbHI/nReaS9uQkAkK9rALX2A5EccApceUWpjMP4fWBigMFgMKoQ8rKSOXRrdRsNtXYDkPMtHFwFZcjX0cN3/8MAAFmNBlIbh/F7wMQAg8FgVCH0NJXBAYrcKgAAGUUVyDQyFv5/5udAyKhqQU6zYaH3cf5/HEb1gYkBBoPBqAJkZWXB398fXl5eIPoDUK1drPvT3t1BdkwoavUYBw6n8FW/jqYSlBXY9FCdYH9tBoPBqKR8/foVV65cgZeXF65fv47U1FTo6OhAb2AzRJAmqIBJPTPiDX7cPwHFxmbg1lBD9pf3SH11A4pN/oDqX30LHVOGy0EPwzpl8TiMSgwTAwwGg1FJICK8efMGXl5e8Pb2xsOHDwEA7dq1w7///gtLS0s8e/YM63YfBln9V2A/MqqaAJeL5Efnwc/OgGxNbdTsOgpqbfuBw5Up1AYenzCyvY5Un4tR+WFigMFgMCqQrKws3L59G97e3vDy8kJ4eDhUVFRgYWGBQ4cOwcbGBioqKti/fz/69u2LL1++YNCgQcjSlsebbzliiw/J1aoH7SGrim2LDJeDjk00oV9HVRqPxqhCMDHAYDAY5Yw497+uri7s7OxgZ2eHbt26QUFBAT9+/MCuXbvg4uKCxMREjBgxAv/++y+aN2+OyMR0mG+5DR4RwCm4NHFxkOVysLa/qVT6YlQtmBhgMBiMMiav+9/LywuPHj0CALRv3x7//vsv7OzsYGJiAs7/T+rx8fFYvXo1duzYgYyMDIwbNw7z589H48aNhX3yU76B9+Qk0GaI1Oxc2ceYHV9cTWFigMFgMMoAgftfsP8vzv1fp45ooF5MTAw2b96MPXv2gIgwefJkzJkzB/Xr1xdpFxQUBAsLC8jLy2PcREccehZfanvnWTTDkL9YrEB1hYkBBoPBkBJfv37F5cuX4e3tXaj7/1c+f/6MDRs24NChQ1BQUMCsWbMwa9YsaGlp5Wv76NEj2NjYoEGDBrh27Rrq1asHQ90ILPN8i1w+FXqA0a/IcDmQ5XKwso8xEwLVHA4RFfnOSU5Ohrq6On78+AE1NbWimjMYDEa1gIjw+vVrYfBfXve/nZ0dbG1tRdz/vxIcHAxnZ2ccO3YMNWvWhJOTExwdHaGuri62va+vL/r3749WrVrB29sbtWrVEl6LTEzHfxde425YPIjPKzRrQIbLAY9P6KKvhbX9TdnWwG+MpPM3EwMMBoNRDApy/1taWsLOzg7W1tb53P+/8vLlS6xduxZnzpxBvXr1MHfuXDg4OEBZueCqf2fOnMGIESNgbm6Os2fPQklJ/AS+brc7Nl54CKOe/yAqKfOXSoUEXU1l9DCsg5HtdVjWQDVA0vmbbRMwGAxGEQjc/4Lo/7S0NInc/7/y8OFDrFmzBt7e3mjcuDF2796NsWPHFnnv3r17MWXKFAwbNgzu7u6Qk5MrsO2TG15onhaLuwv2IC0rFzvcT2LZilVobqiPVk3rw8N5f7Gfn/H7w8QAg8Fg/ILA/S+I/n/8+DGAn+7/RYsWwc7ODsbGxgW6/3/t69atW1izZg38/PzQokULeHh4YNiwYZCVLfwrmIjg7OyMRYsWYdq0adi2bRu43IJLCefk5ODGjRuYN28eAEBZQRb6morIjglBi65mCHn7uhi/BUZ1gokBBoPBwE/3/61bt4T7/xEREUL3/5QpU2BjY4PatSU/D4CIcOXKFaxevRoPHz6EmZkZzp49i/79+xc6oQvg8/mYO3cuXFxcsGLFCixZsqRI8REQEIDk5GRYW1sLXxNsPTRp0gRXrlwBEUkkYhjVCyYGGAxGtSUuLk6k+E9aWhr09PTQt29f2NraSuz+zwuPx8P58+exdu1aBAYGomPHjrh8+TKsra0lnoRzcnIwfvx4HD16FK6urnB0dJToPh8fH9SpUwdmZmbC1wRiQFdXFykpKYiOjkbDhoWfWsiofjAxwGAwqg0Fuf87dOhQbPf/r+Tk5OD48eNwdnZGcHAwzM3NcevWLXTr1q1Y/WVkZGDIkCHw8fHBsWPHMGzYMInv9fHxgbW1tYjnQSAGBLUKgoKCmBhg5IOJAQaD8VuTmZkpEv1fWve/uP7d3d2xfv16fP78GX369MHhw4fRrl27Yvf148cP2NnZ4enTp/Dy8oKVlZXE90ZFReHVq1f47z/RA4wEYkBNTQ01atQQFixiMPLCxACDwfjtiIuLEyn+k9f9b2dnh65duxbb/f8raWlp2Lt3LzZt2oTY2FgMHjwYly5dQsuWLUvUX2xsLKysrBAREYGbN2+iQ4cOxbr/6tWr4HK56NWrl8jrghTEzMxMNG/eHEFBQSWyj/F7w8QAg8Go8hARXr16JQz+y+v+X7x4MWxtbUvs/v+VpKQkuLq6YuvWrfjx4wdGjRqFhQsXwtDQsMR9fvr0Cb169UJ6ejru3LkDExOTYvfh4+OD9u3bQ0NDQ+R1gWcgLS0NRkZGTAwwxMLEAIPBqJKUtfv/V759+wYXFxfs3LkTWVlZmDBhAubNmwddXd1S9fv69WtYWlpCWVkZ9+/fFzmMSFJ+TSnMy69igGUUMMTBxACDwagyCNz/Xl5e8PX1LRP3/69ER0dj06ZN2Lt3L7hcLqZOnYrZs2ejbt26pe47ICAAvXv3hq6uLq5duwZtbe0S95OcnAwbG5t81xQUFMDlcoVi4Pv374iLi5OK/YzfByYGGAxGpUXg/hes/n91/9vZ2cHIyKhMVrkfP37E+vXr4e7uDiUlJcybNw8zZsyApqamVPr38fHBwIED8ddff8HT07PA8wgk4cqVK9DW1kbr1q3zXeNwOFBWVkZ6ejqMjIwA/MwoYGKAkRcmBhgMRqUiMzNTWPxH4P5XVVWFpaUlpk6dCmtra6m6/38lKCgIzs7OOHHiBDQ1NbFy5UpMmTJFqueynDhxAqNHj4a1tTVOnTqFGjVqlKo/Hx8fWFlZFVjMSFlZGWlpaWjSpAnk5eURFBSEv//+u1RjMn4vmBhgMBgVTmxsrLD4jzj3f7du3SAvL1+mNrx48QJr1qzB+fPn0aBBA7i4uGD8+PEFHghUUlxdXTFjxgyMHj0aBw4cKLIkcVFERUXh9evXWLRoUYFtBGJAVlYWzZo1Y0GEjHwwMcBgMMqdvO5/QfQ/h8MpF/f/r9y/fx9r1qyBj48PmjZtin379mH06NFSFx9EhBUrVmDFihVwcnLCpk2bJCpLXBQFpRTmRSAGALCMAoZYmBhgMBjlgsD9L9j/j4yMFLr/HR0dYWNjAy0trXKxhYhw48YNrFmzBv7+/jA2NsaxY8cwePDgUq/UxcHn8zFz5ky4urpi7dq1WLhwodSEzpUrV9ChQ4d8KYV5UVJSEhEDN2/elMrYjN8HJgYYDEaZERsbKyz+I3D/N27cGP379xfW/i9r939e+Hw+vL29sWbNGjx+/Bh//vknLly4gD59+khllS6O7OxsjB07FidPnsTevXvh4OAg1b5v3LiBBQsWFNruV89AfHw8vn37VqaxF4yqBRMDDAZDaohz/3O5XHTo0AFLliyBra1tubn/88Lj8XDmzBmsXbsWr1+/RpcuXXD16lVYWFiUqS1paWkYNGgQ/Pz8cPr0aQwaNEiq/QcEBCAlJUXklEJx/CoGgJ+Bkt26dZOqPYyqCxMDDAajVFQm9/+vZGdn4+jRo1i3bh1CQ0NhaWmJnTt3okuXLmU+dmJiImxtbfHq1StcvnwZ5ubmUh/Dx8enwJTCvCgrKyMmJgYAoK+vD1lZWSYGGCIwMcBgMIqNwP0viP5PT08Xuv8FxX/K0/3/KxkZGTh06BA2bNiAiIgI9O/fH8ePH8eff/5ZLuN/+fIFlpaWiImJgZ+fH9q2bVsm4xSVUihAUGcAAOTl5WFgYMCCCBkiMDHAYDCKhIjw8uVLkeI/Avf/0qVLYWdnhxYtWlR4iduUlBTs2bMHmzdvxrdv3zBs2DD8+++/MDY2LjcbwsLCYGFhgZycHNy9exctWrQok3EiIyPx+vVrLF68uMi2ebcJAJZRwMgPEwMMBkMsmZmZ8PPzExb/Ebj/raysKtz9/yuJiYnYsWMHtm3bhtTUVIwZMwYLFiyAvr5+udoRGBgIKysr1KxZE7dv34aOjk6ZjSVJSqEAcWJg//79ZWYbo+rBxACDwRBS2d3/vxIXF4ctW7Zg165dyM3NhYODA+bOnYtGjRqVuy137tyBnZ0dDAwM4OPjU+aR+j4+PujQoQNq1apVZNu8qYXATzEQGxuLxMTEQlMSGdUHJgYYjGpMXve/l5cXnjx5Uind/78SGRmJjRs3Yv/+/ZCTk4OjoyOcnJxKfNBPafHy8sLgwYPRoUMHXLp0CaqqqmU6nqQphQLEeQYA4N27d+jUqVOZ2MioWjAxwGBUMwTuf8H+f1RUlND9P336dFhbW1ca9/+vhIWFYd26dfDw8ICqqir+/fdfTJ8+XaLVcVnh4eGBcePGoU+fPjh+/DgUFRXLfExJUwoFCAII+Xw+uFwuDA0NweVyERQUxMQAAwATAwxGtUCc+79JkyYYOHAgbG1tK537/1fevHkDZ2dnnDx5EnXq1MHatWsxadKkMl+BF8XWrVvh5OSE8ePHY8+ePWVSvVAcV65cQd26dYtMKRSgrKwM4GeWhbKyMhQVFdG0aVMWRMgQwsQAg/EbQkQIDAyEt7e3iPu/Y8eOldr9/ytPnz7FmjVrcPHiRejo6GDHjh0YN25cuay+C4OIsGTJEqxZswYLFiyAs7Nzuf4uJU0pFCAQA+np6cL/ZhkFjLwwMcBg/CZUZff/r9y5cwdr1qzB9evXYWBggEOHDmHkyJGQk5OraNPA4/Hg6OiIvXv3YuPGjZg7d265jh8ZGYk3b95gyZIlEt8jEABpaWnCwEYjIyMcOXKkTGxkVD2YGGAwqjAxMTFC9/+NGzdE3P92dnbo0qVLpXb/54WIcO3aNaxZswb37t1Dy5YtcfLkSQwaNAgyMjIVbR4AICsrCyNHjsT58+dx6NAh2Nvbl7sNxUkpFJBXDAgwMjJCVFQUkpOToaamJnU7GVULJgYYjCqEwP0vWP3ndf8vW7YMtra2VcL9nxc+n49Lly5hzZo1ePbsGdq2bQtPT0/Y2tpWqudITU3FgAEDcOfOHZw7dw79+vWrEDuKk1IoQJwYEBRievfuHdq1ayddIxlVDiYGGIxKTkZGhkjt/6ioKKipqVVJ939ecnNzcerUKTg7O+Pt27fo3r07fH190bNnz0olAgAgISEBNjY2ePfuHXx8fNCjR48KsSM7Oxu+vr74999/i3WfkpISAFEx0KxZM3A4HAQFBTExwGBigMGojPxO7v9fycrKgoeHB9avX48PHz7AxsYG+/btQ8eOHSvaNLFERUXBwsIC8fHxuH37Ntq0aVNhtty/fx+pqakSpxQKEOcZUFJSQuPGjVkQIQMAEwMMRqUgr/vfy8sLT58+FXH/29nZoXnz5pVuxVwc0tPTceDAAWzcuBHR0dEYOHAgzpw5AzMzs4o2rUCCg4NhYWEBALh37x4MDQ0r1B4fH59ipRQKECcGAJZRwPgfTAwwGBVERkaGSPR/dHS00P0/c+ZMWFlZVUn3/68kJydj165d2LJlCxITEzF8+HD8+++/ZXaAj7R49uwZrKysUKdOHVy7dg0NGzasaJOEKYXFFYWFiYHTp09LzT5G1YWJAQajHBHn/m/atCn++ecf2NraVmn3/68kJCRg+/bt2L59O9LT02Fvb4/58+ejSZMmFW1akdy6dQt9+/aFkZERLl++DE1NzYo2qUQphQJkZGSgoKAgPMZYgJGRET5//oy0tDShYGBUT5gYYDDKkOrg/v+VmJgYbNmyBbt37wafz8fkyZMxZ84cNGjQoKJNk4gLFy5g6NCh6NatG86fPw8VFZWKNgnAT6+AjIxMsVIK8/Lr+QTA/84oeP/+Pf74449S28ioujAxwGBImaLc/9bW1pVipSltwsPDsWHDBhw8eBAKCgqYOXMmZs2aVean90mTQ4cOYeLEiRg0aBA8PDygoKBQ0SYJKUlKYV7EiYHmzZsDAIKCgpgYqOYwMcBgSIGYmBhh6d8bN24gIyND6P63s7ND586dfxv3/6+EhITA2dkZR48ehbq6OpYsWQJHR0fUrFmzok0rFhs2bMCCBQswefJkuLq6VppCR8D/TiksbkphXn49xhgAVFVVoaOjw4IIGUwMMBglgYjw4sULoQAQuP87deqE5cuX/5bu/1959eoV1q5di9OnT6NevXrYsGEDHBwcqtzeMxFhwYIF2LhxIxYvXoyVK1dWur9bSVMK8yLOMwCwjALGT5gYYDAkJCMjAzdv3oS3t3e1cv//yqNHj7BmzRp4eXlBT08Pu3fvxtixYyuVS11ScnNzMXnyZBw8eBAuLi6YNWtWRZskluKeUiiOwsSAp6dnKaxj/A4wMcBgFEJR7v8uXbpUisNz0rJy8TkhDdm5fMjLcqGnqQxlBel9vIkI/v7+WL16NW7evInmzZvj8OHDGDZsWKV4/pKQmZmJ4cOHw9PTEx4eHhg1alRFm1QgPj4+sLa2LpXHojAx4OLigoyMDNSoUaM0ZjKqMEwMMBh5ELj/BdH/z549E7r/V6xYATs7O2EZ14omNC4Fxx5F4FbwV0QkpoPyXOMA0NFQQo9mdTCinQ4MtFVLNAYRwcfHB2vWrEFAQABat26NM2fOoH///pVqT724JCcno1+/fnjw4AEuXrwIW1vbijapQCIjI/H27VssW7asVP0oKysjNTU13+tGRkYgIgQHB5fK88Co2jAxwKj2CNz/guj/L1++QF1dHVZWVpg1a1alc/9HJqbjvwuvcTcsHjJcDnh8yteGAIQnpuPIo3C4P/iMLvpaWNvfFI00lCQag8/n4/z581i7di1evHiBDh064PLly6VenVYGvn79Cmtra4SFheH69evo0qVLRZtUKKVNKRSgrKyMuLi4fK8Lij8FBQUxMVCNYWKAUS358uWLSPEfgft/8ODBlcr9/ysnn0Rgmedb5P6/ABAnBPIiuB7wMQHmLv5Y0ccYQ//SKbB9Tk4OTpw4AWdnZ7x//x49e/aEn58funfvXuVFAPAz/dHCwgI/fvyAv79/lZj8BCmFpc3OKGiboGbNmqhfvz4LIqzmMDHAqBZUJfd/QbjeCsWm6yElupfHJ/D4hIXnXyM+NQvTehiIXM/KyoK7uzvWrVuHz58/w87ODm5ubmjfvr00TK8UBAUFwcLCAvLy8rh//z6aNm1a0SYViSCl8L///it1XwWJAYBlFDCYGGD8xhTm/ndycoKVlVWlcv8XxsknERIJgR8Bp5B05wjktHRQf8IusW02XQ9BbRUFDPlLB2lpadi3bx82bdqEmJgYDB48GJcuXULLli2l/QgVyqNHj2BjY4MGDRrg2rVrqFevXkWbJBH37t0rdUqhAHF1BgQYGRnh2rVrpR6DUXVhYoDxW/Hlyxdh9P/NmzeRkZEBfX19DBkyRFj7vzK6/wsjMjEdyzzfFtkuNzkePx6cBkdOsci2Sz3f4vnVUzi0fQOSkpIwcuRILFy4EM2aNZOGyZUKX19f9O/fH61atYK3t3eJK/hVBD4+PqhXrx5atWpV6r6K8gzs3LkTWVlZVTJFlFF6mBhgVGmICM+fPxcKAIH7v3PnzlXG/V8U/114LYwRKIzvtw5CoX4zEJ8PfkZyoW0zs3Pg8SEbgwcPxvz586GrqystcysVZ86cwYgRI2Bubo6zZ89CSUmyAMrKQklPKRRHUWKAx+MhNDQUJiYmpR6LUfVgYoBR5UhPTxep/f+r+9/a2hoaGhoVbaZUCI1Lwd2w+CLbZUa8Qfr7+6hnvx2JvnuKbM/hykBBtzWcnGZAt07J0g4rO3v37sWUKVMwbNgwuLu7VzmPUEREhFRSCgUoKysjJycHOTk5+X4XggOLgoKCmBiopjAxwKgSFOb+F9T+r2pf9pJw7FFEgemDAojPQ6LvHqi0soB8HT2J+5bhcnD0YQSW9zGWgqWVByKCs7MzFi1ahGnTpmHbtm3gcrkVbVaxkVZKoQBBmej09HSoq6uLXNPU1ESdOnVYEGE1hokBRqVE4P4XrP7zuv9XrlwJW1vbKu/+l4RbwV+LTB9MfeGD3ORv0B62plh98/iEWyFfsRy/jxjg8/mYO3cuXFxcsGLFCixZsqTKvkd8fHzQsWNHqR34JBADaWlp+cQAwDIKqjtMDDAqDenp6SK1/wXuf2tr69/O/S8JqVm5iEhML7QNLyMZSXePoWbHIZBRyv8FXxQRCelIy8qVauniiiInJwfjx4/H0aNHsXPnTkydOrWiTSox2dnZuHnzplRSCgXkFQPiMDIygr+/v9TGY1Qtqv43AKNKEx0dLVL8JzMzs1q4/yUhPCENRYUNJt05Am4NFaj+aVeiMQjA54Q0GNcvvpCoTGRkZGDIkCHw8fHBsWPHMGzYsIo2qVRIM6VQgCB4sjAxsH//frExBYzfHyYGGOVKXve/l5cXnj9/DhkZGXTq1AmrVq2CnZ0dDA0Nq6xrV5pk5/ILvZ6TGI3UwGuo1XMieCmJwteJlwPi85CbFAeOghJkahQeIFjUOJWdHz9+wM7ODk+fPoWXlxesrKwq2qRSI82UQgGSeAZycnLw4cMHNG/eXGrjMqoGTAwwyhyB+9/LywuXL18Wcf/PmTMHVlZW1cr9XxBZWVl4//49Xr9+jTdv3uBJWAxgMLjA9ryUBID4+H5jL77f2JvvevSe8VD9sw80zB0KHffVi+fQU21TpfLvBcTGxsLKygoRERG4efMmOnToUNEmSYUrV65I/RyIosSAsfHP2JGgoCAmBqohTAwwyoTo6GiR6H/m/v8fPB4PHz58wJs3b/DmzRvh5B8aGgoejwcA0NHRQYuWrQEioIAJQa62LmoPWJTv9aQ7R8DPzoCGuQNkaxZeaY+IYP+PLSgnE40bN4aZmZnIT7169Sqtl+bTp0/o1asX0tPTcefOnd8mJS4iIgJBQUFYsWKFVPstSgzUrl0bmpqaCAoKwoABA6Q6NqPyw8QAQyrw+XyR4j/i3P+/Y3W7wiAiREdHCyd7wU9QUBAyMzMBAFpaWjA1NUWvXr3g5OQEExMTGBsbC6O9u228hfACgghllNShZJh/JZz85BIAiL32Kw3U5OET+AwvXrzA8+fP8eLFC2zevBlJSUkAAG1t7XwCoUmTJhWeqvf69WtYWlpCWVkZ9+/fR+PGjSvUHmkiSCk0NzeXar95UwvFweFwWEZBNYaJAUaJyev+9/b2RkxMTLV1/yckJORb6b958wY/fvwA8POL2MTEBGZmZhg9ejRMTExgYmKCOnXqFLry7tGsDo48Ci8yvbAkEJ+H97c8MfV6MOzt7bFy5UooKyuDiBAeHi4iEA4fPgxnZ2cAgJqaGlq3bi0iEFq0aFFunp6AgAD07t0benp6uHr1KrS1tctl3PJC2imFAhQVFcHhcAr0DAA/4wYePnwo1XEZVQMmBhjFQpz738DAAMOGDYOdnR06der0W7v/09LS8PbtW5GV/uvXrxEbGwsAkJOTQ4sWLWBiYoLevXvDxMQEpqam0NHRKdFqekQ7Hbg/+Fyse+qOWCdROw5XBkuGdsflEx8wduxYTJs2DYMHD4a9vT06deoEPT099O/fX9j+69evePHihVAkXL58Gdu2bQMAKCgowNTUVEQgtGzZUurlf318fDBw4ED89ddf8PT0FJsvX5XJysrCjRs3sGhR/u2f0sLhcAotSQz8FAPu7u7g8XiQkZGRug2MygsTA4xCEbj/BdH/L168gIyMDDp37vxbu/+zs7MREhKSb6X/8eNHAD+/WJs2bQoTExNMnDhRuNI3MDCQqhgy0FZFF30tBHxMkKp3QIbLQccmmnAa3xtO44chPDwchw8fhpubGw4dOgQDAwOMHTsWo0ePRsOGDQEAderUgaWlJSwtLYX9JCcn4+XLl0KB8OjRI7i5uSE3NxdcLhfNmjVDmzZtRERCSQMVT5w4gdGjR8Pa2hqnTp1CjRo1pPK7qEzcu3cPaWlpsLGxKZP+Czu5EPgpBrKysvDp0yfo6+uXiQ2MygmHiIr8hklOToa6ujp+/PgBNTW18rCLUYGkp6fjxo0bwuI/ed3/dnZ2v5X7n8/n49OnT/lW+sHBwcjNzQUANGjQQDjZC1b6LVq0KLdDbyIT02Hu4o8sKaYAKshyccOpGxppiD4Dn8+Hv78/3NzccPbsWWRlZcHCwgL29vbo06cPFBWLPhExMzMTb9++FdlmePnyJTIyMgAAurq6+QRC/fr1C90ucXV1xYwZMzB69GgcOHAAsrK/5zpm7ty5OHHiBKKiosokcLNJkyYYMmSIcMvnV758+YIGDRrg0qVL6NOnj9THZ5Q/ks7fTAwwAABRUVHC4j953f92dna/hfufiBAbG5tvpf/27VthQFXNmjVhamoKU1NT4cRvbGxcKYTP8Uef8d/Foo8xlpT1A0wx5C+dQtskJyfj9OnTcHNzQ0BAAGrVqoXhw4fD3t4ebdq0KdZkxePxEBISIiIQXrx4ge/fvwP4Gcn+q0Bo2rQpOBwOVq5cieXLl8PJyQmbNm2q8ODFssTY2Bjt27fHwYMHy6R/U1NT9OjRA9u3bxd7nYhQq1YtLFy4EAsXLiwTGxjlCxMDjEIpzP1vZ2cnrP1fFUlKShJZ6QsEQGLiz8I8NWrUgLGxschK38TEpNKm0RERZsyYgSPPv6Fm11Gl7k8uyAcPDi6HlpaWxPcEBwfD3d0dhw8fRkxMDExNTWFvb4+RI0eidu3aJbKDiBARESESh/DixQtER0cDAFRUVKCqqoqYmBgMHDgQixcvhrGxcZUWpYURHh4OPT09nDlzBoMGDSqTMdq3bw9jY+NCxUbHjh2hr68PDw+PMrGBUb4wMcDIh8D9Lyj+ExMTg5o1a8La2hq2trZVzv2fkZGBd+/e5VvtR0VFAQBkZGTQrFkzkQnfxMQEjRs3rlLBURs2bMCCBQuwZ88eqLexxjLPt8jlU7FiCGS4HMhyOZjaTgtrxvWGrq4ubt68WezPc25uLq5fvw43NzdcunQJRAQ7OzvY29vD2tpaKu77b9++4fHjx1i0aBFevnyJOnXq4OvXrwAAeXl5mJiYiHgRWrZsKUybq8rs2bMH06ZNQ3x8vNQzCQT07NkTderUwYkTJwpsM2HCBAQGBuLp06dlYgOjfJF0/v49N94YQqKiooR7/1U1+j83NxehoaH5VvofPnwAn/9zH71x48YwMTHBqFGjhJO/oaEhFBQUKtj60nH06FEsWLAAS5YswaRJkwAAnZpq4b8Lr3E3LL7I4425HIBPQGOlHLhN6YVGGkroeu0aunfvjr59++LKlSvFCsSTlZWFjY0NbGxskJCQgOPHj8PNzQ19+vSBtrY2Ro0aBXt7exgZGZX4mZWUlODq6op3794JV8kpKSkigYpPnjyBu7u7MFDR0NAQZmZmIiKhKglb4GemRKdOncpMCAAoMpsA+BlEeOLECfD5/N96S4YhCvMM/Gbw+Xw8e/ZMmP73q/tfUPu/MiJwG/+60n/37h2ys7MB/CyC8+tK38jICKqqhdffr4r4+vrCxsYGo0aNwsGDB/NtYYTGpWCvXxBO3H4FOY16AP53nQNAR1MJPQzrwP/gasR/fIOXL18Kv9zv3bsHCwsLmJub49y5c6UWhC9fvoSbmxuOHj2KhIQEtG3bFvb29hg6dGixJrfExETY2tri1atXuHjxYqGFd7KyssQGKgpiQHR0dPIJhAYNGlTKraCsrCxoampi8eLFZbpXP2zYMHz9+hU3b94ssM3Vq1dhbW2Njx8//lbFnKorEs/fJAE/fvwgAPTjxw9JmjPKmbS0NLp06RJNmDCB6tWrRwCoZs2aNGzYMDp+/DglJiZWtIn5iIuLo5s3b9K2bdto4sSJ1L59e1JVVSX8PEiP1NTUqGPHjuTg4EDbt2+nW7du0devXyva7HLj+fPnpKKiQtbW1pSdnV1gu8uXLxMAehscRloGrWnWqq30JjqJUjNzhG3u3r1LAOjixYsi9/r4+JCcnBwNHz6ceDyeVOzOysqis2fPUu/evYnL5ZKioiINHz6cfH19ixwjOjqaTExMSFNTkx49elSi8XNzc+ndu3d0/PhxmjdvHvXs2ZM0NDSE7ystLS3q1asXLViwgE6ePEnBwcFSe/bScOPGDQJAgYGBZTrOmPEO1KZnH3oenpjvfSIgPDycAJC3t3eZ2sIoHySdv5lnoIoicP97eXnBz88PmZmZMDQ0FAb/VRb3f0pKCt6+fZuvJK9gD1hBQQEtWrQQWembmJigUaNGlXIFVx58/vwZHTp0QIMGDXD79m2oqKgU2NbZ2Rnr1q1DUlISatWqhUWLFmHevHn52nXr1g0ZGRl49OiRyO/19OnTGDp0KKZMmQJXV1ep/s5jYmJw5MgRuLm54f3799DR0cGYMWMwduxYNGnSRKRtWFgYLCwskJOTg+vXr6NFixZSs4OIEBkZmS9QURBboqKiglatWol4EIyMjCAvLy81G4qiLFMKQ+NScOxRBG4Ff0V4QprIWRccADoaSujRrA5GtNOBgbYqiAhqampYunSp2PcSo2rBAgh/MwTuf0HpX4H7v0uXLrC1ta1w97/gxL1fS/KGh4cDALhcLgwMDPJF8Ddt2vS3zRkvCQkJCejUqRNycnIQEBBQZKndIUOGICYmBnfu3IGqqipWrlwJJyenfO18fX1hYWGBa9euwcLCQuTa/v374eDggEWLFmH16tVSfR7g52T86NEjHDp0CCdPnkRKSgq6desGe3t7DBo0CKGhobCyskLNmjVx/fp16OgUnvIoLb59+4bAwEARgRAaGgoigry8PIyNjUW2GVq1alVmgYpGRkbo0KGDVFMKIxPTJY4tEVzvoq+Ftf1NMdCqO4yNjeHm5iY1exgVAxMDvwFpaWkixX9iY2OF0f+C4j/lfewsj8fDx48f8630Q0JChCfuNWrUKN9Kv0WLFhIVrKnOZGRkwNzcHCEhIQgICICBgUGR9zRv3hwWFhbYvn07atSogfXr12PGjBn52hER2rVrB0VFRdy5cyff9Y0bN2L+/PnYtGkT5syZI5XnEUd6ejrOnz8PNzc3+Pn5oUaNGsjNzUWTJk1w584d1KlTp8zGloSUlBS8evVKRCC8ffsWOTk54HA4YgMVNTU1SzWmIKXw7NmzGDhwoFSe4+STiFJlnejGP8aP51fw6NEjqdjDqDhYNkEVpSD3/4gRI4TR/+Wxkqb/P3Hv15V+3hP3NDU1YWpqip49e2LmzJkwNTUVOXGPITk8Hg/Dhw9HYGAgbt26JZEQSEtLQ0hIiNCVW1g9eQ6Hg8WLF6Nv3764c+cOunbtKnJ93rx5+P79O+bOnYuaNWti/PjxpX8oMSgpKWHkyJEYOXIkDhw4gClTpkBWVhbBwcHo0qWLsARygwYNymT8olBVVUWnTp3QqVMn4WvZ2dn5AhW9vLyEUfmNGjUSCgOBSGjYsKHE7n4fHx/IyspK7ZRC11uh2HQ9pET38v5fPITU/BPpNcJARNV2u666wTwDFUxe97+XlxcCAwOF7n/B/n9Zu//znriX90dwjK2ysjKMjY3zrfa1tbXZF4UUICJMmzYNe/fuxaVLl9C7d2+J7nv06BHat2+PJ0+e4M8//4SMjAx27dolTEH8FT6fDzMzM9StWxfXrl0Ta4ejoyP27t2LU6dOlVnhGwDw8PDAuHHj0KdPHxw9ehQPHz6Em5sbzp07J1ICuW/fvpUyPZTH4yEsLCxfRcWEhAQAP4XyrwLBwMBAbKpe3759kZSUBH9//1LbdfJJBBaef13qfgQs6N4QUyxbSa0/RvnDtgkqMQL3v6D4T2xsLGrVqiVS/Kcs3P9paWkICgrKl7oXExMD4OeJe82bN8+3r6+rq8vyjcsQZ2dn/Pfff9i/fz8mTJgg8X179+6Fo6MjUlJSoKioCC6XW2Qfp06dwtChQ/H48WP89ddf+a7z+XyMHDkSZ8+ehZeXl8ihRNJi69atcHJywvjx47Fnzx4RT9ePHz+EJZAfPHgADQ0NYQlkMzOzSi0+iQhRUVH5BEJkZCSAn6K6VatWIgJBX18f9erVk0pKoeAMi4z0NCQ/Oo+sL8HIjgkBPzMVmjazoNIyv+chJz4SiTf3IysqCBwZWdRo+hdq9ZwAGSX1n7ETMhz4zemR7wwLRtWhWoqBtKxcfE5IQ3YuH/KyXOhpKkNZoXLshERGRooU/8nKyhJG/0vb/Z+Tk4Pg4OB8RXo+ffokdPs1adIk30rf0NCwUmQgVCcOHz6MsWPHYvny5Vi2bFmx7p06dSr8/f3x9u1b5ObmQk5ODocOHYK9vX2B9/B4PBgZGaFFixa4ePGi2DY5OTno378//Pz84OvrK+IyLw1EhCVLlmDNmjVYsGABnJ2dC53c379/D3d3d3h4eCAmJgYtW7aEvb09RowYUeISyBVBfHw8AgMDRQRCSEgIiAgyMjLg8Xjo27cvevbsiTZt2qBVq1aFZpAUxKiDjxDwMQFZibGI3jMeMmq1IVuzLrIiXosVA7nJ8YhxmwGugjJU/7QDZWci+fF5yKjVRr0xW8CRkQMHhM76tXFkfDtp/ToY5Uy1EQN502YiEtOR92HEpc2UF3w+H0+fPhXu/5eF+5/P5+Pz58/5VvrBwcHIyckBANSvXz/fSr9Fixa/RfnWqs61a9dga2uLsWPHYt++fcVe9Xbq1Al6eno4duwYsrKyoKioiMOHD2P06NGF3ufu7g57e3u8evUKpqamYttkZGTA2toagYGBuH37Nlq3bl0s236Fx+MJtyA2btyIuXPnSnyvoATyoUOH4OnpCQCwtbXFuHHjYGVlVSWzUVJTU/Hq1SssWbIEDx8+hKGhoUigooGBQb5thsLOkgiNS0GvrT8DQyk3B/zMVMio1EJWTChiDzuJFQMJ13Yh7fVN1J+4G7LqPwM3Mz4H4uvJxdCwmgbV1lbCtjecukK/zu9X2Ks68NuLgdKkzZSVy6sw97+dnR0sLS1L5P6nPCfu5V3p/3ri3q+V+UxMTKpcSdbqwrNnz9CtWzd0794dFy9eLPaExufzhbng8+fPR3p6OpSVlXHs2DEMHz680HtzcnJgYGCADh06FFqjPjk5GX///TciIyNx9+7dEovXrKwsjBo1CufOncOBAwcK9VwURXx8vLAEcmBgIOrWrSssgSzN2gTlhZGRETp27IgDBw4gOzsbQUFB+SoqpqamAgAaNmwocqpjmzZthPU4lnu+xZFH4fm+BwsTA5HbR0JRxwS1+4luT0TvmwRZVS1oD1sD4Of356h2uljex7gMfxOMsuK3FgOlTZtZ0ccYQ4s4vlVSBO5/QfR/VlYWmjVrJsz9L677PykpSWyRHkFgkqKiotgT94o6D55Refj06RM6dOgAXV1d+Pn5lchLExYWBgMDA2HdAMFn9OTJkxgyZEiR9+/ZswdTp07Fu3fvCj2dMj4+Hl26dEF6ejru3buHRo0aFcvO1NRUDBgwAHfu3MHJkyfRr1+/Yt1fGIGBgXBzc8OxY8eQkJCAdu3aCUsgV4WMFklSCvl8vthAxfj4eACAhoYGzMzMEPPnZKRx8p8xUZAYyE2JR/TOsajZfSzU24sGisZ7bUbGh6doNOt/QlFXUwn+c3tI47EZ5cxvm1oojbSZhedfIz41C9N6FJ2+9SsC97+g+E9e9//atWthZ2cnUVpY3hP38rr58564Z2hoKEzdE0z+TZo0qVIn7jFEiY+Ph5WVFVRVVeHl5VXi7ZrAwEAAQKtWPyO9BTUeJH1vjB07FitXrsS6desKLSyjpaUFX19fdO7cGb169cLdu3cl3q9PSEiAjY0N3r17Bx8fH/ToId3JpHXr1ti2bRs2bNgAb29vHDp0CFOnTsWsWbMwYMAAjBs3Dj169Ki0wa+SpBQKDmEyNDQUijxB2q9AIDx9+QapUERxlgK81O8AABmV/J5DGZVa4GemgHJzwJH9GUMUkZCOtKzcShODxZA+Veove/JJRIFCgJ+dIXEELQBsuh6C2ioKGCKBhyAtLQ2+vr7w9vbO5/5fsGCBsHqaOHJzcxEWFpZvpR8WFiY8cU9PTw8mJiYYOXKkcKXfrFmzSplSxSg56enpsLOzw/fv3/HgwYNSFdh5+fIltLW1hRUKBWJAUi+UoqIi5s2bh/nz52PZsmXQ09MrsG3Dhg3h6+uLLl26wMrKCn5+fkWuvKOiomBhYYH4+Hjcvn0bbdq0kezBSoCCggIGDhyIgQMH4suXL8ISyMePH4eurq6wBHJlO3TnypUr6Nixo0ReDD6fj+zsbOTk5CAnJwdycnIwMzODiYkJ2samYopnRLHGptwsAABHJn/AMEdGXthGIAYIwOeENBjXr/weF0bJqDJiIDIxHcs83xZ4nZ+ejB/3T0BGrTbk6jRGVkTRubZLPd+iY1MtsTEEBbn/R44cKaz9n/eLl/KcuJd3pZ/3xL06derAxMQE1tbWwpW+sbHxb3niHkOU3NxcDBs2DK9fv8bt27fRtGnTUvX38uVLkaC+4noGAMDBwQFr167Fhg0bsGvXrkLbCrYkunfvjj59+uDq1asFHn0cHBwsLHl87969ci2TXb9+fSxYsADz58/Hw4cPcfDgQWzZsgUrV65Ep06dMHjwYFhaWkJOTk44sQp+8k62hf1Io11WVhYeP34MbW1tGBsbF9mXYOEgDvl6hqg3Zkuxfk8c2Z8LDeLl5LtGvGyRNgKycwu2gVH1qTJi4L8Lr5FbWJCgigYaTjsiEkFbFLl8wn8XXuPI+HYi7n8vLy+8fPkSMjIy6Nq1K5ydnWFrayt0/3/79g137tzJV6QnJSUFwM8qZiYmJmjbti3GjRsnrMxX0aVWGRWDoJjP5cuX4eXlhT///LPUfQYGBmLYsGHC/8/NzQVQPDGgrKwMJycnrFy5EosXL0b9+vWF9vJ4vHwTWq1atbB3716MGTMGlpaW2LRpE4hIpM27d++wbNkyqKmpYd68eQgICIC/v3+5T7aCn7whUffv38f9+/dL9XuXlZWFnJxckT/y8vL5XlNQUICKigrk5OTw7ds38Pl8dOnSBfXq1StWn7m5uYiPj0dsbCzi4uLwKSkHn4v5HDIqPwOZeamJ+a7xUr+Dq6gq9AoIkJetnNstDOlQJcRAaFwK7obFF9qGIysnfINLCo9PuBsWj6EOs3Db8yTi4uKE7v+FCxeiU6dOwpK8rq6u+U7ck5eXF56417dvX+FqX0dHhwXzVUOICLm5ufkmqi1btmDfvn1YvXo1GjRogGfPnpVq4ktOTkZkZCRev36NadOmIScnB9+//9wDXr9+PQ4cOCBxf9nZ2cjOzhbGogiuF8Xdu3fRrl3BuefJycmYOXOm8P9LOoHKycmhRo0aUFNTK7KdJH0mJibi9u3b8PX1xdevX9GoUSP06dMH/fr1Q4MGDYrsT1qf6zlz5iAoKAgnT54U22dGRgY+fPiA0NBQhISEIDQ0VPjfsbGxwnaamppo2twIaEYipxEWhayqFrhK6siODct3LSsmBPLaolsqHAB6miwd+XemSoiBY48iikwfLCnE5+HJd0VYWlpCR0dHmN6zcOFCkRP39PX1YWJigsmTJwv39fX19atkjnNlg4gqxFUr7XaC1XlBLF68GIsXL5b498LhcMROSIItgeDgYHz58gVycnJCN3JKSgqUlJQgJycHZWVliSbQ27dv4/79+1i8eDE0NDQkmmTv3r2LxYsXY9CgQVixYgVu376NWbNmoX379jh8+DBq1aolbCsrK1upxPGECRPA5/Nx+/ZtuLm54eDBg9i9ezcsLS1hb2+PPn36lHm8zpUrV9CrVy/hRP/rhB8VFSX0aqipqcHAwAAGBgbo1q0bDA0Nhf8vSB3utvEWwhPTi2WDUrOOSHvth9zkb5BV+xkUmvE5ELmJ0VD7q69IWx1NJRY8+JtTJf66t4K/lokQAAAOVwaZmk3hsXc9gJ/BUqamphg8eLDIiXsF7Y9WJHw+v1JPjpK2E0xu0oLL5ZZoBSr4UVRULNYKtKB2r169wtq1a2FlZYU5c+ZAQUGhWCvaglz+W7duxb///ovg4GChGA0NDYWhoSG2bNmC7t27F+v35ejoCD09PWRmZmLq1KkS3dOlSxfUrVsX48ePR2pqKq5du4ZBgwbBw8OjSgS+crlc/P333/j777/h6uqKU6dOwc3NDYMHDxaWQB43bhzMzMxKNQ6Px0N4eLjIhP/q1Su8f/8eISEhcHd3BwDUqFFDOMGPGDFCZMKvU6dOkWKqR7M6InUGkp95gZ+ZJtwGyAh7jNyUn95VtT/swFVUhnqHwUh/fx9xx/+D6p99QDk/g7DlautBxbSXsG/i89C+EYtr+t2p9GIgNSsXEcVUvMVFrlY9HD99Di0MmqBGjRoiE1VGRgYePXpUYRNpYW0KCyoqCTIyMiWaPAU/SkpKpZ5ApdGuMqSSPXnyBGPHjkXv3r1x/vx5qXqQAgMDYWJiItJnSQIIBWhpaWHKlCnYsWOH8NRCSRg3bhwuXLgAb29vtG/fHsePH6+Saa/q6upwcHCAg4MD3r17JyyB7OrqilatWglLIBdUAZDP5yM6OjrfCj80NBQfPnwQbrvIy8ujadOmwu2GLVu2oGXLljAwMED9+vVL9b4d0U4H7g8+C/8/+dEF8JK/Cv8/PSQACAkAAKgY9wBXURmyarWhPdwZ3/0OIMnfHRyuLGro/4Vaf48XiRfgcGXQWiWlxLYxqgaVXgyEJ6ShbHwCeeFgzLS5yPn6qUR3iwsqknQSU1RUhKqqaoVPoLKyspViEv0d+PDhA3r37g1TU1OcPHlS6ltJL1++xB9//CHyWnFTC39l9uzZ2LFjB3bu3IlFixYV2Z6IsHDhQnh7e6Nz5864d+8eDh48CAcHhxKNX1lo0aIF1q9fjzVr1uDatWtwc3PDvHnzMHfuXFhYWKBr167Q0NAQ7ueHhoYiLCwMGRkZAH6KscaNG8PAwAAWFhYiK3wdHR3IyMigT58+qFWrlkhMRWmJC30JTtx78GsbgMOVQcOphyS6T762LrSHrCrwugwHSPv0Akk6mgBY0aHfmUovBsornWW76y4YahY9if460Va2/VBGxfLt2zdh3Qlvb28oKUm39LUgpmX8+PEir5fGMwAA9erVw4QJE+Di4oKZM2cWelBObm4uJk+ejIMHDwrbz5gxA5MnT4a6urpEFRArKwkJCSJ797KysmjRogWCg4Nx5coVXLlyBcDPfXxjY2N07twZ48aNE074jRs3hpxcwYd9ZWVl4ebNm1i6dKlU7E1NTcV///0HV1dX/NndEkn1WyCbJ53l08+A2BwovDyPIC3pHFbFqLxUejFQXuksi/9biKYaCtDX14eBgYHw3wYNGkBTU7NcbGBUbdLS0mBra4uUlBQEBAQUerBMSXn//j2ys7OFlQcFlCS18Ffmz5+PvXv3Yu/evZgzZ47YNpmZmRg+fDg8PT3h4eGBUaNGAQC2bduGpKQkjBw5EmpqarC2ti6xHWVNcnKyyISf162fmPi/VLv69evDwMAAbdu2Fe7j5+bmws/PD6dOncKDBw9ARGjdujU6d+4sUfGgO3fuID09XSq/nxs3bmDixImIi4vDli1bMH36dJx5Ho2F54uusSIJHA4H2tF38PjdC1xI/or169dLXdwyKg+VXgzoaSqDA5TxVgFh+tihCP/w84vh5s2biIuLE16tVatWPpEg+FdDQ4N5BhjIzc3FkCFDEBQUBH9/fzRp0qRMxnn58iUAoGXLliKvl3abAAB0dHQwevRobNq0CY6OjlBUVBS5npycjH79+uHBgwe4ePEibG1thde4XC4OHTqEHz9+YODAgbh27Rq6dOlSYltKS3p6OsLCwsRO+nk/21paWjA0NETz5s1hZ2cndOvr6+sX6B0ZNGgQXFxc4OXlBTc3N0yZMkVYAtne3r7QEsg+Pj5o0KBBgadFSsKPHz8wd+5cHDhwAN27d8eNGzeERayG/qWDL4mp2H77E0DFSzf8lXkWzTC1uw1svr/H1atX0aZNGxw9elQqdTIYlY9KLwaUFWSho6EkUdqMJBG04tDVVMayuaInd6WkpCAsLEz4hSL418/PTyTPt2bNmmJFAhMK1QciwpQpU3Dt2jVcvny5TEvvBgYGonHjxvlWoaXdJhCwcOFCuLu7C+v8C/j27Rusra0RFhaG69evi53o5eTkcPr0aVhbW8PW1ha3b98udTR+YWRlZeHjx49iJ3zBGR/AzwBBwSTfs2dPkX18SYMlf0VBQQGDBg3CoEGDEB0dLSyBfOzYsUJLIPv4+MDa2rrE3wuXL1/GpEmTkJycjD179mDixIn5hMe7sy5IeRkLTYsp4BFKdJjbyj7GwlLtY8eOxdWrV6GoqIgOHTpg6dKl+Pfff1la9W9GlTi1sKDjOX8latc4kQjavDSYfBCyNbXzX+Dz0Embj8MzbCV+c6ekpAgDiH4VC5IIBX19fWhqajKh8JuwYsUKLF++HIcPH8bo0aPLdCxzc3Ooqanh/PnzIq/fu3cPXbp0QVBQUKmP8h0+fDju37+PsLAwyMnJISIiAr169cKPHz9w7dq1fFsUv5KSkoKePXvi8+fPuHv3bqGnIhZFbm4uPn/+LHbCDw8PF2bUKCkpiUzyBgYGwv/X0tIql88aEeHBgwdwc3PDqVOnkJKSgh49esDe3h4DBw7E169f0bhxY5w7dw4DBgwoVt8JCQmYNWsWjh49CktLS+zbtw86OvnPVTlz5gwGDx6MAwcOwKL/MKkc8/769Wu0bNkSt27dgp+fH9asWYO2bdviyJEj0NfXL9ZzMMqf3+oI49C4FPTaeqfM+o/ePxkNVGQwc+ZMjB8/vlTPmJqaKtajEBYWhpiYGGG7mjVrFrj1wIRC1eHAgQOYOHEi1q5di3///bdMxyIi1K5dG9OnT8eyZctErvn7+6N79+4IDg4u9VkAb968gampKQ4dOoR27drBwsIC8vLy8PX1lfhMhYSEBHTt2hUpKSm4d++e2IlLAJ/PR2RkpMjevWDS//jxozAeQkFBAU2bNhWZ9AX/Xa9evUr1mUlLS8P58+fh5uaGW7duQVVVFaampnj06BESEhKKdcTyuXPnMHXqVGRnZ2Pr1q0YPXq02GcNDw9Hq1atYGFhgVOnTgnbhMal4NijCFx+8RlfM0jkXiJCbUXAtk1jjGyvA/06+esJZGVlQUlJCbt374aDgwMePHiAUaNGISYmBi4uLpg4cWKl+t0zRPmtxAAAjDr4CAEfE6RbfIjPg0kdeaz6WxtbtmzByZMnoaSkhIkTJ2LGjBmFfoGVhNTU1AI9CnmFgrq6eoEehfJa5TCKxtvbG/369YODgwN27txZ5n+X6OhoNGzYEBcuXEC/fv1Ervn5+aFnz5748OGDVOIV+vfvj2fPniEtLQ0NGjTAtWvXUK9evWLb27lzZ8jLy+POnTvg8/n5Ku0JcvEzMzMB/Ix5aNy4sdgJv2HDhlWyjsGnT5/g7u6ODRs2IDMzE82aNYO9vT1GjRolPA9CHHFxcXB0dMS5c+fQt29f7N69u8C/QW5uLrp3746oqCgEBgaK3f5wc3PD+ElT8Tw0CsThQl6Wi97d2qK/rQ1cXFwKfYZmzZrB2toaW7duBfDzu2zOnDnYt28fbG1tceDAAeEJmozKxW8nBiIT02Hu4o8saaYa8nIQvX8KZowbjtWrVyMxMRE7duzA3r17kZKSgn/++Qdz5swpl4AZgVD4VSSIEwoFeRSYUCg5aVm5+JyQhuxcPuRludDTVC60/Orjx4/Ro0cPWFhY4OzZs+UySV25cgW9e/fGp0+f8h057OvrCwsLC3z+/Bm6urqlHmvnzp2YNm0aDA0N8fDhQ9SqVfS5H0SEhIQEkQn/+fPn8PX1BZ/PF7r0ORwOdHV1xbr1dXV1C03Nq6pkZmZCU1MTI0aMQHp6Os6dO4fs7GxYWVnB3t4ednZ2wsqNRIRjx45h5syZ4HK5cHV1xeDBgwv9bC9fvhyrVq3CnTt30KmT+DTANWvWYOvWrfj27ZvwtbFjx+LVq1d4/vx5ofb3798faWlpuH79usjrXl5ewvLO+/fvzydSGRWPpPN3lYkAaaShhBV9jKWWNgMAzgPNEF1nDhYvXowrV67A3d0d69atw+LFi+Hm5oatW7fir7/+QpcuXTBnzhzY2tqW2Ze+iooKWrVqJXY/Ni0tTezWw507d/DlyxdhOyYUiofAfXor+CsiEtNFMlY4AHQ0lNCjWR2MaKcDA+3/uU/DwsLQu3dvtG7dulyr7gUGBkJdXV3sZC+N1EIBZ86cgZOTE7S0tCArK5vPpZ2UlCTi0s+7yk9KShK2a9CgAQwMDNCvXz9cvnwZenp6OHr0KIyNjatEyWJpcvfuXaSnp2P69OkwNTXFzp07hSWQ//nnH2hoaGDEiBGwsbGBq6srLl++jKFDh2L79u2oXbt2kX2vWrUKy5YtK1AIAEBMTEw+z0LXrl3h4eGBHz9+FLp1YWRkhMOHD+d73c7ODq9fv8bEiRPRv39/jBs3Dlu3bmXHsldBqoxnQIDrrVBsuh5S4vuJfu6ZzbNoBsceP4NfgoKCMGbMGDx//hwLFizAsmXLoKCgAB6Ph0uXLmHz5s0ICAiAvr4+nJycMGbMGCgrV44TvNLS0grcesgrFASHnYgTC7Vr165WQiEyMb3EgVXyOSno2LEj5OTkcP/+/XKtQTFkyBDExsbC398/3zVvb2/Y2dkhJiYGdevWLfEYe/fuxZQpU/DPP/+gV69emDhxIkaMGAE5OTnhhJ93ZVmnTh0RV77gv5s2bSryGXn48CHMzc3RpUsXXLp0CfLy8iW2sSoye/ZsnD59GpGRkfk+a+/evcOhQ4ewb98+JCcnQ1ZWFmPGjMG6deuKrFXx/ft3tGrVCnp6erh161ahYnDAgAFIS0vDtWvXhK99+PAB+vr68Pb2Ru/evQu899ixYxg5ciSSkpLEigYigpubG2bOnInatWvjyJEjhQoTRvnx220T5OXkkwgs83yLXD4VK4aA+Dxw+Dyk3nFDwJFNIoFWubm5WLduHVauXInmzZvDw8MDrVu3Fl5/+PAhtmzZgnPnzqFmzZqYPHkypk2bVux91PJEIBTEBTNGR0cL26mpqRXoUfjdhEJJ3zuClCu5VxeR8NgTDx48yOeqL2uaNWsGS0tLbN++Pd+1S5cuoV+/fvj69WuRK0kBmZmZ+PjxI0JCQhASEoIzZ87g6dOnUFZWRlpamrCdjIwM/vjjj3xufQMDg2IFwt24cQO9e/dGv379quw5BiWlRYsW6Ny5M/bv35/v2qdPnzBx4kTcvHkT5ubmUFRUFE7Yffr0gb29PSwtLfNlOxER/vnnH/j5+SEwMLDIGKcOHTqgefPmcHNzE+mjYcOGGDlyJNavX1/gvS9evECbNm3w4MEDtG/fvsB2Hz9+xKhRo/Dw4UMsWLAAy5cvr3bCr7LxW4sBoGSrO135dARsm456avKoWbMmHj58mK+iVmBgIMaMGYOgoCAsXboUCxcuFNnD/Pz5M7Zt24YDBw4gKysLw4cPx+zZs/MVganspKWlCXO088YnFCQUxNVRqGpCobReJUERlxGmalgzvHwL6qSlpUFVVRUHDhzAuHHj8l0/d+4cBg0ahISEBOGxtgCQk5ODz58/56u0FxISgoiICOExuXJycsjJyYGxsTH69esnnPi/fPmCQYMG4erVq7C0tCz1c5w/fx7//PMPxo8fj71791ap909J+fTpE5o0aZIvpZDP52PXrl1YuHAhNDQ0sH//fuHv+Nu3bzh+/DgOHTqEV69eoV69ehg1ahTs7e3RvHlzAMD+/fvh4OAgcaqinp4ehg8fjrVr14q8PmzYMHz+/BkPHjwo8N709HSoqKgU+P7LC4/Hw4YNG7B06VKYmJgIt4YYFcNvLwYECPd9Q74iIkHMvq+mEnoY1sHI9jporKmEjh07IiEhAdHR0RgyZAjc3NzyfSFlZ2dj5cqVWLduHVq3bo3Dhw/nezP/+PED+/fvx7Zt2xAVFQVzc3PMmTMHlpaWVf4LTpxQEPybVyioqqoWuPUgybGr5cnJJxFSjTdZP8BUWJSlPHj48CE6dOiAp0+fij2kaPfu3Zg+fTo2bdokTNMLCQnBp0+fhAWJFBUVhX8jwWTfuHFj7NmzB2fPnoWrq2u+I4yJCO3bt4eCggLu3JFOeq+7uzvs7e0xf/78Qlejvwu7du3CzJkzkZCQIPz+DAkJwfjx43Hv3j1MmTIF69atE/vdSkR48eIF3NzccPz4cSQmJqJ9+/awsrLC+vXrMWrUKOzdu7dIG4gIioqK2Lx5M6ZNmyZybc+ePZg+fTqSkpIK3f5s2rQp+vfvj02bNkn03M+fP8fIkSPx8eNHrF+/HtOnT2eHoVUA1UYM5EWSiPBXr16hTZs26NevH86dO4f9+/djwoQJYvt7/PgxxowZg48fP2L16tWYPXt2PtdmTk4Ozp49i82bN+PZs2cwMjLC7NmzMWLEiHzlXH8H0tPTC9x6yFv1TVVVtcCth/IWCkVlouQkRiPp7lFkRQWBn5EKGbXaUDbqBrV2/cGVE/83VJDl4oZTN5HiLGXJnj174OjoiCtXriA8PFxkhf/hwwdkZ2cD+LnCb9KkSb59fEFqXt4v44yMDAwZMgQ+Pj7w8PDAsGHDxI7t5eWFPn36wN/fH127dpXK82zbtg2zZs2Cs7MzFi5cWPQNVRg7Ozukpqbi1q1byM3NhYuLC5YuXYoGDRoISwpLQlZWFjw9PXHgwAFcv34dHA4HQ4YMwcSJE9G9e/dCJ9qEhARoaWnh7NmzGDhwoMi1oKAgGBsbw9fXF+bm5oU+B4/HEx7WJAkZGRn4999/sW3bNvTs2RPu7u5o2LChxPczSk+1FAOSsnDhQmzduhX9+vXDxYsX8eDBgwLLpmZkZGDJkiXYsmULOnToAHd3dxgYGORrR0S4e/cuNm/eDC8vL9SuXRuOjo6YMmWKxHu4VZ309PQCPQrihII4saCtrS11oVBYjYrc5G+IOTgNHAVlqJpZg1tDFVnR75H2+gZq6LdDnUFLxPYpw+WgYxNNHBnfTmp2EhG+ffuWr9JeSEgIgoKChBkDXC4Xenp6IgF7ERER2LRpE1JSUgo9cVDAjx8/YGdnh6dPn+L8+fOwsrIq1K7WrVujbt26IsFnpWX58uVYsWIFdu3ahSlTpkit38qEIKVw2bJlsLGxwbhx4/D06VM4OTlh1apVJTr4Z+bMmdi7dy8mTZoEHx8fhIaGQk9PT1gCWVwsi6CQ1P3799GxY0eRa0SEOnXqYPLkyVi1quDjjBcsWIBTp07h8+fPxbb5xo0bGDt2LNLS0rB7924MHTq02H0wSgYTA4WQnp4OU1NTNGzYECkpKfjx4weePXtWaJ3ye/fuYezYsfjy5QvWr18PR0fHApV4SEgItm7dCnd3dxARRo8eDScnJ+FeX3UkIyOjwDoKeYWCiopKgR6FkgiFoqpX/gg4jaQ7Hqg3fifka/8vZS/eewvS3vih4ayTkFEseHK94dRVbNW2wvj+/bvYCT80NBTJycnCdo0aNRJO+FevXoWuri727t2LJk2a5AvKErjes7Ozi8zTj42NhZWVFSIiInD58mV06NChSJtPnz6NIUOG4NGjR2jbtm2xnrcgiAizZs3Cjh07cOzYsQI9E1UZQf0HR0dH7Nu3D02bNsWhQ4ck+p2LQ5A1sn37dkyfPh1EhICAAGEJ5NTUVPz999+wt7fHgAEDhGLj+vXrsLS0FFujAgAGDhyI+Ph4sZkqAg4fPoyxY8dKLDh/JTExEVOnTsWpU6cwbNgw7Ny5U6L6FYzSwcRAEQg+pOvXr4ezszO6du2KixcvFjrZpKWlYcGCBdi5cyd69OiBQ4cOFRpRnpCQgD179sDV1RWxsbHo3bs35syZg+7du1eq/fSKpiChEBYWhsjISGG7kgiFos61+H7bHckPz6LhjGOQUVIXff3ReTRyOg2uvPitAhkuB6Pa6WJ5n/zBUampqWKPyA0JCUFCQoKwXd26dfNV2jMwMEDTpk2FX+R8Ph9qampYtmwZ5s2bJ9aWgwcPYsKECeDxeIW6iz99+oRevXohPT0d169fh4mJSYFt88Lj8WBsbIxmzZrh0qVLEt0jCXw+H+PGjcOxY8dw8eLFQtPbqiIjRozAmTNnwOfzsWDBAixZsqTE24cxMTFo2bIl2rdvD09Pz3zv97S0NJw7dw5ubm64ffs21NTUMGTIENjb2yM4OBj29vbIyMgQO/727dsxf/58JCUlFWjfkydP0LZtWzx58qRUhdhOnDiBKVOmQEVFBYcPH0bPnj1L3BejaJgYkIBRo0bh8uXL2LZtG0aPHo3169dj/vz5Rd538+ZNjBs3DomJidiyZQsmTJhQ6OSelZWFEydOYMuWLXj9+jXMzMwwe/ZsDB48mKXdFEFGRkaBWw/ihMKvImHh/UxE/8guuP+Pz/D19DLU0G+Hml1G/P82wTskXHWFimkvaJhPLNS+eiqymG+Unm+Vn/fAKk1NTbEH6Ojr60v0eQoNDYWhoSGuXbsGCwsLsW327duHyZMnC6v8ieP169ewtLSEsrIyrl+/nu9EvaIQrAxfvnwp1eyZ3Nxc/PPPP7h69SquXr2Kbt26Sa3viiIzMxMrV66Es7MzNDQ04OvrW6rTLPl8PiwtLfH27Vu8fPmyyK3Hjx8/4vDhw3B3d0dERARq164tPDdFXAnkwMBAmJmZFRoXkpqaClVVVakcyBUZGYmxY8fCz88Ps2bNwtq1a1GjRo1S9ckQDxMDEvDt2zc0b94c1tbWaNSoETZu3IibN29K9GWUnJyM2bNn4+DBg7CyssKBAwfQoEGDQu8hIty4cQNbtmzB1atXUb9+fcyYMQMODg7MXVYCBEKhQI+CnCIaOZ0u0guTdP8kkh+cAeVmCV9T6zgEtbqOKtIGIkLkln+goigntp6+4Cjr0nD27Fn8888/iI2NLbD+uyBiPScnR+z1gIAA9O7dG3p6erh69WqJ6sjn5OTA0NAQ7dq1w8mTJ4t9f2FkZmaid+/eePLkCW7dupUvY6Iq8eDBA4wbNw4fPnxATk4OTp06hcGDB5eqzw0bNmDhwoXw9fUt1kqaz+fDz88Pjo6OCA0NBYfDgZWVFcaNGwc7OzvhYoTH40FTUxNz587F4sWLC+xPT08PQ4cOxbp160r1PALbtm/fjoULF6Jp06Y4evRomR55XV2ReP4mCfjx4wcBoB8/fkjSvErh7u5OAOjy5cvUvXt3qlu3Ln358kXi+y9fvkz16tWjmjVrkoeHB/H5fInue/PmDY0fP57k5eVJWVmZpk+fTmFhYSV9DMYvpKenk+fd56S70LvIH03bOaTYuA1pWE2j2v3/I+WWvQjgUK1ekyS6/86rjxL/3UvCokWLqG7duoW22b59OykqKoq9duXKFapRowZ17dqVkpKSSmXL7t27icPh0Pv370vVjziSk5Opbdu2pKWlRe/evZN6/2VNWloaOTk5EYfDob/++osWLVpEsrKypf7efPToEcnKytKCBQtK3MegQYOoe/futGfPHmrXrh0BIE1NTZoxYwa9ePGCiIhsbW3J3Ny80H6sra3Jzs6uxHaI482bN9S6dWuSk5MjZ2dnys3NlWr/1R1J5+9qn/Q5evRo/P3333B0dMTBgwfB4XAwbNgwYeR2UdjY2ODNmzfo3bs3Ro8ejf79+yMuLq7I+4yNjXHgwAFERERg9uzZOH78OAwMDDBw4EDcv39fWAyGUTJq1KiBhjp6RbZLC/JH4lVXaFrPgGprKyg16wgtm5lQNu2JpNvu4GUkF9mHinrNMo0BefnypdgzK/LC4/HEVvQ7ceIE+vTpA3Nzc1y9erVYFQPFMXbsWNSrV08qK8NfUVVVhY+PD7S1tdGrVy+Eh4dLfYyy4vbt22jZsiV2796NDRs2ICAgAIGBgejcuXOpvKkpKSkYPnw4zMzMCo30L4ovX75AR0cHkyZNwsOHD/H27VuMGzcOp06dgpmZGczMzMDlchEQEFCgdwn4eUZBUFBQie0Qh7GxMR49eoQ5c+bgv//+Q7du3fDx40epjsEommovBjgcDvbs2YOYmBjs2bMHJ0+exL179wp1lf2KhoYGjh49ivPnzyMgIADGxsY4c+aMRPdqa2tj5cqViIyMxJ49e/D27Vt07twZHTp0wJkzZyQWJYz8yMsW/fZOeX4F8tpNIKsmWgNeSb8tKCcL2XFFfyn17N4NxsbGsLKywoQJE7BixQocPHgQ169fR1BQEFJSUkr8DMBPMZC3NLY4cnNz84kBV1dXjBgxAiNGjMD58+elsierqKiIuXPn4siRIyVKMSsKDQ0NXL9+HfLy8jA3N5dIWFckKSkpmDp1Knr06IF69erh5cuXmDt3LnJzc+Hn5wdra+tS9e/o6IivX7/ixIkTpTrN8ddDioyMjLBhwwZERkbC09MTjRs3xuXLl5Geng5LS0tcuXJF7HePkZERPn78iIyMjBLbIg55eXk4OzvD398f0dHRaNWqFQ4dOsQWReVItRcDAGBgYIClS5diy5YtUFNTg7OzM9avXw9PT89i9dO/f3+8ffsW3bt3x+DBgzF06FCRyPHCqFGjBhwcHBAUFARvb28oKSlh8ODBMDAwwNatW0VSzhiSoaepjKLW67z0JBDlD7oj/s+qfRD8WyCEOZNGo2fPnqhRowZevnyJ3bt3Y8KECbC0tISxsTHU1NSgrq4OExOTYguGxMREREZGSuQZENSuJyKsWLEC06dPh5OTEw4dOpSvrn1pEMS4bNiwQWp95qV+/fq4ceMG0tLSYGFhge/fv5fJOKXl2rVrMDExgYeHB3bs2AF/f3/heSd37txBRkYGbGxsStz/0aNHceTIEezatQtNmzYtcT9EhC9fvog9R0VOTg52dnY4f/48IiIiIC8vj3fv3qF3797Q0dHBwoULERwcLGxvZGQEIhJ5TZp06dIFL1++xODBgzF+/HgMGDBA5GAsRtnBxMD/M3fuXLRo0QITJ06Ek5MT+vXrh9GjRxfbXVW7dm2cOXMGx48fx/Xr12FsbFwsUcHlctG7d2/4+fnh2bNn6Ny5M+bNm4dGjRph7ty5iIiIKO6jVVuUFWShU0SFQLla9ZEd9wE5idEir6cF+QMcLuRq6xV6v2zGdyjIANOmTcOFCxfw5MkTxMbGIisrCx8/fsSdO3dw/PhxLFq0CH///bfEgmHixIlYsWKF0B2vqqpaqIdBsE3A5/MxY8YMLF++HGvXrsWmTZukXgJWWVlZGDyb92RMadK4cWP4+voiKioKvXv3Fjk4qaL5/v077O3tYWVlBQMDA7x+/RrTpk0T+T37+PigYcOGJa7J/+HDB0yZMgUjR47EyJEjS2VvUlISsrKyxGYR5KV+/fro1q0b2rRpg2fPnmHgwIHYt28fmjdvjo4dO2L//v3CIGlpbxXkRU1NDQcPHsT58+dx7949mJiY4PLly2U2HuMn1Tqb4FcePHiATp06wcXFBWPGjMGff/4JNTU1BAQElCg3+MuXL3BwcMDly5cxZswYbN26tdDCRgURFRUFV1dX7N27FykpKRg8eDBmz55dqlzf6kJRdQYyI94g7sR/4NZQg+ofvSFTQw3pYY+R+fEZVFpZQNN6RoF9c0DQSHiDoCMrkJmZCUNDQ/Tp0wd2dnbo2LFjkavx7OxsREdHIyoqCpGRkWL//dVNrq6ujoYNG6Jhw4Zo1KiR8F9/f39cvnwZPXr0wLlz57Bnzx44ODgU/xcmIT9+/ICuri7GjRuHLVu2lNk4jx8/Rs+ePdGxY0d4enpCQUGhzMaShEuXLmHy5MlIT0/H5s2bMX78eLHxIs2bN0fXrl2xb9++Yo+Rk5ODzp07Iz4+Hi9evCj1d66g3PDdu3fRuXPnQtuuWbMGGzZsQGJiImRkZJCZmQlPT0+4ubnh+vXrUFBQAIfDQf/+/eHh4VHmZw3ExsZiwoQJuHz5MiZNmoRNmzaVqOBRdYalFpYQR0dHHD58GEFBQcJDQUaPHl2iDzXw00Xn7u6OmTNnQl1dHQcPHiwwV7woUlNT4ebmBhcXF3z69Aldu3bF7NmzYWdnxw4AKYCiKhACQNaXYCTdO46cuI/gZaRAtqY2VEx6Qq39QHC4hR+zu/RPDoZYdcPNmzfh5eUFb29vxMbGQkNDAzY2NujTpw8sLS1L/LkZNWoUXr58iZ07d0osGJSUlNC4cWMRsfCrgFBVLV7VRLHPvnQpNm/ejM+fP5dpyW0/Pz/Y2NjAzs4OJ0+erJCjj799+4YZM2bg5MmT6N27N/bs2VNgjf2PHz+iadOmOH/+PPr371/ssf79919s2rQJ9+/fl0q1xxs3bqBXr1748OEDmjRpUmjbu3fvomvXrnj+/Hm+NL/o6Gh4eHhg9erVSE9Ph56eHsaOHYsxY8aU6XHeRIR9+/Zh9uzZqF+/Po4cOVLoMcoMUZgYKCE/fvyAkZER2rRpA09PTxw6dAgTJkyAu7s7xowZU+J+IyIiMH78eNy4cQOTJk3Cxo0bS/yFzOPxcOnSJWzevBkBAQEwMDDArFmzMHbs2BLVOv/dKexsgpLC5QByiR8RsncGOnTogFWrVuHvv/8GEeHp06fw8vKCp6cnXr16BTk5OXTv3h12dnaws7Mr1henmZkZ/vzzT+zfv7/ANrGxsTAzM0NcXBwWLlwIdXV1REVFSeRh+FUw5P23qBVYQkICdHV1MXPmTKxZs0biZyoJly5dwsCBAzF27Fjs37+/3Cp4EhFOnz6NadOmCfPihw8fXuj4O3fuxKxZs0ROKZSUmzdvolevXnB2dsaCBQtKaz4A4MiRIxg9ejTS09OLDCLNysqCuro61q1bh1mzZoltM3PmTFy8eBHm5uY4ffp0gSWQpU1oaChGjRqFJ0+eYNGiRViyZEmpgiqrC0wMlIILFy5gwIABOHPmDAYNGoRx48bh5MmTePToEUxNTUvcLxFhz549mDt3LrS1teHm5lbqamsPHz7Eli1bcO7cOdSsWRNTpkyBo6Oj2GCh6kpRpxaWBAVZLnxndcW7p/ewZMkSPHnyBF27dsWqVatEKriFh4fDy8sLXl5euHXrFnJycmBqaircTvjrr78K9OpkZ2dDRUUFW7ZsyXfsrIAvX77A0tISHz58QK1atUSOmM5LVlYWvnz5UqB3ITIyEl+/fhW5R11dXaxXIe+/K1aswL59+xAeHl6iLbDi4OHhgTFjxmDOnDnYuHFjmQuCmJgYTJ06FRcvXsSgQYPg6uoqUbEmW1tbpKenw8/Pr1jjffv2Da1atYKRkRGuX78uNW/fhg0bsHbtWiQlJUnUvnv37tDQ0MD58+fFXt+3bx+mTp2KtLQ05Obm4uzZs3Bzc4O/vz/U1NQwdOhQ2Nvbo127dlL/G+Xm5sLZ2RkrVqyAmZkZjh49imbNmkl1jN8NJgZKSf/+/fHw4UO8e/cO8vLy6NChAzIyMvD06dNS/w4+fPgAe3t73L17FzNnzsTatWtLraY/f/6Mbdu24cCBA8jOzsbw4cPh5OQk1bKxVZmTTyKw8PxrqfW3foAphvylA+CnyPP29sbSpUsRGBgIc3NzrFq1Kp8rMzk5GdevX4enpycuX76MxMREaGtrw9bWVlgLIO/74NWrV2jVqlWBe71hYWGwsLBATk4OevXqhXv37iEkJKTEz5SVlSWMYZBUMKipqSElJQX6+vro3r27WNEgzT3eHTt2YMaMGVi9ejUWLVoktX7zQkQ4fPgwnJycIC8vj507d2LQoEES3ZuZmQkNDQ2sWLGiwHMkChqzb9++CAgIwKtXr4oM9isOs2bNEmatSMLSpUuxa9cufP36VawguXfvHrp06YLXr1+LnG3x4cMHHD58GIcPH0ZERASaN28Oe3t7jBo1SuqLkydPnmDkyJGIjIzExo0bMXXqVHbeSwGwCoSlJDIyklRVVWnSpElERBQSEkJqamo0aNAgqVSb4/F4tGXLFlJUVCRDQ0N68OBBqfskIvr+/Ttt3LiRGjZsSADI3NycfHx8yrRCXlVhh1+IRBUFC/xZ4EW6C73J1S9UbP88Ho/OnTtHJiYmBIBsbGzo6dOnYtvm5OTQnTt3aN68edSsWTMCQIqKimRra0t79+6l6OhoOnz4cIGfuxcvXpC2tjY1a9aMwsPDycnJiVq0aCHV35c4MjMz6cOHD+Tv709Hjx6ldevWkampKcnJyVHr1q2pTp06BEDkp2bNmmRiYkJWVlY0ceJEWrFiBR06dIiuX79O7969o5SUlGLZsHLlSgJArq6uUn++8PBwsrS0JAA0cuRIio+PL9b9165dIwD0+vXrYt23Y8cOAkBeXl7Fuk8SBg8eTH///bfE7W/cuEEA6M2bN2Kvx8fHEwA6efKk2Os8Ho98fX1p+PDhpKioSDIyMtS7d286e/YsZWVllegZxJGWlkaOjo4EgCwtLSk6Olpqff9OSDp/MzFQCIIP6N27d4mI6Ny5cwSAXFxcpDbGu3fvqG3btsTlcmnBggWUmZkplX6zs7Pp+PHj9McffxAAMjIyogMHDlBGRoZU+q+qnHgcTk3/9SSdeReLJQQa/+tNOnPO0aAFW4ocg8fj0cmTJ6l58+YEgPr27UsvX74s9J7g4GDatGkTde3albhcLgEgbW1tqlWrFr148UJEzPn7+5Oamhr98ccf9PXrVyIimjFjBpmYmJTul1NCwsPDSVZWljZt2kRERBkZGfkEg6OjI/Xt25fatGlTqGCwtramiRMn0sqVK+nQoUPk6+ubTzDw+XxycnIiAHTkyBGpPAOPx6Pdu3eTiooKNWjQgLy9vUvUz8yZM6lhw4bFEt8vX74kBQUFmj59eonGLIrOnTvTyJEjJW6fmppKsrKytGvXrgLbaGtr09KlS4vs6/v377R7925q27YtASAtLS2aOXMmBQYGSmxPUfj4+FDdunVJQ0ODzpw5I7V+fxeYGJACubm51K5dO2rRooVwkp49ezbJysrS/fv3pTZOTk4OrV27luTk5MjY2LjA1WRJ4PP55O/vT3369CEOh0N16tShFStWCCeR6kZCQgJp6TWj1k4HSXehNzX573KhIkBwfeSBh7Ro7RbicDh08+ZNicbKzc0lDw8Patq0KQGgf/75h96+fVvkffHx8XTkyBGqU6cOycrKEgBq1KgRTZ06lZYvX06Kior0999/U3JysvAeR0dHatWqVUl/LaVm/PjxVLduXYnFpkAw3L59m44ePUrOzs7k6OhIffr0kUgwTJgwgczMzIjD4dCKFSvo3bt3lJqaWiLbw8LCqHv37gSAJk6cWKrzGwwNDWnixIkSt09LS6MWLVpQy5Yty0yoN23alObNm1esezp06EBDhgwp8HqPHj1o0KBBxerzzZs3NHfuXNLW1iYAZGZmRtu3by+290Uc3759o4EDBxIAGjVqVKnP4PidYGJASrx8+ZJkZWVp5cqVRPRzxd2pUydq0KABxcXFSX2s1q1bk4yMDC1btoyys7Ol2n9wcDBNmTKFatSoQYqKiuTg4FAlD4QpDdOmTSM1NTWKjY2lkNhkWnbpDXXd6Ed6v4gAvYXe1HWjHy279IZC435Oujwej/7++2+qX79+sb7AsrOz6cCBA6Srq0scDodGjBhBwcHBhd7D5/NJU1OTFi9eTL6+vjR9+nTS0tIiACQjI0P9+vUjd3d3oaibNGkStWnTpuS/mFISGhpKXC6Xdu7cKbU+ixIMtWvXFisYTE1NC/Qw5BUMubm55OLiQjVq1CA9PT3y9fUtlb0fPnwgAHThwgWJ75k0aRLVqFFDIpFYEvh8PikpKdGWLUV7tPKyYMECqlevXoEeDkdHRzIyMiqRTdnZ2eTp6Un9+vUjWVlZkpeXp0GDBtGVK1dKdUgRn88nDw8PUlNTIx0dHbp9+3aJ+/qdYGJAiixcuJDk5eWFJ7VFRUVRnTp1yNzcXOonbGVlZdHSpUtJRkaGzMzM6NWrV1Ltn+jnynP16tVUt25dAkC2trbk5+f328cVvHr1irhcLm3evDnftdTMHHoTnUTPwxPpTXQSpWbmiO0jKiqKNDQ0qF+/fsX+fWVlZdHu3bupQYMGJCMjQ2PHjqWPHz8WOA4AunjxIhERubi4EADq378/rVq1itq1a0ccDoe4XC516tSJ/vrrLzI1Na3Qv+Hw4cNJR0dHqvvCRZGUlESdOnWiGjVq0MqVKyUWDIaGhlSzZk0CQO3ataPdu3eTr68vvX//vsQeBldXV5KTkxPx2BSGYNtx7969JRpPEpKSkgrd3y+IK1euEAAKCQkRe33nzp0kKytb6gVLXFwcbdmyhUxNTQkA1a9fnxYuXFikWC6Mz58/U9euXYnD4dDcuXOltvVaVWFiQIqkp6dT06ZNqVu3bsIv2xs3bhCXy6UlS5aUyZhPnjwhIyMjkpeXJ2dnZ8rJET85lYbMzExyc3MTfhDNzMzoyJEj5fplXl7w+Xzq3r07NWvWrNTPd+HChVJ9iWdkZNC2bdtIW1ubZGVlycHBgSIiIkTaeHt7EwD6+PEjLVq0iADQggULRCb7mJgYOnDgAPXt25dkZGQIAOnr65OTkxPdunVL6p6lonj9+jUBoIMHD5bruCkpKdS+fXvS0NAQu8LOyMigsLAwun37Nrm7u5OlpSVxuVxSVlYmAwMDsYKhVq1aQg+Dg4MDrVy5ktzc3AoVDL1796YePXpIZHNERATVqlWLBgwYUKYC7t27dwSA/P39i3VfUlIScblcOnDggNjrt27dIgAUFBQkDTOJz+fT06dPydHRkWrVqkUAqGPHjrR///4SzTu5ubm0ceNGkpeXJ1NT0yJjdn5nmBiQMr6+vvm+6FavXk0A6MqVK2UyZkZGBs2fP584HA61a9euTM6QJ/r5Qbx+/bowirpBgwa0bt06SkxMLJPxKoLTp08TAPLx8ZFKfwL3bmm+DNPS0mjTpk2kpaVF8vLy5OjoKIyIXrNmDampqZGDgwMBoI0bNxba17Bhw8jIyIgcHByofv36whXw8OHD6cSJE/T9+/cS21kc+vfvT/r6+uV+Jn1iYiKZmppS/fr1C/S2BAYGUps2bYjL5dL8+fMpPT1deC2vYDhy5Ag5OzvT1KlTqU+fPmRmZlaoYLCxsaHx48eTrKwsDR48mG7cuFGohyE3N5e6du1KDRs2pISEhDL5fQi4efNmoSv8wmjTpg2NGjVK7LW4uDgCQGfPni2tifnIyMigU6dOkaWlJXE4HFJSUqJRo0aRn58f8Xi8YvX18uVLMjExIXl5edq4cWO5vy8rA0wMlAGjR4+mWrVqUWxsLBH93EO2sbEhDQ0N+vz5c5mNe//+fdLX1ydFRUVycXEp9geiOLx+/ZrGjRtH8vLypKysTNOnT6cPHz6U2XjlQVpaGjVq1Ij69Okj1T6bN29OrVu3LrUbMiUlhdauXUu1atUiRUVFcnJyIhsbG9LS0iIul0uHDh0qso/hw4dT9+7diejn+/LJkye0dOlSat26NQEgWVlZ+vvvv8nFxaVM/55Pnz4lAHT8+PEyG6MgYmJiqGnTptS0aVP68uWL8HXB1pusrCwZGxvT48ePS9S/QDDcunWLjhw5QmvXrqWpU6eSnZ2dMEi0MMHg4OBAq1atov79+xOHw6EjR46UeEtCUo4ePUoAip2+SUTk5OREurq6Yq8JYloEsVRlRWRkJK1Zs4b09fUJADVu3JhWrFhRrO/bjIwMmjt3LnE4HOrWrVuZfldXRpgYKAO+fftGmpqaNGzYMOFrCQkJpKurS23bti3Tvam0tDSaMWMGAaCuXbuW+QQdGxtLS5YsIU1NTeJyuTRgwACpZlCUJ8uWLSN5eXkKCwuTar/Pnz8nOTk5mjNnjlT6S0pKouXLl5OqqioBIA6HQ4cPH5bo3iFDhlDPnj3FXgsPD6edO3eSlZUVycvLEwAyNjamhQsXUkBAgNRXS1ZWVmRiYlKmorUgPn36RPXr1ydTU1NKSEigx48fk4mJCcnKytLSpUvL7DM6c+ZMatSoEaWnpxcoGMzMzIRxCr8KhpYtW5KNjQ1NmjSJVq1aRe7u7kIPQ1paWont2rhxI6mqqpboXsF2WEGTZ5cuXWjo0KEltq048Pl8unv3Lo0bN45UVFSIw+FQz5496ejRoyIensK4desW6ejokJqaGnl4eJR4e0bS+KLKAhMDZYSgEExed/OTJ0+Ebt6yxs/Pj3R1dUlZWZl2795d5gFj6enptGfPHmFhnPbt29Pp06fLJIahLPj06RMpKirSf//9Vyb9b968mQDQtWvXpNJffHy8cDUvJydHKioqtHjx4iK3bAYNGkQWFhZF9p+cnEznzp2jMWPGCLMTateuTfb29nT+/PkSrSB/5d69e8WOqpcmb9++JQ0NDapXrx5xuVwyMzOTal67OAwNDcnBwaHQNt+/fycdHR3q0KEDvXv3rkDBIPi7SCoYgoODCxQMTk5O1KxZsxI9k6C4kIeHh9jrkyZNopYtW5ao79KQkpJCbm5u1LVrVwIg3E578OBBkd+HSUlJNGrUKAJAgwYNkjgrSJh5tKGAzKMNPzOPQmIlCx4tT5gYKCP4fD717NmT9PT0RFx8u3btKjf3aHJyMk2cOJEAkIWFRb7gs7KAx+ORl5cX9ejRgwCQnp4eubi4SBw5XVEMHDiQGjRoIJVJThw8Ho8sLCyobt26pa7dEBkZSS1atBAGUN24cYPmzZtHNWrUIHV1dVqxYkWBn8F+/fqRjY1NscbLzc2le/fu0YIFC6hFixYEgBQUFMja2pp2795NkZGRJX6Wbt260R9//FEh2Q13794lHR0dAkBNmzYts7+9gLCwsCLFD5/Pp8GDB5O6urpEbur09HQKDQ2lW7dukYeHB61du5amTJlCdnZ21Lp1a7GCQUNDI59gaNeuHbVq1apQwVAYJiYmNGHCBLHXtm3bRgoKChW6MAgLC6PFixdTo0aNCAC1aNGCNmzYQDExMYXed/r0aaFgLCyOKCIhjUYeeFjsmiQRCSX35kgbJgbKkNDQUFJUVKS5c+cKX+Pz+TRixAhSVlaWWoRtUfj4+FCDBg1ITU2N3Nzcyu2L99mzZzRixAiSlZUlNTU1mjt3brkIkuIiKKt67NixMh3ny5cvpKWlRba2tiX+G7x//550dHRIR0eHVqxYQTIyMsIiNDExMTRr1ixSUFAgDQ0NcnZ2zjfB2dnZkZ2dXameIzQ0lLZs2UI9evQQZie0adOGli1bRs+ePSvWswkCbq9evVoqm4pDSkoKTZ8+nTgcDrVv357c3d1JQUGB+vfvX6YT1o4dO4pMKTx48CABoFOnTklt3NIIht69e9OkSZNo9erV5O7uTjdv3hQrGKZOnUoGBgZixxf8jUsSnChtcnNz6fr16zRs2DBSUFAgGRkZsrW1pXPnzhWYPRQdHU0WFhYEgBwdHfM9+4nH4WS4+EqRIkCcKDBcfIVOPA4vj0cvEiYGypi1a9cSl8ulZ8+eCV9LTU0lIyMjatGiRZmvRgR8//6dRo8eTQDIzs5OJHCqrImMjKQFCxZQzZo1SUZGhoYNGybV6omlITs7m4yNjalTp07lIpK8vLwIQImK7jx9+pRq165NRkZGFBkZSZMnTyZjY+N87aKiomjq1KkkJydHtWvXps2bNwv3S21sbKhfv36lfg4BiYmJdPz4cRo6dCipq6sLs0wmT55Mly9fLrJaHp/Pp3bt2lHnzp2lZlNh3Lhxg/T09KhGjRrk4uIijIPw9PQU1nQoqxgGGxubQlMK379/T0pKSjR+/PgyGb8w9PX1afz48eTn50ceHh60Zs0amjJlCtna2kokGMzNzQkAbd26NZ9giI6OFqmFUVlITEykXbt20V9//UVA4SWQ+Xw+ubq6Cs+IEQSXlvock///2eFX8UKJiYEyJjs7m0xMTOiPP/4QWXW8e/eOlJWVadiwYeXqIr148SLVqVOHNDQ06MSJE+U6dkpKCm3fvp0aN24sDHC8dOlShQSQCdi2bRtxOBx6/vx5uY3p6OhIioqKBR7wIg4/Pz9SVVWldu3aCfcvO3ToQCNGjCjwnvDwcJo4cSLJyspS3bp1afv27WRubk4DBw4s9TOIIzs7m27evEmzZs2iJk2aEABSUlKifv360aFDhwqsxOnp6VmiHPfikJSUJNwy6969O4WG5j9E6ujRo8ThcGjWrFlS/1xkZGRQjRo1Ckz9zMzMpNatW1OzZs3KPHNAHCoqKsIzIwpC4GEQJxgEh26JEwytWrUiWVlZatu2La1evZoOHz5coIehonjz5g3NmTNHWN66TZs2tGPHjnwpne/evaM///yTZGVlacTSnVIRAoKfkxXsIWBioBx48OABcTicfAcXnThxosSrxNLw7ds3Gjx4sDA4przPH8jNzaWzZ89Sx44dCQAZGBjQrl27yv2L4evXr6Suri48cbK8SE9PJ2NjYzI1NZWozvz58+dJXl6eevXqJfQk8Xg8UlZWpg0bNhR5/4cPH2jMmDHE5XJJQUGB/vjjjzIvGMXn8+nt27fk7OxMHTt2JA6HQxwOhzp06EBr166lN2/eCCdcPp9PrVq1ol69epWJLd7e3tSgQQNSUVGh3bt3Fyo+d+7cSQBoxYoVUrXh6tWrBBR8wp+TkxPJy8uXqygVkJycLJU4JkFwZEhICPn5+dHhw4eFgqFWrVpUq1Yt0tTULFAw9O7dmyZPniwiGEJCQsr1eyE7O5suXbokUgL5n3/+ESmBnJ2dTbMWr6ZGc84JTyjN+1N3zBZSbdOb5LR0iCOnQDJqtUmpeWeq77C3UDFguPhKhcYQMDFQTkybNo2UlZXzBQVNmzaN5OTk6NGjR+Vu08mTJ0lDQ4Pq1KlTYRHdDx48oH/++Ye4XC5paGjQokWLigzqkRYODg5Us2ZN+vbtW7mMlxfBCXQzZswotN3BgweJy+XS4MGDRdLdQkJCCABdv35d4jHfv38vXPno6enRoUOHyi2oKy4ujtzc3Kh///6krKwszAWfMWMG3bhxg44dO0YApPo5iI+PF0aEW1paUni4ZCsvQZGwbdu2Sc2WGTNmUKNGjcR6HAQlfYt7LoC0CA4OJgB069atUvUzYcKEAk/EnDBhgvBMjPT09HyCYfLkyWRra0utWrUSKxg0NTWpVatWZGtrK1YwSJo2WBzi4uJo8+bNQq9H3hLIIw88pMb/ip/UlZp1JBnlWqT6hx1pWE8n9S4jiatckzhyilRvvGuhMQQjDzyU+nNIiqTzN4eICEWQnJwMdXV1/PjxA2pqakU1r1YkJyfDyMgIrVu3hpeXFzgcDgAgOzsbXbt2RUxMDJ4/fw5NTc1ytSs2NhaTJk2Cp6cnRo4cie3bt6NWrVrlagMAfPr0Cdu3b8eBAweQnZ2N4cOHY/bs2TA1NS2T8Z4/f44///wT27dvx7Rp08pkjKLYvn07Zs6ciStXrsDa2jrf9Y0bN2L+/PmYPHkyXF1dISMjI7x25swZDB48GHFxcahTp47EY3bt2hU1a9aEgoICzp49C319fSxbtgzDhg0T6b8syczMxK1bt+Dl5QVPT09ER0dDTU0NRAQDAwPcuHGj1O/Bc+fOYerUqcjOzoaLiwvGjBkj/MwVBRFh3rx52Lx5Mw4fPozRo0eXyhYAMDQ0RI8ePbB3716R12NjY9GyZUv8+eef8Pb2BpfLLfVYxcXf3x/du3fH+/fv0axZsxL3c+TIEYwePRrfvn2DlpaWyDUXFxcsWrQIqampEj1jeno6oqOjERUVhcjISLH/JiQkiNyjqamJhg0bolGjRmL/bdiwIWrUqFHs5yIiPHv2DG5ubjh+/DjSZFRRf+LuAttnRr2DQj19cGTkhK/lJEbjy8FpUG7eCVp2cwsd74ZTV+jXUS22naVF0vmbiQEpcPHiRfTv3x+nTp3C4MGDha9HRESgTZs2aNu2bYV8IRARPDw8MHPmTCgrK+PgwYOwsrIqVxsEJCUl4cCBA9i2bRuioqLQq1cvzJkzBxYWFhJ/mRcFEaFz585ITk7GixcvICsrK5V+S2JH79698ezZM7x69Qra2trC1xcuXIgNGzZgyZIlWLFiRb5nX7x4MQ4ePIiYmJhijdmxY0c0b94chw4dQmBgIJYtWwZPT0+0aNECy5cvx6BBg8r1/UdECAwMhKenJ9zd3fH582fIyMigS5cusLOzg52dHQwMDCTuLy4uDtOmTcPZs2fRt29f7N69G/Xq1SuRXRMnToS7uzvOnj2Lfv36FbsPAR8+fIC+vj4uXLgg0g+fz4e1tTVevnyJV69eFUvUSZMTJ05g+PDhSE5OhqpqySehiIgI6Orq5ntOALh27RqsrKzw8eNHNG7cuJQW/0QgGAoSC2UhGDIzMzFupw8CvskCnOJ9TmLcZgIA6tlvK7CNDJeDUe10sbyPcbH6lgZMDJQzAwYMQEBAAN69eyey+rl69SpsbGywcuVKLF68uEJsi4qKwvjx43H9+nVMmDABmzdvrrC/Y05ODs6ePYvNmzfj2bNnMDY2xuzZszF8+HAoKiqWqu9jx45h5MiRuHnzJv7++28pWVwy4uLi0LJlS/zxxx+4fPkyeDweJk+ejIMHD2Lr1q2YOXOm2Pvs7OyQm5sLHx+fYo3Xrl07tGzZEvv37xe+9uTJEyxbtgw+Pj4wNTXFihUr0K9fP6mJL0nJyclBkyZNoK2tDW1tbdy8eRNZWVlo3rw57Ozs0KdPH3To0EGsB4OIcPz4ccyYMQNcLheurq4YPHhwqZ6Bx+Nh2LBhuHTpEq5cuYKePXuWqB9XV1fMnj0bCQkJIpPt5s2bMXfuXFy7dg0WFhYltrO0bNmyBUuXLkVqamqp+9LT00P//v3h4uIi8npkZCR0dHTg7e2N3r17l3ocSSlKMERGRiIxMVHkHk1NzULFwrgLkYj8nlEsO4gI0bvGQk5LB9pDVhXaVldTCf5zexT7WUuLxPO3NPccqjNRUVGkqqoqtgrZ0qVLicPhlPq89NLA5/Npz549pKysTLq6uuTn51dhtgjs8ff3pz59+hCHw6E6derQypUrS7zPn5ycTPXq1aNBgwZJ2dKSI9gz3rRpE/Xv359kZGQKrOYmoGHDhrRgwYJij/XHH38UGDB5//596tmzJwE/T6b08vIq92JAe/bsIQ6HIzzA58KFCzRu3DhhrIOmpiaNHj2azp49K8zXj4qKIltbWwJAQ4cOlWpAbFZWFllaWpKysjI9fFj0fq64ErQ2Njb0999/i7R7+vSpVEtUl4Y5c+aQvr6+VPoaPXq0MDYgL3w+n1RUVCQKeC1v0tLSKDg4mG7evEnu7u60evVqmjRpEvXu3ZtatWpFGhoawtgFjnwN0hETNFjUj6btnJ/vX+sZRbbVW+hdIaWLWcxABbBz505MmzYNd+7cQZcuXYSv83g8WFtbIzAwEC9evECDBg0qzMaPHz9i3Lhx8Pf3x/Tp0+Hs7AxlZeUKswcAQkJCsHXrVri7u4OIMGbMGDg5ORVrn/Pff//F1q1b8f79e+jq6pahtcVj8uTJ2LdvH+Tl5XH27FnY2toW2DYhIQFaWlo4ceIEhg4dWqxxWrdujU6dOmHnzp0FtvH398eSJUtw9+5dtGvXDitXrkSvXr3KxVOQlZWFJk2aoFevXnB3dxe+zufz8fjxY3h6esLLywtv3ryBnJwcDA0N8eHDB6iqqmLfvn2lcucXRFpaGiwtLREUFIQ7d+7AxMRE5HpoXAqOPYrAreCviEhMR94vSg6AnKRYtKkrj82T+8FAWxWpqalo06YN1NTUEBAQAHl5eanbXBxGjBiBqKgo+Pv7l7qvgwcPwsHBAYmJiVBXVxe51q5dOxgZGcHNza3U45Q36enpiIqKQsC7CCx/mFWse3MSIhHjMQfyWjrQHrEeHG7RsTmXp3eGcX31IttJE0nn7/KPavmNmTx5Mtq3bw8HBwdkZf3vjSUjI4Njx45BQUEBgwcPRk5OToXZ2KRJE/j5+WHr1q3Yv38/WrdujYCAgAqzB/gZhLVr1y5ERERg8eLFuHjxotCFfPv2bRSlV8PCwrBlyxYsXLiwUgmBb9++4cmTJ+BwOKhbt26R7uiXL18CAFq1alXssXg8XpExEt26dYO/vz98fX3B4XBgaWmJrl274vbt28Uer7goKChg3rx5OHr0KD5//ix8ncvlon379li7di1ev34Nf39/NG7cGG/fvkVWVha+ffuG5cuXY+nSpXjy5An4fL7UbFJWVoa3tzd0dHRgYWGBjx8/AgAiE9Mx6uAj9Np6B0cehSP8FyEA/FxOytasizdZGui19Q5GHXyECbMW4MuXLzhx4kSFCwEAiImJKVFchTi6desGPp+P+/fv57tmZGSEoKAgqYxT3igpKcHQ0BCtzP4o1n281O/4emYFuArK0Or3r0RCAACyc6X3/pU2TAxIERkZGezbtw9hYWFYv369yLXatWvj9OnTePz4MRYuXFhBFv6Ey+Vi5syZePnyJbS0tNC5c2fMnz8fmZmZFWqXlpYWFi1ahPDwcLi5ueHz58/o0aMH/vzzTxw7dqxAETV79mzUq1cP8+fPL2eLCyYiIgKdO3dGdHQ0Tp8+jbi4OMydW3i08cuXL6GoqFiswDoBPB5PoqwBDocDc3NzBAQE4PLly8jIyECPHj3Qs2dPsV/00mTixInQ0NDI99kAfnoIXF1dYWNjg4yMDFy9ehXfv3/HyZMnYWJiAldXV7Rt2xYNGzaEg4MDvL29kZFRvP1dcdSsWRPXrl2DiooKzM3Nscf3Fcxd/BHw8WeAGo9fuBAVXL4f9g0BNXvCfvWBEv39yoIvX76gfv36UumradOmqFevHu7cuZPvmkAMSOBkrhRkZmbi9evXOHPmDFatWoXhw4djzKgREt/Pz0xD3Oll4Gemoc7gFZBVlTxTTF628k65ldeyKoqpqSnmz5+PNWvW4P379yLXOnTogE2bNmHLli04d+5cBVn4PwwNDXHv3j2sW7cO27Ztwx9//IGnT59WtFlQUFDA2LFj8erVK1y/fh21a9fGyJEj0bhxY2zYsAHfv38XtvXx8YGXlxc2bdpUovSisiAoKAgdO3ZETk4O7t+/j4EDB2Lz5s3YtWsXvLy8CrwvMDAQpqamJcqCkFQMCOBwOLCxscGTJ09w8eJFxMfHo3PnzrCyssLjx4+LPb4kKCsrw8nJCYcOHcKXL1+Er4eEhKB79+6YPn06Ro8ejTdv3sDS0hLq6uoYMmQIjh49iq9fv+L27dsYNmwYbt26BTs7O2hqaqJv3744cOAAYmNjS2yXtrY2fH19kdvMHOv8IpGVyy9SBPwKHxxwZeXhFacK11uhJbZFmkjTM8DhcNC1a1exWw5GRkZITU1FVFSUVMaSFgkJCbh37x4OHDiAuXPnwtbWFk2bNoWSkhJatmyJwYMHY8eOHYiKisKfzXSBfP6f/FBuNr6eXYnc79Go889SyGvpSGwPB4CeZsVuyRYGEwNlwOLFi6GjowMHB4d8bs0ZM2bgn3/+gb29PUJDK/5LQ0ZGBvPnz8ezZ8+gqKiI9u3bY8mSJcjOzq5o08DhcNCrVy9cvXoVr1+/hqWlJZYsWYJGjRph5syZeP/+PWbNmoUePXpg4MCBFW0uAODRo0fo0qULNDQ0cP/+fTRt2hQAMGXKFNjZ2WHcuHEFpg2+fPmyRFsEAJCbm1siEcHhcNC3b1+8ePECp0+fRkREBNq1a4c+ffogMDCwRLYUhqOjI5SUlLBp0ybweDxs2rQJrVq1QnR0NG7duoVdu3aJ3deUlZVFt27dsHnzZoSEhODdu3dYsWIFEhMTMWnSJNSrVw/t2rXDmjVr8OrVq2KvUh985YDbum/pHu7/Yy82XQ/BqScRpeurlKSlpSE5OVlqYgD4uVXw9OlTpKWlibxuZGQEABWyVcDj8fDx40dcuXIFmzdvxsSJE9GlSxfUrl0bWlpa6NKlCyZNmoSLFy8C+Jn1tX//fty7dw/x8fH4+vUr7ty5g0P7dkNXo/CJmvg8fLu4Hllf3qN2v4VQaNCiWLbqaCpBWaFi0p0lgQUQlhE3b96Eubk59u/fjwkTJohcS05Oxl9//QUFBQU8fPgQSkpKFWSlKDk5OXB2dsaqVatgbGwMDw8PtGzZsqLNEiEuLg47d+7Erl27hKlDhw8fxqhRoyrYMsDX1xf9+/dHq1at4O3tna/Azrdv39CyZUuYmpri6tWrInn/2dnZUFFRgYuLCxwdHYs9tp6eHkaOHInVq1eX6hl4PB5OnTqF5cuXIzQ0FAMGDMCKFSvyBdeVhqVLl2LDhg0wNjbGixcvMGvWLKxatarEgazx8fG4cuUKvLy8cPXqVaSmpkJXV1eYttitW7dC9/AjE9Nh7uKPrAL2cyk3B0l3jyLt7S3wM1MhV1sPNbuOQo3GZgX2qSDLxQ2nbmikUTGf7bCwMBgYGEg1zfbt27cwMTGBr68vzM3Nha/z+XyoqKhg9erVmD17tlTG+pW0tDSEhITg/fv3eP/+Pd69e4f3798jJCREGJ+lpKSE5s2bC39atGiB5s2bQ19fX6K05eWeb3Hk4WfwCpgRE2/sQ8pTT9TQbwul5l3yXVcxKThtsCrUGWCegTKiZ8+eGDNmDObNm4e4uDiRa2pqajh37hzCwsIwderUSrPXJicnh6VLl+LRo0fg8Xj4888/sWbNGuTm5la0aUK0tbWxcuVKPHr0CPLy8lBXV8fo0aPRoUMHnD17tsJsPXv2LHr37o2uXbvC19dXbKW92rVrw8PDA76+vti6davItXfv3iEnJ6fEnoHibhMUhIyMDIYPH46goCC4ubnhxYsXaNmyJYYNG4bg4OBS95+Tk4OcnBxkZWUhPDwc9+/fx5YtW0qV0aKlpYXRo0fjzJkziI+Px9WrV2Fra4tLly7BwsICWlpa+Oeff3DkyJF8xWoA4L8Lr5FbyLZA/GUXJD+5CGWj7qhl7gAOl4uvZ5YjM/Jtgffk8gn/XXhd4mcqLQLvkzQ9A0ZGRtDS0soXN8DlctGiRYtSewaICHFxcbh9+zb27NmDWbNmwcrKCrq6ulBRUUGbNm0wfPhw7Nu3T7ittWHDBly7dg3h4eFISUnBs2fPcOzYMSxZsgSDBg2CiYmJREIgKSkJMffOFCgEACA77meAaUbYYyR4b873Uxg8PmFke8m3FCoC5hkoQ+Lj49GiRQuYm5vjxIkT+a4LynyK8x5UNFlZWVi+fDk2bNiAP/74A4cPH0aLFsVzi5UlY8eOhbe3N4KDg/HgwQNs3rwZt2/fhp6eHmbNmoVx48aVqupacdi7dy+mTJmCYcOGwd3dHXJycoW2nzNnDnbs2IFHjx7BzOzn6tLDwwNjxowp8WesXr16mDp1KpYsWVKiZyiInJwcuLm5YfXq1YiOjsbIkSOxZMkS6OvrF7uvFy9ewN7eHm/evMFff/2Ft2/fIiIiAjVr1pSqzQKICK9evRKmLT558gRcLhedOnVCnz59YGdnB27N+ui1NX9QnICsL8GI9ZiDmj3GQb3dgJ/95mbjywFHyCiro+6oTYXaUFElaE+dOoWhQ4ciKSkpXypgaRgwYAASExPzZaCMGjUKHz58kCgzKTc3Fx8/fhRZ4Qt+kpKSAPwUpfr6+vlW+c2aNZPq+yU7Oxu7d+/GypUrkZmZiVYz9yMO6oWKguIiw+WgYxNNHBnfTnqdFgPmGagEaGlpwcXFBSdPnsSVK1fyXR81ahQcHBwwbdo0vHjxogIsLBgFBQU4Ozvj/v37+PHjB8zMzLB582bweLyKNg2PHj3C4cOHsXbtWmhqasLW1ha3bt3Cs2fP0KlTJ8ydOxeNGjXC/PnzERkZWWZ2EBHWrl2LyZMnw9HREUeOHClSCADA2rVrYWxsjOHDhwv3XwMDA9GkSZMSi21peQZ+RU5ODg4ODggNDcX27dvh6+uL5s2bY8KECQgPD5eoj8zMTCxatAh//fUXiAiPHz/GhQsXkJ2dDVdXV6nbLIDD4aBVq1ZYsmQJHj9+jOjoaOzZswfq6upYsmQJmjdvDqtpa8ChgtO90oPvAxwuVFv/r4w3R1YeKq16ISv6PXKTvxV4rwyXg6MPKyZ2ICYmBjVq1JD64q1r1654+PBhvswjcRkFycnJePLkCY4cOYJFixZh4MCBMDIygpKSEpo1a4a+fftizZo1CAoKgqGhIebPn4/z58/j3bt3SE9Px/v373Hx4kWsW7cOY8aMQbt27aQmBIgIZ86cgZGREWbPno0BAwYgNDQUp+b2g6yMdKdFWS4Ha/uXzVks0oSJgTJmxIgR6NWrF6ZOnZov8AYAtm3bBmNjYwwaNEioiisT7du3x4sXLzBlyhTMmzcP3bt3x4cPHyrMHj6fj+nTp8PMzAzjx48XudamTRscPXoUnz59wqRJk7Bv3z40adIEI0aMwLNnz6Rux5w5c7Bo0SKsWLEC27dvl7j2v4KCAk6cOIHw8HDhHmtpggeBshMDAhQUFODo6IgPHz5g48aN8PLygoGBAaZMmVJoFPnDhw/Rpk0bbNy4EcuWLcOTJ0/Qpk0b1K1bFxMnToSLi4tUyuVKQv369TFx4kR4eXkhISEBly5dgnxjM1Ahteiz4z5CTqMBuAqie//y9QyF1wuCxyfcCvkqHeOLiSCTQNoFpbp164asrCw8efIE+D/2zjoqqvXr498JOqRLQhERwQBbVFBBFL222GLrtVvx2t2K3X3t7sbuFhQVxQREBAUFyfm+f/gyP5GagQH1Op+1Zi0954l9DjPn2Wc/O/D/6XjDwpCSkoLY2Fh069YNnp6esLS0RJEiRVClShX4+vpi06ZNiIuLg6enJ/z9/XHmzBmEhYUhNjZWqtyPHj0azZs3h4ODQ4Hmabh8+TJcXV3RunVrlCpVCg8ePMDq1athYWEBKwNNTFLwvv7kJk4/zXdEHpTKQAEjEAiwfPlyREZGYsKECZnOq6urY/fu3YiJiUHnzp1/Gf+B79HU1MSCBQtw7tw5hIWFoVy5cli2bJlCE8DIysaNG3Hz5k0sWrQo28XP0tISs2bNwtu3bzFv3jxcvXoVlSpVQu3atXHw4MF8y52SkoKuXbvC398fS5cuxfjx4+V+6Do4OMDf3x+rVq3C3r17cf/+fTg7O+dZpoJWBtLR0NDAkCFDEBoaiqlTp2LXrl2ws7PDoEGDMoT3JSQkYNiwYXB1dYW2tjbu3LmDcePGZXjIjxgxAnFxcVixYkWBy/0jmpqaqFu/IRJF2jm2S/sSA5F2Zv8PkbaB9HxOvI5OQHxS4fuxKDLHAPDNnP7o0SM8f/4campqGDBgACpXrgxdXV1YWlpKn23nzp2Dnp4eunTpgs2bN+PWrVuIi4vDmzdvcOrUKSxatAh9+/ZF3bp1YWFhUah1Mp4+fYoWLVqgZs2aSEpKwpkzZ3DkyBE4OWVc/NtWtsZwr2/KXn6fxyO8SqFN5V/bVyAdpTJQCJQoUQITJ07EggULcOfOnUznixcvjk2bNuHgwYOYM2fOT5BQNtzc3PDgwQP4+vqiX79+8PLywuvXhWcGjY2NhZ+fH9q3b4+aNWvm2l5bWxsDBw5ESEgIdu/ejeTkZDRt2hQODg5Yvnw5EhIS5Jbh69evaNmyJbZu3YqtW7eib9++ebkUAN+S8DRv3hzdu3dHdHR0viwDeQ0tzCtaWloYOXIkQkNDMXbsWGzatAm2trYYMWIEDhw4gHLlymHp0qWYNWsWrly5kmU0grW1NTp37ox58+YpJIGQvLyKjs81spypyYAo89aPQKz6v/M59QfwMjqzRbCgyWuOgY8fP+Lq1atYv349Ro0ahaZNm6JUqVLQ1NSEk5MTfHx8IJFI8PLlS5QrVw7jx4/HwYMH8ejRI6iqqmLIkCHYvXs3pk6dio4dO6JixYqF5ruTHVFRUejfvz+cnJxw+/ZtqZKSU5RFv9p2MAo9CaQmAzlsI2WFSCiAmliIWS3Kol8d+X1rfhZKZaCQGDp0KMqUKYOePXtm6fHeuHFj+Pn54Z9//lFILvGCQltbG8uXL8eJEyfw5MkTlClTBuvWrSsUi8bkyZMRHx+P2bNny9VPJBKhZcuWuHLlCq5cuYLy5cujf//+sLa2xrhx42ROWBMbG4v69evjzJkzOHTokNz1A35EIBBg9erV0u2F/IRxFpZl4Ed0dXUxduxYvHjxAgMGDMDChQvRrFkzJCUl4fz58xgxYkSOSoqfnx/ev3+PdevWFaLU35AlNaxArAqkZc58ma4EpCsF+Z1H0YSHh2erDEgkErx69QonTpyAv78//v77b9SuXRtmZmYwMDCAq6srunfvjp07dyI5ORkNGzbEsmXLcP78eURGRmLKlClITU3FihUrMGLECDRu3Fjq4PcrpSVOSEjA9OnTUaJECfz777+YNm0anjx5go4dO+a6pbdhwwbc3rkIkRsGoJLlN2VGJMzZipF+3tXWEKeHuP82FoF0lMpAIaGiooLVq1fj7t27WLRoUZZtpkyZglq1aqFt27Zy17MvbLy8vBAYGIiWLVuie/fu+OuvvzJklVM0wcHBWLRoEcaMGZOvQk/Vq1fHrl278OzZM3Ts2BH+/v6wsbFBt27dEBiYfSjYu3fv4O7ujqCgIJw+fRoNGjTItq08pGfRA4CdO3fmeZyfpQykc/36dWzfvh2qqqqoV68eoqOj4eXlhYkTJyI2NjbbfnZ2dmjbti1mzZpV6ImuZEkNK9I2QNqXj5mOp28PpG8X5HceRRMREQFjY2M8ePAAO3fuxOTJk9G+fXu4uLhAW1sbxYoVQ4MGDTB69Ghcu3YNZmZm+Pvvv7Ft2zbcvXsXX758wYsXL3Ds2DEsWLAAvXr1gpubG0xMTFC7dm3Ex8dnsnL+KjUK0tLSsHHjRpQqVQoTJkxAt27d8OzZM4wcOVKmMMOIiAgMHjwYQqEQw3p3we7+tXFqsBs6VbWBjaEmflQJBPhWnrhTVRucHuKGzd2r/hY+AplQZAlEJbkzYMAAampq8sWLF1mej4iIoLm5Od3d3ZmSUvjlLvPCwYMHaWZmRn19ff77778KL48rkUjo5eXFEiVK8OvXrwod++PHj5w9ezYtLS0JgF5eXjx+/HiGawgNDWWJEiVobm7OwMBAhc5Pkj4+PrSysqJYLObNmzfzNIZAIODKlSsVLFnuxMTEsGvXrgRADw8PhoaGkiQjIyM5bNgwqqurU09Pj1OnTpWWJv6RoKAgAuDatWsLU3R+/JyQa9lZ3SotCIGQVkN2Zjiu5+ZLACzad/1PL1sbFRXFixcvctWqVRw6dCjr168vLc2b/jE2NmatWrXYs2dPzp8/n0ePHmVoaChTU1Plni85OZmampqZyhZPnjyZBgYGhV4e+3tOnjzJ8uXLEwBbtWrFkJAQucdo0aIF1dTUaGpqys+fP2c6n1U5618ZWddvpTJQyMTFxdHS0pLe3t7Z/mjOnz9PkUhEPz+/QpYu73z48IHt2rUjADZv3pyRkZEKG/vAgQMEwIMHDypszB9JTk7mli1bWKFCBQKgk5MT165dy9u3b9Pc3Jx2dnbShU7RlCxZkv369WPFihVZsmTJLB9AOSGRSAiAa9asKRD5suPAgQM0Nzenrq4uV69eneX3OTw8nAMGDKCqqiqNjIw4e/ZsxsfHZ2rXvHlz2tnZFagCnJqaytu3b3POnDn09vampqYmLXqvynExN/OdRwDUq9NNesx6+D6K9c2palEqV2XCbU6AwmR/9uwZDx8+zLlz57J79+6sUaMGDQ0NpQu+UCiknZ0d69SpQwAcOnQoL1++zA8fPihEhu/x9PRko0aNMhzbvXs3ASj0ty8r9+/flypBrq6uvHLlSp7G2bVrl/R+bty4UcFS/hyUysAvTPritn379mzbzJ49mwB44MCBQpQs/+zatYtGRkY0MjLi7t278z3e169faWtry/r16xfKG4dEIuG5c+fYpEkTAqBAIKCZmRkfPnxYIPN9+fKFAoGAa9eu5ZMnT6ipqclu3brJNUZKSgoBcP369QUi44+8f/9eqvg1bNiQb968ybXP69ev2bt3b4rFYpqamtLf3z+DlefWrVsEwK1btypMTolEwqCgIC5evJjNmzenvr4+AVBFRYXGxsYUi8XU9+xFm5EHclzQNR1qEkIRdau2oEGD/lQrWpoQimjafmaO/Wz/OcIJB4LkkvnLly+8ffs2t2zZwnHjxtHHx4dlypShmpqadJHS1NRkhQoV2KFDB06ZMoW7du1iYGCg9H5eunSJABgUJN/c8jBlyhQWKVIkg2Xh0aNHBMCzZ88W2Lw/8vbtW3bt2pUCgYAlS5bknj178vyciI6OpomJCYsUKcLKlSszLS1NwdL+HJTKwC9OixYtaGJiwpiYmCzPSyQSNmvWjHp6enz+/HkhS5c/3r17x2bNmhEA27dvz+jo6DyPNW3aNIrFYgYHBytQwtw5evQo1dXVaW5uTnV1daqrq7N37958/PixQue5evUqAfD27dskybVr1xIAd+3aJfMYiYmJBMDNmzcrVLYfkUgk3L59O42MjGhgYMDNmzfL/eB98eIFu3XrRpFIRAsLCy5dupSJiYkkSW9vbzo5OeX5ISyRSPjs2TOuWrWKbdu2pampKQFQLBazVKlStLe3p4qKCgGwevXqnD9/Ps/fe5rr27318L3UrdKCIi19QqRCVfOSNGk9Kdd+Nn6HGRKZeWtEIpEwIiKCZ8+e5bJlyzhw4EB6eXnR2to6g2nf3NycderUYZ8+fbhw4UKePHmSr1+/zvX+pL/d5ud3lxvnz58nAN65c0d6LDk5mWKxmEuXLi2wedOJi4vjmDFjqKGhQSMjIy5evJjJycn5GrNz587U0NAgAF69elVBkv58ZF2/lemIfxJhYWFwdHREmzZtsGrVqizbfPr0CZUqVUKRIkVw+fJlmZxffhVIYsuWLRgwYAA0NDSwevVqNGrUSK4x3r59i1KlSqFPnz6YOzfntK+KZNu2bfD19YW3tzd27NiB+Ph4rFy5EosXL0ZkZCQaN26MoUOHwt3dPd9x0itWrED//v3x5csXqKurgyRat26N06dP48GDB7Cyssp1jPj4eGhra2Pr1q1o165dvuTJjoiICPTr1w/79u1Dy5YtsXTpUpiamuZ5vJCQEEyePBlbtmyBlZUVxo0bh5IlS6J27drYu3cvmjdvLtM4b9++xdmzZxEQEICAgAC8fv0aQqEQzs7OMDc3x4cPH3D37l0kJyfD1dUVPj4+aNmyZYb72mntdVwJjZa7bHFOiIQCVCtugPG19DOk201Pv5vuVJmedjfdG//7T17TCC9atAgjR47E169fCyyOPzExEXp6epg1axYGDRokPe7k5IQ6deoUWGbJlJQUrF69GhMnTsTnz58xZMgQjBo1Kt8pl0+cOIEGDRpAW1sbzZo1w+bNmxUk8c9H1vVbqQz8RJYvX46+ffvi/PnzcHNzy7LNvXv3UK1aNXTu3BkrV64sZAnzT1hYGHr06IHjx4+jW7dumD9/vsw/3Pbt2yMgIABPnz4ttO/d0qVLMWDAAPj6+mLNmjUZwuKSkpKwbds2zJs3D0FBQahQoQKGDh2K1q1by5SGOCv69OmDS5cuZYhk+PjxI8qVKwdbW1sEBATkGiWQ/vvcsWMHWrdunSc5soMkNm3ahMGDB0NVVRVLly5Fq1atFDZ+cHAwJk6ciJ07d8LW1haqqqrQ1NTErVu3slzI3r9/j3PnziEgIABnz57F06dPAQDly5dH9erVoaamhsePHyMgIAApKSmoUaOGVAGwtLTMUobcqhbKC0kIJKmIXNcfidFhAL6FYP6YZ9/BwUF6zYpk9OjR2L59O168eKHQcX/E3d0dRkZG2LNnj/RY69at8eHDBwQEBCh0LpI4ePAgRo0ahadPn8LX1xdTpkyRSVnOjc+fP0vzYERFRSEkJCRfEUu/GjKv34o0MyiRj7S0NLq6urJUqVJSU2lWrFmz5rd2aJFIJFy9ejW1tbVpZWXFU6dO5drn4sWLhboPLpFIOHHiRKnjVU6mWIlEwhMnTkgdlooWLcpZs2bx48ePcs9brVo1dujQIdPxc+fOUSAQcNq0abmOERMTQwAK8dH4nlevXrFBgwYEwI4dOxaII1o6Dx48YPPmzaUm8lGjRjE1NZUfP37kgQMHOGjQIJYtW1Z6vlSpUuzTpw/Xr1/PRYsWsWHDhlRRUaFAIGDNmjW5cOFCvn37Vub5t15/JZPZX9ZP0Vo+nDVrFs+cOcPw8PBC9bD39fWlq6trgc8zduxYGhkZZbi2CRMm0NTUVKHzXL9+nbVq1SIAenp68u7duwodv3///tTQ0KBYLOaUKVMUOvavgNJn4DchMDCQYrGYEyZMyLFd165dqaGhwQcPHhSOYAXAixcvpJ7Offv2zdZrPjU1lc7OzqxSpUqhOPGkpaWxf//+BMAZM2bI9eAODAxkt27dqKqqSi0tLQ4cOFDmqIPU1FRqaWlxzpw5WZ7/559/KBKJeO3atRzHef/+PQFw//79MsudE2lpaVyxYgV1dHRoYWHBQ4cOKWRcWbh48SK1tLQIgBoaGhQIBARAa2trdu3alZs3b2ZQUBDXrVtHb29vqQJQq1YtLlq0iGFhYXLPKZFI2L9/f+pWb60QRWDkhjM0NjZmiRIlCt3XhSTr1avHli1bFvg8p06dIoAMzrU7duwgAIUojs+fP2ebNm0IgGXKlOGxY8cUrlRdvHiRAoGATk5OtLGxYUJCgkLH/xVQKgO/EWPGjKGqqiofPXqUbZv4+HiWK1eOJUuW/K3/DmlpaVy8eDE1NDRoa2vLCxcuZGqzYsUKAsh1EVQESUlJbNeuXb7j9CMiIjhu3DgaGhpSKBSyZcuWuYY3PXnyhAB48uTJLM8nJyezSpUqtLW1zTZGP31uAApZtJ89eyZV2Hr06JEna4c8JCYm8ty5cxw/fjxr1qwpdfADQAMDAwKgg4MDN2/ezLVr19Lb25tisTjfCkBMTAyvXLnCNWvWsGLFigRAExMT6jg3oNWwPbQesV8uBcD2nyO0H3uU22+8IvktN4WjoyP19PR45swZRd+2HClTpgz79+9f4PN8+fKFYrGYy5Ytkx4LDAwkAF68eDHP40ZHR3PIkCFUUVGhhYUF165dm6d8CLnx9etXlipVig4ODgTAnTt3KnyOXwGlMvAb8fXrV5YsWZK1atXK8U346dOn1NXVZatWrX5qYg9F8PTpU7q6ulIgEHDo0KFSjTw6OpqGhobs0qVLgcvw5csXNmjQgKqqqnJ57+dEfHw8V6xYQXt7ewJgtWrVuGvXriwfZjt37sw1LvvZs2fU1tamr69v1teQmMKAu0+pam7PlTuP5DkBSmpqKv39/ampqclixYrJtJWTF1JSUnjt2jVOnz6dnp6eVFdXJwDq6+uzRYsWXLJkCR8+fMhy5crR3d2do0aNkioF6W+IixYtYnh4eK5zpaWl8cWLFzx27BgXLFjA3r17083NjSYmJpmS8jg5OXHIkCFcuXIldx87y9bLLkgX+dyUABu/w+y45hpfR2fMn/Dp0yfWq1ePYrG4UHNAGBgYcPr06YUyV7Vq1di2bVvp/xMTEykSifKkWH/9+pVz5syhnp4etbW1OWXKFH758kWR4mZg9OjRVFVVpa2tLd3c3H77Z2p2KJWB34yAgAAC4KpVq3Jst2fPHgLgggULCkewAiQ1NZVz5syhmpoaHRwceP36dfbv3586OjqMiIgo0LljYmLo6upKLS2tAln40tLSeOjQIdauXZsAWLx4cfr7+2d4wx8zZgzNzc1zHWvjxo0EwG3btpEkn76L44QDQXSbHcBiWWS8c5sdwAkHgvj0XfbWhO8JDg5m9erVCYD9+/eXO+lRTqSlpfHu3bucN28e//rrL+ro6BAAtbW12ahRI86dO5d37tyRKsEfPnzgmjVrpFnkBAIB3d3dOWDAAFaqVEmaVOb06dPSh3dCQgLv3bvH7du3c+LEiWzbti2dnZ2lYWIAqK6uzvLly7NNmzacMGECt23bxi5duhAAlyxZkqXs0vs8J/N9th51iBUnHOSEA0FZhg+mk5yczN69exMAR44cWeDbXulhpoXlazNy5Eiam5tnWEhLlSrFQYMGyTxGWloat2zZwmLFilEkErFPnz589+5dAUj7P+7cuUORSMSGDRtSIBBkCJH8r6FUBn5DunTpwiJFiuS6EA4dOpRisZiXL18uJMkKlocPH7JSpUoUCAQUCAScOXNmgc4XFhbGMmXK0NDQkNevXy/QuUjy9u3b7NChA8ViMYsUKcIRI0bwzZs3bNSoERs0aJBrf4lEwrZt21Lf0o4tF5/N9xtrOikpKZwxYwbV1NRYsmTJLLds5EUikTA4OJhLly5ly5YtpRny1NXV6eHhwWnTpvHq1asZYsI/fPjA1atX08vLiyKRiEKhkO7u7jQ1NWW9evWk40ZGRnLu3LksVqyYdBvB3Nxc6leA/0+76+bmxl69eknT7r548SLDIiyRSPjPP/8QAP39/WW6rh9T0JpZ2nDMmDEy35P58+dTIBCwRYsWWWZgVBQvXrwgAB4/frzA5view4cPE0CGtL/NmzeX/t1y49y5c1Ilr2nTpoXiY5GcnExnZ2fpNk7Pnj0LfM6fiVIZ+A358OEDjYyM2KZNmxzbJScns0aNGixatOhPSf1ZECQnJ7N48eJSk62iPYbTCQkJYfHixWlpaZmjj0ZB8ObNG44cOZJFihShWCymhoaGzNsha88F02b43lyz5WW3l73t//ey07l//z4rVqxIoVDIESNG5Mtx6sWLF1y7di07dOhAc3NzaaKfGjVqcNy4cTx79mymmhJRUVFctWoV69WrJ1UA6tSpwyVLlvDq1as8dOiQ1HmsfPnyGbYKhEKhNA0yADo6OnLlypUyO61NmDCBADhv3rw8X7O3tzcbNmwoV58DBw5QS0uLlSpVkmmbIy9cuXKFAArN0fjTp0/SDJrpjBkzhkWLFs2x36NHj9i4cWMCYOXKlXn+/PmCFlXK9OnTKRQK6ePjQ11d3f/MMzQ7lMrAb8q///5LADx8+HCO7d6+fUsTExN6enoWiHNNYZOeNW3JkiUsV64cxWIxJ0+enO+sYt9z9+5dmpqaslSpUnz16lXuHQqIuLg4Tp8+Xbq4ubu78+DBg9makBcH5J4lT5bP4oCnTEpK4oQJEygWi+nk5JQny0hYWBj//fdfduvWTfqWLhAIWKlSJY4cOZLHjx/Pcqvh/fv3XLlyJT09PSkUCikQCOjo6Ehvb2/+9ddfLFOmDFVVVaX3RUtLi6qqqrS2tpam3Q0KCpKG4aalpXHPnj0sU6aMNDXyrVu3cpR98uTJBMBZs2bJfd3f888//8i0xfMjd+7cYdGiRWllZcV79+7lS4asSN9GjIqKUvjY2eHi4pLBp2XLli0EwE+fPmVqGxERwd69e1MkErFYsWLctm1boab9DQ4OppqaGrt06UKhUMi5c+cW2tw/C6Uy8JuSXqHP2to6173b06dPUygUcvz48YUkXcEQHx9Pa2trNm7cmOQ3D/8xY8ZQJBKxYsWKCsmxfuHCBerq6rJixYp8//59vsfLL2fOnCEALly4ULpfb29vz+XLl2cwI2+78S3+3WroLhap0Y7qxStQqK5NADRsODjTgm/mO4/aLg2palqCEIoIIMN5e+8uFIvFHDduXI65Lb7nw4cP3L17N/v27Sv1vE535hs4cCD379+fZVptiUTCwMBADhkyhKVKlZKa87/Ps4/v0u727duXixYtkqbdlUgkXLFiBQUCQY7m47S0NG7bto2lSpUiADZr1oz379/P1G7atGkEIFPuhtxIV17zsrf99u1buri4UFtbO1elX14WL15MFRWVQnWGGzx4MIsVKyb9/927dzOl9P3y5QsnTZpELS0t6uvrc968eTJ//xRFWloaa9SoQTs7O9auXZslS5ZkUlJSocrwM1AqA78xz58/p4aGBocMGZJr26lTp1IgEPDYsWOFIFnBMGHCBKqqqmYqN3r9+nU6ODhQVVWVs2fPzrMF5NChQ1RXV2fdunVzDNErTObNm0cNDQ3pNV25coWtWrWiUCikoaEhx44dy9uPX9J+7NFvSWz+/lazQKRrTDXrstkqA0VqtCOEYqqa2VFsUDSDMmA96hBtRuzj8Ys5l0mOjY3l4cOHOXToUDo7O0sX8ZIlS7J3797cvn17hkUwOTmZwcHB3LdvH2fMmME2bdpIncHSF/z0gk/e3t708/Pjxo0bef369SzfHr8nMTGRFhYW7Ny5c673NCUlhZs2bWKJEiUIgD4+PtIY+FmzZhEAJ02alOs4svDs2TMCyPPv7suXL2zSpAmFQiEXLVqkEJnIbxYLa2trhY0nC3v37iUAqbUtISFBunWQmprK1atX09zcnKqqqhw2bFi29VgKmiVLlhAAp06dqrBQ3N8BpTLwmzNr1iwKhcJczZ5paWls2LAhDQwMfqrpO6+8ePGC6urqHD16dJbnExISOGzYMAoEArq6uvLp06dyjb9x40aKRCK2aNEi0771z8TX15eVK1fOdDw0NJSDBg2itrY2TdtOpc2og/9fLGcfLftv/vb233lBtsqA5YDNtBq2hzZ+h6lToVEmy4DtP0fYcU3G/A3x8fE8deoUR48ezapVq0oXcUtLS3bu3JkbN27k69ev+enTJ16/fp0bNmygn58fmzVrRgcHB4rFYumin95XIBDQzs6Offr04eXLl/O13ePv70+RSCRzMqfk5GSuWbOGNjY2FAgE0rLUirSgpaWlUVdXN18hfKmpqRw2bBgBsF+/fgop39y1a1dWrVo13+PIQ1RUFIGMhbJKlCjB5s2bS7dw2rZtW2AlwGXh5cuX1NbWZs+ePVmiRIlCq4L6K6AsVPSbk5KSgsqVK0MoFOLGjRsZcuT/SExMDCpUqABTU1NcuHABampqhShp/mjVqhWuXr2KJ0+eQFtbO9t2ly5dQpcuXRAeHo5Zs2ahX79+EAqFOY7t7++PIUOGoHv37li5cmWuOf4LE2dnZ1SpUiXbIlW3n4Wj5dq7WZ5LigjBu41DYNhwMLTLeWY7R8zJ5fh85whs/A5nOjfLTRtPbp5HQEAArl69iuTkZJiYmKB27dpwcXGBmZkZ4uLi8OTJE2lxnYiICGl/Kysr2NraQiAQIDw8HCEhIRAIBKhbty5at26N5s2bw8jISM67kjUJCQkoVqwYWrZsieXLl8vcLzk5GR06dMDu3bshEAjQuXNnjB8/HsWLF1eIXO7u7jA1NcXOnTvzNc6qVavQt29feHl5Yfv27fl6xjZo0ACamprYu3dvvmSSlzJlysDV1RWrVq3C3bt34eXlhQ8fPsDNzQ1z585F5cqVC1We7yEJb29vPHz4ED179sTkyZPx4MEDODo6/jSZChNZ1++cn6ZKfhoqKipYvXo17t27h4ULF+bY1sDAALt378a9e/cwfPjwQpIw/wQEBGDPnj2YM2dOjooAANSsWRP3799Ht27dMHDgQHh6euLly5dZtiWJsWPHSiuarV69+pdSBJKTk/Ho0SOUL18+2zaHHn2ESFgwFecoSUOf+Vsxd+5cJCQkoF69emjUqBGsrKxw5MgRjB49Gl27dsWIESNw4cIFGBoaonv37vj3339x4sQJzJs3DyVKlMDFixdx8eJFFCtWDKtWrUJkZCROnTqFnj17KkwRAABNTU0MHToU69atQ1hYmMz9Vq9ejd27d2Po0KFYsGABjh07Bnt7e/Tu3Rtv3rzJt1wuLi64ezdrhU0eevXqhWPHjuHKlSuoWbMmXr9+neexIiIiYG5unm+Z5MXNzQ1nzpyBr68vKlasCIlEAmNjY5w7d+6nKgIAsHnzZpw4cQIzZszAnDlz0K9fvz9GEZAHpTLwC1O5cmUMGDAA48ePz3bhS6dSpUrw9/fHkiVLsH379sIRMB+kpqZi4MCBqFGjhsxld7W0tLBkyRKcPn0az58/R9myZbF69Wp8b9xKS0tDnz59MG3aNMyZMwczZ84ssDKueSU4OBgpKSlwdnbOts3ZJ+8VWlL3ewRCETRsK+Hz58+4efMmrly5go8fP8LZ2RkTJ07EoUOHEBISgvj4eAQGBmLx4sUwMzPD6tWr0aBBA4waNQpqampSBeDEiRPo0aOHQhWAH+nbty80NTVlLmWdXhp66NChmDt3LgYNGoTQ0FDMmDEDe/fuhZ2dHfr374/w8PA8y+Ti4oJnz54hLi4uz2OkU69ePVy5cgVfvnxBlSpVcOPGjTyNEx4eDgsLi3zLIw+xsbEICwtDaGgojh49imXLlmHu3LmIiorCly9fClWWH4mMjMTgwYPRoUMHnD17FqqqqpgwYcJPlemXRZF7DkoUT1xcHC0tLdmgQYNc97gkEgk7dOhALS2tQo+hl5dFixblK/NXbGwsu3fvTgBs0KAB3759y8TERPr4+FAoFHLdunUKllhxbNiwgQCydWb8nJiSKeNdhoiBHHwGvv9k5TPwv88hngw4z/fv32f5vQoPD+fixYvp5uZGgUBAsVjMBg0acO3atYyOji7oW5Ql48ePp4aGRq7RIKtXryYADho0KMtrSw/t1NfXp7q6OocMGZKnWPP79+8TgEKSNaUTGRnJ6tWrU11dXe4U2UlJSQSQIea/IElKSuLChQtpaGgoTSu9YcMGkuTNmzcJgDdu3CgUWbKjVatWNDIy4qlTpygQCLh06dKfKs/PQNb1W2kZ+MXR0dHBsmXLcPz4cezYsSPHtgKBACtXroSNjQ1atmz507Xy7IiKisL48ePRs2dPuLi45GkMXV1drFmzBocPH8b9+/fh5OSESpUq4eDBg9izZw+6du2qYKkVx/3792FrawsdHZ0sz7+KjkfB2AS+RwCLUuVhbGwstZyEh4dj8eLFcHNzQ9GiRTFkyBBoaWlh7dq1iIyMxLFjx9CtWzcYGBgUuHRZMXDgQIhEIixYsCDbNuvXr0evXr3Qr18/LFiwIEurkI6ODkaPHo0XL17Az88Pa9euRfHixeHn54fo6GiZ5SldujTU1NQUslWQjomJCQICAtCsWTP4+PhgxowZGSxfOREZGQkABb5NQBK7d++Gk5MThgwZgmbNmuH58+coWbIkbt68CQBwcHAAADx69KhAZcmJvXv3Yvfu3Vi0aBEmTpwIJycn9OrV66fJ86ujVAZ+Axo3boxWrVph0KBBiImJybGtlpYW9uzZg9evX6NXr14yP0gKk7FjxwIApk6dmu+xGjVqhAsXLkAsFiMoKAiVKlVC9erV8z1uQXLv3r0ctwiSUyWFIkdyqgRhYWFYtGgRatWqBUtLSwwbNgw6OjpYt24d3r9/j6NHj6Jr164/TQH4HkNDQ/Tp0wdLlizBx48fM53ftGkTunfvjt69e2Px4sW5bg8VKVIEEyZMwMuXLzFkyBAsXboUxYoVw7hx4/Dp06dc5VFRUUGZMmUUqgwAgLq6OrZu3Yrx48fjn3/+Qbdu3ZCcnJxrv/Qtj4LcJrhy5Qpq1KgBHx8f2NnZ4d69e1izZg0sLCzg5uaG8+fPAwC0tbVhY2Pz05SBjx8/ol+/fmjcuDEA4PLly/D398/REftPR6kM/CYsXLgQiYmJGDlyZK5tHRwcsGbNGmzbtk0u7+vC4M6dO1i9ejUmT54MY2PjfI/39u1bNGnSBEKhEHPmzMHTp0/h5OSEXbt2KUBaxUMS9+/fz9F5UFVcOD/L3j27w9LSEsOHD0eRIkWwfv16REZG4siRI+jSpQv09fULRQ55GDp0KFJSUrBkyZIMx7ds2YIuXbqge/fuWLp0qVx+Ivr6+pg6dSpevHiBPn36YN68eShWrBimTJmSqz+AopwIf0QgEGDSpEnYvHkztm7dCi8vr1xfBNKjPQrCMhASEoJWrVqhRo0a+Pr1K06dOoVjx46hbNmy0jZubm4ICgqSWlccHR1/mjIwbNgwJCQkYP78+Rg5ciSaNWsGDw+PnyLL74JSGfhNsLCwwKxZs7B27Vqp9p0Tbdu2Rf/+/TF48OA8OyMpGpIYMGAAHB0d0adPn3yP9+TJE9SoUQPx8fG4dOkShg8fjocPH6J27dpo3bo12rZtK5fZtzAICwtDTExMjpaBYoZaKGiXR5KIfvkYo0aNwps3b3D48GF07tz5l1QAvsfMzAw9evSAv7+/dBtsx44d8PX1RefOnbFy5cpcQ06zw8jICLNnz0ZoaCi6du2KadOmoXjx4pg1axbi4+Oz7OPi4oKHDx8iKSkpz9eUEx07dsSZM2cQFBSE6tWrIyQkJNu24eHhEIvFCnXk/PDhAwYOHAhHR0dcv34dGzduxO3bt+HpmTmk1d3dHcC3MGDg5ykDp06dwvr16zF37lxs2bIF79+/l9nx9I9GkQ4ISgqWtLQ0urq6slSpUjIl0ElKSmLVqlVpbW0tcxGXgiS97sKZM2fyPdatW7dobGxMR0dHvnnzJsM5iUTCrVu3Ul9fn6ampjxw4EC+51MUhw4dIgC+fPky2zaRkZEs+8/eTE5/+vV6s0itjtR2aUgA1LR3ZZFaHVmkVkdaDd7xLVNhn3XSY6oW39Lzpv/f8K+h/0tLPGwrTU1Nv42jqcmGDRvS39+fwcHBv3wyllevXlFFRYVz5szhrl27KBKJ2KlTJ4XX6Hj79i379u1LFRUVGhsbc968eZkKOqUXBrp9+7ZC5/6RZ8+esVSpUjQwMMi2qM/YsWNpaWmpkPkSEhI4Y8YM6urqUldXlzNmzJCpmJW1tbU0c+ratWspEAgKtErjj3z+/JnFihVjnTp1+OrVK2poaHDUqFGFNv+viDID4X+UoKAgqqioyJxN7dWrVzQ0NKS3t3ehFgT5kc+fP9PCwoKtWrXK91gBAQHU0dFh1apVc1RywsLC2KjRN4/6zp078+PHj/meO79MnTqVenp6mRbctLQ0njhxgq1ataKKigqN6veRZh9M/4h0TTLk9P/+U/TvtbTxO0zTdtOzbaNmVUaahXDCgSBKJBLeu3ePs2fPpqenp7RIkLW1NXv06MGdO3f+tNSxudGjRw9p9cf27dsXaLGuly9fskePHhSJRDQzM+OiRYukefW/fPlCgUDANWvWFNj86cTExLBu3bpUUVHhxo0bM53v3r17llkt5SEtLY0bN26klZUVxWIxBwwYIFctj06dOrFixYokyatXrxJAniOG8sKgQYOooaHBZ8+esV27djQ1Nf1lUpD/LJTKwH+YsWPHUkVFRZp3PTeOHTtGgUDAqVOnFrBk2TN69Giqq6vn+EYsC3v37qWqqirr1auXayEn8puVYN26ddTR0aGlpSVPnDiRr/nzS6tWreju7i79/9u3bzl58mTa2NhIi/8sXLiQN5+8UUilwuw+IZGZH5Dx8fE8evQoBw8ezNKlS0vLBVetWpXjx4/npUuXFJIyVxGsWLGCAFihQoVCk+nZs2fs3LkzhUIhLS0tuWLFCiYlJdHBwYH9+vUrFBmSk5OlIbVjxozJoOB7e3uzadOmeR771KlTdHZ2JgC2bNlS7tTf5LewTqFQyE+fPvHTp08EwH///TfPMsnD5cuXKRAIOG/ePF68eJEAfukQ48JCmY74P0xiYiLKlSsHU1NTnD9/XqY90gkTJmDq1Kk4efJkoTvSPHv2DE5OThg9ejQmTpyY53HWrVuHnj17olWrVti0aZNcaZdfv36N7t274/Tp0+jduzfmzJmTbWhfQWJvb4/69eujXr16WL16NY4ePQp1dXW0bdsWPXv2RNWqVaXOb53WXseV0GiFJh8SCQVwtTXE5u5Vc2375s0bnDx5EidPnsSpU6fw8eNH6OrqwsPDA/Xr14eXl5fCUvvKw+HDh9GiRQuYm5tDIpHg+fPnUFVVLbT5nzx5gkmTJmH79u2wsbGBqakphEIhrly5Uijzk8ScOXMwatQotG7dGhs2bICGhgZcXFxQrVo1uZ2Gg4KCMHLkSBw7dgzVq1fH3Llz4erqmifZnj59ilKlSuHo0aPw9vaGpaUlOnfujGnTpuVpPFlJTEyEi4sLdHV1cenSJWlE0Y0bN/LsQ/JfQeb1W5GahZLC4+zZswTAlStXytQ+NTWV9erVo7GxMd++fVvA0mWkcePGtLa2ztfe4ezZswmAf//9d55NwhKJhMuWLaOmpiaLFy/Oc+fO5VmevBAYGEgA1NPTIwBWqlSJK1euzPZ39To6Xlq1UFEf+7FH+Tpa/r9Damoqr1+/zsmTJ7NmzZrSgkQlS5Zkv379ePDgwUIxxx47doyqqqps3ry5tFRuYZjosyIwMJAtW7aUFmbauHFjgW5X/MiePXuooaHBqlWr8t27dzQ1NZWrKmNYWBi7d+9OoVDIEiVKcNeuXfn2F5FIJDQzM5Pu09erV4/NmjXL15iykG4tDQwM5Lp16wiAly5dKvB5fweU2wR/AN26dWORIkUYHh4uU/v379/T0tKSNWrUyFcVOXk4evQoAcidTS0diUTCkSNHEgDHjRunEOe2Z8+esVatWtIsdQXp4JSYmMgdO3bQ09NTunfv4+PDu3fvytR/8dE7ClUGtt9QTGXLT58+cd++ffz7779ZvHhxAqCKigrd3d05bdo03rp1S+E+KidPnqSamhqbNGkirUPfokUL2tnZ/dTti+XLl0v/tqVLl+aOHTsKzT/n5s2bNDMzo7W1NQUCAVevXp1rn7i4OI4bN46ampo0NDTkwoULpfdTEbRu3ZrVq1cnSQ4ePJj29vYKGzsr7t27R7FYzIkTJzI2NpampqZs165dgc75O6FUBv4AoqOjaWxsTB8fH5n7XLlyhWKxmEOHDi1Ayb6RlJREe3t71qlTJ0+LeEpKinR/1N/fX6Gypaamct68eVRTU6O9vT2vXr2q0PGDg4M5bNgwGhkZEQBr1KhBX19fikSiXCNBQkNDOWvWLFaqVOlb2uFa7aUphPOjCCwJCFHoNX5PSEgIly5dyqZNm1JHR4cAaGRkxHbt2nH9+vUMCwvL1/hnzpyhuro6GzVqJHXeI8nbt28TALds2ZLfS8gzHz58IABOnTqV3t7eBMCyZcty7969hRKZ8fr1a6mPR06WgZSUFC5fvpympqZUU1PjqFGjCsSpdunSpRSLxYyPj+eqVasoFAoz/M0USUpKCitWrMgyZcowKSmJo0aNooaGBl+/fl0g8/2OKJWBP4QtW7YQAA8dOiRzH39/fwLg7t27C1Aycu7cuRSJRHzw4IHcfb9+/crmzZtTJBJx06ZNBSDdN4KDg1mlShUKhUKOGjUqXw+thIQEbtq0SWp1MDQ05NChQ6V1Inr37s0yZcpk2ff58+ecOXMmK1asSADU0NBgy5YtuX37dn7+/Jnbbryi/dijtP3niFwKgO0/R2g/9qjCLAKykJyczAsXLnDMmDGsVKkSBQKB1Dly2LBhPHHihExhaumcPXuWGhoabNCgQZaKlLe3N52cnH5qtIyVlRVHjhxJ8psjm4eHh9TB8fDhwwWuFKRvGwqFQi5btizDOYlEwgMHDtDBwYEA2KlTJ756VXDfh/TtsNOnT/PSpUsEkKdngCzMmjWLQqGQ169fZ0hICFVVVTlx4sQCmet3RakM/CFIJBLWr1+fVlZWMnnXp/fx8fGhjo5OnjyGZSEiIoI6Ojrs37+/3H1jY2NZp04dqqury6Xk5JWUlBROmzaNKioqdHJy4q1bt+Tqf+/ePfbr149FihQhAHp4eHD79u2ZFItq1aqxY8eO0v8/e/aMM2bMYIUKFaQKQKtWrbhjx44s/5avo+PZcc21bwv9D2GHWSkBNn6H2XHNtTz5CCiSqKgobtu2jV27dqWFhQUBUF1dnV5eXpw3bx4DAwOzXSwvXLhATU1N1qtXL1sF4vLlywTAvXv3FuRl5EiTJk1Yr169DMfOnTsnVQyrVq3KkydPFphScODAAQKQWtIGDx7M1NRU3rhxg+7u7tLvZWGE+aWlpdHQ0JDjx49ndHQ0AXD79u0Kn+fJkydUV1eXWjmbNm1KKyurQs1r8DugVAb+IEJDQ6mhocHBgwfL3Cc2Npb29vYsW7Zsgfx4unTpQkNDQ7kr3L1//54VK1ZkkSJFFFoNThbu379PZ2dnikQiTpgwIUe/iri4OK5atYqVK1cmAJqZmXH06NF89uxZlu1TU1OpqanJUaNGcfr06XRxccmgAOzcuZNfvnzJVcY3b95QxciarWbsoNucgEzVDYv5HabbnABOOBCUZfjgz0YikTAoKIjz5s1j/fr1pdXuLCws2KVLF27bto1RUVEkyUuXLlFLS4t169bN9Ttau3ZtVqhQ4aclTJowYQKNjIwyzS+RSHjq1ClWq1aNAFirVi2ePXtW4fOvWLGCQqGQqampXLx4MYVCoVTxcnJy4tGjRwv13jRr1kwaQmtmZiZzXhRZSUtLY61atWhra8v4+HieOnWKALht2zaFzvNfQKkM/GHMnj2bQqGQN2/elLlPYGAgNTQ02LlzZ4U+KK5du0YAXLFihVz9Xr16RXt7e5qamvLevXsKk0cekpKSOG7cOIpEIrq4uGQwb0okEl67do3du3enlpYWhUIhGzVqxP379+eoOISEhHDo0KFSJzNNTU36+PjIrAB8z4wZM6ihoSH9LX5JTGFQ2CfeeRXDoLBP/JL4a+QBkJWEhASePHmSw4YNY9myZaWe+aVLl6aqqiqdnZ1lSnx0+vRpAuCxY8cKQerM7N+/nwAyZcNMRyKR8MiRI9JtoLp16/Ly5csKm3/8+PG0sLBgTEwMhw0bRrFYTIFAQCsrK7548UJh88jK/PnzqaamxsTERNatW1chyca+Z9myZQTAgIAApqSk0MnJiTVq1Pjls2f+DJTKwB9GSkoKnZ2d6ezsLJdn9aZNmwhAJi9kWUhLS2PlypXp7OwsV5jVw4cPWbRoURYvXjzbt+vC5ObNm3R0dKSqqirHjx/PBQsWSBcra2trTpo0KUcnpadPn3LatGnSJC5qamrSMLi8WmIkEgkdHBzYvn37vF7WL09YWBjHjx9PsVhMsVhMANTW1maTJk24ZMkShoSEZPnAl0gkrFatGl1dXX/KgvDq1SsC4MGDB3NsJ5FIuG/fPpYrV44A2KBBA16/fj3f83fr1o2WlpbU19enlpYWJ02axGvXrtHa2poWFhZyb33ll3THzosXL7J///50dHRU2NivXr2itrY2e/bsSfKbw6JAICj0a/xdUCoDfyA3btygUCjknDlz5OrXq1cvqqmpKWQ/MT3G9+LFizL3uXbtGg0MDFi2bFmZwyQLGolEwpMnT9LR0VH6turl5cVjx45lq+Q8efKEU6dOZfny5QmAWlpabNOmDXfv3s0RI0bQ3Nw8XzJdv36dAH56FsWC5NatW9TT06Orqys/ffrEW7ducfr06XR3d5cqB8WLF+fff//NvXv38tOnT9K+6XUfCsIMnxsSiYQGBgYyx/mnpaVx586d0iiAxo0byxxu+uO827Zto4aGBgGwd+/ejIiIkJ6PiIhglSpVqKmpyX379sk9fl5JTU2lrq4up06dymXLllEsFisknFkikdDb25sWFhb89OkTo6OjaWBgwG7duilA6v8mSmXgD2Xw4MHU0NBgaGiozH2+fv3KChUq0NbWNl+hRp8+faKpqalcb64nT56klpYWXV1df4k8+JGRkZw9ezbt7e2lSXX69u3LYsWKUV1dnQsWLMjgtf748WNOmTJF+qanpaXFtm3bcs+ePRksAI0aNaK3t3e+ZOvbty+LFi1aqIltCpM7d+5QX1+fVatWzfJZExcXx4MHD7J///7Sv49IJGKNGjU4efJkXr16leXKlaOnp+dPkJ708PCQO8FOamoq//33X5YsWZIA2KJFCwYGBsrU9/z581KflSJFimQbYpyQkEAfHx8KBALOnTu30CwnDRs2pJeXF8+dO0cA0qia/LB58+YMFpiBAwdSR0cngwKkJCNKZeAP5fPnz7SysmL9+vXl+tGHhoZST0+PTZo0yfPDYtiwYdTS0pI5w+GuXbuooqJCb2/vn+oB/GORIDU1NbZv355nz56V3ov4+HgOHDhQmjlw8ODB0m0DbW1ttmvXjnv37s3W471o0aL08/PLs4yJiYnU19f/z1Zgu3fvHg0MDFi5cuUMb/s5ERoayhUrVrBFixbSSA4tLS0C4D///FPosebDhw+njY1NnvqmpKRw/fr1LF68OAUCAdu2bcvHjx9n2fbx48ds2rSp9Lt49uxZmpubc8KECdmOn5aWxtGjRxMAe/bsWShJx2bOnEktLS2GhYUpJJQ5MjKSBgYGbNu2LclvW4sikYizZs1ShLj/WZTKwB/MwYMHCYBbt27NU7/Zs2fLPWdwcDDFYjGnTZsmU/sVK1ZQIBCwQ4cOhZYN8Ud+LBLk5OREf3//LCMgHj16xEmTJkmz7QFg5cqVc1QA0omKisp3eNXu3bsV9nb1qxEYGEgjIyNWqFAhz9ahlJQUXr58mWPHjpVGKKRnBBw0aBCPHj0qt7OmvKTn/JA3guZ7kpKSuHLlSlpZWVEoFNLX11fqQ/Pu3Tv26dOHIpGINjY23Lp1K9PS0piamkqhUChTavJ169ZRRUWFHh4eBV7FM7288/Xr12lkZMTJkyfna7w2bdrQ0NCQ79+/p0QioZeXF0uUKFFgCY3+KyiVgT8cHx8fGhsby/1g8vPzo0gkyrZmelak/zBtbW1zza4nkUg4bdo0AuCAAQMKPVFMSkoKDxw4wL/++otCoZCamprs1q0br169mski8vDhQ06cOJFOTk4EQB0dHXbo0EEaMw+AXl5eub6Bpnu6BwcH51nuxo0b57s87a/Iw4cPaWxsTGdn53wtot+T7hQ7e/Zs9ujRg1ZWVgRAVVVVenh4cNasWbx3757CzeWPHj0iAJ45cybfYyUmJnLx4sU0NzenSCRixYoVqampST09Pc6ZMyfD7yw8PFwm58V0zp49S319fTo4OPD58+f5ljU7kpKSqKmpydmzZ9PNzY1t2rTJ81jp0RrpmSbT/UP279+vKHH/syiVgT+c8PBwFilSRG7HmpSUFNauXZtmZmYy78OlJzw5cOBAju3S0tI4ZMgQadrUwvT6Dg0N5ZgxY6Sx1xUrVuSKFSsyfaeDgoI4YcIEqeOgrq4uO3bsyAMHDmRSdI4dO8aiRYtSV1eX69evz/Z65s2bRw0NjTzv9UdGRlIsFnPJkiV56v+rEhwcTFNTU5YrV44fPnxQ2LgpKSksXry4dA9dIpEwODiYCxcuZMOGDampqUkANDU1ZadOnbh582a+e/cu3/Om55KYO3duvsdKH2/58uXU1dWVZhfs2rVrpm24dM99ecKKnzx5Qjs7OxoZGSk0xPFHPDw8+Ndff/Hvv/9m2bJl8zTGx48faW5uzkaNGlEikTApKYklS5akp6enMpRQBpTKgBJpzXd5vasjIiJobm5Od3f3XMMUv379Sltb21x9FJKTk+nr60uBQMClS5fKJU9e+bFIkK6uLvv27ZspaiIoKIjjx4+XenanKwAHDx7M1QQZExPDTp06ST3Cs1KgfH19WaVKlTxfx4IFC6iioqLQBfNn8+TJE5qbm9PJyYnv379X+PgrV66kQCDI0hqTmJjIM2fOcNSoUdLQTwB0dnbmqFGjeObMmTybnqtVq8YOHTrkV3weP35c6pPSpk0bBgYGctasWTQ0NKSamhoHDRok/a6lvyXLW//hw4cPdHNzo5qamtxbirIyefJkFilShP7+/lRVVc1TQakePXpQR0dHaoGbO3cuhUKhzI6WfzpKZUAJ09LSWKNGDdrb2+dqvv+R8+fPUyQS5er0Nm3aNIrF4hxN4AkJCWzcuDHFYnGhZAjLqkjQhg0bpE6KEomEgYGBmRSATp06yaQAZMX+/ftpYmJCAwMDbtu2LYNiVK5cOWlMdF5wdnZmixYt8tz/VyMkJIQWFhYsXbq0Qt7IsyIxMZFFixalr69vrm3fvXvHzZs3s1OnTjQ1NZUmhmrYsCEXLlzI4OBgmd9A+/Tpk6+Y+rt377JevXrSbIU/5iCIjY3llClTqKenRw0NDQ4fPpzz5s2jQCDI00KbmJhIX19fAuDEiRMV/qadHkmQ/mLy5MkTufqnb7GlJzCLjIykrq4u+/Xrp1A5/8solQElJL/tyaqoqHDcuHFy9509e3aO5v83b95QU1OTw4YNy3aMT58+sVatWtTU1CzQ7HBZFQkaMmQIHz58SPKbAvDgwQOOGzdOWrClSJEi9PX15aFDhxTihBQVFUUfHx8CYKtWrfj+/XsmJSVRRUUlz9aQ+/fvy7QF87vw/PlzWlpaslSpUgUeDubv70+RSCRXmG1aWhrv3bvHWbNm0cPDg6qqqtJEUz169OCuXbtydHJMr9Inb3TMmzdv2LlzZwoEApYqVYr79+/PcWH++PEjx40bRx0dHaqoqFBLSyvPPhcSiYRTp04lAHbo0EHuF4ec+Pr1K1VVVTl58mQCkCvXwZcvX1i8eHG6u7tLfYt69uxJfX39/5SVrKBRKgNKpIwfP54qKioMCgqSq59EImGzZs2op6eXpaNR+/btaWJikm0oWEREBMuXL099fX1euXIlT7LnRk5FgiQSCe/fv8+xY8eyVKlSUgWgc+fOPHz4cIF5IW/fvp0GBgY0MTHh/PnzCYCXLl3K01hDhw6lsbHxT4u4UCQvXrygtbU1S5Ysme+SxrIQHx9PY2Nj9u7dO89jfPnyhUePHuWgQYOkViShUMhq1apx/PjxvHz5coY38ps3bxIAr127JtP4nz594ujRo6murk5jY2MuW7ZMrr/1hw8f6OzsTIFAQF1dXU6YMEHm0Mwf2bFjB9XU1FijRg2Fbt3UqlWLzZs3p56enszRRiQ5ZMgQqqurS4up3blzhwKBgIsWLVKYbH8CSmVAiZSvX7/S3t6erq6ucnvvf/z4kSVKlGCFChUyvDFcvHiRALhu3bos+4WGhrJEiRI0NzdX+N5eTkWCJBIJ7927xzFjxkgT0+jp6bFLly48cuQIk5KSFCpLdkRERLBJkybS/ei8lIxNSUmhqakpBw0apHgBC5lXr16xWLFiLFGihMx5KBTBjBkzqKqqqrA5X716xTVr1tDHx4f6+vpSBbNFixZcsWIFHz9+TJFIxOXLl+c4TnJyMhcvXkwjIyNqaGhwzJgxeX6+NmnShJ6enhw6dCjV1dWpr6/PadOmMS5O/kJVV69epYmJCW1tbfMV/fI9Y8aMoZGREV1dXWX2p7h69SoFAoE0zFkikbBWrVp0dHT8TyjGhYlSGVCSge/37uTl7t27VFNTY69evUh+83J2dnZm5cqVs1QuAgMDaW5uTjs7O7lMtDmRU5GgpKQk3r17l//88480k5u+vj67du3Ko0ePFpoCkJXMXl5e0gpy8m6THD58mAAKpexsQfLmzRva2tqyePHihZ4IKDY2lnp6enJV9JSV1NRUXrt2jZMnT2aNGjUoEomkIYxOTk48ePBgpgVZIpFwz549LFmyJAUCQZbRAfJSqVIl9ujRg+S32g79+/enqqoqjYyMOHv2bLm3LF68eEEnJyfq6enx9OnT+ZKN/JZlNH3rzMXFJdf2iYmJdHR0ZKVKlaRWl507d/7nU3EXFEplQEkmunfvTl1d3TyZaNesWUMA3Lhxo9QZKCtT6OXLl6mnp0dnZ2eFOIfFxMRw0aJFmYoEvXr1infu3OHo0aNpZ2cnVQC6devGY8eO/TQF4Efq1KnDBg0a0MvLiwDYo0cPmX9HPj4+LFu27G8dPhUWFkY7Ozva2Njw5cuXP0WGCRMmUENDg5GRkQU6z6dPn7h3717a29tLfQ1UVFTo7u7O6dOnc/369XR1dSUA1q9fn/fv31fIvEWLFs3kE/T69Wv27t2bYrGYpqam9Pf3l8sX4NOnT/Ty8qJYLM53EbPPnz9TJBKxVatWVFdXzzXENr1QVfr9SUhIoLW1NRs3bpwvOf5UlMqAkkxER0fTxMQkz+VEu3btSnV1danZ/UeOHj1KDQ0Nurm55Xnfkvz29nTu3Dl26NCBampqFIvFbNGiBY8ePcqbN2/Sz89PqgAYGBiwe/fuPH78+C9nPkwvXjN58mRKJBKuWLGCWlpatLGxYUBAQI59Y2JiqKqqqrCY9Z9BeHg47e3taWVlpTALUV6Ijo6mtrY2R48eXSjzLViwgOrq6gwODuaSJUvo4eEhLbIkEolYp04dbtiwQSF+E6mpqRSJRFy2bFmW50NDQ9m1a1eKRCJaWFhw6dKlMvvKpKSksE+fPgTAESNG5CtBWNWqVVm7dm0CyDHR0f379ykWizMoN1OmTKGKiorUd0CJfCiVASVZsnXr1hyzlX1JTGFQ2CfeeRXDoLBP/JL4P+eo+Ph4GhoaUigUZvphbt26lWKxmI0bN841PW92/FgkyM7OjjNnzuTJkyfp5+fHEiVKSCMFevTowRMnTvxyCsD3vH79OlMkwPPnz+nu7i7NwJhditzly5dTJBL9tgVY3r17RwcHBxYtWvSXKEk9cuRI6ujoFEoxrPQtuYsXL3LQoEFUUVFh0aJFOXr0aPr5+bFSpUoUCAQEwLJly3LYsGE8efJknn437969kykT39OnT9mxY0cKBAJaW1tz9erVMv12JBIJFyxYQIFAwObNm+c5pfOIESOkYZuHDh3Ksk1KSgorVapER0dHqcLy9u1bampqcvjw4XmaV4lSGVCSDRKJhA0aNKCVlZV0P/PpuzhOOBBEt9kBLOZ3mDbffYr5Habb7ABOOBDEwxdvUyQSUU1Nja1atZKar5csWUKBQMDOnTvLHeucXZGgFStWcOTIkbS1tc2gAJw8efKXVgC+Jz0ZzI/Og2lpafT396e6ujrt7OyyzABXrVo1NmzYsLBEVSiRkZF0dHSkubn5L/M29+7dO6qrq8tcYji/cwGghoYGdXR0OH369EwLfVRUFLdt28YuXbpIs2Kqq6uzfv36nDdvHoOCgmTaHrp79640/78sPHr0iK1btyYA2tracuPGjTL9Zg8ePEgtLS1WrFgxTxaN9N+ClpZWtoWF5s6dS4FAwKtXr0qPdezYkcbGxvmyNP7pKJUBJdkSGhpKTU1N9hg8ih3XXKON32Ha/nMkgxLw4yf9fLGu87hs4w4C4IIFCzhx4kQC4NChQ+UyI2ZVJGjo0KEcMGCAtBiQkZERe/bs+VspAN+Tnhwmu4f648ePWa1aNQoEAo4YMUK6p/v48WMC4I4dOwpTXIUQFRXFsmXL0tTUNNuqez+LAQMG0MDAIE9e9rKQlpbGzZs309ramgBYvnx5mfwU0pNgzZs3j15eXtJCS0WLFmXXrl25bds2RkVFZdn3yJEjBMA3b97IJeuDBw/YvHlzAmCpUqWkRY9y4u7duyxatCgtLS157949ueb7+PEjBQIBixcvzs6dO2c6HxISQnV19QyOnumFjvLrs/CnI+v6LSBJ5EJcXByKFCmC2NhY6Orq5tZcyW9At2lrcPqjAcSqapDk+g34H0IAKmIhHL8+xIH5I0ESM2bMwKhRoyAQCHLsm5qaiqNHj2L16tU4evQo1NXV4eHhAR0dHVy5cgUvX76EkZERWrRoAR8fH9SuXRtisTh/F/oT8fHxQVRUFM6dO5dtm7S0NMydOxfjx4+HnZ0dNm7ciH379mHZsmWIiIiAurp64QmcT2JiYlC3bl1ERETg7NmzcHR0/NkiZeDNmzcoUaIEpk2bhhEjRih07ICAAIwYMQJ37txB8+bNkZCQgKSkJJw9e1busb5+/YqLFy/i5MmTOHHiBIKCgiAQCFCxYkXUr18fXl5eqF69OlRUVLB27Vr07NkTSUlJUFFRkXuuO3fuYPz48Thy5AicnJwwadIkNG/eHEKhMMv24eHhaNy4MZ4+fYrt27ejUaNGMs/l4uKCz58/w8DAADdu3JAel0gkqFu3Ll6/fo3AwEBoaWlBIpGgWrVqSE1Nxc2bNyESieS+NiXfkHX9zvovruQ/zZKzIQj4Yg6hWFUuRQAAJACSUiW4q1IaOtV8oKenh+7du+eoCLx48QJjx46FjY0NmjZtimfPnsHDwwNGRkY4dOgQTp06hfr16+P06dOIiIjAypUr4enp+VsrAgBw7949ODs759hGJBJh1KhRuH37NtTU1FC1alUsWbIErVq1+q0UgY8fP6JevXoICwvDmTNnfjlFAACsrKzQuXNnzJs3D1+/flXImA8fPkSjRo3g4eEBVVVVXLx4EXv37kWtWrVw7949yPCulQkNDQ14eXlh7ty5CAwMRFhYGNatW4eSJUti5cqVcHd3h4GBAZo2bYr9+/dDX18/T4oAAFSoUAGHDx/G1atXUbRoUbRq1QoVK1bEwYMHs5TdwsICFy5cgKenJ5o0aYJFixbJfI3u7u74+PEjHj16lKHPmjVrcP78eaxevRpaWloAgH///Rc3b97EwoULlYpAIaFUBv4wtt98jbknn377Ty5v8rmh7+4LDScPtG/fHmlpaRnOJSUlYefOnahXrx5sbW3h7+8PY2NjmJub4/Hjx7h//z4aNmyIM2fOIDw8HCtWrICHh8dvrwCk8+XLFzx//hzly5eXqX2ZMmVw/fp1dOzYEXFxcTh37hwePHhQwFIqhk+fPsHLywuvXr3CmTNnUKZMmZ8tUrb4+fkhKioKa9euzdc4ERER6NmzJ8qVK4fHjx9j586duHLlCmrWrAng21vwp0+f8PLly3zLbGFhgS5dumDr1q2IjIzErVu3MHr0aMTGxuLIkSOIiYlBiRIl0KdPH+zbtw+xsbFyz1GtWjWcOHECFy5cgJ6eHpo2bYqqVavi+PHjmRZ7LS0t7NmzB0OHDsWgQYPQv39/pKam5jqHm5sbYmJiEB8fjyehL/EwPBYnbj2B38wl6Ny9Fzw8PAB8++34+fmhdevWqFWrltzXoiRvKLcJ/iDexCTAc8F5JKVKMp1LjnqF2EtbkfzuGdLiP0GgogYVQyvoVm0BzZJVsx1TRQi8Wt4Towf0xKRJk/D48WOsWbMGGzduxIcPH2BhYYHExETExMTAxMQELVu2hI+PD9zc3P7TGv/Vq1fh6uqKO3fuwMXFReZ+vr6+OH/+PLS1tRESEoIJEyZg1KhRv6ySFBsbCy8vL4SEhCAgICBXS8ivQMeOHXH+/Hk8f/4cqqqqcvX98uUL5s6dizlz5kBdXR3jx49Hnz59Mo0TEREBCwsL7NmzBy1atFCk+Blo3LgxwsPDUb16dZw8eRIhISEQiUSoVq2adEuhUqVKcv/WAgICMG7cOFy5cgWurq6YPHky6tatm8kCuGrVKvTt2xf16tXDjh07clwfrj9+De8B06BRohJU9C0ynBMAsDbQRJ1SJvhwbR/WLpiGx48fw8bGRi65lWRGuU2gJBP/7AtEajb7Amlx7yFJ/gqtsh7Q9+yJIq5tAABRe6bg873j2Y4pgQCV/p6LyZMno0yZMihdujSWLl2KxMTEb+OmpaFt27Y4e/YswsPDsWzZMtSpU+c/rQgA37YIxGKxXObyz58/Y8+ePejVqxfu3LmDYcOGYfz48XB1dUVwcHABSps3Pn/+DG9vbzx9+hSnT5/+LRQBAPjnn3/w9u1bbN68WeY+qampWLVqFUqWLImZM2eiX79+eP78OQYNGpSlQmFubg5TU1PcvXtXkaJn4v3793B2dsaSJUvw9OlThIaGYunSpTAxMcHcuXNRrVo1mJiYoE2bNli7di3evHkj07h169bFpUuXcPz4caSkpMDT0xN16tTBxYsXM7Tr1asXjh8/jqtXr6JGjRp49epVprHexCSg09rraLMxELoVGmVSBIBvObtfxSRg87WXOEwXOA9ZA6GOcZ7uiZK8oVQG/hBCIj/j4rMPSMtGGdAoURmmbSZDr2Z76Dg3gG7lpjBtPx0qJsURd2N/tuOmSYhwFoHY0BIPHz4EABQpUgSdO3fGuXPnEBYWhqVLl6J27dr/eQXge+7fv4/SpUtDTU1N5j579uzB169f0alTJ6ipqWHGjBm4fPkyYmNj4eLignnz5mXajvlZfPnyBQ0bNsTDhw9x8uRJVKhQ4WeLJDOOjo5o2bIlZsyYkat5myQOHz6McuXKoXfv3vDw8MCTJ08we/Zs6Onp5djXxcWlwJWBiIgImJubS/9fvHhx9O7dG3v37kV0dDQuXbqE/v3749WrV+jVqxesra3h6OiIwYMH49ixY0hISMh2bIFAgPr16+P69es4ePAgYmNj4ebmBi8vL1y7dk3aztPTE1evXkV8fDyqVKmC69evS89tv/kangvO40po9LcDwpyfAWn//3h6Dz14LjiP7Tdf5+GuKMkLSmXgD2HL9dcQCeXzERAIRRDrGEGS9CXHdpSkwbh6C+jo6MDBwQGhoaFYsmQJ3N3d/ygF4Hvu3bsns79AOhs3bkSdOnVgbW0tPVatWjXcvXsXffr0wYgRI1C7dm08f/5c0eLKRXx8PBo1aoT79+/j5MmTqFy58k+VJy+MGTMGz58/x86dO7Ntc/v2bdStWxeNGzeGmZkZbt26hX///Vdm03VBKwMSiQTv3r3LoAx8j1gsRo0aNTBp0iRcu3YNUVFR2LlzJ2rUqIG9e/eiYcOG0NfXh6enJ+bMmYP79+9n6QwoEAjQuHFj3L59G7t375ZuSzRq1Ai3b98GAJQuXRrXr1+HnZ0dateujV27dmHJ2RD47Q1EUqok25eQ7EjjN0dlv72BWHI2RP6bo0RulMrAH8LZJ+9l+kFKkhORlhCLlI8RiLuxH19Db0PdJudFTSAUoaRbMwQEBCA0NBSjRo1SlNi/JWlpaQgMDJRLGXj58iXOnTuHzp07ZzqnqamJBQsWSC0t5cqVw7JlyyCRZPb9KGgSEhLQuHFj3LlzB8ePH0fVqtn7k/zKuLi4oGHDhpg2bVqm+/jy5Ut06NABlSpVwvv373H48GGcOXMGFStWlHuO8PBwvH//XpGiS4mOjkZKSgosLDKb3bPCwMAAPj4+WL16NV69eoXg4GDMnj0bampqmDhxIpydnWFubg5fX1/8+++/iIyMzNBfKBSiZcuWePDgAbZt24bnz5+jUqVKaN68OR48eABjY2OcOXMGLVq0QLepa/7nqJxP5p58ih1KC0GBo1QG/gC+JKXidUz25sDv+RiwBm8XdUD4yp74eHYdNO2rw8CrT679XsckoHRZZ/j7+2PJkiXYvn17fsX+bXn+/DkSEhLk2kPfvHkztLS0cnQ2c3Nzw4MHD+Dr64t+/frBy8sLr18X3kPy69evaNq0KW7cuIFjx47B1dW10OYuCMaMGYNHjx5h//79AL6FR44YMQKlSpVCQEAAVq1ahfv376NRo0a55tDIinTH0YKyDkRERABAtpaBnBAIBHBwcMCgQYOkEQlnzpxB586dERgYiE6dOsHMzAwuLi7w8/NDQEAAkpKSAHxTCtq2bYugoCBs3LgRDx48QPny5dG6dWuEhoZixqJVMGnYP0srQ+KrB3g1868sP0lhj7OVd/zBh3gj4zNMSd5QRhP8ATwMj0WjxZdkapsS/Qapn6OR9jkaCY8vASIxDOv3hUhLP9e+B/tWR5mievD19cX+/ftx8+ZNlC5dOr/i/3bs3LkTbdq0wfv372FsnLsTFEnY29ujRo0a2LBhg0xznDx5Et27d0dsbCz8/f3RtWvXPC1YspKYmIhmzZrhwoULOHbsGNzd3QtsrsKkbt26+PjxI3x9fTF16lQkJiZi5MiRGDZsGLS1tfM1tkQigZ6eHv755x/4+fkpSOL/cfz4cXh7e+Ply5cK97p/9+4dTp8+jRMnTuDkyZN4//49NDU1UadOHXh5ecHLywulSpWCQCBASkoKNm3ahClTpuD169coN2gVPmuYS/f/vyfx1QNEbvsHOhUbQ9XcPsM5DdsKEGkWyVIekVAAV1tDbO7+e1qifiayrt+/ZrySEoWSnEUoYXaoGFpBxdAKAKBd1gOR28fh/e7JMPOdn+tiU7lqdSRHPIVIJIJEIkGZMmVQpEgRiMViiMViqKio5Pjv/J4v7LGy84e4f/8+LCwsZFIEAODKlSt49uwZVq1aJfPfycvLC4GBgRgyZAi6d++OPXv2YPXq1TKbjOUhKSkJLVu2xPnz53HkyJH/jCJAEjVr1sSUKVPw4MEDdO/eHZMmTcrTm3ZWCIVCODs7F7hlwMzMTOFjm5mZoWPHjujYsSMkEgkePHggzYg4YsQIDBo0CNbW1vDy8kL9+vXRokULdOrUCbNWbMTaCPNv4QE5oGblBC2HmjLLkyYhLj77gGfvP8PORCefV6ckK5TKwB+Aqjjvu0GaDjUQc3wJUmPCoGJomWPbSRPGwUiUiNTUVLx9+xZz5syBjY0NfHx8kJqaitTUVKSkpOT47++PJSQk5HhelrEKcl9dIBBkqSzExsZCIBCgZMmSMikWQUFB0NTUxMqVK7Fu3Tq5FBoXFxeoq6tjy5YtKFmyJHx9feHm5pZpjLwqPCTRtm1bnDlzBocOHULdunUL7H4WJpcuXcLw4cNx/fp16OnpoVixYli5cqXCrSsuLi44duyYQsdMJyIiAoaGhnJFrOSFdKXG2dkZI0eORHx8PM6fPy9VDtasWQOhUIgqVaqgSN0eEAogU2ZTSVICBCpqEOQSYZCOSCjAv9deY2ITp3xekZKsUCoDfwDFDLUgQK7KepYw5ds+oSQpPsd2AgADurSFltr/vlJlypRBu3bt0KtXL/Tpk7vfQUEgkUiQlpaWq+KhyPOzZs1C2bJlUatWrVzbJiYmIiwsDNbW1oiKisqXLACwYsUKrFixQuH3USgUonHjxoVuwVG0tefNmzeYM2cOTp48ibJly+LAgQNITk6Gj48PAgICskyskx9cXFywaNEifP78GTo6in2jDQ8PLxBLUG5oaWmhYcOGaNiwIQDg9evXOHnyJE6ePImrHwUQZW3pz0D00YVg8ldAIISalRP063SDmnnJHPukSYizT99jIpTKQEGg9Bn4Q3CfcxavcnDASYv/BJGWXoZjTEvFu03DkBL9FpYD/4VQVSPb/jaGmjg/vE6m4wMGDMCqVatw6dKl3zIETV4+fPgAY2NjbN++HW3atMm1/fbt29GuXTs8ffoUJUvm/DDMCZKQSCTYsWMHBgwYAACYO3cuGjRokCfFIjExEf7+/rhz5w769esHR0fHPFtnFH2+oHMtKFJJ+fz5M06ePAlvb28ULVpUocrRtGnTkJSUhAULFuRprOyKEeWVL0mpKDvxRI4vHYlvg/H55j5o2FaCULMIUj68RtyNfWBKIsw6zoGqWYkc5xAACJpYP8NLh5KckXX9VioDfwgTDz7E5uuvsg0vfL9nKpicADWrMhDpGCLty0fEPzqH1Oi30K/bHbpVmmc7NiVp0Hv/AINqWaBly5YoUuR/rwbJyclwc3NDREQE7ty5A0NDQ4Vf26/EmTNn4OnpieDgYDg4OOTa3tvbG3Fxcbh8+bLCZIiMjMTff/+N/fv3o3379li8eDEMDAxk7p+amooOHTpg37592LNnDxo3bqww2RQBSZmVkc+fP2Pz5s3YuHEjBAIBOnTogMaNG0MgEGRoe+XKFSxevBh+fn6wtrZWmOKSnJyMc+fOoVixYjA2NpZrrHRrT0EhEAgUanVJ1jTBfYuGcsuR8jEcEWsHQM3KCaZtJufa/siAmnCykMH8oASAUhlQ8gMhkZ9Rz/9CtufjH53HlwenkBz1EpKvnyFU1YCqmR10KjbOsTZBOpb31+PK8b1QVVXFX3/9hQ4dOqBhw4ZQU1PD69evUaFCBVSpUgWHDx9W+BvJr8T8+fMxduxYfP78OdeES+Hh4bCyssLy5cvRq1cvhcpBElu2bMGAAQOgoaGB1atXy1RuNi0tDZ06dcKuXbuwc+dONG+evRL4K5OWlobNmzdj7NixeP/+Pfr164exY8dmq4ymO7yWKFEChw4dUqgsFStWRPny5bFu3Tq5+0okkmyVherVq+Ovv/7CwIEDC906k9X5L2pGCC/TIU/3KOrAbCQ8vQLrYXty9SHY18cVLta5Rzcp+YYymkBJBkqa6qCWnRGuhEZnaR3QcnSHlqP8XuLSkJ8ZuxEWFobt27djy5YtaNGiBfT09NCqVSu0b98emzZtwl9//YUZM2ZgzJgxirikX5J79+6hbNmyMmVe3LJlC1RUVNC6dWuFyyEQCNCxY0fUqVMHPXr0wF9//YVu3bph/vz5GSw335OWloYuXbpg586d2LFjx2+rCJw8eRIjRozAgwcP4OPjgxkzZqBEiZzNz0KhEKNHj4avr69MpaflwcXFRZqpT16EQiHU1NQyOQmSRFRUFJycnH6ZctHyhDD/iFjXCEhLBVOSIFDTzLFtfhyilWSP8q7+QUxvXhZiOVMS54ZYKMD05mUBAEWLFsWwYcNw584dPHr0CP369cOZM2dQt25d9OrVC9WqVcO4ceNw+vRphcrwK3H//n2ZFhKS2LhxI5o1a5Zrjvv8ULRoURw9ehSrV6/Gzp07UbZs2Szvv0QiQffu3bF161Zs3boVLVu2LDCZCooHDx6gfv36qF+/PnR0dHD16lXs3LkzV0UgnXbt2qF48eKYPn26QuVycXHBw4cPkZycrLAxY2JikJyc/FMcCLPDWAPIm5sykPrpHQRiVQhU1XNsJ8A3h2glikepDPxBWBloYpKCw3ImN3GClUFmTb506dKYOnUqnj9/jsuXL6Np06YICQkBSTRo0AB+fn4KqfX+K5GUlIRHjx7JlIb4zp07ePjwYZbphxWNQCBAjx49EBgYCDs7O9SrVw/9+vXDly/fak5IJBL06tULmzdvxubNmwvEUlGQvH37Fl27doWzszNevHiBvXv34uLFi6hWrZpc44jFYvj5+WH37t0KrRLp4uKClJQUaSEvRZCf7IOKJCQkBAsXLkT9+vVhZWaClI8RObZPS4jNdCw5MhQJITegXswFAkHOS5K1oabSebCAUCoDfxhtK1tjuJd97g1lQBh0GK5mOVsaBAIBXF1dsXTpUoSHh2Pr1q1QVVXFnDlzULx4cdSsWRPLly/Hhw8fFCLTzyQ4OBipqakyWQY2btwIMzMz1KtXr+AF+3+KFSuG06dPY/HixVi/fj3Kly+P8+fPo0+fPli3bh02bNiA9u3bF5o8+SUuLg5jxoyBvb09Dh8+jMWLF+Phw4do3rx5nsMDO3fuDAsLC8ycOVNhcpYrVw4CgUChyYd+ljLw9etXHD9+HAMHDoSdnR3s7e0xcuRIkMSsWbPQyrU0cjI+Ru2fhfe7JiL2yg58vnccMadX492/IyBQUYN+7S45zi0SClDH3kSxF6REilIZ+APpX6ckZrYoCzWxUO5KhiKhAGpiIYa7mYNBx+Hm5oYXL17I1FdFRQXt2rXDmTNnIBAI4O3tDV1dXQwYMADm5ub466+/sG3bthzLqv7K3Lt3DwBQtmzZHNslJydj69at6NixI8Tiwn3LEQqF6N+/P+7fvw9TU1PUrl0bq1atwooVK9CpU6dClSWvpKSkYNmyZbCzs8P8+fMxZMgQPH/+HP369YOKikq+xlZTU8PIkSOxZcsWhIaGKkRebW1t2NvbK1QZCA8PB1A4ysCLFy+wdOlS/PXXXzA0NIS3tzcOHDiAevXq4eDBg4iOjsbJkycxePBg9PMql2PCIU37akhLiEPcjf2IObkcCY8vQtPeFeZdFkDFyCpHOdIkRMdq1jm2UZJ3lMrAH0rbytY4PcQdrrbfvKtzUwrSz7vaGuL0EHf0966A8+fPQyQSwd3dHc+ePZN57urVq2PevHk4duwYunfvjvDwcCxYsAAxMTFo3749TExM0KlTJxw/fhypqTnXm/+VuH//PkqUKJFrcpmjR48iOjq6ULYIssPOzk5ahU8sFmPBggW4cePGT5NHFkhi//79KFOmDPr3749GjRohJCQE06ZNU2iUU48ePWBgYIDZs2crbExFlzOOiIiAvr4+1NVz3mPPC0lJSThz5gyGDRuG0qVLw9bWFoMHD0ZCQgImT56Mhw8f4uXLl1i+fDkaN26coYbDhcM78fXFnWwXFt1KTWDeeT6sBm+DzcgDsOy/CUaNh0FFP2ffB5FQgFp2RspUxAWIUhn4g7Ey0MTm7lVxarAbOlW1gY2hJn5UCQT4llCoU1UbnB7ihs3dq0p9BKytrXHhwgVoamrCzc0Njx9nX3XsRwYOHAgfHx907doVsbGx6N+/P65cuYLnz5/Dz88Pt27dkiZqGThwIK5fv55lFbRfCVmdBzdu3IgKFSqgTJkyBS9UFpDE0KFDsWTJEqxcuRL379+HtrY2qlevjjFjxkir0/1KXL9+HW5ubmjevDlsbGxw9+5drF+/HpaWOafIzguampoYNmwY1q9fj7dv3ypkTBcXF9y/f19h6bHDw8MVahV48+YNVq1ahWbNmsHQ0BCenp7Yvn07atasib179yI6OhoBAQEYPnw4HB0ds9yGCQsLw7Bhw1BXOxIqCvb4/95RWUnBoMwzoCQD8UmpeBkdj+RUCVTFQhQz1MrVYScyMhIeHh6IiorCmTNnZF7k4uLiULlyZairq+Pq1avQ1PyfIyJJ3L17F1u2bMG2bdsQERGBEiVKoEOHDmjfvj1KlSqVr+tUNCRhaGiIIUOGYNy4cdm2+/DhAywsLDB37lwMHDiwECX8BkmMHDkSc+fOxdKlS9G3b18A30zvs2bNwqRJk1C6dGls2rRJoeF1eSU0NBSjR4+WRkLMmTMH9evXL/B54+LiYGNjg86dO8Pf3z/f4506dQpeXl548uQJ7O3z77Pj4+ODT58+4dSpU3nqn55o6ejRozh27BgCAwMhEong6uoKb29vNGzYUOrrIAsk0axZM9y4cQOPHj3CiWef4bc3ME+yZcWsFmXRprJyiyAvyLp+Ky0DSjKgpSaGk0URuFjrw8miiEyeu6ampjh79izMzc1Ru3Zt6d55bujq6mLPnj0ICQlBv379Mrz5CwQCVKhQAfPmzcObN29w+vRpuLm5wd/fHw4ODqhUqRIWLFggdaT62bx9+xYfP37MdQHdtm0bSKJdu3aFI9h3kMQ///yDuXPnYuHChVJFAPjmzzF27FjcvHkTAoEAlStXxpQpUwo8C152REdHY8iQIXBwcMClS5ewbt063L17t1AUAeDbd3PQoEFYtWoV3r9/n+/xXFxcAEBhWwURERFyWwYiIiKwbt06+Pj4wMjICLVr18aGDRtQoUIF7NixA1FRUbhw4QJGjx6N8uXLy+WEuWvXLhw8eBBLly6Fvr4+2la2RpcK/5/gKZ8WvRFepZSKQCGgVAaUKARjY2MEBASgePHiqFu3Lm7evClTvzJlymDlypXYsGFDthnaRCIRPDw8sG7dOkRGRmL37t2wtraGn58fLC0tUa9ePWzYsAFxcXGKvCS5SFeAcgsr3LhxIxo1aiRzeWNFMmHCBMycORPz58/P1irh7OyMGzduYOTIkZg4cSKqV6+u0JC43EhMTMScOXNgZ2eHNWvWYMKECQgJCUHXrl1lSuSkSAYOHAiRSIQFCxbkeywjIyNYWloqTBmQpUhRamoqLl++jLFjx6JChQqwsLBAjx498PbtWwwfPhy3bt1CREQENmzYgNatW0NfP29Z/T58+ID+/fujZcuWaNGiBYBvTrKHZvaD6PZ2qKmI8uyoPKtFWfSrY5cnuZTICWUgNjaWABgbGytLcyV/MJ8+fWL16tWpq6vLy5cvy9yvV69eVFNT4507d2TuExMTw9WrV7N27doUCARUV1enj48P9+/fz8TExLyIn2emTJlCfX19SiSSbNsEBQURAPfu3VuIkn1j4sSJBMDZs2fL3Of69et0cHCgqqoqZ8+ezdTU1AKTLy0tjVu2bKGNjQ1FIhH79u3LyMjIAptPVkaOHEkdHR3GxMTke6zGjRvTy8sr3+NIJBKqq6vT398/07nIyEhu2rSJbdu2pb6+PgHQ0NCQ7du357///suoqKh8z/8jHTt2pL6+PiMiIqTHhg4dShUVFd66dYuvo+PZcc012vgdpu0/R2jjdzjbT/r5jmuu8XV0vMJl/RORdf1WKgNKFE5cXBzd3NyopaXF8+fPy9Tn69evrFChAm1tbfnx40e553zz5g1nz57N8uXLEwD19fXZs2dPnjt3jmlpaXKPJy8tW7Zk7dq1c2wzYsQIGhoaMikpqcDl+Z4pU6YQAGfMmCF334SEBA4bNowCgYCurq58+vSpwuU7e/YsK1asSABs1qwZHz9+rPA58sq7d++orq7OSZMm5Xus8ePH09jYOEeFURY+fvxIANyxYwfT0tJ4/fp1TpgwgZUrV6ZAICAAVqxYkePGjePVq1cLVIk7cuQIAXDDhg3SY0ePHiUAzp8/P0Pbp+/iOOFAEN3mBLDYD0pAMb/DdJsTwAkHghgSGVdg8v6JKJUBJT+VL1++sG7dutTQ0ODp06dl6hMaGko9PT02bdo0Xw/MoKAg/vPPPyxWrBgB0MrKiiNHjuT9+/fzPGZu2NnZcdCgQdmeT0lJobm5Ofv3719gMmTFjBkzCIBTpkzJ1zgXL15kiRIlqKGhwUWLFilEwXr48CH/+usvAmCVKlV44cKFfI9ZEAwYMID6+vqMi8vfIrVv3z4C4Nu3b/M1zuXLlwmA9evXp7GxMQGwSJEibN26NTds2MB3797la3xZiY2NpZWVFb28vKS/1/DwcBobG9Pb2zvH78iXxBQGhX3inVcxDAr7xC+JKYUi85+IUhlQ8tNJSEhggwYNqK6uzmPHjsnU5+DBg3Kbs7NDIpHw0qVL7NOnDw0NDQmAZcqU4YwZM/jy5ct8j59OXFwcBQIB169fn22bY8eOEQBv3rypsHlzY86cOQTACRMmKGS8L1++sF+/fgTAOnXq8MWLF3kaJyIigr169aJQKGTx4sW5ffv2fL8tFySvX7+miopKvr+TL1++JAAeOnRIrn4SiYR37tzh1KlT6erqKn37d3Bw4OjRo3nx4kWmpBT+YtqnTx9qaWlJvwdpaWn09PSkmZnZL7HFo+QbSmVAyS9BYmIiGzduTFVVVR48eFCmPn5+fhSJRDJvMchCUlISDx06xLZt21JDQ4MAWLNmTS5fvpwfPnzI19jpb2o5+Tu0bduWjo6OhbboLViwgAA4ZswYhc95+vRpWltbU1tbm6tWrZJ5/C9fvnDixInU0tKivr4+58+fX+i+HXmlZ8+eNDExYUJCQp7HkEgk1NfX5+TJk3Nt++nTJ+7atYtdu3almZkZAVBHR4ctWrRgt27dCIDx8T9vT/38+fMEwMWLF0uPzZw5kwKBQGZLoJLCQakMKPllSEpKYsuWLSkWi7l79+5c26ekpLB27do0MzPL4JSkKOLi4rhp0ybWr1+fIpGIKioqbNy4Mbdv356nB+yyZcsoFouzXdg+ffpEdXV1zpo1K7+iy8SiRYsIgKNGjSow5SM2Npbdu3cnADZo0CBH03dKSgpXrVpFMzMzqqqqcvjw4QpxyCtMnj17RqFQyEWLFuVrnLp167J58+aZjkskEj548IAzZ86ku7s7xWIxAdDR0ZHDhw9nQECA1Ndk1qxZLFKkSL7kyA8JCQksWbIka9SoId0KuHbtGsViMf38/H6aXEqyRqkMKPmlSElJYbt27SgSibhly5Zc20dERNDc3Jzu7u4FagJ99+4dFy1axKpVqxIAtbW16evry+PHj8s8b69evVi2bNlsz69atYpCoZBhYWGKEjtbli5dSgAcPnx4oVghDh8+THNzc+rp6XHTpk0Z5pRIJDxy5AidnJwIgO3bt8/z1sKvQMeOHWlpaZkvB9Bhw4axWLFiJL8ppfv27WOvXr1oaWlJANTU1GTjxo25fPnybLeyBg8eTAcHhzzLkF9GjhxJNTU1BgcHk/ym7BYrVozVqlVjcnLyT5NLSdYolQElvxypqans3LkzBQJBBu/j7Dh//jxFIlGhvW2EhIRw0qRJtLe3JwCamppy4MCBvH79eo4La9WqVdmxY8dsz9eoUYP169cvCJEzsHLlSgLg4MGDC3UPPjo6mh06dCAANm3alO/evePt27dZt25dAmDt2rUL1VeioHj48CEFAgFXr16dp/4SiYSzZ88mALq5uVFFRYUAaG9vz8GDB/PEiRP8+vVrruO0bt2adevWzZMM+eXmzZsUCoWcPn06yW/X1KZNG+rq6jI0NPSnyKQkZ5TKgJJfkrS0NPbs2ZMCgYCrVq3KtX36w/PAgQOFIN03JBIJb968ycGDB0v3a0uWLMkJEyZkCq1LTU2lhoYG586dm+VYISEhBMCtW7cWqMxr164lAPbv3/+nOePt2bOHBgYGVFVVJQCWLl2ahw4d+qWdA+WlZcuWLFGihMxWo/j4eB4+fJh9+/aVRrekR08sWrSIISEhcstQq1YtdujQQe5++SU5OZnlypWjs7Oz1AKQ/r3bvn17ocujRDaUyoCSX5a0tDSpV/qSJUtybCuRSNisWTPq6enx+fPnhSTh/0hNTeWpU6fYpUsX6ujoEAArV65Mf39/RkRE8PHjxwTAU6dOZdl/3Lhx1NXVzZfjWW5s2LCBAoGAffr0+WkL78ePH6XmYzU1NQKgj49Pvp0zfzXu3LlDAPz333+zbRMSEsKFCxeyQYMG0ntRvHhx9uvXjwcPHqSGhgbnzZuXZxlKlCjB4cOH57l/Xpk6dSpFIhFv375Nknz06BE1NTXZvXv3QpdFiewolQElvzQSiYRDhw4lgFwfjB8/fmSJEiVYoUIFmcyoBUVCQgJ37tzJpk2bUkVFhUKhkOXKlSOALBWVtLQ02tjYsEePHgUm0+bNmykQCNizZ89CSa70I0lJSfT396ehoSE1NTU5fvx4xsbGcsuWLdTX16epqWmhWnUKg4YNG9LR0VF6v79+/coTJ05w0KBBLFmyJAFQRUWFnp6enD9/Ph8/fpxBScttWyknJBIJNTU1MyX0KWgePnxIVVVV6Zbd169fWb58eTo4OPDLly+FKosS+VAqA0p+eSQSCUePHk0A0j3I7Lh79y7V1NTYq1evQpIuZ6Kjo7ly5UpaWVkRANXV1dm6dWseOHBA6mB29uxZAuDFixcLRIatW7dSKBSyW7duha4ISCQS7ty5kyVKlKBQKGSPHj0yOUiGhYWxYcOGBMDOnTvnKbPkr8iVK1cIgD179uRff/1FTU1NaXKr3r17c//+/fz8+XO2/f/++286OTnlae70Z/G2bdvyKr7cpKamsnr16rS3t5cq4wMGDKCamhrv3btXaHIoyRtKZUDJb4FEIuGkSZOkyXFyMnOvWbOGALhx48ZClDBnGjZsyDp16nDmzJlSK4GBgQF79+5Nb29v2traFojpfseOHRQKhezcuXOhKwKXL19m9erVCYANGzZkYGBgtm0lEgnXrl1LHR0dWlpa8sSJE4UoqeJISkrimTNnOGzYMDo6Okr3/t3d3Tlr1iwGBgbK/HdeuXIlRSJRnraOgoODCUChOThyY+HChRmU2vTEYN/nGFDy66JUBpT8VqSnzfXz88v2oSqRSNilSxdqaGjwwYMHhSxh1lhYWHD06NHS/wcGBtLPz09qMShSpAhHjRqlUHl3795NkUjEDh06FGje+R95+vQpW7RoQQB0cXHhmTNnZO776tUrenp6EgB79+6d79S+hcGbN2+4atUqNm/enNra2gRAMzMzduvWjRMmTCAAHj16VO5xb9y4QQC8fv263H0DAgIIoEBqRGTFixcvqKmpyX79+pEk3759S0NDQzZp0uQ/5Rj6X0apDCj57Zg/fz4BcMiQIdk+aOLj41muXDmWLFnyp38fo6KisvWk3rBhgzS23sDAgABYtmxZzpw5k69evcrznPv27aNYLGbbtm0LLQXt+/fv2b9/f4rFYlpbW3Pz5s15skZIJBIuW7aMmpqaLF68OM+dO1cA0uadlJQUXrhwgX5+flIrj1AoZI0aNTht2jTeuXNH+r2USCSsXr06q1evLvei+PXrV4pEIq5YsUJuGbds2UIAOW5DKAqJREJPT09aW1szLi6OqampdHd3Z9GiRf9zjqH/ZZTKgJLfkiVLlhAA+/Xrl+2C8/TpU+rq6rJVq1Y/9e3k9OnTBJBllT0PDw+6u7uT/GZiPnDgANu0aUN1dXVpnPnKlSsZHR0t83wHDx6kiooKfXx8CkURSEhI4PTp06mrq0tdXV3OnDlTIVERz549Y61atQiA1Cq2bgAAJy1JREFUgwYN+qlpdSMiIrh+/Xr6+PiwSJEiBEBjY2P6+vpy27ZtOf59Dh8+TAAMCAiQe94yZcqwd+/ecvebM2cOdXR05O6XF9atW0cA0roiU6ZMoUAg4NmzZwtlfiWKQakMKPltWbVqFQUCAXv06JGtQrBnzx4CyLKme2Exd+5camhoZDLVv379mgKBgOvWrcvUJy4ujhs3bqSXlxeFQiFVVFTYtGlT7ty5M8eF9siRI1RVVWWLFi0KPMtbWloaN2zYQEtLS4rFYg4cOJBRUVEKnSM1NZXz5s2jmpoa7e3tefXqVYWOn9O8V65c4dixY6VlkwUCAatUqcKJEyfyxo0bMls9JBIJnZ2d6eHhIbccnTp1YpUqVeTuN3ToUNrb28vdT17Cw8Opp6dHX19fkuSlS5coEok4bty4Ap9biWJRKgNKfms2bNhAoVBIX1/fbPfFhw4dSrFYzMuXLxeydN/o1KkTq1atmun4tGnTqKmpmeu+eEREBP39/Vm5cmVpIZrOnTvz5MmTGa75+PHjVFNTY9OmTfOVClcWTp06RWdnZwJgq1at8pQURx6Cg4NZpUoVCoVCjho1qkAKF0VFRfHff//NsGWjr6/Pdu3acfPmzXz//n2ex969ezcByK3MzJ8/n+rq6nJbeNq2bcvatWvL1UdeJBIJmzdvThMTE3748IExMTG0trZmjRo1fkp1RCX5Q6kMKPnt2bZtG0UiEdu2bZvl23BycjJr1KjBokWL5uuBnlfKli2bKdRRIpHQ3t5e7jjyp0+fcuLEidI4dTMzMw4ePJhLliyhmpoa//rrrwJVBB48eMAGDRoQAF1dXXnlypUCm+tHUlJSOG3aNKqoqLBMmTLSpDZ5JS0tjTdv3uSkSZNYtWpVacnfChUqcOzYsbx8+bLCHC/T0tJYunRp/vXXX3L1Sw87DQoKkqufu7s727VrJ1cfedm1axcBcNeuXZRIJGzZsiX19PQUWvZbSeGhVAaU/CfYvXs3xWIxW7RokeVi+PbtW5qYmNDT07NQPesTExMpFou5bNmyDMevXr2aY0bC3JBIJLxx4wYHDRpEfX19AqCWlhbHjRtXIG/pb9++Zbdu3SgUCmlnZ8fdu3f/ND+M+/fv09nZmWKxmBMmTJBrOyQmJobbt2+nr68vTUxMCEDqV7Ju3TqGh4cXmNybN2/OtYT1j3z8+JEAuHnzZrnmsre359ChQ+UVUWaio6NpYmLC5s2bUyKRcMWKFQQgU7VRJb8mSmVAyX+GgwcPUlVVlY0bN87SjHz69GkKhUKOHz++0GRKT0v74xbF33//TUtLy3wrJufOnaOGhgYrVKjADh06SEPbqlatyoULF/Ldu3f5Gj8uLo5jx46lhoYGDQ0NuWjRogLfgpCFpKQkjhs3jiKRiC4uLtmGZEokEt69e5fTpk1jzZo1KRQKpREbo0aN4vnz5wutgl5KSgptbW3ZqlUrufoVL15c7oVdW1s72zoYiqBz587U09NjeHg4g4KCqK6unidHRyW/DkplQMl/imPHjlFdXZ3169fP0tFu6tSpFAgEUs/ngmb9+vUEkMEv4OvXr9TT08uQdyAvXLx4kVpaWvTw8JBea3x8PLdv384mTZpQRUWFIpGI9evX56ZNm+SK2U9JSeGyZctoYmJCdXV1+vn58dOnT/mStyC4efMmS5cuTVVVVc6YMYMpKSmMjY3lnj172L17d1pYWEitJs2aNeOqVav4+vXrnyZvutPro0ePZO7TokUL1qlTR+b2cXFxBCBTCfC8cOzYMQLgunXrmJCQQCcnJzo5ORVoXQ0lBY9SGVDyn+P06dPU0NBg3bp1M+VDT0tLY8OGDWlgYJCvOH5ZGTx4MO3s7DIc27lzZ7ahhrJy5coVamtrs3bt2tmG3H348IErVqyQhudpaGiwbdu2PHToULZvwxKJhPv372epUqUoEAjo6+v7UxdPWUhISGDXrl2lzpVisVhaDXHo0KE8ffp0gTgc5oXExERaWlqyU6dOMveZMmUK9fT0ZN6WefLkSZ5DGXMjLi6O1tbW9PT0pEQiYZ8+faiurp5jdkklvwdKZUDJf5Lz589TW1ubtWrVyvRGHB0dTRsbG1apUqXATd61a9dmy5YtMxxr1KhRltEFsnLt2jXq6OiwVq1aMhd/efnyJWfMmMEyZcoQAA0NDdmnTx9evHhRGiJ348YNurm5EQA9PT3l2tsubD5//swDBw6wd+/etLa2JgCqqalRU1OTYrGYY8eO/SkFmWRh4cKFFIlEMlfXTM9T8OLFC5nanzt3Lt/KZnb079+fmpqaDA0NlYbtLl++XOHzKCl8lMqAkv8sV65coa6uLqtVq5ap+M3NmzepqqrK/v37F9j8EomE+vr6nDJlivTYu3fvKBKJMjkUysrNmzdZpEgR1qhRI8+peu/fv8+RI0dKUyEXLVqUpUuXJgCWKVOGx44d++VSyEokEj5+/JgLFixgvXr1qKqqSgC0s7PjwIEDefz4cX79+pVfvnzhgAEDpAmbfkY569yIj4+niYmJzMW0wsLCCIB79+6Vqf22bdsK5Dl88eJFCgQC+vv789WrV9TT02OLFi1+ue+KkryhVAaU/Ke5efMm9fX1WbFixUxZ4pYtW1agld1evXpFADx48KD02Lx586iqqipXRsF0bt++TT09PVavXl0hv7GoqCi2bt2aQqFQGlZXvnx5zp49+5fYGkhISODRo0fZv39/2traSt/+69evz4ULF+aYdz8gIIA2NjbU0tLi8uXLf7kFa+bMmVRRUeGbN29ybSuRSGhiYiJzIp958+ZRS0tLodf89etXlipVitWrV2diYiJr1qxJKyurPH2PlfyaKJUBJf957t69SyMjI5YvXz5DngGJRMIOHTpQS0tLLocuWUmv2vb9wlquXLlM2waycPfuXerr67NKlSr5duRLTEzk3Llzqa+vT21tbU6ePJnR0dHcv38/fXx8qK6uToFAQHd3d65atYoxMTH5mk8enj9/zsWLF9Pb21uaktnGxoZ9+vThoUOHZN4WIb/tb/fs2ZMA6OXl9UsoOOnExsZSX1+fgwYNkql9/fr1Zc5RMHz48Ex+Kvll9OjRVFVV5cOHDzl+/HgKhcICK7mt5OegVAaU/BEEBgbS1NSUTk5OjIiIkB7//PkzHR0dWbp0aYUXdZk8eTL19fWlb2h3797NZCmQhQcPHtDQ0JAVK1bMtN0hD2lpady6dSuLFStGkUjEv//+O8vQw9jYWK5fv56enp4UCoVUVVVls2bNuGvXLmmdekWRmJjIkydPcvDgwbS3tycAqqiosG7dupw7dy4fPXqU7zfcY8eOsWjRotTV1eX69et/GSvBxIkTqaGhwcjIyFzb+vn5sWjRojKN26FDB9aqVSu/4km5c+cORSIRp0yZwnPnzlEoFHLy5MkKG1/Jr4FSGVDyxxAcHExzc3OWKlWKb9++lR5/9OgRtbS02L59e4UuFC1btsyQEnbw4ME0NjaWK649KCiIxsbGdHFxyZdJ9ty5c9J0xk2aNGFwcLBM/cLDwzl//nxWqlRJmqCna9euPH36dJ5zJLx69YrLly9nkyZNqKWlJfVb6NmzJ/ft21cgZYtjYmLYqVMnAmDjxo0zKIQ/i+joaGpra9PPzy/Xtjt27CAAmTJo1qlTh23atFGEiExOTqazszPLlSvHiIgIFi1alO7u7oWauEtJ4aBUBpT8UYSEhNDKyoolSpTIEFqY7nSVV8e+rLCzs+PgwYNJfnuoGhsbS/8vC48ePaKJiQnLlSuX51KwwcHBbNKkCQGwcuXK+SoH/PjxY44fP54lSpQgAJqbm3PIkCG8detWjkpUcnIyz549yxEjRtDJyYkAKBKJ6ObmxhkzZvD+/fuF9ra+f/9+mpiY0MDAIMuS0oXNqFGjqK2tnaui9/TpUwLgiRMnch3TwcFBru9ZTkyfPp1CoZA3b95kkyZNaGBgIJOfg5LfD6UyoOSP48WLFyxevDhtbGwyeJv379+fqqqqvHHjRr7nSE/8sn79epL/8x+4e/euTP0fP35MMzMzlilTJk/1FN69e8e///6bIpGIxYoV47Zt2xQWaieRSHjt2jUOGDBAmtK3VKlSnDx5Mp89e0bymwf8mjVr2KJFC+ro6BAATU1N2aVLF+7cuTNf2x35JSoqij4+PgRAHx+fn1KvIp13795RXV2dEydOzLFdWloadXR0OHPmzFzH1NXV5ezZs/MtW3BwMNXU1Dhy5EhpyfADBw7ke1wlvyZKZUDJH8nr169ZsmRJWlpaSr3Sk5KSWLVqVVpbW+f5TTydy5cvZ1j8W7ZsyXLlysnU9+nTpzQ3N6ejo6NM+8nf8+XLF06ePJna2trU19fnvHnzCjThTkpKCo8dO8b27dtTQ0ODAKipqSkt+Vu9enVOmTKFt2/f/uXi/rdv304DAwOamJhw3759P02OgQMHUl9fP9ftkZo1a+Zq/o+Pj89TLYMfSUtLY40aNViyZEleu3aNampqBRqGq+Tno1QGlPyxhIeH08HBgWZmZtJoglevXtHQ0JDe3t75WryWLl1KsVjMxMRERkdHU1VVlfPmzcu137Nnz1i0aFE6ODjIVVcgNTWVa9asoYWFBVVVVTl06NACD/uKjIzkxo0b2aZNG+rp6UkzABYtWpQikYgikYje3t78999/Fe6cqSgiIiLYuHFjAmDHjh0LNXIinTdv3lBFRYWzZs3Ksd2AAQNob2+fY5tnz54RAE+fPp0vmRYvXkwAPH78OB0cHFiuXDmFO48q+bVQKgNK/mjevXvHMmXK0NjYWFrs5tixYxQIBJw6dWqex+3Vq5fUErB06VKKRKJcF/fQ0FBaWVnR3t5e5up5EomER48elWYWbNu2LUNDQ/Msd06kpqby2rVrHD9+vNShMN0XYcKECbx27ZrUsSwqKorLli1jjRo1pNaCdu3a8fDhw4VWGEhWJBIJN2zYQF1dXVpYWBRa3Yrv6dmzJ01MTHLM779u3ToKBIIcFasLFy4QQL5CZV++fEktLS326dOHPXr0oKamZoGE3ir5tVAqA0r+eKKioujs7EwDAwPevn2bJKWx1Hl9w6pSpYo0/3yVKlXYqFGjHNu/fPmSNjY2LFGiRIZIh5y4c+cOPTw8pNn2FOHr8CMfPnzgli1b2KFDBxoaGhIA9fT02KZNG27cuFEm68WLFy84bdo0Ojo6EgCNjIzYt29fXr58+ZcJ8yO/bR3Vq1ePANijR49CfY49f/6cIpGIixYtyrZNemjqpUuXsm2THnWQV58MiUTC+vXr09LSkuvWrSMArlmzJk9jKfm9UCoDSpTwW+hZ5cqVqaenx+vXrzM1NZX16tWjsbGxzItzOqmpqdTQ0ODcuXMZHBxMANy5c2e27V+/fs3ixYvT1tZWpsQ4r1+/pq+vLwUCAR0cHHjgwAGFLappaWm8desWJ0+ezOrVq0tL/jo7O/Off/7hpUuXmJKSkqex08sJjxgxgkWLFiUAFi9enGPGjPll3jwlEglXrFhBLS0t2tjYFEixn+zo2LEjLS0ts62XkZSURBUVFS5evDjbMRYsWEB1dfU8fx82btxIAFy7di11dXXZpk2bX0phU1JwKJUBJUr+n9jYWLq6ulJHR4eXLl3i+/fvaWlpyRo1ashl2n78+LF039bPz496enrZ7re+ffuWJUqUYLFixXKtovjp0yf6+flRXV2dJiYmXL58eZ4X5u/5+PEjd+7cyS5dutDU1FS699+yZUuuXbuWYWFh+Z7jR9LS0nj27Fn26NFD6m/g7OzMOXPmyK18FQTPnz+nu7s7AXDAgAFyZT7MKw8fPqRAIODq1auzbePi4sJu3bple37kyJG0tbXN0/wRERHU19dn+/btWa1aNRYrVuyXLFutpGBQKgNKlHzH58+f6e7uTi0tLZ49e5ZXrlyhWCzm0KFDZR5j+/btBMB3796xaNGi/Pvvv7NsFx4ezpIlS9La2jrHinRJSUlctGgRjYyMqKGhwXHjxuUrMY9EIuH9+/c5Y8YM1qpViyKRSFqkaMSIETx79myBV3P8nsTERO7du5etWrWimpoaBQIB69SpwzVr1vzUEMS0tDT6+/tTXV2ddnZ2vHz5coHP2apVK9ra2mar5HXr1o0uLi7Z9u/UqRNr1KiR57mNjY05aNAgikQiXr16NU/jKPk9USoDSpT8QHx8PD09PamhocFTp07R39+fALhnz55s+3xJTGFQ2CfeeRXDv/2msqiNLU+ePEkAWT5UIyIi6ODgQEtLS2ls/o9IJBLu3r2bdnZ2FAgE7NatW57fmuPi4rh371726NFDaqLX0tJikyZNuGLFilytEoXFp0+fuG7dOnp4eFAgEFBNTY0tWrTgnj17fpo3++PHj1mtWjUKBAKOGDGiQOW4c+dOjqGBixcvpoqKSrbKmoeHB318fOSeN70c8ZgxYygQCDh9+nS5x1Dye6NUBpQoyYKvX7/S29ubampqPHz4MH18fKirq5uhUt7Td3GccCCIbrMDWMzvMG2+/4w6xFLDttG21Sg+icj4e4iMjKSjoyMtLCyyrbx35coVurq6EgAbNGggjXSQFYlEwocPH3Lu3LmsW7cuVVRUpMmBhgwZwlOnThVo/gFFEBYWxnnz5rFChQoEwCJFirB79+48c+ZMoafDTU1N5cyZM6mqqkpHR0fevHmzwOZq1KgRS5cunWVo66VLl3JMXuXo6MiBAwfKNV9MTAzNzMzYoEEDmpmZ0cPD45fLCaGk4JF1/RZCiZI/CHV1dezbtw8NGjRA8+bN0bx5c5iZmaFVq1Z4GhaNTmuvo57/BWy+/gqvYhLAHwcQCJCoogOJXU14LbyITmuv401MAqKiouDh4YGYmBgEBASgZMmSGbo9e/YMrVq1gqurKxISEnDq1CkcO3YMZcuWzVXm+Ph4HD58GH379kXx4sXh5OSEsWPHQl1dHQsWLMDz58/x+PFjzJ8/H56enlBTU1PcDSsALCwsMHToUNy+fRvBwcEYMGAAzp49Cw8PD9jY2GD48OG4e/cuyEx3X+GIRCKMGjUKt2/fhpqaGqpVq4bx48cjOTlZ4XONGTMGwcHB2LdvX6Zz5cuXh0AgwN27d7PsGxERAXNzc7nmGzZsGL5+/Yrk5GSkpqZi8+bNEAqVj3wlWSOgDL+4uLg4FClSBLGxsdDV1S0MuZQoKVBSUlLQoUMH7Nu3DzNnzsS07Weh59ELApEYaRLZFyGRUACxEBDe2YOPt4/g3LlzcHBwkJ7/8OEDpkyZgmXLlsHMzAzTpk1Dx44dc30oh4SE4OjRozh69CjOnz+PpKQk2NraomHDhmjYsCFq164NDQ2NPF//rwZJXL9+HVu2bMGOHTsQFRWF0qVLo0OHDmjfvj2KFy9e4DKkpKRg+vTpmDp1KsqUKYONGzeiXLlyCp3Dw8MDHz9+xO3btyEQCDKcK1WqFOrXr49FixZlOP7161doampi48aN8PX1lWmeU6dOwcvLC23atMGOHTtw5MgRNGzYUGHXoeT/2rv7qKjKfQ/g382MvA1vAwyjqIOB2hHRe03Nk2KGgpYWJb7mpLnU7s2rXtPCjrJcWr5kdpd2s5uVSnpr8PSCYSkqR0Eqwda5kW+IkoSigjOCCgwMIzOz7x8e5oTIvMCIL/P9rDUr2LP3s/du4ezvPPu3n+fB4ej1m2GA3JbJZMLMmTOxp9SEoCenQxTFFh/QDhFFQBAw/V+CsGrqMAC3PsA/+OADrF27FgCwdOlSLFy4sNULuMFgQG5uLjIzM7Fv3z6cO3cOnp6eGDFihDUA9OrVq23H94BpbGzEwYMHodFokJGRgbq6OgwdOhRqtRqTJk2CQqG4q/svKCjAjBkzUFxcjBUrVuDNN9+EVCp1Sds5OTkYOXLkHS/OL774Ii5duoQff/yx2fLS0lJERkYiKysLCQkJdveh1+vRr18/KBQK/Prrr1iwYAE2bNjgkuOnBw/DAJED0n4+j2UZhS2WV+7ZiLpTh1rdruu87ZD6h7ZY/s74GJjO/oCUlBRUVFRg7ty5WL58+R0vYKWlpdi3bx8yMzORnZ0Ng8EAlUplvfjHxcXBz8+vfSf4gKurq8Pu3buh0Whw4MABCIKA0aNHQ61W4/nnn4dMJrsr+zUajVi5ciXWr1+PgQMHYseOHejTp0+72xVFEcOG3QqMR44caRbu1q9fj1WrVqG6urpZz9GRI0cQGxuLU6dOoW/fvnb3sXDhQmzZsgVKpRJyuRz5+fn3/a0junsYBojsuHitHvEbc2E0WVq8Z7xchMbrV25bKuLagf+BNFCJ8Dkf3blRcyMuf/oqEkcNw7p165rVDhiNRvz000/W7v8zZ85AKpVi+PDheOaZZzB27FhER0e7xbf/trh69Sq+/vpraDQa5OXlQSaT4YUXXoBarUZCQoLLvr3/0dGjR/Hyyy/jwoULWLNmDV577TVIJJJ2tZmZmYlx48YhOzsbcXFx1uVNXfvFxcXN/m6++eYbTJo0CVVVVQgODrbZdl5eHmJjYzFw4EAUFRWhoKAAvXv3btfx0oONYYDIjunbfkbe71UO1wg0XCyEVvMmgp6cgcChk++8ksWMmDAv7Hl9DADg4sWL1m//hw4dgl6vR3h4uPXiHx8fz39TbVBaWoq0tDRoNBoUFRVBoVBgypQpUKvVGDJkiEsDVX19PVJSUvD+++8jNjYW27dvR1RUVJvbE0URAwcOhFwux6FD/+x9qqyshEKhwJdffonJk//597Vp0yYkJyfDYDDYPK+GhgYMGDAAjY2NKCkpcarGgB5ejl6/WVpKbuk3bS1+PFfpVLFg3elcAAJk0SNaX8lDglOVJsz9y1vo378/VCoV5s6di6qqKixbtgzHjh3DpUuXsHXrViQlJTEItNEjjzyClJQUFBYWWu/x79q1C0888QR69uyJ5cuX48yZMy7Zl6+vLzZu3IjDhw/j8uXL6N+/Pz766CNYLC17lBwhCAJSUlKQnZ2N/Px86/LQ0FB069atxRMF5eXl6NKli92As2bNGpSUlKC8vBxqtRrTp09v0/GRe2LPALmlld8V4vOfLzgcBkSzCZc+nIFOId3Q+aX1tte1mGEuykF88HWMHTsWCQkJkMvlrjhsssFsNiM3NxcajQbp6emorq7GY489BrVajalTpyI8PLzd+9Dr9UhOTsbHH3+MUaNGITU1FSqVyul2LBYLYmJiEBkZiT179liXJyYm4ubNm9i/f7912cyZM1FcXIy8vLxW2zt+/DgGDRqEsLAw+Pj4oKCggJ/VBIA9A0Q25ZzVOdUrYCgtgMVQA1n0U3bXFTwkiBqeiO3bt2Py5MkMAh1EIpFg5MiR2LZtG65cuYL09HT06NEDS5cuRbdu3RAfH4/U1FRUV1e3eR9+fn7YvHkzDhw4gLNnzyImJgapqalOj4ng4eGBZcuWYe/evc16AgYMGNBijIWmnoHWmEwmzJo1C0FBQdBqtdi5cyeDADmNYYDcjt5oQtm1eqe2qTudC3hI4dsn1qH1y67Vo85oasvhkQt4e3sjKSkJ6enp0Gq12LJlCywWC+bMmQOlUomJEyfi22+/hdFobFP7o0ePxsmTJzFhwgTMnj0bzz77LMrLy51qY+rUqYiMjLQ+fgrcCgM6nQ4VFRXWZRUVFTZ7NTZs2IBjx46hsrIS69atw+DBg50/IXJ7DAPkdi5U1bUcWdAGy00DDL8dhc8jAyDxcewblwjgfFVdm46PXCsoKAizZ89GdnY2ysrKsHr1apSUlCApKQmdO3fGK6+8gsOHDztdAxAUFITPPvsM3333HX755RfExMQgLS3N4V4CqVSKpUuXIj09HUVFRQBuhQEAzXoLbI0+2DQWgre3N8aMGYPFixc7dQ5ETRgGyO3cvMOjhLbUFx+F2GiErO9TTm2X/OZSzJ8/H6tWrcKnn36K3bt3Iz8/H7///jvq6hgU7oVu3bpZhzsuLCzEvHnzcPDgQcTFxSEiIgJLlizB8ePHner2f+6551BYWIgxY8ZArVZj4sSJ0Ol0Dm07Y8YMdO3aFe+88w4AQKVSQS6XW8OA0WhEVVXVHXsGmno6BEGAn58fduzYweGGqc1c/2Au0X3OU+rcB2bd6cMQPH3g02uIU9vpq2/gh+OnoNVqUVlZ2eKbp0wmg1KpRFhYGJRKZbPX7csCAwM5/oCLRUdHY/Xq1Vi1ahXy8/Oh0WiQmpqK9957D9HR0dahkHv06GG3rZCQEOzcuRNJSUmYO3cuYmJisHnzZkyYMMHmdp6enliyZAkWLVqEFStWICoqCgMGDMD/HTuJwvJqlF0qR6ewRyBXdG6x7SeffGIdrTAjIwNKpbJN/x+IAD5NQG6ozmhCzMoDDt0qMNdX49KHMyDr8yRCn3vd4X0IAE6tHAOZ1628bTabUVVVBa1Wa33pdLpmv/9xWWNjY7P2PD09WwSE1n4PCQlp98A47qqxsRFZWVnQaDTYvXs36uvrMWzYMOtQyKGhLUedvJ1Wq8Wrr76KjIwMTJs2DZs2bbI5WJDBYECPHj0wKukl9H5mFr7OO406+AC3hb+IYF/EPRoG9RAVvIzX0adPHxgMBiQnJ+Pdd99t97nTw4mDDhHZMOK9HFxwoIiw5pfvcf1vnyBs8lvwiRzocPsRIb7IfSPO/op3IIoibty4YTcwNL3q65ufh4eHBxQKhUO9DmFhYejUqVObjvNhp9frkZGRgbS0NGRlZUEQBDz99NNQq9VITEyEr69vq9uKoogvvvgCCxYsgK+vL7Zs2YJx48bdcd2L1+rx4sbvccnkB4kAmG18Iks8BJgtInyrL6Dky9XoG9EZR48ehaenZ3tPlx5SDANENjg6zkDF/74O0w0tus3fAcHDsW/bEg8B04dEYGWi/XHkXUGv17cICK2FiBs3brTYXi6X271N0bTM1gXwYabT6fDVV19Bo9Hg6NGjkMlkGD9+PNRqNeLj41sdCvny5cuYM2cO9u/fj1mzZmHDhg0IDAy0vv/Xv5dhxXeFMJktNkPA7USzCRDNeP2pCPznOMdDKrkfhgEiG37T1iLh/R/uWvsHFz2JnmH+d639tjIajc2Cgq0QUVlZ2aKQzs/Pz25gaPo5ICDgoaxzKCkpsQ6FfPbsWYSFhVmHQn788cdbnLMoiti6dSsWL14MuVyO1NRUxMfH48Oc3/BfWcXtOBIRgIA3RvfG/Lhedtcm98QwQGSHs3MTOELiIWBoZAg+n+1cseH9yGQyobKy0qFbFTqdDiZT83EVvLy8bNY2/PEVHBz8wFXCi6KIgoICpKWlYefOnaioqEDPnj0xbdo0qNXqFhMEnT9/HrNmzUJOTg6eXbgWJ336u+xY3k3qhymDnR8JkR5+DANEdtiatbCtvKQeOLhoBLoHu1d3uiiKuH79ut3A0PSzwWBotr1EIrHWOdjrdVAoFPddnYPZbMbhw4etQyHX1NRg0KBBUKvVmDJlinWcAIvFgrX//Qm2lCshSDxbFAk2MV45h+qf0mC8dBqiqRHSICX8/vVpBAxKvOP67vp3R/YxDBA54K9/L8Nfdp10WXv8hmafKIrQ6/UOF0jW1NS0aCMkJMThXgdvb+8OPT+DwYC9e/dCo9EgMzMTJpMJI0eOhFqtRlJSEuZ9XYS8kspWawQMpQXQffM2PJVRkP1pOARPb5huXAFEC+Rxs+64zcPUI0WuxTBA5KD237u9JXn0o5gX19MFR0R/1NDQYLdAsun3qqqqFnUO/v7+DhVHKpVK+Pv7u7TO4fr160hPT4dGo0Fubi58u0QhdMb7ra5vMdbj8qf/Bq+ufaAYvxSC4Nytk/u1VoXuHYYBIidYq7otolM1BBIPAVIPAW8n9mWPwH3AZDLh6tWrDvU66HQ6mM3mZtt7e3vbHceh6SWXy52qc7h48SL+Y1sOThqCgFaeTKn9NRPXDnyE8Dmb0Sm0Oyw3GyB08nQoFHT0Uyz0YHD0+s0RCIkATB2swrCoUCz79iR+PFdpfZ67NU3vD40Mwdrx/Xiv9j4hlUrRpUsXm7P8NbFYLC3qHG4PDCdOnLD+fPukRlKptFmdg61eB4VCge7du6NG1h0wtj6+RcP5YxC8fGHSV0G3azVM1y5D6OQNWUwcgke9AkHa+ngCZouInGIdVoJhgJzHngGi2/ymrYXm5zLkFOtQVlXfbKRCAYAqxBdxvcPw0p9V7JJ1E6Ioora21qHRI7VaLWpra5ttLwgCQjp3hWzG5laLBgGgfNt8mG7cmrHQr/9oeKv6oaHsJGp/+R6+fZ6E4vklNo/z9pEvidgzQNRGvZT+WJnYFyvRF3VGE85X1eGmyQJPqQd6hMj4QeuGBEFAQEAAAgIC0KuX/Wf6DQZDi8BwurwGuwy26xHExgaIjUb4DXgGwQn/DgDwfXQoRHMj9Mf2o3G4Gp2Cu7a+PW7Nltk3PLDVdYjuhJ9qRDbIvKT8YCWn+fj4ICIiAhEREdZlv5Zdx67NeTa3a7oNIOszotlyWfRT0B/bD+PlMzbDAOD8rJxEAKcwJiLqEI7MlinxC7n1X1lQ8+WyW4HU0qB3yX6Ibse/GiKiDtAjRAZ7Dy16do4CAJhqq5otN9VeAwBIfG33Ugn/2A+RsxgGiIg6gMxLCpWdp05kfxoOANCfyGq2XH8iC/CQwEvVz+b2qhBf1rRQm/Cvhoiog8Q9GmZztkzPzlGQ9U9A3Ym/4arFAm9VDBrKTqL+zE8IeGISpP4hrbYt8RAQ1zvsbh06PeQYBoiIOoh6iArb88/bXCdkzDxIAxTQnziI+uJ8SAMVkI96BQGDn7e5ndki4qU/c+ArahuGASKiDtJL6Y/hPUNtzpYpSKQIip2GoNhpDrfbNDcBx72gtmLNABFRB1o7vh+kHq6b/wAApB4C1o63XU9AZAvDABFRB+oe7Iu3XDx/wNuJfTkkNrULwwARUQebOliFN0b3dklbyaMf5SRZ1G6sGSAiugfmx/VCqJ8XZ8uk+wJ7BoiI7pGpg1U4uGgEhkb+Y+RBO7UETe8PjQzBwUUjGATIZdgzQER0D3UP9sXns4dwtky6pziFMRHRfYazZZKrcApjIqIHFGfLpI7GmgEiIiI3xzBARETk5hgGiIiI3BzDABERkZtjGCAiInJzDANERERujmGAiIjIzTEMEBERuTmGASIiIjfHMEBEROTmGAaIiIjcHMMAERGRm2MYICIicnMMA0RERG6OYYCIiMjNMQwQERG5OakjK4miCACoqam5qwdDRERErtN03W66jrfGoTBQW1sLAOjevXs7D4uIiIg6Wm1tLQIDA1t9XxDtxQUAFosF5eXl8Pf3hyAILj1AIiIiujtEUURtbS3Cw8Ph4dF6ZYBDYYCIiIgeXiwgJCIicnMMA0RERG6OYYCIiMjNMQwQERG5OYYBIiIiN8cwQERE5OYYBoiIiNzc/wMw5IGl1cJHrAAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# get the graph after dropout\n", + "iso_clauses = kept_clauses + random.sample(drop_clauses, num_selected)\n", + "iso_graph = construct_graph(iso_clauses)\n", + "nx.draw_networkx(iso_graph, with_labels=True, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:12.461569500Z", + "start_time": "2023-07-03T11:45:12.132507800Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "The PQC is similar to the regular QAOA, but the cost Hamiltonian is the original Hamiltonian but the driving Hamiltonian is the one after dropout." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 11, + "outputs": [], + "source": [ + "def QAOAansatz_iso(params, g, each=1, return_circuit=False):\n", + " n = g.number_of_nodes() # the number of nodes\n", + "\n", + " # PQC loop\n", + " def pqc_loop(s_, params_):\n", + " c_ = tc.Circuit(n, inputs=s_)\n", + " for j in range(each):\n", + " # driving layer\n", + " for a, b in g.edges:\n", + " c_.RZZ(a, b, theta=g[a][b][\"weight\"] * params_[2 * j] * driving_factor)\n", + " # mixing layer\n", + " for i in range(n):\n", + " c_.RX(i, theta=params_[2 * j + 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(n)\n", + " for i in range(n):\n", + " c0.H(i)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, K.reshape(params, [nlayers // each, 2 * each]), s0)\n", + " c = tc.Circuit(n, inputs=s)\n", + "\n", + " # whether to return the circuit\n", + " if return_circuit is True:\n", + " return c\n", + "\n", + " # calculate the loss function\n", + " loss = 0.25\n", + " for a, b in hard_graph.edges:\n", + " loss += c.expectation_ps(z=[a, b]) * hard_graph[a][b][\"weight\"] * cost_factor\n", + "\n", + " return K.real(loss)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T11:45:12.464821600Z", + "start_time": "2023-07-03T11:45:12.462095700Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Here, several circuits with different initial parameters are optimized/trained at the same time." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 12, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# use vvag to get the losses and gradients with different random circuit instances\n", + "QAOA_vvag = K.jit(\n", + " K.vvag(QAOAansatz_iso, argnums=0, vectorized_argnums=0), static_argnums=(1, 2, 3)\n", + ")\n", + "\n", + "params_iso = K.implicit_randn(\n", + " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", + ") # initial parameters\n", + "if type(K).__name__ == \"JaxBackend\":\n", + " opt = K.optimizer(optax.adam(1e-2))\n", + "else:\n", + " opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", + "\n", + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(2000):\n", + " loss, grads = QAOA_vvag(params_iso, iso_graph)\n", + " params_iso = opt.update(grads, params_iso) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [f\"circuit {leg}\" for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "After inputting the optimized parameters back to the ansatz circuit, we can perform the projective measurement on the output quantum state to get the solution. Here we directly use the bit string with the maximum probability as the solution since we know all information of the probability distribution of the output quantum state, but which is not feasible in the experiment." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 13, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Circuit #0\n", + "cost: 0.042537812143564224\n", + "max prob: 0.047906018793582916\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #1\n", + "cost: 0.033970173448324203\n", + "max prob: 0.054868899285793304\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #2\n", + "cost: 0.033648744225502014\n", + "max prob: 0.055139534175395966\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #3\n", + "cost: 0.03602508455514908\n", + "max prob: 0.05475332960486412\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #4\n", + "cost: 0.03601868823170662\n", + "max prob: 0.05406792089343071\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #5\n", + "cost: 0.03338256850838661\n", + "max prob: 0.05537496879696846\n", + "bit strings: ['000000111111']\n", + "\n" + ] + } + ], + "source": [ + "# print QAOA results\n", + "for num_circuit in range(ncircuits):\n", + " print(f\"Circuit #{num_circuit}\")\n", + " c = QAOAansatz_iso(params=params_iso[num_circuit], g=iso_graph, return_circuit=True)\n", + " loss = QAOAansatz_iso(params=params_iso[num_circuit], g=iso_graph)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability())\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + " print(f\"cost: {K.numpy(loss)}\\nmax prob: {max_prob}\\nbit strings: {states}\\n\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T12:07:03.904854400Z", + "start_time": "2023-07-03T12:06:31.721659700Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "On average, QAOA with isotropic quantum dropout improves the probability of correct solution (max prob) by nearly 0.015 compared to regular QAOA.\n", + "\n", + "It should be noted that isotropic quantum dropout will lead to more ground state degeneracy, so it does not necessarily lead to better results than conventional QAOA. However, it has a high upper limit, which means that it is possible to get much better results, please refer to [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171) for more analysis and details." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Random Quantum Dropout" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Because the dropout of each layer is different, we need to generate $\\text{nlayers}$ graphs after dropout. In order to perform just-in-time (JIT) compilation more conveniently, here we only save the weights in the order of the edges of the original hard graph, instead of saving each graph after dropout." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 21, + "outputs": [], + "source": [ + "def graph_weights(graph):\n", + " gw = []\n", + " for a, b in hard_graph.edges:\n", + " gw.append(graph[a].get(b, default={\"weight\": 0})[\"weight\"])\n", + " return jnp.asarray(gw)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T13:23:26.871885Z", + "start_time": "2023-07-03T13:23:26.858216600Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 22, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here is the graph of the H_C of the last driving layer:\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# get the graph after dropout\n", + "rnd_graphs_w = []\n", + "for _ in range(nlayers):\n", + " rnd_clauses = kept_clauses + random.sample(drop_clauses, num_selected)\n", + " rnd_graph = construct_graph(rnd_clauses)\n", + " rnd_graphs_w.append(graph_weights(rnd_graph))\n", + "print(\"Here is the graph of the H_C of the last driving layer:\")\n", + "rnd_graphs_w = jnp.stack(rnd_graphs_w, axis=0)\n", + "nx.draw_networkx(rnd_graph, with_labels=True, pos=pos)\n", + "ax = plt.gca()\n", + "ax.set_facecolor(\"w\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T13:23:28.437985100Z", + "start_time": "2023-07-03T13:23:28.262064700Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "The ansatz needs to accept $\\text{nlayers}$ weights of graphs as inputs." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 23, + "outputs": [], + "source": [ + "def QAOAansatz_rnd(params, g, each=1, return_circuit=False):\n", + " n = hard_graph.number_of_nodes() # the number of nodes\n", + " rep = nlayers // each\n", + " g = g.reshape(rep, each, g.shape[-1]) * driving_factor\n", + "\n", + " # PQC loop\n", + " def pqc_loop(s_, pkg):\n", + " params_, g_ = pkg\n", + " c_ = tc.Circuit(n, inputs=s_)\n", + " for j in range(each):\n", + " # driving layer\n", + " for i, (a, b) in enumerate(hard_graph.edges):\n", + " c_.RZZ(a, b, theta=g_[j][i] * params_[2 * j])\n", + " # mixing layer\n", + " for i in range(n):\n", + " c_.RX(i, theta=params_[2 * j + 1])\n", + " s_ = c_.state()\n", + " return s_\n", + "\n", + " c0 = tc.Circuit(n)\n", + " for i in range(n):\n", + " c0.H(i)\n", + " s0 = c0.state()\n", + " s = K.scan(pqc_loop, [K.reshape(params, [rep, 2 * each]), g], s0)\n", + " c = tc.Circuit(n, inputs=s)\n", + "\n", + " # whether to return the circuit\n", + " if return_circuit is True:\n", + " return c\n", + "\n", + " # calculate the loss function\n", + " loss = 0.25\n", + " for a, b in hard_graph.edges:\n", + " loss += c.expectation_ps(z=[a, b]) * hard_graph[a][b][\"weight\"] * cost_factor\n", + "\n", + " return K.real(loss)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-03T13:23:41.855222600Z", + "start_time": "2023-07-03T13:23:41.802298100Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Then, we perform the optimization step, and also optimize several circuits in parallel. Since graph weights Jax arrays are non-hashable static arguments and not supported when using vmap, we use $\\text{partial}$ to wrap the ansatz and accept the graph weights input." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 28, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# use vvag to get the losses and gradients with different random circuit instances\n", + "QAOA_vvag = K.jit(\n", + " K.vvag(partial(QAOAansatz_rnd, g=rnd_graphs_w), argnums=0, vectorized_argnums=0)\n", + ")\n", + "\n", + "params_rnd = K.implicit_randn(\n", + " shape=[ncircuits, 2 * nlayers], stddev=0.1\n", + ") # initial parameters\n", + "if type(K).__name__ == \"JaxBackend\":\n", + " opt = K.optimizer(optax.adam(1e-2))\n", + "else:\n", + " opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))\n", + "\n", + "list_of_loss = [[] for i in range(ncircuits)]\n", + "\n", + "for i in range(2000):\n", + " loss, grads = QAOA_vvag(params_rnd)\n", + " params_rnd = opt.update(grads, params_rnd) # gradient descent\n", + "\n", + " # visualise the progress\n", + " clear_output(wait=True)\n", + " list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))\n", + " plt.xlabel(\"Iteration\")\n", + " plt.ylabel(\"Cost\")\n", + " for index in range(ncircuits):\n", + " plt.plot(range(i + 1), list_of_loss[index])\n", + " legend = [f\"circuit {leg}\" for leg in range(ncircuits)]\n", + " plt.legend(legend)\n", + " plt.show()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 29, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Circuit #0\n", + "cost: 0.034298673272132874\n", + "max prob: 0.061373475939035416\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #1\n", + "cost: 0.034172173589468\n", + "max prob: 0.06166590005159378\n", + "bit strings: ['000000111111', '111111000000']\n", + "\n", + "Circuit #2\n", + "cost: 0.03370116278529167\n", + "max prob: 0.06229700148105621\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #3\n", + "cost: 0.035995520651340485\n", + "max prob: 0.0600101463496685\n", + "bit strings: ['111111000000']\n", + "\n", + "Circuit #4\n", + "cost: 0.03770057111978531\n", + "max prob: 0.05639055743813515\n", + "bit strings: ['000000111111']\n", + "\n", + "Circuit #5\n", + "cost: 0.042536795139312744\n", + "max prob: 0.047668762505054474\n", + "bit strings: ['111111000000']\n", + "\n" + ] + } + ], + "source": [ + "# print QAOA results\n", + "for num_circuit in range(ncircuits):\n", + " print(f\"Circuit #{num_circuit}\")\n", + " c = QAOAansatz_rnd(\n", + " params=params_rnd[num_circuit], g=rnd_graphs_w, return_circuit=True\n", + " )\n", + " loss = QAOAansatz_rnd(params=params_rnd[num_circuit], g=rnd_graphs_w)\n", + "\n", + " # find the states with max probabilities\n", + " probs = K.numpy(c.probability())\n", + " max_prob = max(probs)\n", + " index = np.where(probs == max_prob)[0]\n", + " states = []\n", + " for i in index:\n", + " states.append(f\"{bin(i)[2:]:0>{c._nqubits}}\")\n", + " print(f\"cost: {K.numpy(loss)}\\nmax prob: {max_prob}\\nbit strings: {states}\\n\")" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-04T01:38:27.853435600Z", + "start_time": "2023-07-04T01:37:48.381823700Z" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "On average, QAOA with random quantum dropout improves the probability of correct solution (max prob) by nearly 0.02 compared to regular QAOA.\n", + "\n", + "Compared with isotropic quantum dropout, the standard deviation of the probability of correct solution obtained by random quantum dropout is smaller, but the upper limit is lower. From the physical picture, QAOA after random quantum dropout works like a quantum interferometer. QAOA circuits with different dropouts over driving layers may work through a focusing effect on the true ground state: different clause sets lead to different energy landscapes and minima, whose configurations receive constructive interference and enhanced amplitudes. Being the only common minimum of all $\\hat{H}_{C_i}$ irrespective of the dropouts, the true ground state remains stand-out through all driving layers. Please refer to [Wang, Zheng, Wu, and Zhang (2023)](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.5.023171) for more analysis and details." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 30, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS info: Linux-5.4.119-1-tlinux4-0010.2-x86_64-with-glibc2.28\n", + "Python version: 3.10.11\n", + "Numpy version: 1.23.5\n", + "Scipy version: 1.11.0\n", + "Pandas version: 2.0.2\n", + "TensorNetwork version: 0.4.6\n", + "Cotengra is not installed\n", + "TensorFlow version: 2.12.0\n", + "TensorFlow GPU: []\n", + "TensorFlow CUDA infos: {'cpu_compiler': '/dt9/usr/bin/gcc', 'cuda_compute_capabilities': ['sm_35', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'compute_80'], 'cuda_version': '11.8', 'cudnn_version': '8', 'is_cuda_build': True, 'is_rocm_build': False, 'is_tensorrt_build': True}\n", + "Jax version: 0.4.13\n", + "Jax installation doesn't support GPU\n", + "JaxLib version: 0.4.13\n", + "PyTorch version: 2.0.1\n", + "PyTorch GPU support: False\n", + "PyTorch GPUs: []\n", + "Cupy is not installed\n", + "Qiskit version: 0.24.1\n", + "Cirq version: 1.1.0\n", + "TensorCircuit version 0.10.0\n" + ] + } + ], + "source": [ + "tc.about()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-07-04T01:40:31.531945400Z", + "start_time": "2023-07-04T01:40:31.478214100Z" + } + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/tc_qcloud_sdk.ipynb b/docs/source/tutorials/qcloud_sdk.ipynb similarity index 100% rename from docs/source/tutorials/tc_qcloud_sdk.ipynb rename to docs/source/tutorials/qcloud_sdk.ipynb diff --git a/docs/source/tutorials/qcloud_sdk_demo.ipynb b/docs/source/tutorials/qcloud_sdk_demo.ipynb new file mode 100644 index 00000000..8f0a97a5 --- /dev/null +++ b/docs/source/tutorials/qcloud_sdk_demo.ipynb @@ -0,0 +1,1648 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a246d497", + "metadata": {}, + "source": [ + "# Demo on TensorCircuit SDK for Tencent Quantum Cloud\n", + "\n", + "This notebook is not served as a full user manual for TC SDK for QCLOUD. Instead,it only highlighted a limited subset of features that TC enabled, mainly for live demo and tutorials.\n", + "\n", + "## Import and Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ff5cc3c8", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc" + ] + }, + { + "cell_type": "markdown", + "id": "e66850fe", + "metadata": {}, + "source": [ + "The following two line are by default and no need to run explicitly, \n", + "unless you activate tencent cloud service for the first time when you have to set up the token copied from the web" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4352cc25", + "metadata": {}, + "outputs": [], + "source": [ + "# tc.cloud.apis.set_token(\"123456isnotgoodpassword\")\n", + "# tc.cloud.apis.set_provider(\"tencent\")" + ] + }, + { + "cell_type": "markdown", + "id": "2aa760be", + "metadata": {}, + "source": [ + "## Devices and properties" + ] + }, + { + "cell_type": "markdown", + "id": "735c2d63", + "metadata": {}, + "source": [ + "**Provider agnostic**: The SDK architecture is designed to be provider agnostic so that we have the potential to support multiple QPU providers in the future. And from the user's pespective, no code will change to deploy the quantum program on different QPU providers. We also support some third party and local providers now internally, and the list will be expanding...\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "72106e97", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[tencent, local]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.apis.list_providers()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e35e1518", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[tencent::simulator:tc,\n", + " tencent::simulator:aer,\n", + " tencent::simulator:tcn1,\n", + " tencent::tianshu_s1,\n", + " tencent::tianxuan_s1]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.apis.list_devices()" + ] + }, + { + "cell_type": "markdown", + "id": "4f5ce14e", + "metadata": {}, + "source": [ + "list only devices online that are currently available with `state` argument" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b8456acc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[tencent::simulator:tc,\n", + " tencent::simulator:aer,\n", + " tencent::tianshu_s1,\n", + " tencent::tianxuan_s1]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.apis.list_devices(\"tencent\", state=\"on\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7ced9cc6", + "metadata": {}, + "outputs": [], + "source": [ + "device_name = \"tianxuan_s1\" # 9 qubits chip\n", + "\n", + "# get the device object\n", + "\n", + "d = tc.cloud.apis.get_device(device_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "0e0633c5", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import Image\n", + "\n", + "Image(filename=\"../statics/tianxuan_s1.png\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0461fc24", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'id': 'tianxuan_s1',\n", + " 'type': 'CHIP',\n", + " 'qubits': 9,\n", + " 'T1': 30.593555450439453,\n", + " 'T2': 12.94344425201416,\n", + " 'Err': {'SQ': 0.0008366666666666665,\n", + " 'CZ': 0.01615125,\n", + " 'Readout': {'F0': 0.0209, 'F1': 0.0849111111111111}},\n", + " 'report': {'at': 1683908208,\n", + " 'consumed': 181292436838,\n", + " 'done': 32164,\n", + " 'total': 32175,\n", + " 'waiting': 5039},\n", + " 'at': 1685496713,\n", + " 'state': 'on',\n", + " 'links': {(0, 1): {'A': 0, 'B': 1, 'CZErrRate': 0.0135, 'GateLenInNs': 75.56},\n", + " (0, 2): {'A': 0, 'B': 2, 'CZErrRate': 0.02358, 'GateLenInNs': 78.74},\n", + " (0, 3): {'A': 0, 'B': 3, 'CZErrRate': 0.01899, 'GateLenInNs': 79.94},\n", + " (0, 4): {'A': 0, 'B': 4, 'CZErrRate': 0.03357, 'GateLenInNs': 79.93},\n", + " (1, 5): {'A': 1, 'B': 5, 'CZErrRate': 0.00552, 'GateLenInNs': 74.94},\n", + " (2, 6): {'A': 2, 'B': 6, 'CZErrRate': 0.01951, 'GateLenInNs': 79.71},\n", + " (3, 7): {'A': 3, 'B': 7, 'CZErrRate': 0.00422, 'GateLenInNs': 65.04},\n", + " (4, 8): {'A': 4, 'B': 8, 'CZErrRate': 0.01032, 'GateLenInNs': 76.07}},\n", + " 'bits': {0: {'Freqency': 3974.78,\n", + " 'Qubit': 0,\n", + " 'ReadoutF0Err': 0.035,\n", + " 'ReadoutF1Err': 0.0876,\n", + " 'SingleQubitErrRate': 0.00079,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 34.524,\n", + " 'T2': 9.62},\n", + " 1: {'Freqency': 4180.96,\n", + " 'Qubit': 1,\n", + " 'ReadoutF0Err': 0.0308,\n", + " 'ReadoutF1Err': 0.0732,\n", + " 'SingleQubitErrRate': 0.00064,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 34.459,\n", + " 'T2': 8.321},\n", + " 2: {'Freqency': 4106.44,\n", + " 'Qubit': 2,\n", + " 'ReadoutF0Err': 0.0192,\n", + " 'ReadoutF1Err': 0.0728,\n", + " 'SingleQubitErrRate': 0.00085,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 18.917,\n", + " 'T2': 5.222},\n", + " 3: {'Freqency': 4657.5,\n", + " 'Qubit': 3,\n", + " 'ReadoutF0Err': 0.0073,\n", + " 'ReadoutF1Err': 0.1156,\n", + " 'SingleQubitErrRate': 0.00124,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 31.079,\n", + " 'T2': 42.79},\n", + " 4: {'Freqency': 4405.96,\n", + " 'Qubit': 4,\n", + " 'ReadoutF0Err': 0.0117,\n", + " 'ReadoutF1Err': 0.0483,\n", + " 'SingleQubitErrRate': 0.0006,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 32.353,\n", + " 'T2': 9.3},\n", + " 5: {'Freqency': 4371.74,\n", + " 'Qubit': 5,\n", + " 'ReadoutF0Err': 0.0125,\n", + " 'ReadoutF1Err': 0.0604,\n", + " 'SingleQubitErrRate': 0.00058,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 30.132,\n", + " 'T2': 6.954},\n", + " 6: {'Freqency': 4247.08,\n", + " 'Qubit': 6,\n", + " 'ReadoutF0Err': 0.0465,\n", + " 'ReadoutF1Err': 0.1351,\n", + " 'SingleQubitErrRate': 0.00102,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 34.827,\n", + " 'T2': 4.462},\n", + " 7: {'Freqency': 4462.26,\n", + " 'Qubit': 7,\n", + " 'ReadoutF0Err': 0.0096,\n", + " 'ReadoutF1Err': 0.0525,\n", + " 'SingleQubitErrRate': 0.0006,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 28.269,\n", + " 'T2': 13.429},\n", + " 8: {'Freqency': 4335.34,\n", + " 'Qubit': 8,\n", + " 'ReadoutF0Err': 0.0155,\n", + " 'ReadoutF1Err': 0.1187,\n", + " 'SingleQubitErrRate': 0.00121,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 30.782,\n", + " 'T2': 16.393}},\n", + " 'langs': ['tQASM', 'eQASM'],\n", + " 'memo': 'tQLab 9Gmon',\n", + " 'usage': '9gmon?o=0 \\nthe o(ptimized) to specify optimization level bits: both = 3 (bits 11) = gate decomposition = 2 (bit 10) | qubit mapping = 1 (bit 01)',\n", + " 'native_gates': ['h', 'rz', 'x', 'y', 'z', 'cz', 'cx']}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.list_properties()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b44f1844", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Freqency': 4106.44,\n", + " 'Qubit': 2,\n", + " 'ReadoutF0Err': 0.0192,\n", + " 'ReadoutF1Err': 0.0728,\n", + " 'SingleQubitErrRate': 0.00085,\n", + " 'SingleQubitGateLenInNs': 40,\n", + " 'T1': 18.917,\n", + " 'T2': 5.222}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.list_properties()[\"bits\"][2]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ae4798dc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(['h', 'rz', 'x', 'y', 'z', 'cz', 'cx'],\n", + " 'tianxuan_s1',\n", + " tencent,\n", + " [[0, 1],\n", + " [6, 2],\n", + " [4, 0],\n", + " [0, 4],\n", + " [8, 4],\n", + " [1, 5],\n", + " [3, 7],\n", + " [0, 3],\n", + " [2, 0],\n", + " [5, 1],\n", + " [3, 0],\n", + " [7, 3],\n", + " [0, 2],\n", + " [2, 6],\n", + " [4, 8],\n", + " [1, 0]])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# some meta data for the device\n", + "\n", + "d.native_gates(), d.name, d.provider, d.topology()" + ] + }, + { + "cell_type": "markdown", + "id": "ccd597ae", + "metadata": {}, + "source": [ + "The native gate set and the coupling map information is essential for TC to transpile the circuits so that they conform the standard of the corresponding devices." + ] + }, + { + "cell_type": "markdown", + "id": "dcea5cfe", + "metadata": {}, + "source": [ + "## Tasks" + ] + }, + { + "cell_type": "markdown", + "id": "3ad38549", + "metadata": {}, + "source": [ + "Submit a simple two-qubit task.\n", + "\n", + "Note that there is no need to explicitly add any measurement operations to the circuit. By default, t.results will return the number of (Z-basis) measurement outcomes for all (in this case 2) qubits in the specified circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "01a0fb92", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 494, '11': 391, '10': 80, '01': 59}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = tc.Circuit(2)\n", + "c.H(0)\n", + "c.cx(0, 1)\n", + "\n", + "t = tc.cloud.apis.submit_task(device=d, circuit=c, shots=1024)\n", + "\n", + "t.results() # this will wait until the result is return" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "33b9eb5a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
     ┌───┐     \n",
+       "q_0: ┤ H ├──■──\n",
+       "     └───┘┌─┴─┐\n",
+       "q_1: ─────┤ X ├\n",
+       "          └───┘
" + ], + "text/plain": [ + " ┌───┐ \n", + "q_0: ┤ H ├──■──\n", + " └───┘┌─┴─┐\n", + "q_1: ─────┤ X ├\n", + " └───┘" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "88cfc4ad", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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4oUXXmDNmjVMmTKFE044gQsvvJAXX3yx7DLVSxiQknqE9evXc/3119PU1MTy5ctpa2tj9uzZXHnllVxxxRX85je/YdCgQXzzm98su1T1EgakpB6jtbWVHTt20NrayvPPP88xxxzDvHnzuOCCCwCYMWMGt956a7lFqtcwICX1CCNGjOCTn/wkxx57LMcccwyHH344kyZN4ogjjqC2thaAkSNHsn79+pIrVW9hQErqEbZs2cJtt93GmjVreOqpp3juuee48847yy5LvVht2QVI0v645557OP744zn66KMBeNe73sUDDzzAs88+S2trK7W1taxbt44RI0aUXKl6C0eQknqEY489ll/84hc8//zzZCY///nPGTduHGeddRZz5swB4Oabb+Yd73hHyZWqtzAgJfUIU6ZM4YILLqC+vp5TTz2VnTt3cumll3L11Vfzla98hRNOOIHNmzfz4Q9/uOxS1Us4xSqpx7jqqqu46qqrXrZszJgxPPTQQyVVpN7MEaQkSQUMSEmSCjjFKu3F6NGjGTBgADU1NdTW1tLU1MSyZcu47LLL2L59O6NHj+Z73/seAwcOLLvUbumSWWVX0Hlumll2BSqDI0hpH+69914efvhhmpqaALj44ov58pe/zCOPPML555/PtddeW3KFkg4WA1LqgFWrVjFt2jQApk+fzi233FJyRZIOFgNS2ouI4JxzzmHSpEnceOONAIwfP57bbrsNgB/+8IesXbu2zBIlHUQGpLQXCxcuZOnSpfz0pz/la1/7GgsWLOBb3/oWX//615k0aRLbtm3jsMMOK7tMSQeJASntxa5Llg0ZMoTzzz+fhx56iJNPPpm77rqLJUuWcNFFF/G6172u5ColHSwGpFTgueeeY9u2bbu/vuuuu5gwYQLNzc0A7Ny5ky984QtcdtllZZYp6SAyIKUCmzZtYurUqUycOJHJkyfztre9jbe+9a18//vfZ+zYsZx88skMHz6cD33oQ2WXKukg8TxIqcCYMWNYtmzZHyz/xCc+wSc+8YkSKpLU1RxBSpJUwICUJKmAU6zqFbysmaTO5ghSkqQCBqQkSQUMSEmSChiQkiQVMCAlSSpgQEqSVMCAlCSpgAEpSVIBA1KSpAIGpCRJBQxISZIKGJCSJBUwICVJKmBASpJUwICUJKmAASlJUgEDUpKkAgakJEkFDEhJkgoYkJIkFTAg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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.results.counts.plot_histogram(t.results())" + ] + }, + { + "cell_type": "markdown", + "id": "0596e9f1", + "metadata": {}, + "source": [ + "Check with the analytical exact result is easy, just use tensorcircuit's sota tensornetwork based simulation engine. The answer is a quantum state as $\\vert 00\\rangle + \\vert 11\\rangle$" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "dd798dd7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.49999997 0. 0. 0.49999997]\n", + "{'00': 0.4999999701976776, '11': 0.4999999701976776}\n" + ] + } + ], + "source": [ + "p = c.probability()\n", + "print(p)\n", + "exact_result = tc.results.counts.vec2count(p, prune=True)\n", + "print(exact_result)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "0d5ca58d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.results.counts.plot_histogram([t.results(), exact_result])\n", + "# experiment vs exact" + ] + }, + { + "cell_type": "markdown", + "id": "d48cb1c1", + "metadata": {}, + "source": [ + "Let us further investigate the Task object ``t`` returned by ``submit_task``, it contains enriched information on manager, compiling, etc." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "598448da", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'id': '3a8840fa-1831-48c3-85fd-67a66523ed8f',\n", + " 'queue': 'txq.low',\n", + " 'device': 'tianxuan_s1?o=3',\n", + " 'qubits': 2,\n", + " 'depth': 3,\n", + " 'state': 'completed',\n", + " 'shots': 1024,\n", + " 'prior': 1,\n", + " 'at': datetime.datetime(2023, 5, 31, 11, 45, 7, 695261),\n", + " 'ts': {'completed': datetime.datetime(2023, 5, 31, 11, 45, 7, 695261),\n", + " 'pending': datetime.datetime(2023, 5, 31, 11, 45, 6, 364959),\n", + " 'scheduled': datetime.datetime(2023, 5, 31, 11, 45, 6, 359719)},\n", + " 'md5': '9cb407b41938a256ec15dfec163dca1d',\n", + " 'runAt': 1685504730279662,\n", + " 'runDur': 1016276,\n", + " 'source': 'OPENQASM 2.0;\\ninclude \"qelib1.inc\";\\nqreg q[2];\\nh q[0];\\ncx q[0],q[1];',\n", + " 'version': '1',\n", + " 'lang': 'OPENQASM',\n", + " 'result': {'00': 494, '01': 59, '10': 80, '11': 391},\n", + " 'optimization': {'progs': [{'code': 'Tencent Quantum Program\\nversion 1.0\\nqubit involved: q0,q1,q2,q3,q4,q5,q6,q7,q8\\n# section: eqasm\\n# section lines 3\\neqasm program\\nbs 1 H q0\\nbs 1 CX (q0, q1)\\nMEASZ q0,q1\\n# section: end\\n',\n", + " 'lang': 'QEXE'},\n", + " {'code': 'Tencent Quantum Program\\nversion 1.0\\nqubit involved: q0,q1,q2,q3,q4,q5,q6,q7,q8\\n# section: eqasm\\n# section lines 3\\neqasm program\\nbs 1 H q0\\nbs 1 CX (q0, q1)\\nMEASZ q0,q1\\n# section: end\\n',\n", + " 'lang': 'QEXE_COMPACT'}],\n", + " 'pairs': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8}},\n", + " 'results': {'00': 494, '01': 59, '10': 80, '11': 391},\n", + " 'frontend': ,\n", + " 'backend': }" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.details(prettify=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "c6a539ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'completed'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.status()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b3fcd4ec", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'3a8840fa-1831-48c3-85fd-67a66523ed8f'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.id_" + ] + }, + { + "cell_type": "markdown", + "id": "f951f18c", + "metadata": {}, + "source": [ + "The task can be retrieved from cloud with the id without task object `t`" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "00e6c83d", + "metadata": {}, + "outputs": [], + "source": [ + "t1 = tc.cloud.apis.get_task(t.id_)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "19a5e66b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
     ┌───┐     \n",
+       "q_0: ┤ H ├──■──\n",
+       "     └───┘┌─┴─┐\n",
+       "q_1: ─────┤ X ├\n",
+       "          └───┘
" + ], + "text/plain": [ + " ┌───┐ \n", + "q_0: ┤ H ├──■──\n", + " └───┘┌─┴─┐\n", + "q_1: ─────┤ X ├\n", + " └───┘" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t1.details(prettify=True)[\"frontend\"].draw()\n", + "# exactly the task we submitted" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "1e7520af", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00': 494, '11': 391, '10': 80, '01': 59}" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t1.results()" + ] + }, + { + "cell_type": "markdown", + "id": "303cf6c3", + "metadata": {}, + "source": [ + "Task group management is also possible but not shown here. Try using ``group`` argument when ``submit_task`` and ``list_task`` when retrieving." + ] + }, + { + "cell_type": "markdown", + "id": "ce9f8313", + "metadata": {}, + "source": [ + "## Cloud simulator\n", + "\n", + "We can also submit tasks to run on tc simulators on the cloud, the only thing you need to change is the device name, and now the result becomes exact." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "adadefd1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'11': 546, '00': 478}" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = tc.Circuit(2)\n", + "c.H(0)\n", + "c.cx(0, 1)\n", + "\n", + "t = tc.cloud.apis.submit_task(device=\"simulator:tc\", circuit=c, shots=1024)\n", + "\n", + "t.results() # this will wait until the result is return\n", + "# instead, using wait=False for t.results(wait=False), the task objects can be returned in async mode" + ] + }, + { + "cell_type": "markdown", + "id": "c00c7dde", + "metadata": {}, + "source": [ + "**Batch submission:** Tasks can also submitted in batch, either on real devices or on simulators, a list of task object is returned by ``submit_task``, if the circuit submitted is in a list. In this way, the joint tasks are executed on the QPU at the same time so that the noise profile remains consistent." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "7f57f4e2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'10': 524, '00': 500}\n", + "{'00': 519, '01': 505}\n" + ] + } + ], + "source": [ + "c1 = tc.Circuit(2)\n", + "c1.h(0)\n", + "\n", + "c2 = tc.Circuit(2)\n", + "c2.h(1)\n", + "\n", + "ts = tc.cloud.apis.submit_task(device=\"simulator:tc\", circuit=[c1, c2], shots=1024)\n", + "for t in ts:\n", + " print(t.results())" + ] + }, + { + "cell_type": "markdown", + "id": "1e72f1ab", + "metadata": {}, + "source": [ + "## Compling: gate decomposition and qubit mapping" + ] + }, + { + "cell_type": "markdown", + "id": "7bea5aba", + "metadata": {}, + "source": [ + "Say we want to simulate the following logic circuit, however, the gate set and the coupling for two-qubit gates are both incompatible with our real device" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "2fc080c9", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = tc.Circuit(5)\n", + "c.rx(0, theta=1.5708)\n", + "for i in range(4):\n", + " c.cx(i, i + 1)\n", + "c.measure_instruction(*range(5))\n", + "# note for tasks involving qubit mapping, we recommend you add the measure instruction explicitly\n", + "c.draw(output=\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ea2b3692", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00000': 4014, '11111': 4178}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# the ideal answer with shot noise\n", + "c.sample(allow_state=True, batch=8192, format=\"count_dict_bin\")" + ] + }, + { + "cell_type": "markdown", + "id": "79349e8e", + "metadata": {}, + "source": [ + "The target state we prepare is the so called GHZ state (here is GHZ-5), which is also famuous as Schordinger cat state, as it is a superposition of two very different (macroscopic) quantum states: $\\vert 00000\\rangle + \\vert 11111\\rangle$. GHZ state is also a great measure to determine the quality of the quantum hardware.\n", + "\n", + "\n", + "By default the **backend compiler** options are both enabled which we write expicitly below" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "f381a9f7", + "metadata": {}, + "outputs": [], + "source": [ + "t = tc.cloud.apis.submit_task(\n", + " circuit=c,\n", + " shots=8192,\n", + " device=d,\n", + " enable_qos_gate_decomposition=True,\n", + " enable_qos_qubit_mapping=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "0704b37f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00000': 3794,\n", + " '11111': 862,\n", + " '00010': 584,\n", + " '10000': 311,\n", + " '00011': 258,\n", + " '01111': 254,\n", + " '00110': 221,\n", + " '10111': 188,\n", + " '00111': 176,\n", + " '11101': 169,\n", + " '11000': 128,\n", + " '00100': 113,\n", + " '11100': 104,\n", + " '10010': 102,\n", + " '01010': 89,\n", + " '00001': 87,\n", + " '10100': 84,\n", + " '11110': 79,\n", + " '11011': 78,\n", + " '01011': 71,\n", + " '01000': 66,\n", + " '01101': 63,\n", + " '01110': 63,\n", + " '10110': 49,\n", + " '01100': 43,\n", + " '10011': 42,\n", + " '00101': 26,\n", + " '10101': 25,\n", + " '10001': 18,\n", + " '01001': 15,\n", + " '11001': 15,\n", + " '11010': 15}" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rb = t.results()\n", + "rb" + ] + }, + { + "cell_type": "markdown", + "id": "9847ccaa", + "metadata": {}, + "source": [ + "We can inspect the circuit compiled after the backend server compiling:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "24748fe7", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4EAAAEDCAYAAACLTQE2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAzXUlEQVR4nO3deXxU1f3/8ffMJCRA2EKEsEMgiRAJSxRZxBBXoFqpChYtrUhFAdui7bffb7/WVn/YtKW0tX5rXVortiptQVqtghWVRJRFWSUohD0EAoQQAiELSWZ+f1xDCCQzk+TO3Jnc1/PxyMN45+bkw80h3Pecc89xeDwejwAAAAAAtuC0ugAAAAAAQPAQAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARiKsLiDU7fpAOnPcmu/doZuUfF3zvnb5Rulwsbn1+KNXF+n2K5v3tVbVLLWsbqv6SDj2Dyk8+0g49g+p+X0kHGsGAAD+IwT6cOa4dCrf6iqa7nCxtNeim7jmCseapfDsI+F6rcOx7nDsH+FYMwAA8B/TQQEAAADARgiBAAAAAGAjTAcFAAAB4/FI+cVSXpF0tESqqpYiXFL3jlKfrlLfWMnJW9K2VlIm7T8h5Z+USiskh0Pq3E7qEyv1v0xq18bqCluPolLpwAnp8Emp7JxxrbvG1F3rqBBMBueqjZoPFRn1uz1S2zbG8/r946S4DlZXGJ5C8EcNAADCXXWNtG6PtCZXOn668fO6xkhjB0njk6U23JXYyp5j0uovpM8PS55Gzol0SWn9pYwhxhsHaJ4d+VL2Lin3aOPnREdKoxKkjMFSl/bBq60xJWVS1k5p/V6p/Fzj5w3sJl2bLKX2MUIt/MOvW5N8/9kJ+uLgOrlckXI6XYrvMkB3X/+o0odNtbo0hAD6B7wJ1/4RrnUj8PJPSq+tk46c8n1uUan0761GYJw+xrihQ+tWUSX9a5Nxc+9LVY1x3sb90sRU6brBjBw3xZkKadmn0rY83+dWVEkf7pI27JVuGymNGWRNqPJ4pE/3S//cKJVX+T5/73HjI6WXNG2U1Kld4GtsDfhrZKJ7bnhM//5ZqZY/XqSbr7pXP3/tbh0+scfqshAi6B/wJlz7R7jWjcD5/LD01Lv+BcALnSiVnnnPuNlH63WmQnr6Xf8C4IWq3dJbW6WXPzJGmeFbUan01H/8C4AXqqyW/vGJtPRTY+plMHk80ptbjDeR/AmAF9pxWPrNO9KxksDU1toQAgPA5YrQpKvvV427WnuPbLW6HIQY+ge8Cdf+Ea51w1z7C6U/f9j8m3S3R3p1rXEzh9bnXLX0/AdNf4PgQtsOSX/bYFpJrdbZSukP7xtBsLnW7jaCdzCtyjGmCDdXSbnx5y4pN6+m1ooQGABV1ef01tpnJUm945Isrgahhv4RGk4XHtC7z99rdRmXCNf+Ea51wzyV1UaAq3Z7P++pe4yPxngkLVlvLBCC1mXlZ8YiQd746h+SMVq85aB5dbVGyzf6DoD+XOsPPjee3QyGvCKjj3jjT80l5dLST4xRRTSOZwJN9Nr7P9PS7EUqrzwjlytSj0z9kxJ6pkqSVn7yot7b9Nfz5xac3KehA8brR3e/alW5CDL6B7wJ1/4RrnXXqq4xRp2KzxqLIlzRW4qJtroq3wpOGTdmbo/UO1ZKuMz6BRHeyzGmdJqhtEJ6e5t019XmtNcSeUXGyoSSNCDOWNE01JWdk3LypbJKqWNbo19bvehOwSkpqwUjPBdb9qnxDJjVf64zFcaiKxVVxmIqKb2M1W+tlHtU2nTAvPb+vkH60a2SM4C/Yzwe4/uYldty8o2PoX1MarCZatzSF0ekE2ekqEhpSC+pU1tra6oV0iHQ7XbrN7/5jZ5//nkdOnRIycnJevrppzV79mylp6frhRdesLrEeu6+/lHdc8OPdaasWL9eOkvb9qzWpFGzJEmTRs06//nJ00f1g+czNHPiz6ws9xIlx/fpo7/9t47sWqOqilJFte+i7gOu1KTv/F2uiNBbn3nZkxPU94obNGrKj/06brVw7h/hdq19yXr5Ozq271OdPnFAy56coPH3/FrdB6RZWlO49o9wrVsyFiL59xbjhrmW8xNp9CDp9jTrb+QaUnxWemWtsQjChbp3lO4eI/WLs6auqhpprcmPgn66X7pluNQ+ytx2/XW0xBjZPHSy/vE+sdI3xkrdO1lTlzdutxGes3fWH5GNipRuvsJY9dGqNwvW7DLvBl8ypjtuPiiNHmhio01QVWMsXLJ+b/3n5tpHSV8dIV1tUV2SsbiLmQrPSDuPGAEmUPYdlw77GCVuqg93WRsCNx2Q/rmp/qwGp8NY7XbqKOvfwAjp6aCzZs3SggUL9MADD2jlypWaNm2apk+frn379iktzdobNm86tOuiR6b+SRt2vq21OW/Ue83tduvnS+7RrEk/V3xsf2sKbMQbv5qs9p176Ju/2qU5fzqjaT9dp76pN8vDeLqpwrV/hIuS4/v09tNT9cd58frDrBi9+N0+euu3X1NNdd2d/oRv/Z8mPfQ39UudqDt/nGV5ALxQuPaPcKv741zjXeeyi5Ydd3uM52AWfxT8BRF8qV1QY9/xS187flr6/XvGqpxW+PywcVNupuoa66b8nThjXOuGrmd+sfS7d1v2rFWgLP1Uev/zS6fkVlYZi238Z7s1dVXXSBsPmN/uJ01cXMYsbo+0eI3xxsfFvyfOVhrTmddZtD5WaUVgnqn9ZJ/5bV5oQwDa331MOmnR39NN+6W/fnzptHb3lyuf/jHLGCW0UsiGwCVLlmjx4sV688039YMf/EAZGRl69NFHNWbMGFVXV2vkyJFWl+hVx3axumP8I/rzO/8rt7vup/zXVU9oQPxQjbtiinXFNaD8TJGKC3Zp6PUPKqpdJzkcDnXo2lup1z+oiEiL3oZtxcKtf4ST1vBmRrj2j3Cpu7JKemOL93Ny8qXdXvbTssLqL6TisoZHUzwybvz/7ePPFSi10yXNdjBA7fryznZjX7IGr7XHeM2qQNWYw8W+g8e7OdJpCxbMOFpiLApjtryT1txI7yrwHbT+tcl4TjbY8ooC8yxcoP6OB7r9g0WBadeb6hpp+Sbv5+w+Jm3PD049jQnZEJiZmamJEycqPT293vFBgwYpMjJSqanGMycHDhxQenq6kpKSNHToUK1Zs8aKchv0tfHf08nTBVq16S+SpM2739em3Hd1/1cWWlzZpdp26KquvVP0/p++rS/W/EVFhz8Pq5vmcBRO/SNctKY3M8K1f4RD3VvyfN+QOmTdO/kNcbt91+PxSLuOWjNCZfY0rkC3603ZOWnLAe9TFz0ypnpVNHEJ+0Bat8fot964PYEf0WlIoH6O1TXGKHiwrdvje1ptZXXTt2YwQ6Cu9aky80f7a1XVSIUB+jla8Ttkhx8zIxwyZp1YyeEJwTv9/Px89enTRy+++KLuu+++eq9Nnz5dO3fu1JYtxtudN998s2677TbNnTtXa9eu1dSpU7V//361aeP9GTaHn5PiFz24WsMGTmjWn+NCtc/DZM5a6fd0qG17s/SD5zKa9f3ueHS1eg+e0KSvKT9zQptX/EYHP3tHRfk5imrfWcNu/I5GTfmx39cr/4ssvf6z4NS87MkJOrp3g1wX3dxXVZRq9O2PN+k5tZbUbUYfCfX+ESrX2p+6X/mfK9SmbUcNve5BdUu4UrE9BzfYf08XHtD65Y/rpgcWB7Rmq/qH1Pw+Eq6/9/w1dtrPdOWt/yOHw/v7oIUHt+q1R0cEtBZ/RcfE6oHn/HtL+/XM65T/+eoAV1TfXU9sUPzAUfWO+VrBryHzL1oz6PSJg3ppfv/mF9YMXXun6Bu/yPHr3L/8cLCKj+wMcEX+mfLDd9T3ihvl8LKTurumWp+vWaz3/3R/ECuTht/8XaXP+F29Y83pH9KlfeQfT4xTwe61zayseb7xixx17Z3i9RyPx6NP3nhS65f9JEhVGcbd9Qtdeet/1ztm1rV+6eEEnS40fyPPth3iNPvZwnrHzKp526pnlPXyQ82srHnSbvmhrvn6L32ed/rEAb00f4Dp39/faBeSC8Pk5xvjo/Hx8fWOl5eXKzs7W5MmTZIknThxQh999JHefPNNSdLYsWPVs2dPrV69WjfffHNwi/bhlfcW6GxFiX7193vPH+tzWbLm3/m8dUVdpG2HOI27K1Pj7spUVWWZdm/4h95/8X7FxPZSSvp9vhuwwKjbHm1wsZJwEw79I1yu9R2PZmnzit9oyztPeX0zwxUZrS49LrewUv+FQ/9oSKjWXVVZ5jMAetxuVVWeDVJFvlWf838OX3VlWQAraZi7JjDz3tw1wR9qa8rP3Ypr3ZiqyrPyeNxyeJnk5XA4WlX/MNq2oI9UnJHH7fYauC271u7wu9YB7R8BvB6N8ed3iMfjsfzfmJAcCdyzZ48SExP129/+VvPnzz9//IknntDjjz+uZ555RnPnztXmzZt15513at++urkN06ZN0w033KDZs2ebUsvGv0mnLJqz27m3dOXXm/e1/7fq0tXjmmPJj9PUI2mcJnzzab/OH9hN+s6NzfteTa3ZzBUrW1K3VX0kmP0jVK51U+u+8M2M6+57vtlvZoRj/5Ca30fCseamOFIsLVzh+7yvjpCuGxLYWpri2feNpd+9/aPdIVp6/GuSK8gPe7yy1ti7zR+17/Bf/I59Qy7vIT14XfPrag6PR/rl29KxksavtUNSj87Sf022fmuOWp/sk15b5/u8uddLSfG+zzPTF0ek5/0cnG5K/5Ckn90Z/BVk39vh3ybq/3OLFB/kVWQ37DUWpvFHU651pEv6xbTA/G7xeKRHl126UFdDmto/br9Suja5+bU1R1GptOAN3+fddIU0eVjg62lMSD4TmJCQoNTUVGVmZuovf/mL3n//fc2ZM0d//vOfJSmkVwYNVxVni/Xx33+kE4dyVFNdJXdNtXZ/8rqK8nPUK3m81eUBzRIZ1U5Drr1XcX1SVXhwq9XlIET07GLcBDd27+6QsWeglUu8NyRjiO8l9jMGBz8ASsa2CeHUrjcOhxH+fT0TeN2Q0AmAkjSin7EnYGM11QbXxO7BrMoQqJ9jbHtrthAZPVCKivD+O+TyHsEPgFLgrnWvLoH73eJwGPudBoIVv0O6xkjD+jb+ukNGqB4zKGglNSgkQ6DT6dTSpUuVkpKiOXPmaObMmYqLi9O8efPkcrnOLwrTt29fHTt2TJWVdU9f7t+/X/369bOq9LDlcrVR2enjevt3t+v5B2P1wpzL9OkbTyp9xtNKvHqq1eUBfuHNDPjrm+OMG2Lp0hu5NpHS7AnW7U/XmMt7SF/78j3QC2uuvekfPVCaMDjoZUkK3P5hgdyXzJurBkg3fPnIV71r/eV/b0yRrjT/UZ4WiXRJD2ZI7S9aEqG25tgYo19bEVxjoqV+Xc1vN8Wi/hETLT2Qcek+b7WXtmcXaca4oJclyQiese3NbzfQ1zoQ7XeItiYEStL00XX7tl78Vy7CJX07XeoSgJ9TU4TkM4GSlJSUpNWr688dmDFjhoYMGaK2bdtKkuLi4jRu3Di9+OKL5xeGOXz4sDIyAruoQGsUGd1eN97/otVlNMmdP85q0nE0X7hc6wvfzDh7qkBOZ4Q6XtafNzNwiZhoaf7NxmbT63bXLSN+81Bp7CCpUztr62tM+uVSQjfpo1xj2pdk3DyNSzRColUjU5d1ML7/zgLz2uzdReofZ157TeFwGBvVD+5pXOva/QqH95PGJxk/g1DUs4sxBXH93rrpij27GG8QXJVgjHBbZVySdNCP6apNbdMqCd2kH91qrPD47pfrCPWNM0Z3RvazbiNwp1Mam+jfdFV/uZzS6ACPWl2VIL29VTpXY16bYwYZgcsK0ZHSd26QtuZJH++W9n+57s31Q4zf17Ex1tR1oZANgQ3ZuHGjRo8eXe/Yc889p3vvvVdPPfWU2rRpoyVLlvhcGRRA6xSOb2bAOm0ijJvj0QPrni+ZlGptTf7oE2u8y1wbAr+d7v38YJmUauyfZtZCA5OHWT/dcmA346M2BH7rGmvr8UdMtDGKWRsC/muypeWcN7KfsddlwSlz2ruyvzXTLS/UuZ3RT2tD4MMhsibhuETjzYtTJq1Lk55sjKoFUrs20nUp0jufmdNeTFTwnwW8WITLmDFw5YC6f2NuDY0FpyWF6HTQhpSWlio3N/eSTeITEhL04YcfKjc3Vzk5OZfsK2ilEyWH9Yc35uuLvA363u/Hav4z1+jZNx+2uiyEEPoIWhv6tH31izNvIZ1RCdZNBUVgRLiku8dIThOCfYdo6WtXtryd1qptG+muq81pq1tHaVKQFi+5McWYAWCGqaOMN0TQuLAZCYyJiVFNjYljxEGwKXeV0pJuVPfO/fSrBz5Qm8ho/fy1e7S/YLsG9BhqdXkIAfQRNGTb3iw9/vLXlNBjmI6e3K+BPYfr/830Y6mxEECftrfJw6Rjp6UcL6vL+lrVb2A36c6rzK0LoaFPrBEEX13b+Iixr/4RHSndPyH0ntkNNYN7SreNlN7Y3Pg5vq51h2jp/nTjedNgcDmlWenS0+9KxY2MYvqzKujEod4XZoEhbEJgqGvopq1Du1g9NOX/1DaqbuKvyxkpp9OiCcqwFH0E/ho64Fol9xmlX9z/H/1yyTc1a/LPrS6pQfRpXMzllGaOl5Z9Kq3b0/SvH9ZXumeMdc9TIfCuHGCMCv5tvVTRxG3nusZI9463brGPcJMx2Pi79M9NUnUTx1F6dJLuSzee9w2mLu2l794kvfihlH+yaV/rckq3DrdugaxwEzbTQUNd7U3br+dkKTUhXd+9/Q+qOHe23o3QviOfqeRsofp1D6GNpxA09BH4q+DkPvWITZAkFZYcUlyn0JwXR59GQ1xOYyra7AnGTbs/OrU1Vmy99xoCoB0M7yv991ekK3r7d77LaSzI88PJBMCmGpdoPBc6yM+tQSJdxv51358U/ABYq0t74/nKyanGVhz+6B8nfX8iAbAp+FVrkotv2k6VFiqhZ90k6tNlJ/X7fz2kH3/jH1aVCIvRR+Cvg0d3qF98imrcNXI4Qve9Ovo0vBnSq27F0E0HpLwiqfBM3etdY4wb+hH9jDBgxf6GsE6X9saiRsdPS+v3SPsKpcPFUtWXI1Zt2xj9Iyne2LMz0AuTtGbdO0oP3WBc3/V7pQOF0pFTUo3beD0mytinb3BPY5XOdiGwvqLLKd00VLr2cmnjfunzw9Khk9KZCuN1p0Pq2dl4FvnqgVLfAGxB0toRAk1y8U3b5t2rlJZ4oySppqZav1jyDc2+ZZFiO8ZbXCmsQh+Bvw4c26Eh/caoqrpSp0qPq+h0gbp27GF1WZegT8MXp9MIg7WLvFTXSD/4m/H5Y7dZVxdCR7eO0le/XPPP7ZYeWWJ8nnmn9avDtja9ukh3fLmgTo1b+v6X13rBHaF7raMjpWuSjA+PR3r4NeP4r77OG0ctxeUzyYFjO9S/e8r5m7bNu99TUm/jb1r2Z0uVe+hT/fHtH+r7z07Q5wdM3igHYYE+An/dff3/avigDEW3aac/fn97SAZAiT6NprNqzy6EB+cFd6WhGkpaC1cYXusL6yQAthwjgSa5+/r/Pf/5H7+/Xdnb/iHnl7/NrhsxXdeNmG5VaQgR9BG0NvRpAADCEyHQhw7dmvd1t/WeZtn3lowhfyu05PtaVXNLv7dVfSQc+0dLv3c49uuW/JxaqrnfO1x/7wEAAP8QAn1Ivs7qCprn9jDcRDUca5bCs4+E67UOx7rDsX+EY80AAMB/zKgFAAAAABshBAIAAACAjRACAQAAAMBGCIEAAAAAYCOEQAAAAACwEUIgAAAAANgIIRAAAAAAbIQQCAAAAAA2QggEAAAAABshBAIAAACAjRACAQAAAMBGCIEAAAAAYCOEQAAAAACwEUIgAAAAANgIIRAAAAAAbIQQCAAAAAA2QggEAAAAABshBAIAbMvjkU6V1f1/jdu6Wpqisqru87OV1tVhB+XnGv4cAMJZhNUFAAAQTNU10rY86dP9Ul6RVHbBjf1//13q2UVK7SONHijFRFtX58UKTklrd0u7jkqFp+uOP7pM6tJOSugmjR1k/NfhsKzMViGvyLjWe45JJ0rrjv9oqRQXIw3qLo1LlPp0ta5GAGgJQiAAwDa25UnLPpXOVDT8erXbCAB5RdLKz6Trh0g3XSFFuIJb54VOlxs1f3ao8XOKy6RNB4yPvl2l6aOlHp2DVGArcuKM9PcN0u5jXs4pNT7W75WS4qW7rpa6xgSvRgAwA9NBAQCtXnWN9Oo66aU1jQfAi9W4pXdzpN+8IxWfDWx9jdlVIP38Le8B8GJ5RdKildJHuYGrqzXafEBauMJ7ALxY7lHpl29LWw8GrCwACAhCIACgVatxSy9/JH26r3lff+SU9PSq+s8OBsMXR6QXVjfvObQatzF6mL3T/Lpao437pb9+LJ2rbvrXnqs2+temA6aXBQABQwgEALRqq3Kk7fnez3nqHuOjMcVnpZfXSO4gLRxzqswIFjWexs/xVbMk/WuTtPe4ubW1NgWnpCXrJS+X2ue19kh6bZ10tMTk4gAgQAiBAIBW60ixMaXTDPtPSB/uMqctbzwe47m0iirf5/psS9KSdc0b4bIDt9sIb2asClvzZVvBeqMAAFoipEOg2+3WokWLlJiYqOjoaA0bNkzZ2dlKTk7W7NmzrS4PABDi3s2R3N6GeJpo1Q7j+cJAyisypoKa5USp9VMVS8qkf2+Rfvx63bHlG42FWKy047B06KR57Zn9swOAQAnpEDhr1iwtWLBADzzwgFauXKlp06Zp+vTp2rdvn9LS0qwuDwAQwk6XN21BFX+crZS25pnb5sU+2h2ANi1cJKbglLHgyvufS6UXLMrz4S7j+P5Cy0oLzLUOQJsAYLaQ3SJiyZIlWrx4sbKyspSeni5JysjI0ObNm7V8+XKNHDnS4goBAKEs96i5o4C1dh6RrhxgfruSMRV0ZwBGkg4XS2fKpQ5tzW/bmxq39EJW/b0YL1RVbbz++BQpKjKIhckY0d3ThJVA/ZV71Gjbym1FAMCXkB0JzMzM1MSJE88HwFqDBg1SZGSkUlNTJUk/+clPlJSUJKfTqWXLlllRKgAgBJk5zS8Y7UpSSbn/W1g0VSDrbsyOw8aiOp5GwrhHxuqnmy3YYuHIKXOeBbxYjZsFYgCEvpAcCczPz1dOTo4efvjhS17Ly8tTSkqKoqKiJEkTJ07Uvffeq/vuu69J38PhcJhSKwAgNH3le69r0FW31zvmazXNxl6f/2rd5/mFZXI42rewuob1SByjaT9d61dNvl6/sGZJ+vq35mj7+8+1oLqmu27ms0rJuF9OZ+PDYu6aav3s92/q7d/dEcTKpEFX3a6vfO/1esfMutbpN03Rvk1vtKC6lvveK0byDrf7nXCsOxxrlsKz7nCsWQpu3Z7G3nW7SMiGQEmKj4+vd7y8vFzZ2dmaNGnS+WNjx44Nam0AgPDg8BI8QrHdcG67Mc6INo0PA9ZyOOSKaBOcgi78tgG8Ht5CLwCEgpAMgXFxcZKk3NxcTZ48+fzxhQsXqqCgwJRFYfxNyQCA8PTaOumTizaIv3jEplbtCE9jr18otkNUwP4NKTgl/fLt+sfMqFmS/vz875U24PfNrq05Vn8hvbHZ+zlOp0uz7rlFbywK7r/LuwqkZz+of8ysa73izdeVGO/7vECqrTXc7nfCse5wrFkKz7rDsWYpNOsOyRCYkJCg1NRUZWZmKjY2Vr169dKyZcu0YsUKSWJlUACAT71jLw2BZrUbKN06SpEuqSoA21D0CmDdjblqgPTWVt/P3o0dFJRy6gnkz7FXl8C1DQBmCMmFYZxOp5YuXaqUlBTNmTNHM2fOVFxcnObNmyeXy3V+URgAABoz4LLAtNs/QO1Kkssp9Yszv932UVK3Dua360tMtDTFx2LeN10hxVlQW/soI3SbrXtHqV2U+e0CgJlCciRQkpKSkrR69ep6x2bMmKEhQ4aobdsgr3ENAAg7vbsYH/nF5rXpdEijEsxrryGjB5q/dcHVCZLTord9xydL0ZHS29ukU2V1x2OijQA4PsmauiTjWr+5xdw2x1gwqgkATRWyIbAhGzdu1OjRo+sde+yxx/TSSy+psLBQ27dv1/z585Wdna2BAwdaVCUAIBQ4HFL65dKr68xrc3hfqXM789pr7Hv8e4uxXYQZXE5pnIVBS5KuSpDS+kv7CqXT5cYo3KDuRm1Wunqg9G6OVFFlTnvRkcafFQBCXUhOB21IaWmpcnNzL9kkfsGCBcrPz1dlZaWKioqUn59PAAQASDI2dU8yaYGOdm2kKUF4JD3CJd11tXntTUqVusaY115zOZ1G8BvZX0ruYX0AlIwwaubP9PYrjTYBINSFzUhgTEyMamoC8KQ8AKDVcjik6aOl3/7HGIFqjK9VHx0y2ukYpKcRhvSSrk2WPtzV+Dn+rFSZFC9lDDavrtbo6gRp5xFpa17j5/hzrUf2MxbCAYBwEALvwwEAEDhd2ktzr5c6NTPAOR3SN8ZKQ/uYW5cvU9JatmpmYndp1rWhMeIWyhxf/nxTW/DzHdZXunuM0RYAhAP+aQAAtHrxnaQfTJaGNfFGP76TNP9mKc2CER6nQ5o6yggX0ZFN+7qJqdKD10lRTfg6O4twSfdeYwTvyCbs8x7pMqaAfusaow0ACBdhMx0UAICW6BAt3Tte2lkgfZQrfX5Yamzb3p6djcVURiU0LRSYzfHlaqTJPaSPc6V1e6QzFQ2fGxVhPAM5PtkIr2gap1OacLk0tLe0Zpe0Ya9U3siCMW3bGCuLXpMUGs9bAkBTEQIBALbhcEiDexofpRXSoZPSkWKpstqYNtmto9Qn1rixD6WpfZ3aSpOHSTcPlQpOGXWXlBkhNibK2Pi8VxepDf+qt1jXGGNE8Jbh0pFTUl5RXfDuGC316Wq8ScDIH4Bwxj8XAABbiomuC4ThwuU0Al/vWKsraf0iXFLfrsYHALQ2PBMIAAAAADZCCAQAAAAAGyEEAgAAAICNEAIBAAAAwEYIgQAAAABgI4RAAAAAALARQiAAAAAA2AghEAAAAABshBAIAAAAADZCCAQAAAAAGyEEAgAAAICNEAIBAAAAwEYIgQAAAABgI4RAAAAAALARQiAAAAAA2AghEAAAAABshBAIAAAAADZCCAQAAAAAGyEEAgAAAICNEAIBAAAAwEYIgQAAAABgIxFWFwAAAICWq6yWdhVIh4rqjr20RurRSerbVUqKlyJc1tUHIHQQAgEAAMLYmQppVY70yT6poqr+a9vypG1ffh4TLY0ZKF2fIkVHBr1MACGEEAgAABCmtuZJSz+Rzlb6Pre0Qlq1Q9q4X5o+xhgZBGBPPBMIAAAQhj74XFq8xr8AeKHiMum5D4wwCMCeCIEAAABh5pN90ptbmv/1bo/06lppZ4F5NQEIH4RAAACAMFJ8Vnr9U+/nPHWP8eGNR9KSdVLZOdNKAxAmQjoEut1uLVq0SImJiYqOjtawYcOUnZ2t5ORkzZ492+ryAAAAgu6NzcZKoGYoKZfe3W5OW0AgXbjq7fo9UmVV4+fCt5BeGGbWrFlavny5HnvsMaWlpWnt2rWaPn26CgsL9cgjj1hdHgAAQFCdKpM+O2Rum+v3SpOGSVEhfVcIuzpdbjz7uq+w7tjfNkjLN0m3jZTGJVpXWzgL2b/uS5Ys0eLFi5WVlaX09HRJUkZGhjZv3qzly5dr5MiRFlcIAAAQXFsOGs/zmamiStqRL43sb267QEtVVknPvCcdP33pa+eqjZVxI5zS1QODX1u4C9npoJmZmZo4ceL5AFhr0KBBioyMVGpqqoqLi3XLLbcoKSlJw4YN00033aQ9e/ZYVDEAAEBgHTwRmHbzinyfAwTbJ/ukY6eN51cb8++tUo07WBW1HiEZAvPz85WTk6OpU6de8lpeXp5SUlIUFRUlh8Oh+fPnKzc3V9u2bdMtt9yimTNnWlAxAABA4B05FV7tAi2xbo/k8HFOaYX0xZGglNOqhOR00Pz8fElSfHz9XUzLy8uVnZ2tSZMmSZI6d+6sG2644fzrY8eO1cKFC/36Hg6Hry4FAAAQWu77XZ46dO1T75i3VUAbe23+q/X/P3vNOs27YWwLq2u5771ijPmE031aONYshUfdDzxXpOiYWJ/n3TNznj577w9BqKh5gnmtPR7/5ouH5EhgXFycJCk3N7fe8YULF6qgoEBpaWkNft1TTz2lKVOmBLo8AAAAS9RUB2Y/h0C1C7REZVmJX6GmsrwkCNW0LiE5EpiQkKDU1FRlZmYqNjZWvXr10rJly7RixQpJajAEPvHEE9qzZ48++OADv76HvykZAAAgVDy/+tKpbxeP6kl1I4ANvdaQqbema9mT1t8b1dYbTvdp4VizFB51v7VVem+H93MinNLmD15RuzavBKWm5gjFax2SI4FOp1NLly5VSkqK5syZo5kzZyouLk7z5s2Ty+VSampqvfOffPJJvfXWW3rnnXfUrl07i6oGAAAIrD6+Z8Y1S+8AtQu0xLhEqU2E9+cCr0mS2rUJWkmtRkiOBEpSUlKSVq9eXe/YjBkzNGTIELVt2/b8sSeeeEIrVqzQqlWr1Llz5yBXCQAAEDypfaR3c8xt0+mQruhlbpuAGbq0lx7MkF7IMrYyqeWQsWLoiH7SrSMsKi7MhWwIbMjGjRs1evTo8/+/Y8cOPf744xo4cKAmTJhw/vjWrVuDXxwAAECA9Y6V+sWZu1XE0D5SJyZSIUQldJMeu83YLmL7IamqRurWURo7yHgthNe1CWlhEwJLS0uVm5uruXPnnj+WkpISUnNrAQAAAu2rI6Tfr/K+d5q/IpzS5FTf5wFWah8lZQw2PmCOsAmBMTExqqmpsboMAAAASw3sJl17uZS9s+VtfWW41L1Ty9sBEF7CJgQCAADA8NURUlGplJPf8Ov+rAo6NlGacLm5dQEIDyG5OigAAAAa53JKM8cbKyM2ldMhTRwqTb2K56kAu2IkEAAAIAy5nNKdVxkrhv5rk3TklO+vGXCZdHua1KdrwMsDEMIIgQAAAGEsKV76r8nS/kJpa550qEg6dtpYRbFNhNSjs9Q3VhrZn/0AARgIgQAAAGHO4TCWy0/oZnUlAMIBzwQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAaIYzFXWf5xVJ56qtqwVoigirCwAAAADCxdES6ePd0vZD0qmyuuO/eUdyOKQenaWrBkijEqT2UZaVCXhFCAQAAAB8KDsnvbFZ2rC38XM8HulIsfRGsbTyM+mrI6SxiZLTEbw6AX8QAgEAAAAvjhRLL2TVH/nz5Vy1tOxTacdh6d7xUhR33QghPBMIAAAANOJoifT795oWAC/0xRHphdU8L4jQQggEAAAAGlBVIy1eY0wFbcxT9xgf3uw9Lq3YZm5tQEsQAgEAAGA5t6fuc4+n8fOC6d3txkigGbJ3SgdOmNNWS9W4ra4AVgvpEOh2u7Vo0SIlJiYqOjpaw4YNU3Z2tpKTkzV79myrywMAAEALnauWVuVIT/yz7tivVkjr91obBiuqpA93mdeeR9J7O8xrrznKKqW3t0o/WV537Kn/SFvzLCsJFgnpR1RnzZql5cuX67HHHlNaWprWrl2r6dOnq7CwUI888ojV5QEAAKAFKqukZ9439ti7UMEp6W/rpf2F0tevNrZeCLZN+6VKk5/j25EvFZ+VurQ3t11/nKmQnn5XKjxT//jBImPK640p0leGB78uWCNkQ+CSJUu0ePFiZWVlKT09XZKUkZGhzZs3a/ny5Ro5cqTFFQIAAKAl/r310gAoGaNmkrEdw8Buxp57wZZ71Pw2PZL2HJOusuDPs/QT6cSZS4/Xjrau2iEN6i4l9whuXbBGyE4HzczM1MSJE88HwFqDBg1SZGSkUlNTJUlTpkxRamqqRowYoVGjRum9996zolwAAAA0QUWV9z33JGMEcI2JUzKbIr84MO0eOhmYdr0pPmtsbu9tdq3DYe70V4S2kBwJzM/PV05Ojh5++OFLXsvLy1NKSoqioqIkSYsXL1bnzp0lSVu2bNGECRN08uRJuVwur9/DYcW8AgAAAEiSeg1O152PZnk9x+MxQlNkdHtVVzZzj4ZmemhxpVwRbc7/v68VQBt7ff6r9f//xb8s1R1XTWthdU2TNObrmjRviddzPB5p695SOTI6BKkq+/jeK0b8Dkb+8Pj5IG1IjgTm5+dLkuLj4+sdLy8vV3Z2dr2poLUBUJJKSkrkcDj8/sMDAADAGk6n9zfsm3uueQJzw+5wBP/22+Hn9fP3PIS/kBwJjIuLkyTl5uZq8uTJ548vXLhQBQUFSktLq3f+vHnztHLlSpWUlOj1119XRITvPxZBEQAAwDpnKqSfLq+/NcTFHJJiY6SKs6eDvjjMT5dLJeV1/3/xiF6t2hHAxl6/2DfvvkNv/S6496FHS6RfvOX9HIekxF5tuUcOgNq+EUrXNiRDYEJCglJTU5WZmanY2Fj16tVLy5Yt04oVKyTpkhD4zDPPSJKys7P18MMP68MPP1RMTEzQ6wYAAIB/OkRLw/tKWw42/qyaR9L4JGtWB+3VpX4INEufrua36Ut8J2OBnX3HfV9r2ENITgd1Op1aunSpUlJSNGfOHM2cOVNxcXGaN2+eXC7X+UVhLpaeni6n06mPP/44yBUDAACgqW4bKXVq1/jEy4HdpGssCiYDuwWm3YTLAtOuL9NGSW3bNH6th/eVhvcLakmwUEiOBEpSUlKSVq9eXe/YjBkzNGTIELVt21aSVFpaqqKiIvXrZ/TYLVu2aO/evRo8eHDQ6wUAAEDTdGonPXyzsVXEloNSjds4Hh0pjU2UJqVKERY9pjYqQVrxWV1NZhjYTereybz2mqJ7p7prvT2/bmuImCjp2sul64dITtZNtI2QDYEN2bhxo0aPHn3+/8+ePau77rpLpaWlioiIUHR0tF555RX17dvXwioBAADgr07tpG+Mlb6WJh0rMaZ+9uoitbH4LrVDW+mqAdJ6H9tYNEWGxeMUl3WU7rvWmOZ64owU4ZR6x0qukJwbiEAKmxBYWlqq3NxczZ079/yx7t27a/369RZWBQAAADO0j5ISAjQFs7m+OkL6/Ih02oRnA0f0k67o3fJ2zNCprfEB+wqbEBgTE6OamhqrywAAAIBNtIuSZoyVnlvd+LRQf1YF7dZRuuNKc2sDWoLBXwAAAKARifHSt9OlyGY+mxjfSZp7vRQTbW5dQEsQAgEAAAAvBveUfji56St7XpssPTxR6twuMHUBzRU200EBAAAAq1zWUXroRmlHvvTRbim3oOE999pESGn9jT33enYJdpWAfwiBAAAAgB+cDmloH+Ojoko6fFI6fsZ4XjA6UurZ2diKgdU2EeoIgQAAAEATRUdKA7sbH0C44X0KAAAAALARQiAAAAAA2AghEAAAAABshBAIAAAAADZCCAQAAAAAGyEEAgAAAICNEAIBAAAAwEYIgQAAAABgI4RAAAAAALARQiAAAAAA2AghEAAAAABshBAIAAAAADZCCAQAAAAAGyEEAgAAAICNEAIBAAAAwEYIgQAAAABgI4RAAAAAALARQiAAAAAA2AghEAAAAABshBAIAAAAADZCCAQAAAAAG3F4PB6P1UUAAAAAQGtwrlrKyZcOnJCOnJL2HDOOp/WXesdKV/SSLutoZYWEQAAAAABosYoq6d3t0ro9UnmV93OTe0iTU6V+ccGp7WKEQAAAAABogd3HpNfWSsVl/n+NQ9J1Q6TJwyRXkB/SIwQCAAAAQDN9dkh6eY1U08xUldpH+tY1wQ2CLAwDAAAAAM1w4ETLAqBkhMjXN5pXkz8IgQAAAADQRFU10mvrfAfAp+4xPrxZu1vaWWBebb6EdAh0u91atGiREhMTFR0drWHDhik7O1vJycmaPXu21eUBAAAAsKmPcqXjp81r7/VPJXeQHtQL6RA4a9YsLViwQA888IBWrlypadOmafr06dq3b5/S0tKsLg8AAACADbk9Rgg0U+EZafdRc9tsTERwvk3TLVmyRIsXL1ZWVpbS09MlSRkZGdq8ebOWL1+ukSNHWlwhAAAAADvKK5KKSs1vd9MBY/uIQAvZkcDMzExNnDjxfACsNWjQIEVGRio1NbXe8RdeeEEOh0PLli0LZpkAAAAAbCavKDDtHgpQuxcLyRCYn5+vnJwcTZ069ZLX8vLylJKSoqioqPPHdu/erZdeekmjR48OZpkAAAAAbOjoqQC1e1pyuwPT9oVCcjpofn6+JCk+Pr7e8fLycmVnZ2vSpEnnj1VXV+u+++7Ts88+q/nz5/v9PRwOhym1AgAAALCXmx54WYPHf7PeMV8rgDb2+vxX6z73eKQ20W1VU1XRrLr83QI+JEcC4+LiJEm5ufWftly4cKEKCgrqLQqzYMECTZo0ScOHDw9miQAAAABsqrqZIc0bj8cjj9std/U509u+WEiOBCYkJCg1NVWZmZmKjY1Vr169tGzZMq1YsUKSzofADRs26IMPPlBWVlaTv4e/KRkAAAAALpS1U/rXpvrHLhzRu1DtCGBjr9dyOBzq3skht7um5QX6EJIjgU6nU0uXLlVKSormzJmjmTNnKi4uTvPmzZPL5Tq/KMzq1au1d+9eDRw4UP3799f69es1d+5c/frXv7b4TwAAAACgteobG5h2+3QNTLsXc3jCaEhsxowZ2rZtmz777LMGX58wYYIeeugh3XnnnUGuDAAAAIBd1LilBW9Ip8p8n+vvSKAk3T9BSunVotL8EpIjgY3ZuHEjm8QDAAAAsJTLKY1NNLfN2PbS4CDsESiFUQgsLS1Vbm6u103is7KyGAUEAAAAEHDpyVLXGPPa+1qa5AxSOgur6aAAAAAAECr2HJOeeU9qaaC6coD0jbGmlOSXsBkJBAAAAIBQMqi7dPcYqSU7kCf3kO662rSS/MJIIAAAAAC0wI58ackGqbSJ2wdekyhNSZMiXIGpqzGEQAAAAABoodIK6e1t0sb9UpWPrf76xUlfGSYlxQentosRAgEAAADAJGWV0pY86eAJ6UixVF5lrCZ6WQepd6x0RW+pT4D2GfQXIRAAAAAAbISFYQAAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANkIIBAAAAAAbIQQCAAAAgI0QAgEAAADARgiBAAAAAGAjhEAAAAAAsBFCIAAAAADYCCEQAAAAAGyEEAgAAAAANvL/Aashf+kJ3MJ3AAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.details(prettify=True)[\"backend\"].draw(idle_wires=False, output=\"mpl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "5f0ad718", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{0: 1, 1: 3, 2: 2, 3: 0, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.get_logical_physical_mapping() # the logical qubit - physical qubit mapping is also returned by the server" + ] + }, + { + "cell_type": "markdown", + "id": "98b2b053", + "metadata": {}, + "source": [ + "To better customize and use the advanced compiling system, we strongly recommend the users to compile the circuit before task submission as **frontend compiling**" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "4debc9ad", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'logical_physical_mapping': {0: 6, 1: 2, 2: 0, 3: 4, 4: 8}, 'positional_logical_mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}}\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c1, info = tc.compiler.default_compile(\n", + " c, compiled_options={\"coupling_map\": d.topology()}\n", + ")\n", + "print(info)\n", + "c1.draw(idle_wires=False, output=\"mpl\")" + ] + }, + { + "cell_type": "markdown", + "id": "258236df", + "metadata": {}, + "source": [ + "We now submit the compiled circuit ``c1`` for the qcloud, with now the ``logical_physical_mapping`` in ``info``, the result is improved with tc built in compiler" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "3a165a8c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00000': 3506,\n", + " '11111': 1962,\n", + " '01111': 523,\n", + " '11011': 279,\n", + " '10000': 262,\n", + " '11110': 257,\n", + " '10111': 174,\n", + " '11000': 167,\n", + " '00111': 148,\n", + " '11101': 109,\n", + " '01000': 92,\n", + " '01011': 90,\n", + " '00001': 87,\n", + " '01110': 85,\n", + " '00011': 80,\n", + " '11100': 72,\n", + " '11010': 45,\n", + " '00100': 42,\n", + " '10011': 31,\n", + " '00110': 24,\n", + " '01101': 24,\n", + " '00010': 22,\n", + " '10110': 18,\n", + " '11001': 17,\n", + " '01100': 16,\n", + " '01010': 15,\n", + " '10100': 11,\n", + " '00101': 10,\n", + " '10001': 10,\n", + " '10101': 8,\n", + " '01001': 4,\n", + " '10010': 2}" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t = tc.cloud.apis.submit_task(\n", + " circuit=c1,\n", + " shots=8192,\n", + " device=d,\n", + " enable_qos_gate_decomposition=False,\n", + " enable_qos_qubit_mapping=False,\n", + ")\n", + "rf = t.results()\n", + "rf" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "22d46c41", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdEAAAFTCAYAAABmuzZIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAybElEQVR4nO3deXwV5dn/8c8FgSxCBFQIAWRfwxqjNDaCyw+xLn1cqlal7mL1UYs7LlXE+qitUitqpVo3HmvrUvcNN5ZoHjSgKIugsmiQTdmChGDI9ftjJukhBiFjOCfL9/16nRcnM/eZXOOJ53vmnnvuMXdHREREaq5JogsQERGprxSiIiIiESlERUREIlKIioiIRKQQFRERiUghKiIiElFSoguoS/bee2/v0qVLossQEZE6ZNasWd+4+z7VrVOIxujSpQuFhYWJLkNEROoQM1u2o3XqzhUREYlIIZpA69evp0WLFqSmppKSksLw4cMB2HPPPUlNTSU1NZWmTZvSvn17AJYsWUJmZiapqam0aNGCZ599drvtbd26lbS0NNq1axf3fRERaYwUogmUnp7O559/TklJCWvXrmXWrFk8+OCDbNiwgZKSEkpKSsjIyOCYY44B4KSTTqJ3796UlJTw5JNPcs4552y3vRNPPJG2bdsmYldERBolhWgCNWnShIyMDAA2b95MeXk5Zla5vqioiBUrVnDDDTcAsGzZMk444QQAjjzySIqLi5k7dy4AH3zwATNmzODiiy+O816IiDReCtEE27p1K6mpqeyzzz4MGDBgu6PL8ePHk5mZSceOHQHo0aMHDz30EAAPP/wwZWVlfPTRRwAcd9xx3H333TRt2jTu+yAi0lglLETN7BozczO7J2aZmdk4M/vazErMbKqZZVV5XWszm2xmG8LHZDNrVaXNADObFm5juZndYLGHeHVI8+bNKSkpYenSpSxatGi785zPPvssp5xySuXPTz75JMXFxaSmpnLzzTeTlpZGs2bNuOGGG2jVqhWjRo1KxC6IiDRalohboZnZz4AngI3ADHe/KFx+NXA9cCawELgByAN6u3tx2OZVYF/g3HBzDwKL3f2YcH06sAiYDowH+gAPA+Pc/c4fqysnJ8cTeYnLoYceSlpaGi+99BILFy6kb9++rF27llatWv2gbXl5Oc2bN2fp0qWceOKJvP/++5gZ7k55eTldunRh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UjjmmGOYNWtWAvai4VCISo01bdqUjz76iKKiIt5//33mzp3LrbfeyqeffsoHH3zA2rVruf322390G2VlZcyYMYM77riDDz74gMWLF+vbsMgOLFiwgGXLlgFUDizKzs6uHHtQXl7Oo48+SteuXQF46623KC8vB+Dxxx+nvLycnj17cvrpp1NaWsqCBQsq2/Xt2zf+O9SAKEQlslatWnHIIYfw2muv0b59e8yM5ORkzjrrLN5//30guIdfxX0GAYqKiirv6zd48GC6detGUlISxx577HaDjkTkP+bNm0ffvn1JTU0lMzOT/fbbj/Hjx3PIIYeQkpJCWloa69evr7wP8R133EFaWhqpqan89re/ZeLEiTRp0oTmzZtz4403kp2dTUpKCu7OQw89lNidq+cUolIja9asYf369UBwA/E33niDPn36sGLFCiAYqPbcc8/Rv39/AH75y1/y2GOP4e783//9H3vuuSft27dn//33Z/369axZswaAt99+m379+iVkn0Tqul/96lds3ryZkpIStmzZUnnec926dWzZsoUtW7awZMmSyhG8r776Klu2bKGkpITi4mIuvPDCym2NHTu2cjuff/65xiP8RBpYJDWyYsUKzjjjDLZt20Z5eTknnXQSRx99NIceeihr1qzB3Rk8eDD3338/AEceeSSvvPIKPXr0IC0tjYcffhgIuoTvuOMODjvssIqR0Zx33nmJ3DURkRrTBPQxamsC+oY8OldEpLHRBPQiIiK7gUJUREQkIoWoiIhIRApRERGRiBSiIiIiESlERUREIlKIioiIRKQQFRERiUghKiIiEpFCVEREJCLNnSsikgD1bXpQ0BSh1dGRqIiISEQ6EhW+6D0u0SXUWPeF4xJdgoiIjkRFRESiUoiKiIhEpBAVERGJSCEqIiISkUJUREQkIoWoiIhIRApRERGRiBSiIiIiESlERUREIlKIioiIRKQQFRERiUghKiIiEpFCVEREJCKFqIiISEQKURERkYgUoiIiIhEpREVERCJSiIqIiESkEBUREYlIISoiIhKRQlRERCQihaiIiEhEClEREZGIFKIiIiIRKURFREQiUoiKiIhEpBAVERGJSCEqIiISUdxC1Mz+28w+NrON4aPAzI6KWW9mNs7MvjazEjObamZZVbbR2swmm9mG8DHZzFpVaTPAzKaF21huZjeYmcVpN0VEpBGJ55FoEXA1kA3kAG8Dz5nZwHD9VcDlwMXA/sBq4A0zaxmzjX+Erz8ifGQDkytWmlk68AawKtzG74Argct2216JiEijlRSvX+Tuz1dZdJ2ZXQDkmtknwBjgNnd/BsDMziAI0lOBSWbWlyA489y9IGxzPjDDzHq7+0LgNCANOMPdS4C5ZtYHuMzMJri77/49FRGRxiIh50TNrKmZ/RpoAbwHdAUygCkVbcIQnA4cGC7KBTaF7Su8C3xXpc2M8LUVXgcygS61viMiItKoxe1IFILzlUABkEIQiMe5+ydmVhGCq6q8ZBXQIXyeAayJPZp0dzez1eG6ijZF1WyjYt2SamoaDYwGyMzMZOrUqQB069aNli1bMmfOHAD22msvsrKymD59OgBJSUnk5eUxe/ZsNm7cCEBOTg6rVq0Cuu/afxCJrDbep6+++gqAnj17kpyczNy5cwFo27YtvXr1Ij8/H4Dk5GRyc3MpLCxk06ZNAAwdOpSioiKWL18OQO/evWnatCnz588HICMjg65du1JQUABAamoqQ4cOZebMmZSUBN/xcnNzWbJkCStXrgSgX79+bNu2jYULFwLQoUMHOnbsyMyZMwFo0aIFOTk5FBQUUFpaCkBeXh6LFi1i9erVAPTv35/S0lI+++wzADp16kS7du0oLCwEID09nezsbPLz8ykrKwNg2LBhzJs3j2+//RaAQYMGUVxczOLFiwHo0qULbdq0Yfbs2QC0bt2aQYMGMW3aNNwdM2P48OHMmTOHdevWAZCdnc3atWtZunSp3qcdvE+wN/VNfn7+Lr1P33zzDWeeeSbr1q0jKSmJCy+8kOzsbG666SaWL19OWloaq1evJi0tjQcffJBNmzYxduxYNm/eTFJSErfccgvDhw/f7n264oormDdvHg8//HDc/3/6MRbPHk4zaw7sC+wJ/Ao4DzgYSCc4quzs7l/GtH8I6ODuI83sWuBcd+9WZZuLgQfc/VYzmwIUufvZMev3BZYBB1Z0A+9ITk6OV3zY/BTn3fWTNxFXY/86LtEl1Fj3heMSXYLIT1LfPicAHhiza+1WrFjBihUryM7Opri4mP3224/nnnuOfv36Vba5/PLL2XPPPbnhhhv48MMPadeuHZmZmcydO5eRI0dWfvEB+Pe//83TTz/Nxx9/XPklKp7MbJa751S3Lq7due6+1d0/d/dZ7n4N8BFwKbAybNKuykvaxaxbCewTO9I2fN62SpvqtkFMGxER2Y3at29PdnY2AC1btqRv377bhaK78+STT3LKKacAMGTIEDIzMwHIysqipKSk8ghw06ZNTJgwgeuvvz7Oe7FrEn2daBMgmaCbdSUwomKFmaUAB/Gfc6AFBOdQc2NenwvsUaXNQeFrK4wAvgaW1n75IiLyY5YuXcqHH37I0KFDK5fNmDGDdu3a0bNnzx+0f+aZZ8jOziY5ORmA3//+91x++eWkpaXFreaaiOd1oreZ2UFm1iW8lvNWgq7cx8PznHcBV5vZ8WbWH3iE4LzpPwDcfQHwGsFI3VwzywUmAS+FI3MJ224GHjGz/mZ2PDAW0MhcEZE427RpEyeccAJ33XUX6enplcufeOKJyqPQWPPmzePqq69m0qRJAHz00Ud88cUXHHfccXGruabiObAoA/jf8N8NwMfAL9z99XD9H4FU4F6gNTATONzdi2O2cSowkWDELcALwEUVK919g5mNCLdRCKwD7gQm7KZ9EhGRanz//feccMIJnHbaaRx//PGVy8vKyvj3v//NrFmztmtfVFTEcccdx2OPPUb37sHgzIKCAgoLC+nSpQtlZWWsXr2agw8+uHJgYV0Qz+tEz9zJegfGhY8dtVkHjNrJdj4BhtW4QBERqRXuzjnnnEPfvn257LLt57p588036dOnDx07dqxctn79eo466ihuu+02fv7zn1cuv+CCC7jggguAoFv46KOPrlMBCok/JyoiIg3Mu+++y+TJk3n77bcZPHgwgwcP5pVXXgHgn//85w+6cu+55x4+//xzxo8fX9m+4jKTui6u14mKiEjDl5eXx46GoTzyyCM/WHb99dfvdPRtly5dEnJ5y87oSFRERCQihaiIiEhEClEREZGIFKIiIiIRKURFREQiUoiKiIhEpBAVERGJSCEqIiISkUJUREQkIs1YJCIiu+SL3uMSXUKNdF84brf/Dh2JioiIRKQQFRERiUghKiIiEpFCVEREJCKFqIiISEQKURERkYgUoiIiIhEpREVERCJSiIqIiESkEBUREYlIISoiIhKRQlRERCQihaiIiEhEClEREZGIFKIiIiIRKURFREQiUoiKiIhEpBAVERGJSCEqIiISkUJUREQkIoWoiIhIRApRERGRiHY5RM1smJklVbM8ycyG1W5ZIiIidV9NjkTfAdpUs3zP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VUyaNIkNGzZUvm7ChAlcc801zJ07l549e0b63V/0HldLexEf9e1vor59TkD9+6yorb8JM5vl7jnVratL3bkrw3/bVVneLmbdSmCf2JG24fO2VdpUt43Y3yFSL0ycOJF99tmHvn37kpaWxjHHHMOMGTNo3rw5V155JQC33XZb5VE2wNNPP83VV1/NCy+8EDlARWTX1KUQXUIQciMqFphZCnAQ/zkHWkAwwjc35nW5wB5V2hwUvrbCCOBrYOnuKFxkd8nKyuLLL7/km2++oby8nLfeeos+ffowZMgQHn74YQDuvvtu0tLSgKBL85RTTuGee+5h5MiRiSxdpFGI6zlRM2sB9Ah/bALsa2aDgbXu/qWZ3QVca2afAouA6wkGEv0DwN0XmNlrBCN1R4fbmQS8FI7MJWx7I/CImf0B6AWMBW7SyFypb8455xwee+wxOnTogJmRmZnJQw89xLp169h///1JSUmhWbNmlYF65plnsm3bNsaMGcOYMWNo0qQJ3333XYL3QqThivfAohzgnZifbwofjwJnAn8EUoF7gdbATOBwd48d5XAqMJFgxC3AC8BFFSvdfYOZjQi3UQisA+4EJtT+7ojsftOmTfvBsvT09MrBD7EqBlGISHzE+zrRqcAOZw4KjxTHhY8dtVkHjNrJ7/kEGBalRhERkV1Vl86JioiI1CsKURERkYjq0mQLIg1WvbwmMNEFiNQDOhIVERGJSCEqIiISkUJUREQkIoWoiIhIRApRERGRiBSiIiIiESlERUREIlKIioiIRKQQFRERiUghKiIiEpFCVEREJCKFqIiISEQKURERkYgUoiIiIhEpREVERCJSiIqIiESkEBUREYlIISoiIhKRQlRERCQihaiIiEhEClEREZGIFKIiIiIRKURFREQiUoiKiIhEpBAVERGJSCEqIiISkUJUREQkIoWoiIhIRApRERGRiBSiIiIiESlERUREIlKIioiIRKQQFRERiUghKiIiEpFCVEREJCKFqIiISEQKURERkYgUoiIiIhEpREVERCJSiIqIiESkEBUREYlIISoiIhKRQlRERCQihaiIiEhEClEREZGIFKIiIiIRKURFREQiUoiKiIhEpBAVERGJSCEqIiISkUJUREQkogYbomZ2oZktMbMtZjbLzA5KdE0iItKwNMgQNbOTgb8A/wMMAd4DXjWzfRNamIiINCgN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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.results.counts.plot_histogram([rb, rf], number_to_keep=2)\n", + "# backend compiling vs frontend compiling" + ] + }, + { + "cell_type": "markdown", + "id": "60ba2314", + "metadata": {}, + "source": [ + "## Readout Error Mitigation" + ] + }, + { + "cell_type": "markdown", + "id": "acc9f9ab", + "metadata": {}, + "source": [ + "The above results can be further improved via readout error mitigation (a classical algorithmic postprocessing on the measurement results)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "da287ca9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'00000': 3931.5654653719635,\n", + " '11111': 3736.9302177814375,\n", + " '11000': 156.2388037789295,\n", + " '00111': 139.79207327296174,\n", + " '10000': 82.70413218088015,\n", + " '10111': 62.54914892519676,\n", + " '11100': 40.2309011836783,\n", + " '00011': 34.01063384376864,\n", + " '01111': 5.923071025515406,\n", + " '00001': 2.0555526356691276}" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mit = tc.results.rem.ReadoutMit(d.name + \"?o=0\")\n", + "mit.cals_from_system(9)\n", + "mr = mit.apply_correction(t.results(), qubits=5, **info)\n", + "mr" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "1cbf19de", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.results.counts.plot_histogram([t.results(), mr], number_to_keep=2)\n", + "# raw vs mitigated" + ] + }, + { + "cell_type": "markdown", + "id": "73a6c287", + "metadata": {}, + "source": [ + "We can also collect the readout calibriation from the API, but the results can be wrose since it is not up to date" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "43ea80ec", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mit1 = tc.results.rem.ReadoutMit(d.name + \"?o=0\")\n", + "mit1.cals_from_api(9)\n", + "mr1 = mit1.apply_correction(t.results(), qubits=5, **info)\n", + "tc.results.counts.plot_histogram([mr, mr1], number_to_keep=2)\n", + "\n", + "# mitigated via real time calibriation vs. mitigated via api calibriation data" + ] + }, + { + "cell_type": "markdown", + "id": "8ec8d9c8", + "metadata": {}, + "source": [ + "Readout error mitigation in tc supports many other options for subset measurement, scalable mitigation for hundereds of qubits, customized calibriation in local and global mode and native error mitigated expectations, please refer to the API documentation for more interesting usages. For example, we can directly compute the expectation $$ (ideal value should be 1) as" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "77e7d8e1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array(1.+0.j, dtype=complex64), 0.9584156264735034)" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.expectation_ps(z=[0, 1]), mit.expectation(t.results(), [0, 1])" + ] + }, + { + "cell_type": "markdown", + "id": "7b156c6f", + "metadata": {}, + "source": [ + "## High level API\n", + "\n", + "Ultimately, for near term quantum computing tasks, the users only want to evaluate some given observable expectation for a circuit without worrying too much details above: compilation, error mitigation, subset measruement, positional/logical/physical mapping etc. Therefore, for most of the applications, `batch_expectation_ps` method is all you need." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "f07070b5", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "\n", + "logger = logging.getLogger(\"tensorcircuit.cloud\")\n", + "logger.setLevel(logging.INFO)\n", + "# ch = logging.StreamHandler()\n", + "# ch.setLevel(logging.INFO)\n", + "# logger.addHandler(ch)\n", + "\n", + "# we enable log for the high level API to see what happen behind the scene" + ] + }, + { + "cell_type": "markdown", + "id": "4f50a8f1", + "metadata": {}, + "source": [ + "$\\langle Z_0Z_1\\rangle$" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "2100ff5d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 4.873 seconds\n", + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 2 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 2 tasks in 7.6044 seconds\n" + ] + }, + { + "data": { + "text/plain": [ + "array([0.82589585])" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.wrapper.batch_expectation_ps(c, pss=[[3, 3, 0, 0, 0]], device=d)\n", + "# compute Z0Z1" + ] + }, + { + "cell_type": "markdown", + "id": "630b8791", + "metadata": {}, + "source": [ + "$\\langle Z_0Z_1\\rangle+0.5\\langle Z_1Z_2\\rangle$" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "c405123f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 4.9699 seconds\n" + ] + }, + { + "data": { + "text/plain": [ + "array(1.54442738)" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.wrapper.batch_expectation_ps(\n", + " c, pss=[[3, 3, 0, 0, 0], [0, 3, 3, 0, 0]], device=d, ws=[1, 0.5]\n", + ")\n", + "# compute Z0Z1 + 0.5*Z1Z2" + ] + }, + { + "cell_type": "markdown", + "id": "0965380b", + "metadata": {}, + "source": [ + "The interface is also unifying the numerical simulation (exact) interface with QPU experiments, by spcifying the device as ``None``, we can obtain the expected result from tc simulator" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "5744293b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(1.5+0.j)" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.wrapper.batch_expectation_ps(\n", + " c, pss=[[3, 3, 0, 0, 0], [0, 3, 3, 0, 0]], device=None, ws=[1, 0.5]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "300cff3a", + "metadata": {}, + "source": [ + "The results with readout error mitigation disabled can become worse. Note how we cache the readout error calibriation within tc, so that REM is effcient to use." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "0e49467d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 3.6587 seconds\n" + ] + }, + { + "data": { + "text/plain": [ + "array(0.8828125)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tc.cloud.wrapper.batch_expectation_ps(\n", + " c,\n", + " pss=[[3, 3, 0, 0, 0], [0, 3, 3, 0, 0]],\n", + " device=d,\n", + " ws=[1, 0.5],\n", + " with_rem=False,\n", + " shots=1024,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "da002ef1", + "metadata": {}, + "source": [ + "**QPU support for tf/torch ML:** Above this API, we also have corresponding keras and torch layers for hybrid deployment" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "718d7215", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Z_i: [[3, 0, 0, 0, 0], [0, 3, 0, 0, 0], [0, 0, 3, 0, 0], [0, 0, 0, 3, 0], [0, 0, 0, 0, 3]]\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import tensorflow as tf\n", + "from functools import partial\n", + "\n", + "tc.set_backend(\"tensorflow\")\n", + "\n", + "pss = []\n", + "for i in range(5):\n", + " ps = [0 for _ in range(5)]\n", + " ps[i] = 3 # Z_i\n", + " pss.append(ps)\n", + "print(\"Z_i:\", pss)\n", + "\n", + "\n", + "def quantum_func(inputs, weights, device=None):\n", + " c = tc.Circuit(5)\n", + " for i in range(5):\n", + " c.rx(i, theta=inputs[i])\n", + " for i in range(5):\n", + " c.rz(i, theta=weights[0, i])\n", + " for i in range(5):\n", + " c.rx(i, theta=weights[1, i])\n", + " return tc.cloud.wrapper.batch_expectation_ps(c, pss=pss, device=device)\n", + "\n", + "\n", + "qlayer = tc.KerasLayer(quantum_func, [2, 5])\n", + "model = tf.keras.Sequential([qlayer, tf.keras.layers.Dense(1)])\n", + "inputs = tf.stack([0.1 * tf.ones([5]), 0.2 * tf.ones([5])])\n", + "model(inputs)" + ] + }, + { + "cell_type": "markdown", + "id": "f2b675fa", + "metadata": {}, + "source": [ + "``model`` is a model with quantum layer simulated using CPU/GPU and a classical layer on CPU/GPU while ``model1`` shares exactly the same architecture but is with quantum layer on real QPU while classical layer still live on CPU/GPU, namely, TC is powerful enough to handle these quantum-classical hybrid tasks with an interface familiar to any ML engineers." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0ec02dac", + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 5.2411 seconds\n", + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 5.3121 seconds\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qlayer1 = tc.KerasHardwareLayer(partial(quantum_func, device=d), [2, 5])\n", + "model1 = tf.keras.Sequential([qlayer1, tf.keras.layers.Dense(1)])\n", + "model1(inputs)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "51620507", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"sequential\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " quantum_layer (QuantumLayer (2, 5) 10 \n", + " ) \n", + " \n", + " dense (Dense) (2, 1) 6 \n", + " \n", + "=================================================================\n", + "Total params: 16\n", + "Trainable params: 16\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n", + "\n", + "\n", + "Model: \"sequential_1\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " hardware_layer (HardwareLay multiple 10 \n", + " er) \n", + " \n", + " dense_1 (Dense) multiple 6 \n", + " \n", + "=================================================================\n", + "Total params: 16\n", + "Trainable params: 16\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n" + ] + } + ], + "source": [ + "model.summary()\n", + "print(\"\\n\")\n", + "model1.summary()" + ] + }, + { + "cell_type": "markdown", + "id": "3b5423ca", + "metadata": {}, + "source": [ + "we align the weights between the two models (numerical one vs hybrid one)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "ab5ca8a5", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 5.5113 seconds\n", + "INFO:tensorcircuit.cloud.wrapper:submit task on tencent::tianxuan_s1 for 1 circuits\n", + "INFO:tensorcircuit.cloud.wrapper:finished collecting count results of 1 tasks in 5.2209 seconds\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model1.set_weights(model.get_weights())\n", + "model1(inputs)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/qubo_problem.ipynb b/docs/source/tutorials/qubo_problem.ipynb new file mode 100644 index 00000000..a4779366 --- /dev/null +++ b/docs/source/tutorials/qubo_problem.ipynb @@ -0,0 +1,580 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "6ddb8a88-779a-43f7-ae14-115463bd87f5", + "metadata": {}, + "source": [ + "# Solving QUBO Problem using QAOA\n", + "\n", + "## Overview\n", + "\n", + "In this tutorial, we will demonstrate how to solve quadratic unconstrained binary optimization (QUBO) problems using QAOA. There is a specific application for portfolio optimization and we will introduce it in another [tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/portfolio_optimization.html).\n", + "\n", + "## QUBO problem\n", + "\n", + "### What is QUBO?\n", + "\n", + "Quadratic unconstrained binary optimization (QUBO) is a type of problem that aims to optimize a quadratic objective function using binary variables. The primary goal of a QUBO problem is to determine the assignments of binary variables that minimize or maximize the quadratic objective function. These variables represent choices or decision variables that can be either selected (1) or not selected (0). The objective function captures the associated costs, benefits, or constraints related to these decisions.\n", + "\n", + "From a computational perspective, solving a QUBO problem is NP-hard. This classification implies that solving the optimal solution to a QUBO instance is believed to be computationally challenging, and no known polynomial-time algorithm that can efficiently solve all QUBO problems.\n", + "\n", + "However, a promising approach called Quantum Approximate Optimization Algorithm (QAOA), introduced in [this tutorial](https://tensorcircuit.readthedocs.io/en/latest/tutorials/qaoa.html), has the potential to offer significant advantages when applied to QUBO problem-solving. QAOA leverages inherent quantum parallelism and interference effects to explore the solution space more efficiently compared to classical methods. This efficiency can lead to faster and more optimal solutions. In QAOA, each qubit represents a binary variable, and the objective function is calculated as the expected value of a quantum state generated by the ansatz (a quantum circuit with parameters to be decided). The parameters in the ansatz are iteratively optimized by a classical algorithm to improve the solution quality.\n", + "\n", + "### General Case\n", + "\n", + "For the general QUBO case, we wish to minimize a cost function of the form\n", + "\n", + "$$ \n", + "x^T Q x\n", + "$$\n", + "\n", + "where $x\\in\\{0,1\\}^n$ and $Q\\in\\mathbb{R}^{n\\times n}$ is a real symmetric matrix.\n", + "\n", + "This function maps to an Ising Hamiltonian \n", + "\n", + "$$\n", + "\\frac{1}{2}\\left(\\sum_{i=1}^n C_{ii} + \\sum_{i{n_qubits}}\"\n", + " states.append(a)\n", + "\n", + " # Calculate the probabilities of each state using the circuit's probability method\n", + " probs = K.numpy(c.probability()).round(decimals=4)\n", + "\n", + " # Sort the states and probabilities in descending order based on the probabilities\n", + " sorted_indices = np.argsort(probs)[::-1]\n", + " if reverse == True:\n", + " sorted_indices = sorted_indices[::-1]\n", + " state_sorted = np.array(states)[sorted_indices]\n", + " prob_sorted = np.array(probs)[sorted_indices]\n", + "\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\tprobability\")\n", + " print(\"-------------------------------------\")\n", + " if wrap == False:\n", + " for i in range(len(states)):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " # Print the sorted states and their corresponding probabilities\n", + " elif wrap == True:\n", + " for i in range(4):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\" ... ...\")\n", + " for i in range(-4, -1):\n", + " print(\"%10s\\t |\\t %.4f\" % (state_sorted[i], prob_sorted[i]))\n", + " print(\"-------------------------------------\")" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "da315228", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\tprobability\n", + "-------------------------------------\n", + " 10\t |\t 0.8848\n", + " 11\t |\t 0.1051\n", + " 01\t |\t 0.0093\n", + " 00\t |\t 0.0008\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "c = QAOA_ansatz_for_Ising(final_params, nlayers, pauli_terms, weights)\n", + "\n", + "print_result_prob(c)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "294ea9ce-5064-4176-94d0-8dbb7d1707f8", + "metadata": {}, + "outputs": [], + "source": [ + "def print_output(c):\n", + " n = c._nqubits\n", + " N = 2**n\n", + "\n", + " # Generate labels for the x-axis representing the binary states\n", + " x_label = r\"$\\left|{0:0\" + str(n) + r\"b}\\right>$\"\n", + " labels = [x_label.format(i) for i in range(N)]\n", + "\n", + " # Create a bar plot with the probabilities of each state\n", + " plt.bar(range(N), c.probability())\n", + "\n", + " # Set the x-axis ticks to the generated labels and rotate them for better visibility\n", + " plt.xticks(range(N), labels, rotation=70)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "fc1353ab-7a7a-4cdc-931c-3b90417c4961", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGuCAYAAABC7AYqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAcuklEQVR4nO3dcXDW9X3A8U8iwRMIOgQTiYK2KrjWlcLBTLde1XQb1XU3rwy33rW7Ye0YtS3F0RbKVECl9DQ7Z3t2cx0y3dFxenO6tmOmerPagIKDoUXXVqg2KQGKDlbAQPjuj9bcMgLmAemHhNfr7nOlv/x+PF/49jne/T1PnlRFRAkAgCTV2QsAAE5uYgQASCVGAIBUYgQASCVGAIBUYgQASCVGAIBUYgQASDUoewF9NXr06Ni9e3f2MgCACtTW1kZ7e/sRz+kXMTJ69Ohoa2vLXgYAcBQaGhqOGCT9IkbeuCPS0NDg7ggA9BO1tbXR1tb2pv9294sYecPu3bvFCAAMMN7ACgCkEiMAQCoxAgCkEiMAQCoxAgCkEiMAQCoxAgCkEiMAQCoxAgCkEiMAQCoxAgCkEiMAQCoxAgCkEiMAQKpB2QsAqNQdG1uzl3DSuuGSxuwlMAC5MwIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApBIjAEAqMQIApDqqGJk1a1Zs3rw59u7dG6tXr47Jkycf8fxPf/rT8cILL8SePXvi5Zdfjubm5jj11FOPasEAwMBScYxMnz49mpubY+HChTFx4sTYsGFDrFq1KkaNGtXr+X/0R38UX/ziF2PhwoVx8cUXx7XXXhvXXHNN3Hbbbce8eACg/6s4RubMmRP33HNP3HvvvbFp06aYOXNm7NmzJ2bMmNHr+e95z3viqaeeihUrVsSPfvSjePTRR2PFihUxZcqUY148AND/VRQjNTU1MWnSpGhpaek+VkqJlpaWaGxs7PWa7373uzFp0qTul3LOP//8uPLKK+Ob3/zmYR9n8ODBUVtb22MAgIFpUCUnjxw5MgYNGhQdHR09jnd0dMT48eN7vWbFihUxcuTIePLJJ6Oqqipqamri7rvvjiVLlhz2cebNmxc333xzJUsDAPqp4/7dNO973/ti/vz5MWvWrJg4cWJcffXVcdVVV8WCBQsOe82SJUti+PDh3dPQ0HC8lwkAJKnozsiOHTviwIEDUVdX1+N4XV1dbN26tddrFi9eHPfdd1987Wtfi4iI5557LoYOHRp/8zd/E7feemuUUg65prOzMzo7OytZGgDQT1V0Z2T//v2xbt26aGpq6j5WVVUVTU1N0dra2us1Q4YMiYMHD/Y41tXV1X0tAHByq+jOSEREc3NzLF++PNauXRtPP/10zJ49O4YOHRrLli2LiIjly5dHW1tbzJ8/PyIiHnnkkZgzZ078x3/8R6xZsyYuuOCCWLx4cTzyyCOHRAoAcPKpOEZWrlwZo0aNikWLFkV9fX2sX78+pk6dGtu2bYuIiDFjxvSIjFtuuSVKKXHLLbdEQ0NDbN++PR555JH4whe+8Nb9KQCAfqsqIg5908YJpra2Nnbt2hXDhw+P3bt3Zy8HSHbHxt5fFub4u+GS3j/GAXrT13+//WwaACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACCVGAEAUh1VjMyaNSs2b94ce/fujdWrV8fkyZOPeP7pp58eX/7yl6O9vT327dsXL774YnzgAx84qgUDAAPLoEovmD59ejQ3N8fMmTNjzZo1MXv27Fi1alWMGzcutm/ffsj5NTU18eijj8a2bdti2rRp0dbWFmPHjo3XXnvtrVg/ANDPVRwjc+bMiXvuuSfuvffeiIiYOXNmXHXVVTFjxoxYunTpIefPmDEjRowYEe95z3viwIEDERHxox/96NhWDQAMGBW9TFNTUxOTJk2KlpaW7mOllGhpaYnGxsZer/m93/u9aG1tja985SuxdevW2LhxY8ybNy+qqw//0IMHD47a2toeAwAMTBXFyMiRI2PQoEHR0dHR43hHR0fU19f3es3b3va2mDZtWpxyyilx5ZVXxuLFi+OGG26IBQsWHPZx5s2bF7t27eqetra2SpYJAPQjx/27aaqrq2Pbtm3x8Y9/PJ599tlYuXJl3HrrrTFz5szDXrNkyZIYPnx49zQ0NBzvZQIASSp6z8iOHTviwIEDUVdX1+N4XV1dbN26tddrfvKTn8T+/fvj4MGD3cc2bdoUZ599dtTU1MT+/fsPuaazszM6OzsrWRoA0E9VdGdk//79sW7dumhqauo+VlVVFU1NTdHa2trrNU899VRccMEFUVVV1X3soosuivb29l5DBAA4uVT8Mk1zc3Ncd9118dGPfjTGjx8fd999dwwdOjSWLVsWERHLly+P2267rfv8u+++O0aMGBF33nlnXHjhhXHllVfG/Pnz4ytf+cpb96cAAPqtir+1d+XKlTFq1KhYtGhR1NfXx/r162Pq1Kmxbdu2iIgYM2ZMj5dkfvzjH8fv/M7vxF/+5V/Gf/7nf0ZbW1vceeedvX4bMABw8qmKiJK9iDdTW1sbu3btiuHDh8fu3buzlwMku2Nj7y8Lc/zdcEnvH+MAvenrv99+Ng0AkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkOqoYmTWrFmxefPm2Lt3b6xevTomT57cp+uuueaaKKXEP/3TPx3NwwIAA1DFMTJ9+vRobm6OhQsXxsSJE2PDhg2xatWqGDVq1BGvGzt2bNx+++3xxBNPHPViAYCBp+IYmTNnTtxzzz1x7733xqZNm2LmzJmxZ8+emDFjxuEfpLo6/uEf/iFuuummeOmll45pwQDAwFJRjNTU1MSkSZOipaWl+1gpJVpaWqKxsfGw1914442xbdu2+Lu/+7s+Pc7gwYOjtra2xwAAA1NFMTJy5MgYNGhQdHR09Dje0dER9fX1vV7zG7/xG3HttdfGdddd1+fHmTdvXuzatat72traKlkmANCPHNfvphk2bFjcd999cd1118VPf/rTPl+3ZMmSGD58ePc0NDQcx1UCAJkGVXLyjh074sCBA1FXV9fjeF1dXWzduvWQ89/+9rfH+eefH4888kj3serqn/fP/v37Y9y4cb2+h6SzszM6OzsrWRoA0E9VdGdk//79sW7dumhqauo+VlVVFU1NTdHa2nrI+S+88EK8853vjAkTJnTPww8/HI8//nhMmDAhXnnllWP/EwAA/VpFd0YiIpqbm2P58uWxdu3aePrpp2P27NkxdOjQWLZsWURELF++PNra2mL+/Pnx+uuvx/PPP9/j+tdeey0i4pDjAMDJqeIYWblyZYwaNSoWLVoU9fX1sX79+pg6dWps27YtIiLGjBkTBw8efMsXCgAMTFURUbIX8WZqa2tj165dMXz48Ni9e3f2coBkd2w89GVhfjluuOTwH+MA/19f//32s2kAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRiBABIJUYAgFRHFSOzZs2KzZs3x969e2P16tUxefLkw577sY99LJ544onYuXNn7Ny5Mx599NEjng8AnFwqjpHp06dHc3NzLFy4MCZOnBgbNmyIVatWxahRo3o9/7LLLosVK1bE5ZdfHo2NjfHKK6/Ev/3bv8Xo0aOPefEAQP9XFRGlkgtWr14dzzzzTHzyk5/8+W9QVRWvvPJK3HXXXbF06dI3vb66ujpeffXVuP766+O+++7r02PW1tbGrl27Yvjw4bF79+5KlgsMQHdsbM1ewknrhksas5dAP9LXf78rujNSU1MTkyZNipaWlu5jpZRoaWmJxsa+/Q90yJAhUVNTEzt37jzsOYMHD47a2toeAwAMTBXFyMiRI2PQoEHR0dHR43hHR0fU19f36fdYunRptLe39wia/2/evHmxa9eu7mlra6tkmQBAP/JL/W6az33uc/GHf/iHcfXVV8frr79+2POWLFkSw4cP756GhoZf4ioBgF+mQZWcvGPHjjhw4EDU1dX1OF5XVxdbt2494rU33HBDfP7zn4/3v//9sXHjxiOe29nZGZ2dnZUsDQDopyq6M7J///5Yt25dNDU1dR+rqqqKpqamaG09/BvK5s6dG3/xF38RU6dOjXXr1h39agGAAaeiOyMREc3NzbF8+fJYu3ZtPP300zF79uwYOnRoLFu2LCIili9fHm1tbTF//vyIiPjsZz8bixYtig9/+MOxZcuW7rsq//M//xM/+9nP3sI/CgDQH1UcIytXroxRo0bFokWLor6+PtavXx9Tp06Nbdu2RUTEmDFj4uDBg93n/9mf/Vmceuqp8eCDD/b4fW6++eZYuHDhMS4fAOjvKv6ckQw+ZwT4v3zOSB6fM0IljsvnjAAAvNXECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQSowAAKnECACQalD2AgAgIuKOja3ZSzhp3XBJY+rjuzMCAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQSIwBAKjECAKQadDQXzZo1K+bOnRv19fWxYcOG+OQnPxnPPPPMYc+fNm1aLF68OM4777z4/ve/H5/73OfiW9/61lEvGvrijo2t2Us4ad1wSWP2EoB+pOI7I9OnT4/m5uZYuHBhTJw4MTZs2BCrVq2KUaNG9Xp+Y2NjrFixIr72ta/Fu9/97njooYfioYceine84x3HvHgAoP+rOEbmzJkT99xzT9x7772xadOmmDlzZuzZsydmzJjR6/mf/vSn41//9V/j9ttvjxdeeCFuvPHGePbZZ+P6668/5sUDAP1fRS/T1NTUxKRJk2LJkiXdx0op0dLSEo2Nvd+WbWxsjObm5h7HVq1aFb//+79/2McZPHhwnHrqqd3/vba2tsd/Ql8Mrj4lewknreP9XLW3eY7n3trXPMdrX/v6+1YUIyNHjoxBgwZFR0dHj+MdHR0xfvz4Xq+pr6/v9fz6+vrDPs68efPi5ptvPuR4W1tbJcsFkly/a1f2EjhO7O3AdLz3tba2Nnbv3n3Yrx/VG1iPtyVLlhxyN2XEiBGxc+fOpBWdmGpra6OtrS0aGhqOuMn0L/Z14LK3A5e9Pbza2tpob28/4jkVxciOHTviwIEDUVdX1+N4XV1dbN26tddrtm7dWtH5ERGdnZ3R2dnZ45jNPbzdu3f7+xmA7OvAZW8HLnt7qL78fVT0Btb9+/fHunXroqmpqftYVVVVNDU1RWtr799G2dra2uP8iIjf+q3fOuz5AMDJp1Qy06dPL3v37i0f/ehHy/jx48tXv/rVsnPnznLWWWeViCjLly8vt912W/f5jY2NpbOzs8yZM6eMGzeu3HTTTeX1118v73jHOyp6XHPo1NbWllJKqa2tTV+Lsa/G3p7MY2+PeSq/6BOf+ETZsmVL2bdvX1m9enWZMmVK99cef/zxsmzZsh7nT5s2rbzwwgtl3759ZePGjeUDH/hA9h96QMzgwYPLTTfdVAYPHpy+FmNfjb09mcfeHttU/eIXAAAp/GwaACCVGAEAUokRACCVGAEAUokRACCVGAEAUokRACDVCfmD8ji8c889Ny688MLYsmVLtLe3xznnnBOvvfZa7NixI3tpHCN7OzDZ14HL3r51xEg/Mnr06Pj4xz8ekydPjne+851RSok1a9bEeeedF2eddVbcddddcdddd8W+ffuyl0qF7O3AZF8HLnv71vIJrP3MmDFj4qyzzorvf//7MW7cuGhoaIiXX3453vWud8XHPvaxePbZZ+NLX/pSvPzyy9lLpUL2dmCyrwOXvX1rpX8mvXlr5tJLLy3//M//XJ544oly+eWXp6/H2FtjX0/WsbcVT/oCzFs4tbW15Y477ijPPPNMmTNnThkyZEj6mkzfpqqqyt6ehGNf++94zr6Ff5e/+AX9wBlnnBF/8id/EmeeeWacdtppsXnz5vjmN78ZL7300iHnXnvttfHhD384mpqaElbK8WRv+w/PWSLsbV+IkX7i3HPPjfvvvz/Gjh0b27dvjx07dsSIESNiyJAh0draGn/7t38bTz/9dFRVVUUpP9/ShoaGaGtr63GME8+wYcNiwoQJ8b3vfS9effXVPu2VvT3xec4OXJ6zx0f67RlzhFtXv7gNeOedd5bHH3+8nH322SUiyujRo8sVV1xRvvCFL5THHnusPPbYY+Vtb3tb+npN36e6urpERLn11ltLV1dX+cY3vlH+9E//tFx88cVl6NChPc6tr68v119/fTn11FPT122OPJ6zA3c8Z4/rpC/A9GG+853vlOuvv77Xr1188cVl7dq15dvf/nb3k8X0n3n22WfLsmXLyoMPPlj27dtXdu7cWVasWFGmTZtWxo4dW0455ZSyYMGC8swzz6Sv1fR9PGcH7njOHpdJX4B5k6muri5f/OIXy/PPP1/Gjh3b6zmNjY3l+eefL7/2a7+Wvl7T92loaCiPPvpomTZtWvexj3zkI+W73/1u6erqKlu2bCl33nln6ejoKHPnzi0RUU455ZT0dZsjj+fswB3P2eM26QswfZhx48aV1atXl/vvv79MmTKl1NTU9Pj6r/7qr5Y9e/aUYcOGpa/V9H3OOOOM8qEPfag0NjYe8rURI0aUz372s+XHP/5x6erqOuQ2sDmxZ9y4caW1tbX8/d//vefsAJo3nrO//uu/fsjXPGePfryBtZ+oqqqKK664IpYuXRrvfve744knnogHH3wwXnrppZgwYUK8973vjQMHDsQHP/jBqK6ujoMHD2YvmT465ZRToqurKyIiqquro6amJrq6uuLAgQMREXHHHXfExIkT4/LLL7e3/cxVV10VS5cujYsuuij+/d//PR566KHYvHmz52w/V1398x/r9saeVVdXR1VVVffz2HP26KQXkTnynHbaaWXIkCHlnHPOKTU1NWXSpEnly1/+ctm6dWvZsmVLee6558rtt9/efTvYa9D9Z4YMGVKGDRtWJk2aVM4888weX6uuri6nn356+cEPflD++I//2N7243n/+99fvv71r5ef/vSn5Yc//KHn7ACe008/vfzwhz/0nK180hdgepk33pH/27/926WlpaX893//d1m/fn1pbW0tf/3Xf13e+973logo559/fqmvr09frzn6vX311VfL2rVry1NPPVWWL19ePvjBD3bf0h88eHCZMmVK+ppN3+fNXnYZP378IeFp+sf09SW1yZMnp6+1v42XaU5gp59+erz44ovx4IMPxje+8Y0455xzYuzYsTFhwoQYPXp0PPXUUzF37tzYu3dv9lKpUG97O2bMmJgwYULU1dXFmjVr4sYbb4ydO3dmL5UKDBkyJP7qr/4qHnvssVi9enW0t7f3+oPSRo8eHe3t7Qkr5Gj1dW/r6+tj69atCSvs/9KLyPQ+n/nMZ8ratWsPuc130UUXldmzZ5eXX365/Mu//Is3SfXD6cvePvzww97c2E/mjbtdn/rUp0pXV1fZu3dvaW9vL1/96lfL1KlTy+jRo8ugQYNKRJSRI0eWlpYWnzHST6aSvT3zzDPLt7/9bXt7dJO+AHOY+fM///OyatWqctppp/X69UsvvbT84Ac/KJdeemn6Wo29NVG+/vWvlyVLlpRRo0aVT3ziE+W5554rXV1d5fnnny+LFy8uU6ZMKXPnzi2vvvpq+lqNvT3BJn0B5jBzySWXlB07dpSbb765jBw58pCvV1dXl3Xr1pVPfepT6Ws19vZkn8GDB5fPf/7zZcGCBT2On3feeWXp0qWlvb297Nmzp3R1dZXbbrutRPj8if4y9vaXMukLMEeYWbNmlfb29rJq1aryoQ99qJx99tmltra2nHbaaWXKlCllz5495e1vf3v6Oo29NVHOOeeccsEFF5SIKDU1NYf8VNdrrrmmdHV1lXPPPTd9rcbenmCTvgDzJvObv/mb5Vvf+lbZt29f2b59e3n44YfL6tWry5YtW8pdd91VIt78R1mbE3Ps7cCdN/atqqqq+71BCxYsKD/5yU/saz8fe3sc/k5/8QtOMHV1dXHFFVfEAw88EPv374+IiLPOOiuuuuqquOyyy+LFF1+MNWvWRGtra+zZs8dPguxH7O3AVF9fH5dddlk88MAD3R9YFxE9PvTqM5/5TGzfvj3uv//+Hh92x4nN3h5/YuQEdeGFF8Ytt9wSZ5xxRvzXf/1XrFy5Mr7zne90f90/UP2XvR2Y/u++btq0KR544IF48skne5wzdOjQ+NnPfpa0Qo6WvT3+xMgJbtiwYXH11VfH7/7u78av/MqvRGtra/zjP/5jfO9738teGsfI3g5M/3dfzzjjjHjyySdj5cqV8eKLL2YvjWNkb48fMXIC+///D3nMmDHxB3/wB/G+970vhg8fHh/5yEfilVdeSVwhR8veDkz2deCyt8df+htXTOXzrne9K30Nxt4a+2rs7Vsx7owAAKmqsxcAAJzcxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACpxAgAkEqMAACp/hfD9CqCsTZO9wAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_output(c)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c48e4a38", + "metadata": {}, + "source": [ + "## Improve the performance with CVaR\n", + "\n", + "Conditional Value-at-Risk (CVaR) is a risk measure that quantifies the potential loss beyond a certain threshold (alpha), considering the tail end of the distribution. As proposed by [Barkoutsos et al. (2020)](https://arxiv.org/abs/1907.04769), incorporating CVaR as an objective function in QAOA allows for addressing risk-averse optimization problems effectively. By optimizing for CVaR, the algorithm focuses on minimizing the expected value of the worst-case scenario, rather than solely optimizing for the mean or expected value, which usually leads to faster convergence to a more accurate result.\n", + "\n", + "To showcase the performance of CVaR, a more complicated QUBO problem is used. This QUBO problem is described as a randomly generated symmetric Q matrix. The Q matrix is:" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "02ec55b6", + "metadata": {}, + "outputs": [], + "source": [ + "Q = np.array(\n", + " [\n", + " [-60.3657, 11.68835, 12.23445, 11.7274, 11.9959, 11.80955],\n", + " [11.68835, -59.7527, 11.6231, 13.23295, 11.96335, 12.44725],\n", + " [12.23445, 11.6231, -59.69535, 11.29525, 12.00035, 11.78495],\n", + " [11.7274, 13.23295, 11.29525, -59.12165, 12.1006, 12.5461],\n", + " [11.9959, 11.96335, 12.00035, 12.1006, -60.45515, 12.07545],\n", + " [11.80955, 12.44725, 11.78495, 12.5461, 12.07545, -59.9126],\n", + " ]\n", + ")\n", + "pauli_terms, weights, offset = QUBO_to_Ising(Q)" + ] + }, + { + "cell_type": "markdown", + "id": "76879a55", + "metadata": {}, + "source": [ + "Then let's define a function to classically brute-force calculate all feasible combinations of stocks and their associated cost. The results are printed below." + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "id": "46e9cbd9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "-------------------------------------\n", + " selection\t |\t cost\n", + "-------------------------------------\n", + " 110010\t |\t-109.2784\n", + " 100011\t |\t-108.9717\n", + " 011010\t |\t-108.7296\n", + " 111000\t |\t-108.7219\n", + " 101100\t |\t-108.6685\n", + " 001110\t |\t-108.4798\n", + " 001011\t |\t-108.3416\n", + " 101001\t |\t-108.3157\n", + " ...\t |\t ...\n", + "-------------------------------------\n" + ] + } + ], + "source": [ + "def print_Q_cost(Q, wrap=False, reverse=False):\n", + " n_stocks = len(Q)\n", + " states = []\n", + " for i in range(2**n_stocks):\n", + " a = f\"{bin(i)[2:]:0>{n_stocks}}\"\n", + " n_ones = 0\n", + " for j in a:\n", + " if j == \"1\":\n", + " n_ones += 1\n", + " states.append(a)\n", + "\n", + " cost_dict = {}\n", + " for selection in states:\n", + " x = np.array([int(bit) for bit in selection])\n", + " cost_dict[selection] = np.dot(x, np.dot(Q, x))\n", + " cost_sorted = dict(sorted(cost_dict.items(), key=lambda item: item[1]))\n", + " if reverse == True:\n", + " cost_sorted = dict(\n", + " sorted(cost_dict.items(), key=lambda item: item[1], reverse=True)\n", + " )\n", + " num = 0\n", + " print(\"\\n-------------------------------------\")\n", + " print(\" selection\\t |\\t cost\")\n", + " print(\"-------------------------------------\")\n", + " for k, v in cost_sorted.items():\n", + " print(\"%10s\\t |\\t%.4f\" % (k, v))\n", + " num += 1\n", + " if (num >= 8) & (wrap == True):\n", + " break\n", + " print(\" ...\\t |\\t ...\")\n", + " print(\"-------------------------------------\")\n", + "\n", + "\n", + "print_Q_cost(Q, wrap=True)" + ] + }, + { + "cell_type": "markdown", + "id": "04d4ea38", + "metadata": {}, + "source": [ + "The QAOA with CVaR and three different alpha (1, 0.25, 0.1) will be run and a callback function will be used to record the parameters during the solving procedure. When alpha is $1$, the complete measurement results are accepted and the model changes to the standard QAOA." + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "id": "d3b386d6", + "metadata": {}, + "outputs": [], + "source": [ + "# Set the number of layers to 2\n", + "nlayers = 2\n", + "\n", + "# Define a list of alpha values\n", + "alpha_list = [0.1, 0.25, 1]\n", + "\n", + "\n", + "# Define the callback function to record parameter values\n", + "def record_param(xk):\n", + " xk_list.append(xk)\n", + "\n", + "\n", + "# Generate initial parameters randomly for all alpha\n", + "init_params = K.implicit_randn(shape=[2 * nlayers], stddev=0.5)\n", + "\n", + "# Create an empty list to store parameter values for each alpha\n", + "params_list = []\n", + "\n", + "# Iterate over each alpha value\n", + "for alpha in alpha_list:\n", + " # Create a new empty list for callback function\n", + " xk_list = []\n", + "\n", + " # Run the QUBO_QAOA_cvar function with the specified parameters\n", + " final_params = QUBO_QAOA_cvar(\n", + " Q,\n", + " nlayers,\n", + " alpha=alpha,\n", + " callback=record_param,\n", + " maxiter=100,\n", + " init_params=init_params,\n", + " )\n", + "\n", + " # Append the parameter values for the current alpha to the params_list\n", + " params_list.append(xk_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "id": "b3da7c48", + "metadata": {}, + "outputs": [], + "source": [ + "best = 50 # Represents the binary number 110010\n", + "prob_list = [] # Create an empty list to store probabilities\n", + "loss_list = [] # Create an empty list to store loss values\n", + "\n", + "# Iterate three times\n", + "for i in range(3):\n", + " c = QAOA_ansatz_for_Ising(init_params, nlayers, pauli_terms, weights)\n", + " loss = [cvar_loss(nlayers, Q, 1000, alpha_list[i], True, init_params)]\n", + " prob = [c.probability()[best].numpy()]\n", + "\n", + " # Iterate 100 times\n", + " for j in range(100):\n", + " if j < len(params_list[i]) - 1:\n", + " params = params_list[i][j]\n", + " else:\n", + " pass\n", + " c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights)\n", + " loss.append(cvar_loss(nlayers, Q, 1000, alpha_list[i], True, params))\n", + " prob.append(c.probability()[best].numpy())\n", + "\n", + " loss_list.append(loss) # Append the loss values to the loss_list\n", + " prob_list.append(prob) # Append the probability values to the prob_list" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "id": "d1f375ce", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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u3dvceLECfHNN99UVpu9/9Ju9LJr1y7x0UcfyZ8VCoW4ePGiePnll73etupSateuLYQQ4uabbxYARGhoqCgsLBT33nuvXKdly5ZCCCF69Ojh9fb6WwkODhaJiYli0KBBYuvWrXJwxPdccWX27Nli27ZtLutcvnxZTJo0Sf4cGhoqDAaDeOCBB7zefn8pq1evFl988YXdsZ9++kksW7aM77mCiqPgqLR32qpVKyGEEF26dJHr3HrrrcJsNou6detWeBvZreZlGo0GXbp0webNm+VjQghs3rwZcXFxXmxZ9RIWFgYAuHr1KgCgS5cu0Gq1du89MTERSUlJfO9lsHDhQqxduxZbtmyxO873XHHuuusu7NmzBz/88ANSUlKwb98+PPHEE/L5m266CXXr1rV719nZ2di9ezfftQf++usvDBo0CM2bNwcAdOjQAX369MG6desA8D1XBnfeaVxcHDIyMrB37165zubNm2GxWNCjR48KbxM3nvWy2rVrQ61WIyUlxe54SkoKWrVq5aVWVS8KhQIffPABduzYgSNHjgAAoqOjUVhYiKysLLu6KSkpiI6O9kYz/dYDDzyAzp07Oxwnx/dccZo0aYKnnnoK8+bNw9tvv41u3brhww8/hNFoxNKlS+X36ei/JXzX7nvnnXcQGhqK48ePw2w2Q6VS4dVXX8W3334LAHzPlcCddxodHY3U1FS782azGVevXq2U987giKq9hQsXol27dujTp4+3m1LtNGjQAAsWLMDgwYO5pUIlUyqV2LNnD1599VUAwIEDB9CuXTtMnDgRS5cu9XLrqo+RI0dizJgxGD16NI4cOYKOHTvigw8+wOXLl/mebyDsVvMyvV6PoqIiREVF2R2PiopCcnKyl1pVfXz00UcYNmwYBgwYgEuXLsnHk5OTERAQIHe3SfjePdOlSxdERUVh3759MJlMMJlM6N+/P5577jmYTCakpKTwPVeQK1eu4OjRo3bHjh07hpiYGACQ3yf/W1I+c+bMwTvvvIPvv/8e//77L5YvX4758+dj6tSpAPieK4M77zQ5ObnELFeVSoWaNWtWyntncORlJpMJe/fuxaBBg+RjCoUCgwYNQkJCghdb5v8++ugjjBgxAgMHDsS5c+fszu3duxdGo9Huvbdo0QKNGjXie/fAli1b0K5dO3Ts2FEu//zzD7755ht07NgRe/bs4XuuIDt37kTLli3tjrVo0QJJSUkAgLNnz+LKlSt271qn06FHjx581x4ICgqCxWKxO2Y2m6FUWn9d8j1XPHfeaUJCAiIiItC5c2e5zsCBA6FUKrF79+5KaZfXR67f6GXkyJHCYDCIhx9+WLRq1Up89tln4urVq6JOnTpeb5u/loULF4qMjAzRt29fERUVJZcaNWrIdT755BNx7tw50b9/f9G5c2exc+dOsXPnTq+33d+L7Ww1vueKK127dhVGo1FMnTpVNG3aVDz44IMiNzdXjB49Wq7z0ksviatXr4o777xTtGvXTqxcuZJTzD0sX331lbhw4YI8lf/uu+8Wqamp4p133uF7LkcJDg4WsbGxIjY2VgghxPPPPy9iY2NFw4YN3X6nv/32m9i7d6/o1q2b6NWrl0hMTORU/upennnmGXHu3DlRUFAgdu3aJbp37+71NvlzcWbcuHFynYCAAPHxxx+L9PR0kZubK37++WcRFRXl9bb7e7k+OOJ7rrhyxx13iEOHDgmDwSCOHj0qnnjiiRJ1ZsyYIa5cuSIMBoPYtGmTaN68udfb7U8lJCREzJ8/X5w7d07k5+eLU6dOiTfffFNoNBq+53KUfv36Ofxv8ldffeX2O42IiBDffPONyM7OFpmZmWLx4sUiODi4UtqruPYDEREREYFjjoiIiIjsMDgiIiIissHgiIiIiMgGgyMiIiIiGwyOiIiIiGwwOCIiIiKyweCIiIiIyAaDIyIiIiIbDI6IyOds3boV8+fP93Yz7AghMHz4cG83g4iqiNeXFWdhYWGxLRERESIkJEQAEGfPnhXx8fFV9uw33nhD7N+/v8TxqKgoodVqvf5uWFhYKr+oQUTkYzIyMir8nhqNBiaTqczXp6SkVGBriMjXeT1CY2FhYbEt0ua1W7duLbFRpVSnd+/eYtu2bSI/P1+cP39eLFiwQAQFBcnnz549K1577TWxZMkSkZWVJW9w+c4774jExESRl5cnTp8+LWbOnCnUarUAIMaNG+d0s2IhhBg+fLh8/3bt2oktW7aI/Px8odfrxaJFi+w2wfzqq6/EypUrxaRJk8Tly5eFXq8XH3/8sfwsAOKpp54SJ06cEAaDQSQnJ4sff/zR6++ehYUFAj7QABYWFha7IgVHERER4vz58+K1114TUVFRIioqSgAQTZo0ETk5OSI+Pl40a9ZMxMXFib1794ovv/xSvsfZs2dFZmameOGFF0STJk1EkyZNBADx6quviri4ONGoUSMxbNgwceXKFTF58mQBQNSoUUPMmTNHHD58WH5ejRo1BGAfHAUFBYlLly6Jn376SbRt21YMGDBAnD592m6H8a+++kpkZmaKTz75RLRs2VLccccdIjc3VzzxxBMCgOjSpYswmUxi1KhRIiYmRnTs2FE8++yzXn/3LCwsEPCBBrCwsLDYFSk4AhyPOfr888/FZ599Znesd+/eoqioSAQEBMjX/fLLL6U+a9KkSeKff/6RPzsbc2QbHD3xxBMiPT3dLlN12223iaKiIlGnTh0BWIOjs2fPCqVSKdf5/vvvxYoVKwQAMWLECJGZmSmPrWJhYfGdwjFHROR3YmNj0aFDB4wZM0Y+plAooFKpcNNNN+H48eMAgD179pS4duTIkXjuuefQtGlThISEQK1WIzs726Pnt27dGgcPHkR+fr58bOfOnVCpVGjZsiVSU1MBAEeOHIHFYpHrXLlyBe3btwcAbNq0CUlJSThz5gzWr1+P9evXY+XKlTAYDB61hYgqHqfyE5HfCQkJwaJFi9CxY0e5xMbGolmzZjh9+rRcLy8vz+66nj174ptvvsFvv/2GYcOGoVOnTpg1axa0Wm2ltPP6AeBCCCiV1v/s5ubmonPnznjwwQdx5coVzJw5EwcPHkRYWFiltIWI3MfMERH5NKPRCJVKZXds3759aNOmjV0g5I5evXohKSkJb7/9tnysUaNGpT7veseOHcMjjzyCoKAgOXvUu3dvmM1mJCYmut0es9mMLVu2YMuWLZgxYwYyMzMxcOBArFy50oNvRUQVjZkjIvJp586dQ9++fVGvXj3UqlULAPDuu++iV69e+Oijj+SM0V133YWPPvrI5b1OnjyJmJgYPPDAA2jSpAmeffZZjBgxosTzbrrpJsTGxqJWrVoOs0rffPMNCgoKsGTJErRt2xb9+/fHRx99hGXLlsldaqW544478OyzzyI2NhYxMTF4+OGHoVQqPQquiKhyMDgiIp82bdo0NG7cGKdPn4ZerwcAHD58GP369UOLFi2wfft27N+/HzNnzsTly5dd3mv16tWYP38+Pv74Yxw4cAC9evXCm2++aVfn559/xvr167F161bo9Xo8+OCDJe5jMBhw6623ombNmvjnn3/w008/YcuWLfi///s/t79XZmYm7rnnHvz+++84duwYJk6ciAcffBBHjx51+x5EVDkUsI7MJiIiIiIwc0RERERkh8ERERERkQ0GR0REREQ2GBwRERER2WBwRERERGSDwRERERGRDQZHRERERDYYHBERERHZYHBEREREZIPBEREREZENBkdERERENv4flMrniyoj9T4AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for loss in loss_list:\n", + " plt.plot(loss)\n", + "plt.legend([\"alpha = 0.1\", \"alpha = 0.25\", \"alpha = 1\"])\n", + "plt.xlabel(\"iterations\")\n", + "p = plt.ylabel(\"cost\")" + ] + }, + { + "cell_type": "markdown", + "id": "6a88dda3", + "metadata": {}, + "source": [ + "The depicted figure illustrates that utilizing CVaR results in quicker convergence towards a lower loss." + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "id": "f81fdeae", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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/vSnP8He3h5//vOfMWjQIJw7dw4zZ87sF88uISIiop6hejf3rAXPADEYDIbpQqvVSnJysnh5eameC+PZDy8vL0lOThatVtvhte78/lb9m6CJiMi8VVZWAgB8fHxUzoT6gof/TvR6/VPtR/VLYEREZN4aGhpw5swZREZGAgBu3LihPBWd6CFra2v4+PggMjISZ86ceeIXPz5xfz2UFxER0Y+WmJgIAIiKilI5E3rWnTlzRvn38jQs8OBaGH2PRqNBbW0tHB0d+Z1AREQmZGdnB2dn5371hXvUM0QEer2+0zM/3fn9zTNARET0zGhsbMSdO3fUToPMABdBExERkdlhA0RERERmhw0QERERmR2uAeqERqNROwUiIiLqou783mYD9AgPC1haWqpyJkRERNRdGo3miXeB8Tb4x3B3d++VW+A1Gg1KS0vxwgsv8Bb7XsQ6mwbrbBqss2mwzqbR23XWaDQoKyt74jyeAXqMrhTvadTV1fE/mAmwzqbBOpsG62warLNp9Fadu7pPLoImIiIis8MGiIiIiMwOGyATa25uxh/+8Ac0NzernUq/xjqbButsGqyzabDOpvGs1JmLoImIiMjs8AwQERERmR02QERERGR22AARERGR2WEDRERERGaHDZAJrVixAkVFRTAYDDh//jyCgoLUTqlPe/vtt/H111+jtrYWOp0OqampGDVqlNEcW1tb7Nq1C3q9HnV1dTh8+DBcXFxUyrh/WL9+PUQE8fHxyhjr3DPc3d1x4MAB6PV6NDY24ptvvkFgYKDRnJiYGJSVlaGxsRGnTp3CiBEjVMq2b7K0tERsbCxu376NxsZG3Lp1C5s2beowj3XuvpdffhmfffYZSktLISKIiIjoMOdJdXVycsInn3yCe/fuobq6Gvv374e9vX2v5SyM3o/IyEhpamqSt956S0aPHi379u2TqqoqGTJkiOq59dU4fvy4LF68WMaMGSPjx4+Xf/3rX1JcXCx2dnbKnD179khJSYlMnTpVAgIC5KuvvpJz586pnntfjZdeeklu374teXl5Eh8fzzr3YAwaNEiKiork448/lqCgIBk2bJhMnz5dPD09lTnr1q2T6upqmTt3rowbN06OHj0qhYWFYmtrq3r+fSU2bNgg//nPf+S1114TDw8Pef3116W2tlaio6NZ56eMmTNnyubNm2XevHkiIhIREWH0elfq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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for prob in prob_list:\n", + " plt.plot(prob)\n", + "plt.legend([\"alpha = 0.1\", \"alpha = 0.25\", \"alpha = 1\"])\n", + "plt.xlabel(\"iterations\")\n", + "p = plt.ylabel(\"probability of the best answer\")" + ] + }, + { + "cell_type": "markdown", + "id": "0ae45348", + "metadata": {}, + "source": [ + "The data presented in this figure indicates that QAOA with CVaR typically shows a higher probability of obtaining the correct measurement outcome." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc_dev", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/sklearn_svc.ipynb b/docs/source/tutorials/sklearn_svc.ipynb new file mode 100644 index 00000000..5226eb08 --- /dev/null +++ b/docs/source/tutorials/sklearn_svc.ipynb @@ -0,0 +1,299 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Support Vector Classification with SKLearn\n", + "\n", + "Authored by [_Mark (Zixuan) Song_](https://marksong.tech)\n", + "\n", + "We use the `SKLearn` library to implement `SVC` in the following tutorial." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "The aim of this tutorial is to implant a quantum machine learning (QML) transformer into SVC pipeline. And this is a general introduction to connect `tensorcircuit` with `scikit-learn`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup\n", + "\n", + "Install `scikit-learn` and `requests`. The data that is going to be used is [German Credit Data by UCI](http://home.cse.ust.hk/~qyang/221/Assignments/German/GermanData.csv)\n", + "\n", + "```bash\n", + "pip install scikit-learn requests\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import tensorflow as tf\n", + "from sklearn.svm import SVC\n", + "from sklearn import metrics\n", + "from time import time\n", + "import requests\n", + "\n", + "K = tc.set_backend(\"tensorflow\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Data Preprocessing\n", + "\n", + "The data has 20 variables and each is a integer value. In order for the model to use the data, we need to normalize the data to between 0 and 1." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def load_GCN_data():\n", + " link2gcn = \"http://home.cse.ust.hk/~qyang/221/Assignments/German/GermanData.csv\"\n", + " data = requests.get(link2gcn)\n", + " data = data.text\n", + " data = data.split(\"\\n\")[:-1]\n", + " x = None\n", + " y = None\n", + "\n", + " def destring(string):\n", + " string = string.split(\",\")\n", + " return_array = []\n", + " for i, v in enumerate(string):\n", + " if v[0] == \"A\":\n", + " return_array.append(int(v[1 + len(str(i)) :]))\n", + " else:\n", + " return_array.append(int(v))\n", + " return K.cast([return_array[:-1]], dtype=\"float32\"), K.cast(\n", + " [return_array[-1] - 1], dtype=\"int32\"\n", + " )\n", + "\n", + " for i in data:\n", + " if x is None:\n", + " temp_x, temp_y = destring(i)\n", + " x = K.cast(temp_x, dtype=\"float32\")\n", + " y = K.cast(temp_y, dtype=\"int32\")\n", + " else:\n", + " temp_x, temp_y = destring(i)\n", + " x = K.concat([x, temp_x], axis=0)\n", + " y = K.concat([y, temp_y], axis=0)\n", + " x = K.transpose(x)\n", + " nx = None\n", + " for i in x:\n", + " max_i = K.cast(K.max(i), dtype=\"float32\")\n", + " temp_nx = [K.divide(i, max_i)]\n", + " nx = K.concat([nx, temp_nx], axis=0) if nx is not None else temp_nx\n", + " x = K.transpose(nx)\n", + " return (x[:800], y[:800]), (x[800:], y[800:])\n", + "\n", + "\n", + "(x_train, y_train), (x_test, y_test) = load_GCN_data()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quantum Model\n", + "\n", + "This quantum model takes in 1x20 matrices as input and output the state of 5 qbits. The model is shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def quantumTran(inputs):\n", + " c = tc.Circuit(5)\n", + " for i in range(4):\n", + " if i % 2 == 0:\n", + " for j in range(5):\n", + " c.rx(j, theta=(0 if i * 5 + j >= 20 else inputs[i * 5 + j]))\n", + " else:\n", + " for j in range(5):\n", + " c.rz(j, theta=(0 if i * 5 + j >= 20 else inputs[i * 5 + j]))\n", + " for j in range(4):\n", + " c.cnot(j, j + 1)\n", + " return c.state()\n", + "\n", + "\n", + "func_qt = tc.interfaces.tensorflow_interface(quantumTran, ydtype=tf.complex64, jit=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Wrapping Quantum Model into a SVC\n", + "\n", + "Convert quantum model into svc that can be trained." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def quantum_kernel(quantumTran, data_x, data_y):\n", + " def kernel(x, y):\n", + " x = K.convert_to_tensor(x)\n", + " y = K.convert_to_tensor(y)\n", + " x_qt = None\n", + " for i, x1 in enumerate(x):\n", + " if i == 0:\n", + " x_qt = K.convert_to_tensor([quantumTran(x1)])\n", + " else:\n", + " x_qt = K.concat([x_qt, [quantumTran(x1)]], 0)\n", + " y_qt = None\n", + " for i, x1 in enumerate(y):\n", + " if i == 0:\n", + " y_qt = K.convert_to_tensor([quantumTran(x1)])\n", + " else:\n", + " y_qt = K.concat([y_qt, [quantumTran(x1)]], 0)\n", + " data_ret = K.cast(K.power(K.abs(x_qt @ K.transpose(y_qt)), 2), \"float32\")\n", + " return data_ret\n", + "\n", + " clf = SVC(kernel=kernel)\n", + " clf.fit(data_x, data_y)\n", + " return clf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Traditional SVC" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def standard_kernel(data_x, data_y, method):\n", + " methods = [\"linear\", \"poly\", \"rbf\", \"sigmoid\"]\n", + " if method not in methods:\n", + " raise ValueError(\"method must be one of %r.\" % methods)\n", + " clf = SVC(kernel=method)\n", + " clf.fit(data_x, data_y)\n", + " return clf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test\n", + "\n", + "Test the accuracy of the quantum model SVC with the test data and compare it with traditional SVC." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Accuracy:(linear as kernel) 0.78\n", + "time: 0.007764101028442383 seconds\n", + "\n", + "Accuracy:(poly as kernel) 0.75\n", + "time: 0.024492979049682617 seconds\n", + "\n", + "Accuracy:(rbf as kernel) 0.765\n", + "time: 0.011505126953125 seconds\n", + "\n", + "Accuracy:(sigmoid as kernel) 0.695\n", + "time: 0.010205984115600586 seconds\n", + "\n", + "Accuracy:(qml as kernel) 0.66\n", + "time: 3.0243749618530273 seconds\n" + ] + } + ], + "source": [ + "methods = [\"linear\", \"poly\", \"rbf\", \"sigmoid\"]\n", + "\n", + "for method in methods:\n", + " print()\n", + " t = time()\n", + "\n", + " k = standard_kernel(data_x=x_train, data_y=y_train, method=method)\n", + " y_pred = k.predict(x_test)\n", + " print(\"Accuracy:(%s as kernel)\" % method, metrics.accuracy_score(y_test, y_pred))\n", + "\n", + " print(\"time:\", time() - t, \"seconds\")\n", + "\n", + "print()\n", + "t = time()\n", + "\n", + "k = quantum_kernel(quantumTran=func_qt, data_x=x_train, data_y=y_train)\n", + "y_pred = k.predict(x_test)\n", + "print(\"Accuracy:(qml as kernel)\", metrics.accuracy_score(y_test, y_pred))\n", + "\n", + "print(\"time:\", time() - t, \"seconds\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Issue with `SKLearn`\n", + "\n", + "Due to the limitation of `SKLearn`, `SKLearn`'s `SVC` is not fully compatible with quantum machine model (QML). \n", + "\n", + "This is because QML outputs a result as complex number (coordinate on the bloch sphere) whereas SKLearn only accept float. This is causing the result output by QML must be converted into float before it can be used in SVC, leading to a potential loss of accuracy.\n", + "\n", + "## Conclusion\n", + "\n", + "Due to the present limitation of SKLearn, quantum SVC is worse than traditional SVC in both accuracy and speed. However, if the limitation is removed, quantum SVC might be able to outperform traditional SVC in both accuracy." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/tutorials/sklearn_svc_cn.ipynb b/docs/source/tutorials/sklearn_svc_cn.ipynb new file mode 100644 index 00000000..c737dc72 --- /dev/null +++ b/docs/source/tutorials/sklearn_svc_cn.ipynb @@ -0,0 +1,299 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 结合SKLearn实现的支持向量分类\n", + "\n", + "[_Mark (Zixuan) Song_](https://marksong.tech) 撰写\n", + "\n", + "本示例结合了`sklearn`库中的`SVC`类,实现了支持向量分类。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 概述\n", + "\n", + "本示例的目的是将量子机器学习(QML)转换器嵌入到SVC管道中并且介绍`tensorcircuit`与`scikit-learn`的一种连接方式。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 设置\n", + "\n", + "安装 `scikit-learn` 和 `requests`. 本模型测试数据为 [德国信用]The data that is going to be used is [German Credit Data by UCI](http://home.cse.ust.hk/~qyang/221/Assignments/German/GermanData.csv)\n", + "\n", + "```bash\n", + "pip install scikit-learn requests\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorcircuit as tc\n", + "import tensorflow as tf\n", + "from sklearn.svm import SVC\n", + "from sklearn import metrics\n", + "from time import time\n", + "import requests\n", + "\n", + "K = tc.set_backend(\"tensorflow\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 数据处理\n", + "\n", + "数据集包含20个变量,每个变量都是整数值。为了使模型能够使用数据,我们需要将数据归一化为0到1之间。" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def load_GCN_data():\n", + " link2gcn = \"http://home.cse.ust.hk/~qyang/221/Assignments/German/GermanData.csv\"\n", + " data = requests.get(link2gcn)\n", + " data = data.text\n", + " data = data.split(\"\\n\")[:-1]\n", + " x = None\n", + " y = None\n", + "\n", + " def destring(string):\n", + " string = string.split(\",\")\n", + " return_array = []\n", + " for i, v in enumerate(string):\n", + " if v[0] == \"A\":\n", + " return_array.append(int(v[1 + len(str(i)) :]))\n", + " else:\n", + " return_array.append(int(v))\n", + " return K.cast([return_array[:-1]], dtype=\"float32\"), K.cast(\n", + " [return_array[-1] - 1], dtype=\"int32\"\n", + " )\n", + "\n", + " for i in data:\n", + " if x is None:\n", + " temp_x, temp_y = destring(i)\n", + " x = K.cast(temp_x, dtype=\"float32\")\n", + " y = K.cast(temp_y, dtype=\"int32\")\n", + " else:\n", + " temp_x, temp_y = destring(i)\n", + " x = K.concat([x, temp_x], axis=0)\n", + " y = K.concat([y, temp_y], axis=0)\n", + " x = K.transpose(x)\n", + " nx = None\n", + " for i in x:\n", + " max_i = K.cast(K.max(i), dtype=\"float32\")\n", + " temp_nx = [K.divide(i, max_i)]\n", + " nx = K.concat([nx, temp_nx], axis=0) if nx is not None else temp_nx\n", + " x = K.transpose(nx)\n", + " return (x[:800], y[:800]), (x[800:], y[800:])\n", + "\n", + "\n", + "(x_train, y_train), (x_test, y_test) = load_GCN_data()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 量子模型\n", + "\n", + "这个量子模型是输入为1x20的矩阵,并输出为5个量子比特的状态。模型如下所示:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def quantumTran(inputs):\n", + " c = tc.Circuit(5)\n", + " for i in range(4):\n", + " if i % 2 == 0:\n", + " for j in range(5):\n", + " c.rx(j, theta=(0 if i * 5 + j >= 20 else inputs[i * 5 + j]))\n", + " else:\n", + " for j in range(5):\n", + " c.rz(j, theta=(0 if i * 5 + j >= 20 else inputs[i * 5 + j]))\n", + " for j in range(4):\n", + " c.cnot(j, j + 1)\n", + " return c.state()\n", + "\n", + "\n", + "func_qt = tc.interfaces.tensorflow_interface(quantumTran, ydtype=tf.complex64, jit=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 将量子模型打包成SVC\n", + "\n", + "将量子模型打包成`SKLearn`能使用的SVC模型。" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def quantum_kernel(quantumTran, data_x, data_y):\n", + " def kernel(x, y):\n", + " x = K.convert_to_tensor(x)\n", + " y = K.convert_to_tensor(y)\n", + " x_qt = None\n", + " for i, x1 in enumerate(x):\n", + " if i == 0:\n", + " x_qt = K.convert_to_tensor([quantumTran(x1)])\n", + " else:\n", + " x_qt = K.concat([x_qt, [quantumTran(x1)]], 0)\n", + " y_qt = None\n", + " for i, x1 in enumerate(y):\n", + " if i == 0:\n", + " y_qt = K.convert_to_tensor([quantumTran(x1)])\n", + " else:\n", + " y_qt = K.concat([y_qt, [quantumTran(x1)]], 0)\n", + " data_ret = K.cast(K.power(K.abs(x_qt @ K.transpose(y_qt)), 2), \"float32\")\n", + " return data_ret\n", + "\n", + " clf = SVC(kernel=kernel)\n", + " clf.fit(data_x, data_y)\n", + " return clf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 创建传统SVC模型" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def standard_kernel(data_x, data_y, method):\n", + " methods = [\"linear\", \"poly\", \"rbf\", \"sigmoid\"]\n", + " if method not in methods:\n", + " raise ValueError(\"method must be one of %r.\" % methods)\n", + " clf = SVC(kernel=method)\n", + " clf.fit(data_x, data_y)\n", + " return clf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 测试对比\n", + "\n", + "测试量子SVC模型并于传统SVC模型进行对比。" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Accuracy:(linear as kernel) 0.78\n", + "time: 0.00810384750366211 seconds\n", + "\n", + "Accuracy:(poly as kernel) 0.75\n", + "time: 0.024804115295410156 seconds\n", + "\n", + "Accuracy:(rbf as kernel) 0.765\n", + "time: 0.011444091796875 seconds\n", + "\n", + "Accuracy:(sigmoid as kernel) 0.695\n", + "time: 0.010396003723144531 seconds\n", + "\n", + "Accuracy:(qml as kernel) 0.66\n", + "time: 6.472219228744507 seconds\n" + ] + } + ], + "source": [ + "methods = [\"linear\", \"poly\", \"rbf\", \"sigmoid\"]\n", + "\n", + "for method in methods:\n", + " print()\n", + " t = time()\n", + "\n", + " k = standard_kernel(data_x=x_train, data_y=y_train, method=method)\n", + " y_pred = k.predict(x_test)\n", + " print(\"Accuracy:(%s as kernel)\" % method, metrics.accuracy_score(y_test, y_pred))\n", + "\n", + " print(\"time:\", time() - t, \"seconds\")\n", + "\n", + "print()\n", + "t = time()\n", + "\n", + "k = quantum_kernel(quantumTran=func_qt, data_x=x_train, data_y=y_train)\n", + "y_pred = k.predict(x_test)\n", + "print(\"Accuracy:(qml as kernel)\", metrics.accuracy_score(y_test, y_pred))\n", + "\n", + "print(\"time:\", time() - t, \"seconds\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `SKLearn`的局限性\n", + "\n", + "因为`SKLearn`的局限性,`SKLearn`的`SVC`并不完全兼容量子机器学习(QML)。\n", + "\n", + "这是因为QML输出的为复数(布洛赫球上的坐标),而`SKLearn`只接受浮点数。这导致QML输出的结果必须在使用SVC之前转换为浮点数,从而可能导致精度损失。\n", + "\n", + "## 结论\n", + "\n", + "由于`SKLearn`的局限性,量子SVC在准确性和速度上都不如传统SVC。但是,如果这种局限性被消除,量子SVC可能会在准确性上都优于传统SVC。" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tc2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb b/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb index eca8c1ad..14a5cbea 100644 --- a/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb +++ b/docs/source/tutorials/tfim_vqe_diffreph_cn.ipynb @@ -420,7 +420,9 @@ "\n", "Jx = np.array([1.0 for _ in range(n - 1)]) # xx 相互作用的强度 (OBC)\n", "Bz = np.array([1.0 for _ in range(n)]) # 横向场强\n", - "hamiltonian_mpo = tn.matrixproductstates.mpo.FiniteTFI(Jx, Bz, dtype=dtype) # 矩阵乘积算子\n", + "hamiltonian_mpo = tn.matrixproductstates.mpo.FiniteTFI(\n", + " Jx, Bz, dtype=dtype\n", + ") # 矩阵乘积算子\n", "hamiltonian_mpo = quoperator_mpo(hamiltonian_mpo) # 从 mpo 生成 QuOperator" ] }, diff --git a/examples/analog_evolution_interface.py b/examples/analog_evolution_interface.py new file mode 100644 index 00000000..9cc00a9b --- /dev/null +++ b/examples/analog_evolution_interface.py @@ -0,0 +1,40 @@ +""" +jax backend is required, experimental built-in interface for parameterized hamiltonian evolution +""" + +import optax +import tensorcircuit as tc +from tensorcircuit.experimental import evol_global, evol_local + +K = tc.set_backend("jax") + + +def h_fun(t, b): + return b * tc.gates.x().tensor + + +hy = tc.quantum.PauliStringSum2COO([[2, 0]]) + + +def h_fun2(t, b): + return b[2] * K.cos(b[0] * t + b[1]) * hy + + +@K.jit +@K.value_and_grad +def hybrid_evol(params): + c = tc.Circuit(2) + c.x([0, 1]) + c = evol_local(c, [1], h_fun, 1.0, params[0]) + c.cx(1, 0) + c.h(0) + c = evol_global(c, h_fun2, 1.0, params[1:]) + return K.real(c.expectation_ps(z=[0, 1])) + + +opt = K.optimizer(optax.adam(0.1)) +b = K.implicit_randn([4]) +for _ in range(50): + v, gs = hybrid_evol(b) + b = opt.update(gs, b) + print(v, b) diff --git a/examples/analog_evolution_jax.py b/examples/analog_evolution_jax.py new file mode 100644 index 00000000..f5e92ca0 --- /dev/null +++ b/examples/analog_evolution_jax.py @@ -0,0 +1,42 @@ +""" +Parameterized Hamiltonian (Pulse control/Analog simulation) with AD/JIT support using jax ode solver +""" + +import optax +from jax.experimental.ode import odeint +import tensorcircuit as tc + +K = tc.set_backend("jax") +tc.set_dtype("complex128") + +hx = tc.quantum.PauliStringSum2COO([[1]]) +hz = tc.quantum.PauliStringSum2COO([[3]]) + + +# psi = -i H psi +# we want to optimize the final z expectation over parameters params +# a single qubit example below + + +def final_z(b): + def f(y, t, b): + h = b[3] * K.sin(b[0] * t + b[1]) * hx + K.cos(b[2]) * hz + return -1.0j * K.sparse_dense_matmul(h, y) + + y0 = tc.array_to_tensor([1, 0]) + y0 = K.reshape(y0, [-1, 1]) + t = tc.array_to_tensor([0.0, 10.0], dtype=tc.rdtypestr) + yf = odeint(f, y0, t, b) + c = tc.Circuit(1, inputs=K.reshape(yf[-1], [-1])) + return K.real(c.expectation_ps(z=[0])) + + +vgf = K.jit(K.value_and_grad(final_z)) + + +opt = K.optimizer(optax.adam(0.1)) +b = K.implicit_randn([4]) +for _ in range(50): + v, gs = vgf(b) + b = opt.update(gs, b) + print(v, b) diff --git a/examples/analog_evolution_mint.py b/examples/analog_evolution_mint.py new file mode 100644 index 00000000..0af4fc04 --- /dev/null +++ b/examples/analog_evolution_mint.py @@ -0,0 +1,36 @@ +""" +jax backend analog evolution targeting at minimizing evolution time +""" + +import optax +import tensorcircuit as tc +from tensorcircuit.experimental import evol_global + +K = tc.set_backend("jax") + +hx = tc.quantum.PauliStringSum2COO([[1]]) + + +def h_fun(t, b): + return K.sin(b) * hx + + +def fast_evol(t, b): + lbd = 0.08 + c = tc.Circuit(1) + c = evol_global(c, h_fun, t, b) + loss = K.real(c.expectation_ps(z=[0])) + return loss + lbd * t**2, loss + # l2 regularization to minimize t while target z=-1 + + +vgf = K.jit(K.value_and_grad(fast_evol, argnums=(0, 1), has_aux=True)) + +opt = K.optimizer(optax.adam(0.05)) +b, t = tc.array_to_tensor(0.5, 1.0, dtype=tc.rdtypestr) + +for i in range(500): + (v, loss), gs = vgf(b, t) + b, t = opt.update(gs, (b, t)) + if i % 20 == 0: + print(v, loss, b, t) diff --git a/examples/circuit_compiler.py b/examples/circuit_compiler.py new file mode 100644 index 00000000..349eac9a --- /dev/null +++ b/examples/circuit_compiler.py @@ -0,0 +1,77 @@ +""" +compilation utilities in tensorcircuit +""" + +import tensorcircuit as tc + + +c = tc.Circuit(3) +c.rx(0, theta=0.2) +c.rz(0, theta=-0.3) +c.ry(1, theta=0.1) +c.h(2) +c.cx(0, 1) +c.cz(2, 1) +c.x(0) +c.y(0) +c.rxx(1, 2, theta=1.7) + + +c0, _ = tc.compiler.qiskit_compiler.qiskit_compile( + c, + compiled_options={"optimization_level": 0, "basis_gates": ["cx", "cz", "h", "rz"]}, +) + +c1, _ = tc.compiler.qiskit_compiler.qiskit_compile( + c, + compiled_options={"optimization_level": 1, "basis_gates": ["cx", "cz", "h", "rz"]}, +) + + +c2, _ = tc.compiler.qiskit_compiler.qiskit_compile( + c, + compiled_options={"optimization_level": 2, "basis_gates": ["cx", "cz", "h", "rz"]}, +) + + +c3, _ = tc.compiler.qiskit_compiler.qiskit_compile( + c, + compiled_options={"optimization_level": 3, "basis_gates": ["cx", "cz", "h", "rz"]}, +) + +print( + "qiskit can become worse with higher level optimization when the target gate is not U3 but rz" +) +print("level 0:\n") +print(c0.draw()) +print("level 1:\n") +print(c1.draw()) +print("level 2:\n") +print(c2.draw()) +print("level 3:\n") +print(c3.draw()) + + +compiler_wo_mapping = tc.compiler.DefaultCompiler() +c4, _ = compiler_wo_mapping(c) +print( + "compiled with tc default compiler: combining the good from qiskit and our tc own" +) +# we always uuggest using DefaultCompiler for tasks on qcloud +# internally we run optimized compiling using U3 basis with qiskit which has good performance +# and we unroll u3 with rz and apply replace/prune/merge loop developed in tc to further optimize the circuit +print(c4.draw()) + +print("gate number comparison (last ours vs before qiskit (0, 1, 2, 3))") +for c in [c0, c1, c2, c3, c4]: + print(c.gate_count()) + +# if we want to apply routing/qubit mapping + +compiler_w_mapping = tc.compiler.DefaultCompiler( + {"coupling_map": [[0, 2], [2, 0], [1, 0], [0, 1]]} +) +c5, info = compiler_w_mapping(c) +print("circuit with qubit mapping") +print(c5.draw()) +print(info) diff --git a/examples/cotengra_setting_bench.py b/examples/cotengra_setting_bench.py new file mode 100644 index 00000000..d1b3f1b7 --- /dev/null +++ b/examples/cotengra_setting_bench.py @@ -0,0 +1,162 @@ +""" +Optimization for performance comparison with different cotengra settings. +""" + +import itertools +import sys +import warnings + +import cotengra as ctg +import networkx as nx +import numpy as np + +sys.path.insert(0, "../") +import tensorcircuit as tc + +try: + import kahypar +except ImportError: + print("kahypar not installed, please install it to run this script.") + exit() + + +# suppress the warning from cotengra +warnings.filterwarnings( + "ignore", + message="The inputs or output of this tree are not ordered." + "Costs will be accurate but actually contracting requires " + "ordered indices corresponding to array axes.", +) + +K = tc.set_backend("jax") + + +def generate_circuit(param, g, n, nlayers): + # construct the circuit ansatz + c = tc.Circuit(n) + for i in range(n): + c.H(i) + for j in range(nlayers): + c = tc.templates.blocks.QAOA_block(c, g, param[j, 0], param[j, 1]) + return c + + +def trigger_cotengra_optimization(n, nlayers, graph): + + # define the loss function + def loss_f(params, n, nlayers): + + c = generate_circuit(params, graph, n, nlayers) + + loss = c.expectation_ps(z=[0, 1, 2], reuse=False) + + return K.real(loss) + + params = K.implicit_randn(shape=[nlayers, 2]) + + # run only once to trigger the compilation + K.jit( + loss_f, + static_argnums=(1, 2), + )(params, n, nlayers) + + +# define the benchmark parameters +n = 12 +nlayers = 12 + +# define the cotengra optimizer parameters +graph_args = { + "1D lattice": nx.convert_node_labels_to_integers( + nx.grid_graph((n, 1)) + ), # 1D lattice + "2D lattice": nx.convert_node_labels_to_integers( + nx.grid_graph((n // 5, n // (n // 5))) + ), # 2D lattice + "all-to-all connected": nx.convert_node_labels_to_integers( + nx.complete_graph(n) + ), # all-to-all connected +} + +methods_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#drivers + "greedy", + "kahypar", + # "labels", + # "spinglass", # requires igraph + # "labelprop", # requires igraph + # "betweenness", # requires igraph + # "walktrap", # requires igraph + # "quickbb", # requires https://github.com/dechterlab/quickbb + # "flowcutter", # requires https://github.com/kit-algo/flow-cutter-pace17 +] + +optlib_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#optimization-library + "optuna", # pip install optuna + # "random", # default when no library is installed + # "baytune", # pip install baytune + # "nevergrad", # pip install nevergrad + # "chocolate", # pip install git+https://github.com/AIworx-Labs/chocolate@master + # "skopt", # pip install scikit-optimize +] + +post_processing_args = [ # https://cotengra.readthedocs.io/en/latest/advanced.html#slicing-and-subtree-reconfiguration + (None, None), + # ("slicing_opts", {"target_size": 2**28}), + # ("slicing_reconf_opts", {"target_size": 2**28}), + ("reconf_opts", {}), + ("simulated_annealing_opts", {}), +] + +minimize_args = [ # https://cotengra.readthedocs.io/en/main/advanced.html#objective + # "flops", # minimize the total number of scalar operations + # "size", # minimize the size of the largest intermediate tensor + # "write", # minimize the sum of sizes of all intermediate tensors + "combo", # minimize the sum of FLOPS + α * WRITE where α is 64 +] + + +def get_optimizer(method, optlib, post_processing, minimize): + if post_processing[0] is None: + return ctg.HyperOptimizer( + methods=method, + optlib=optlib, + minimize=minimize, + parallel=True, + max_time=60, + max_repeats=128, + progbar=True, + ) + else: + return ctg.HyperOptimizer( + methods=method, + optlib=optlib, + minimize=minimize, + parallel=True, + max_time=60, + max_repeats=128, + progbar=True, + **{post_processing[0]: post_processing[1]}, + ) + + +if __name__ == "__main__": + for graph, method, optlib, post_processing, minimize in itertools.product( + graph_args.keys(), + methods_args, + optlib_args, + post_processing_args, + minimize_args, + ): + print( + f"graph: {graph}, method: {method}, optlib: {optlib}, " + f"post_processing: {post_processing}, minimize: {minimize}" + ) + tc.set_contractor( + "custom", + optimizer=get_optimizer(method, optlib, post_processing, minimize), + contraction_info=True, + preprocessing=True, + debug_level=2, # no computation + ) + trigger_cotengra_optimization(n, nlayers, graph_args[graph]) + print("-------------------------") diff --git a/examples/hamiltonian_building.py b/examples/hamiltonian_building.py index e00c6a7e..80385265 100644 --- a/examples/hamiltonian_building.py +++ b/examples/hamiltonian_building.py @@ -3,36 +3,101 @@ """ import time + +import jax import numpy as np import quimb +import scipy +import tensorflow as tf + import tensorcircuit as tc +tc.set_dtype("complex128") nwires = 20 -# tc outperforms quimb in large nwires +print("--------------------") -# 1. tc approach for TFIM +# 1.1 tc approach for TFIM (numpy backend) + +tc.set_backend("numpy") +print("hamiltonian building with tc (numpy backend)") +print("numpy version: ", np.__version__) +print("scipy version: ", scipy.__version__) g = tc.templates.graphs.Line1D(nwires, pbc=False) -time0 = time.time() -h1 = tc.quantum.heisenberg_hamiltonian( +time0 = time.perf_counter() +h11 = tc.quantum.heisenberg_hamiltonian( g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True, numpy=True ) -time1 = time.time() +time1 = time.perf_counter() + +print("tc (numpy) time: ", time1 - time0) +print("--------------------") + +# 1.2 tc approach for TFIM (jax backend) + +tc.set_backend("jax") +print("hamiltonian building with tc (jax backend)") +print("jax version: ", jax.__version__) + +g = tc.templates.graphs.Line1D(nwires, pbc=False) +time0 = time.perf_counter() +h12 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (jax) time: ", time1 - time0) + +time0 = time.perf_counter() +h12 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (jax) time (after jit): ", time1 - time0) +print("--------------------") + +# 1.3 tc approach for TFIM (tensorflow backend) + +tc.set_backend("tensorflow") +print("hamiltonian building with tc (tensorflow backend)") +print("tensorflow version: ", tf.__version__) + +g = tc.templates.graphs.Line1D(nwires, pbc=False) +time0 = time.perf_counter() +h13 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (tensorflow) time: ", time1 - time0) + +time0 = time.perf_counter() +h13 = tc.quantum.heisenberg_hamiltonian( + g, hzz=1, hxx=0, hyy=0, hz=0, hx=-1, hy=0, sparse=True +) +time1 = time.perf_counter() + +print("tc (tensorflow) time (after jit): ", time1 - time0) + +print("--------------------") -print("tc time: ", time1 - time0) # 2. quimb approach for TFIM -builder = quimb.tensor.tensor_gen.SpinHam() +print("hamiltonian building with quimb") +print("quimb version: ", quimb.__version__) + +builder = quimb.tensor.SpinHam1D() # spin operator instead of Pauli matrix builder += 4, "Z", "Z" builder += -2, "X" -time0 = time.time() +time0 = time.perf_counter() h2 = builder.build_sparse(nwires) h2 = h2.tocoo() -time1 = time.time() +time1 = time.perf_counter() print("quimb time: ", time1 - time0) @@ -43,4 +108,25 @@ def assert_equal(h1, h2): np.testing.assert_allclose(h1.data, h2.data, atol=1e-5) -assert_equal(h1, h2) +# numpy +assert_equal(h11, h2) + +# jax +scipy_coo = scipy.sparse.coo_matrix( + ( + h12.data, + (h12.indices[:, 0], h12.indices[:, 1]), + ), + shape=h12.shape, +) +assert_equal(scipy_coo, h2) + +# tensorflow +scipy_coo = scipy.sparse.coo_matrix( + ( + h13.values, + (h13.indices[:, 0], h13.indices[:, 1]), + ), + shape=h13.shape, +) +assert_equal(scipy_coo, h2) diff --git a/examples/keras3_tc_integration.py b/examples/keras3_tc_integration.py new file mode 100644 index 00000000..ba45363c --- /dev/null +++ b/examples/keras3_tc_integration.py @@ -0,0 +1,95 @@ +""" +keras3 is excellent to use together with tc, we will have unique features including: +1. turn OO paradigm to functional paradigm, i.e. reuse keras layer function in functional programming +2. batch on neural network weights +""" + +import os + +os.environ["KERAS_BACKEND"] = "jax" +import keras_core as keras +import numpy as np +import optax +import tensorcircuit as tc + +K = tc.set_backend("jax") + +batch = 8 +n = 6 +layer = keras.layers.Dense(1, activation="sigmoid") +layer.build([batch, n]) + +data_x = np.random.choice([0, 1], size=batch * n).reshape([batch, n]) +# data_y = np.sum(data_x, axis=-1) % 2 +data_y = data_x[:, 0] +data_y = data_y.reshape([batch, 1]) +data_x = data_x.astype(np.float32) +data_y = data_y.astype(np.float32) + + +print("data", data_x, data_y) + + +def loss(xs, ys, params, weights): + c = tc.Circuit(n) + c.rx(range(n), theta=xs) + c.cx(range(n - 1), range(1, n)) + c.rz(range(n), theta=params) + outputs = K.stack([K.real(c.expectation_ps(z=[i])) for i in range(n)]) + ypred, _ = layer.stateless_call(weights, [], outputs) + return keras.losses.binary_crossentropy(ypred, ys), ypred + + +# common data batch practice +vgf = K.jit( + K.vectorized_value_and_grad( + loss, argnums=(2, 3), vectorized_argnums=(0, 1), has_aux=True + ) +) + +params = K.implicit_randn(shape=[n]) +w = K.implicit_randn(shape=[n, 1]) +b = K.implicit_randn(shape=[1]) +opt = K.optimizer(optax.adam(1e-2)) +# seems that currently keras3'optimizer doesn't support nested list of variables + +for i in range(100): + (v, yp), gs = vgf(data_x, data_y, params, [w, b]) + params, [w, b] = opt.update(gs, (params, [w, b])) + if i % 10 == 0: + print(K.mean(v)) + +m = keras.metrics.BinaryAccuracy() +m.update_state(data_y, yp[:, None]) +print("acc", m.result()) + + +# data batch with batched and quantum neural weights + +vgf2 = K.jit( + K.vmap( + K.vectorized_value_and_grad( + loss, argnums=(2, 3), vectorized_argnums=(0, 1), has_aux=True + ), + vectorized_argnums=(2, 3), + ) +) + +wbatch = 4 +params = K.implicit_randn(shape=[wbatch, n]) +w = K.implicit_randn(shape=[wbatch, n, 1]) +b = K.implicit_randn(shape=[wbatch, 1]) +opt = K.optimizer(optax.adam(1e-2)) +# seems that currently keras3'optimizer doesn't support nested list of variables + +for i in range(100): + (v, yp), gs = vgf2(data_x, data_y, params, [w, b]) + params, [w, b] = opt.update(gs, (params, [w, b])) + if i % 10 == 0: + print(K.mean(v, axis=-1)) + +for i in range(wbatch): + m = keras.metrics.BinaryAccuracy() + m.update_state(data_y, yp[0, :, None]) + print("acc", m.result()) + m.reset_state() diff --git a/examples/matprod_vmap.py b/examples/matprod_vmap.py new file mode 100644 index 00000000..bbf8f137 --- /dev/null +++ b/examples/matprod_vmap.py @@ -0,0 +1,42 @@ +""" +matrix product: a new twist +rewrite matrix product in a vmap style +""" + +from functools import partial + +import numpy as np +import tensorcircuit as tc + +for bk in ["jax", "tensorflow"]: + with tc.runtime_backend(bk) as K: + print("~~~~~~~~~~~~~~~~~~~~~") + print(f"using {K.name} backend") + + @partial(K.jit, jit_compile=True) + def mul(a, b): + return a @ b + + def ij(i, j): + """ + Inner product + """ + return K.tensordot(i, j, 1) + + vij = K.vmap(ij, vectorized_argnums=1) + vvij = K.vmap(vij, vectorized_argnums=0) + + @partial(K.jit, jit_compile=True) + def mul2(a, b): + b = K.transpose(b) + return vvij(a, b) + + for shape in [(256, 4096), (4096, 256), (2048, 2048)]: + print(shape) + a = K.implicit_randn(shape) + b = K.implicit_randn([shape[1], shape[0]]) + print("plain matprod") + r1, _, _ = tc.utils.benchmark(mul, a, b, tries=10) + print("vmap matprod") + r2, _, _ = tc.utils.benchmark(mul2, a, b, tries=10) + np.testing.assert_allclose(r1, r2, atol=1e-5) diff --git a/examples/mipt_pideal.py b/examples/mipt_pideal.py new file mode 100644 index 00000000..c419446b --- /dev/null +++ b/examples/mipt_pideal.py @@ -0,0 +1,112 @@ +""" +demo example of mipt in tc style, with ideal p for each history trajectory +p is also jittable now, change parameter p doesn't trigger recompiling +""" + +from functools import partial +import time +import numpy as np +from scipy import stats +import tensorcircuit as tc + +K = tc.set_backend("jax") +tc.set_dtype("complex128") +# tf backend is slow (at least on cpu) +tc.set_contractor("cotengra-16-64") + + +def delete2(pick, plist): + # pick = 0, 1 : return plist[pick]/(plist[0]+plist[1]) + # pick = 2: return 1 + indicator = (K.sign(1.5 - pick) + 1) / 2 # 0,1 : 1, 2: 0 + p = 0 + p += 1 - indicator + p += indicator / (plist[0] + plist[1]) * (plist[0] * (1 - pick) + plist[1] * pick) + return p + + +@partial(K.jit, static_argnums=(2, 3)) +def circuit_output(random_matrix, status, n, d, p): + """ + mipt circuit + + :param random_matrix: a float or complex tensor containing 4*4 random haar matrix wth size [d*n, 4, 4] + :type random_matrix: _type_ + :param status: a int tensor with element in 0 or 1 or 2 (no meausrement) with size d*n + :type status: _type_ + :param n: number of qubits + :type n: _type_ + :param d: number of depth + :type d: _type_ + :param p: measurement ratio + :type p: float + :return: output state + """ + random_matrix = K.reshape(random_matrix, [d, n, 4, 4]) + status = K.reshape(status, [d, n]) + inputs = None + bs_history = [] + prob_history = [] + for j in range(d): + if inputs is None: + c = tc.Circuit(n) + else: + c = tc.Circuit(n, inputs=inputs) + for i in range(0, n, 2): + c.unitary(i, (i + 1) % n, unitary=random_matrix[j, i]) + for i in range(1, n, 2): + c.unitary(i, (i + 1) % n, unitary=random_matrix[j, i]) + inputs = c.state() + c = tc.Circuit(n, inputs=inputs) + for i in range(n): + pick, plist = c.general_kraus( + [ + K.sqrt(p) * K.convert_to_tensor(np.array([[1.0, 0], [0, 0]])), + K.sqrt(p) * K.convert_to_tensor(np.array([[0, 0], [0, 1.0]])), + K.sqrt(1 - p) * K.eye(2), + ], + i, + status=status[j, i], + with_prob=True, + ) + bs_history.append(pick) + prob_history.append(delete2(pick, plist)) + inputs = c.state() + c = tc.Circuit(n, inputs=inputs) + inputs = c.state() + inputs /= K.norm(inputs) + bs_history = K.stack(bs_history) + prob_history = K.stack(prob_history) + return inputs, bs_history, prob_history, K.sum(K.log(prob_history + 1e-11)) + + +@partial(K.jit, static_argnums=(2, 3)) +def cals(random_matrix, status, n, d, p): + state, bs_history, prob_history, prob = circuit_output( + random_matrix, status, n, d, p + ) + rho = tc.quantum.reduced_density_matrix(state, cut=[i for i in range(n // 2)]) + return ( + tc.quantum.entropy(rho), + tc.quantum.renyi_entropy(rho, k=2), + bs_history, + prob_history, + prob, + ) + + +if __name__ == "__main__": + n = 12 + d = 12 + st = np.random.uniform(size=[d * n]) + ## assume all X gate instead + rm = [stats.unitary_group.rvs(4) for _ in range(d * n)] + rm = [r / np.linalg.det(r) for r in rm] + rm = np.stack(rm) + time0 = time.time() + print(cals(rm, st, n, d, 0.6)) + time1 = time.time() + st = np.random.uniform(size=[d * n]) + print(cals(rm, st, n, d, 0.1)) + time2 = time.time() + print(f"compiling time {time1-time0}, running time {time2-time1}") diff --git a/examples/rem_super_large_scale.py b/examples/rem_super_large_scale.py new file mode 100644 index 00000000..a10e7290 --- /dev/null +++ b/examples/rem_super_large_scale.py @@ -0,0 +1,54 @@ +""" +Demonstrate the failure of rem when qubit number is much larger than 1/p +""" + +from functools import partial +import numpy as np +import tensorcircuit as tc + + +def simulate_engine(p, ans): + fans = "" + for a in ans: + if p > np.random.uniform(): + if a == "0": + fans += "1" + else: + fans += "0" + else: + fans += a + return fans + + +def run(cs, shots, p=0.1): + # we assume only all 0 and all 1 results for simplicity + rds = [] + for c in cs: + if len(c.to_qir()) < 2: + ans = "0" * c._nqubits + else: + ans = "1" * c._nqubits + rd = {} + for _ in range(shots): + r = simulate_engine(p, ans) + rd[r] = rd.get(r, 0) + 1 + rds.append(rd) + return rds + + +if __name__ == "__main__": + for p in [0.1, 0.05, 0.02]: + print(p) + n = int(3 / p) + c = tc.Circuit(n) + c.x(range(n)) + runp = partial(run, p=p) + r = runp([c], 8192)[0] + mit = tc.results.rem.ReadoutMit(runp) + mit.cals_from_system(n) + for i in range(n): + print(i, "\n", mit.single_qubit_cals[i]) + rs = [] + for i in range(n): + rs.append([i, np.abs(mit.expectation(r, list(range(i))))]) + print(rs[i]) diff --git a/examples/shvqe.py b/examples/shvqe.py new file mode 100644 index 00000000..4083fa6d --- /dev/null +++ b/examples/shvqe.py @@ -0,0 +1,246 @@ +""" +Schrodinger-Heisenberg quantum variational eigensolver (SHVQE) with DQAS-style optimization. + +DQAS part is modified from: examples/clifford_optimization.py +""" + +import sys + +sys.path.insert(0, "../") + +import numpy as np +import tensorflow as tf + +import tensorcircuit as tc +from tensorcircuit.applications.vqes import construct_matrix_v3 + +ctype, rtype = tc.set_dtype("complex64") +K = tc.set_backend("tensorflow") + +n = 10 # the number of qubits (must be even for consistency later) +ncz = 2 # number of cz layers in Schrodinger circuit +nlayersq = ncz + 1 # Schrodinger parameter layers + +# training setup +epochs = 1000 +batch = 1000 + +# Hamiltonian +h6h = np.load("./h6_hamiltonian.npy") # reported in 0.99 A +hamiltonian = construct_matrix_v3(h6h.tolist()) + + +def hybrid_ansatz(structure, paramq, preprocess="direct", train=True): + """_summary_ + + Parameters + ---------- + structure : K.Tensor, (n//2, 2) + parameters to decide graph structure of Clifford circuits + paramq : K.Tensor, (nlayersq, n, 3) + parameters in quantum variational circuits, the last layer for Heisenberg circuits + preprocess : str, optional + preprocess, by default "direct" + + Returns + ------- + K.Tensor, [1,] + loss value + """ + c = tc.Circuit(n) + if preprocess == "softmax": + structure = K.softmax(structure, axis=-1) + elif preprocess == "most": + structure = K.onehot(K.argmax(structure, axis=-1), num=2) + elif preprocess == "direct": + pass + + structure = K.cast(structure, ctype) + structure = tf.reshape(structure, shape=[n // 2, 2]) + + # quantum variational in Schrodinger part, first consider a ring topol + for j in range(nlayersq): + if j != 0 and j != nlayersq - 1: + for i in range(j % 2, n, 2): + c.cz(i, (i + 1) % n) + for i in range(n): + c.rx(i, theta=paramq[j, i, 0]) + c.ry(i, theta=paramq[j, i, 1]) + c.rz(i, theta=paramq[j, i, 2]) + + # Clifford part, which is actually virtual + if train: + for j in range(0, n // 2 - 1): + dis = j + 1 + for i in range(0, n): + c.unitary( + i, + (i + dis) % n, + unitary=structure[j, 0] * tc.gates.ii().tensor + + structure[j, 1] * tc.gates.cz().tensor, + ) + + for i in range(0, n // 2): + c.unitary( + i, + i + n // 2, + unitary=structure[n // 2 - 1, 0] * tc.gates.ii().tensor + + structure[n // 2 - 1, 1] * tc.gates.cz().tensor, + ) + else: # if not for training, we just put nontrivial gates + for j in range(0, n // 2 - 1): + dis = j + 1 + for i in range(0, n): + if structure[j, 1] == 1: + c.cz(i, (i + dis) % n) + + for i in range(0, n // 2): + if structure[j, 1] == 1: + c.cz(i, i + n // 2) + + return c + + +def hybrid_vqe(structure, paramq, preprocess="direct"): + """_summary_ + + Parameters + ---------- + structure : K.Tensor, (n//2, 2) + parameters to decide graph structure of Clifford circuits + paramq : K.Tensor, (nlayersq, n, 3) + parameters in quantum variational circuits, the last layer for Heisenberg circuits + preprocess : str, optional + preprocess, by default "direct" + + Returns + ------- + K.Tensor, [1,] + loss value + """ + c = hybrid_ansatz(structure, paramq, preprocess) + return tc.templates.measurements.operator_expectation(c, hamiltonian) + + +def sampling_from_structure(structures, batch=1): + ch = structures.shape[-1] + prob = K.softmax(K.real(structures), axis=-1) + prob = K.reshape(prob, [-1, ch]) + p = prob.shape[0] + r = np.stack( + np.array( + [np.random.choice(ch, p=K.numpy(prob[i]), size=[batch]) for i in range(p)] + ) + ) + return r.transpose() + + +@K.jit +def best_from_structure(structures): + return K.argmax(structures, axis=-1) + + +def nmf_gradient(structures, oh): + """compute the Monte Carlo gradient with respect of naive mean-field probabilistic model + + Parameters + ---------- + structures : K.Tensor, (n//2, ch) + structure parameter for single- or two-qubit gates + oh : K.Tensor, (n//2, ch), onehot + a given structure sampled via strcuture parameters (in main function) + + Returns + ------- + K.Tensor, (n//2 * 2, ch) == (n, ch) + MC gradients + """ + choice = K.argmax(oh, axis=-1) + prob = K.softmax(K.real(structures), axis=-1) + indices = K.transpose( + K.stack([K.cast(tf.range(structures.shape[0]), "int64"), choice]) + ) + prob = tf.gather_nd(prob, indices) + prob = K.reshape(prob, [-1, 1]) + prob = K.tile(prob, [1, structures.shape[-1]]) + + return K.real( + tf.tensor_scatter_nd_add( + tf.cast(-prob, dtype=ctype), + indices, + tf.ones([structures.shape[0]], dtype=ctype), + ) + ) # in oh : 1-p, not in oh : -p + + +# vmap for a batch of structures +nmf_gradient_vmap = K.jit(K.vmap(nmf_gradient, vectorized_argnums=1)) + +# vvag for a batch of structures +vvag_hybrid = K.jit( + K.vectorized_value_and_grad(hybrid_vqe, vectorized_argnums=(0,), argnums=(1,)), + static_argnums=(2,), +) + + +def train_hybrid( + stddev=0.05, lr=None, epochs=2000, debug_step=50, batch=256, verbose=False +): + # params = K.implicit_randn([n//2, 2], stddev=stddev) + params = K.ones([n // 2, 2], dtype=float) + paramq = K.implicit_randn([nlayersq, n, 3], stddev=stddev) * 2 * np.pi + if lr is None: + lr = tf.keras.optimizers.schedules.ExponentialDecay(0.6, 100, 0.8) + structure_opt = K.optimizer(tf.keras.optimizers.Adam(lr)) + + avcost = 0 + avcost2 = 0 + loss_history = [] + for epoch in range(epochs): # iteration to update strcuture param + # random sample some structures + batched_stucture = K.onehot( + sampling_from_structure(params, batch=batch), + num=params.shape[-1], + ) + vs, gq = vvag_hybrid(batched_stucture, paramq, "direct") + loss_history.append(np.min(vs)) + gq = gq[0] + avcost = K.mean(vs) # average cost of the batch + gs = nmf_gradient_vmap(params, batched_stucture) # \nabla lnp + gs = K.mean(K.reshape(vs - avcost2, [-1, 1, 1]) * gs, axis=0) + # avcost2 is averaged cost in the last epoch + avcost2 = avcost + + [params, paramq] = structure_opt.update([gs, gq], [params, paramq]) + if epoch % debug_step == 0 or epoch == epochs - 1: + print("----------epoch %s-----------" % epoch) + print( + "batched average loss: ", + np.mean(vs), + "minimum candidate loss: ", + np.min(vs), + ) + + # max over choices, min over layers and qubits + minp = tf.math.reduce_min( + tf.math.reduce_max(tf.math.softmax(params), axis=-1) + ) + if minp > 0.5: + print("probability converged") + + if verbose: + print("strcuture parameter: \n", params.numpy()) + + cand_preset = best_from_structure(params) + print(cand_preset) + print("current recommendation loss: ", hybrid_vqe(params, paramq, "most")) + + loss_history = np.array(loss_history) + return hybrid_vqe(params, paramq, "most"), params, paramq, loss_history + + +print("Train hybrid.") +ee, params, paramq, loss_history = train_hybrid( + epochs=epochs, batch=batch, verbose=True +) +print("Energy:", ee) diff --git a/examples/stabilizer_simulation.py b/examples/stabilizer_simulation.py new file mode 100644 index 00000000..699983bf --- /dev/null +++ b/examples/stabilizer_simulation.py @@ -0,0 +1,151 @@ +import numpy as np +import stim + +import tensorcircuit as tc + +np.random.seed(0) + +tc.set_dtype("complex128") + +clifford_one_qubit_gates = ["H", "X", "Y", "Z", "S"] +clifford_two_qubit_gates = ["CNOT"] +clifford_gates = clifford_one_qubit_gates + clifford_two_qubit_gates + + +def genpair(num_qubits, count): + choice = list(range(num_qubits)) + for _ in range(count): + np.random.shuffle(choice) + x, y = choice[:2] + yield (x, y) + + +def random_clifford_circuit_with_mid_measurement(num_qubits, depth): + c = tc.Circuit(num_qubits) + operation_list = [] + for _ in range(depth): + for j, k in genpair(num_qubits, 2): + c.cnot(j, k) + operation_list.append(("CNOT", (j, k))) + for j in range(num_qubits): + gate_name = np.random.choice(clifford_one_qubit_gates) + getattr(c, gate_name)(j) + operation_list.append((gate_name, (j,))) + if np.random.uniform() < 0.2: + measured_qubit = np.random.randint(0, num_qubits - 1) + sample, p = c.measure_reference(measured_qubit, with_prob=True) + # Check if there is a non-zero probability to measure "0" for post-selection + if (sample == "0" and not np.isclose(p, 0.0)) or ( + sample == "1" and not np.isclose(p, 1.0) + ): + c.mid_measurement(measured_qubit, keep=0) + operation_list.append(("M", (measured_qubit,))) + return c, operation_list + + +def convert_operation_list_to_stim_circuit(operation_list): + stim_circuit = stim.Circuit() + for instruction in operation_list: + gate_name = instruction[0] + qubits = instruction[1] + stim_circuit.append(gate_name, qubits) + return stim_circuit + + +# ref: https://quantumcomputing.stackexchange.com/questions/16718/measuring-entanglement-entropy-using-a-stabilizer-circuit-simulator +def get_binary_matrix(z_stabilizers): + N = len(z_stabilizers) + binary_matrix = np.zeros((N, 2 * N)) + for row_idx, row in enumerate(z_stabilizers): + for col_idx, col in enumerate(row): + if col == 3: # Pauli Z + binary_matrix[row_idx, N + col_idx] = 1 + if col == 2: # Pauli Y + binary_matrix[row_idx, N + col_idx] = 1 + binary_matrix[row_idx, col_idx] = 1 + if col == 1: # Pauli X + binary_matrix[row_idx, col_idx] = 1 + return binary_matrix + + +def get_cut_binary_matrix(binary_matrix, cut): + N = len(binary_matrix) + new_indices = [i for i in range(N) if i in set(cut)] + [ + i + N for i in range(N) if i in set(cut) + ] + return binary_matrix[:, new_indices] + + +# ref: https://gist.github.com/StuartGordonReid/eb59113cb29e529b8105?permalink_comment_id=3268301#gistcomment-3268301 +def gf2_rank(matrix): + n = len(matrix[0]) + rank = 0 + for col in range(n): + j = 0 + rows = [] + while j < len(matrix): + if matrix[j][col] == 1: + rows += [j] + j += 1 + if len(rows) >= 1: + for c in range(1, len(rows)): + for k in range(n): + matrix[rows[c]][k] = (matrix[rows[c]][k] + matrix[rows[0]][k]) % 2 + matrix.pop(rows[0]) + rank += 1 + for row in matrix: + if sum(row) > 0: + rank += 1 + return rank + + +# ref: https://quantumcomputing.stackexchange.com/questions/27795/exact-probabilities-of-outcomes-for-clifford-circuits-with-mid-circuit-measureme +def simulate_stim_circuit_with_mid_measurement(stim_circuit): + simulator = stim.TableauSimulator() + + for instruction in stim_circuit.flattened(): + if instruction.name == "M": + for t in instruction.targets_copy(): + expectaction_value = simulator.peek_z(t.value) # 1, 0, -1 + # there is a non-zero probability to measure "0" if expectaction_value is not -1 + if expectaction_value != -1: + simulator.postselect_z(t.value, desired_value=0) + else: + simulator.do(instruction) + + return simulator.current_inverse_tableau() ** -1 + + +if __name__ == "__main__": + # Number of qubits + num_qubits = 12 + # Depth of the circuit + depth = 24 + # index list that is traced out to calculate the entanglement entropy + cut = [i for i in range(num_qubits // 3)] + + tc_circuit, op_list = random_clifford_circuit_with_mid_measurement( + num_qubits, depth + ) + print(tc_circuit.draw(output="text")) + + stim_circuit = convert_operation_list_to_stim_circuit(op_list) + + # Entanglement entropy calculation using stabilizer formalism + stabilizer_tableau = simulate_stim_circuit_with_mid_measurement(stim_circuit) + zs = [stabilizer_tableau.z_output(k) for k in range(len(stabilizer_tableau))] + binary_matrix = get_binary_matrix(zs) + cur_matrix = get_cut_binary_matrix(binary_matrix, cut) + stim_entropy = (gf2_rank(cur_matrix.tolist()) - len(cut)) * np.log(2) + print("Stim Entanglement Entropy:", stim_entropy) + + # Entanglement entropy calculation using TensorCircuit + state_vector = tc_circuit.wavefunction() + assert np.linalg.norm(state_vector) > 0 + # Normalize the state vector because mid-measurement operation is not unitary + state_vector /= np.linalg.norm(state_vector) + tc_entropy = tc.quantum.entanglement_entropy(state_vector, cut) + print("TensorCircuit Entanglement Entropy:", tc_entropy) + + # Check if the entanglement entropies are close + np.testing.assert_allclose(stim_entropy, tc_entropy, atol=1e-8) diff --git a/examples/training_deep_tunable_structures.py b/examples/training_deep_tunable_structures.py new file mode 100644 index 00000000..9f084870 --- /dev/null +++ b/examples/training_deep_tunable_structures.py @@ -0,0 +1,172 @@ +""" +An integrated script demonstrating: +1. shortcut setup of cotengra contractor (with correct interplay with multiprocessing); +2. jit scan acceleration for deep structured circuit with multiple variables; +3. tensor controlled tunable circuit structures all in one jit; +4. batched trainable parameters via vmap/vvag; +and yet anonther demonstration of infras for training with incremental random activation +""" + +import time +import numpy as np +import jax +import optax +import tensorcircuit as tc + + +def main(): + tc.set_contractor("cotengra-40-64") + K = tc.set_backend("jax") + tc.set_dtype("complex128") + + ii = tc.gates._ii_matrix + xx = tc.gates._xx_matrix + yy = tc.gates._yy_matrix + zz = tc.gates._zz_matrix + + n = 12 + nlayers = 7 + g = tc.templates.graphs.Line1D(n) + ncircuits = 10 + heih = tc.quantum.heisenberg_hamiltonian( + g, hzz=1.0, hyy=1.0, hxx=1.0, hx=0, hy=0, hz=0 + ) + + def energy(params, structures, n, nlayers): + def one_layer(state, others): + params, structures = others + # print(state.shape, params.shape, structures.shape) + l = 0 + c = tc.Circuit(n, inputs=state) + for i in range(1, n, 2): + matrix = structures[3 * l, i] * ii + (1.0 - structures[3 * l, i]) * ( + K.cos(params[3 * l, i]) * ii + 1.0j * K.sin(params[3 * l, i]) * zz + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + + ### YY + for i in range(1, n, 2): + matrix = structures[3 * l + 1, i] * ii + ( + 1.0 - structures[3 * l + 1, i] + ) * ( + K.cos(params[3 * l + 1, i]) * ii + + 1.0j * K.sin(params[3 * l + 1, i]) * yy + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + + ### XX + for i in range(1, n, 2): + matrix = structures[3 * l + 2, i] * ii + ( + 1.0 - structures[3 * l + 2, i] + ) * ( + K.cos(params[3 * l + 2, i]) * ii + + 1.0j * K.sin(params[3 * l + 2, i]) * xx + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + + ### Even layer + ### ZZ + for i in range(0, n, 2): + matrix = structures[3 * l, i] * ii + (1.0 - structures[3 * l, i]) * ( + K.cos(params[3 * l, i]) * ii + 1.0j * K.sin(params[3 * l, i]) * zz + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + ### YY + + for i in range(0, n, 2): + matrix = structures[3 * l + 1, i] * ii + ( + 1.0 - structures[3 * l + 1, i] + ) * ( + K.cos(params[3 * l + 1, i]) * ii + + 1.0j * K.sin(params[3 * l + 1, i]) * yy + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + + ### XX + for i in range(0, n, 2): + matrix = structures[3 * l + 2, i] * ii + ( + 1.0 - structures[3 * l + 2, i] + ) * ( + K.cos(params[3 * l + 2, i]) * ii + + 1.0j * K.sin(params[3 * l + 2, i]) * xx + ) + c.any( + i, + (i + 1) % n, + unitary=matrix, + ) + s = c.state() + return s, s + + params = K.cast(K.real(params), dtype="complex128") + structures = (K.sign(structures) + 1) / 2 # 0 or 1 + structures = K.cast(structures, dtype="complex128") + + c = tc.Circuit(n) + + for i in range(n): + c.x(i) + for i in range(0, n, 2): + c.H(i) + for i in range(0, n, 2): + c.cnot(i, i + 1) + s = c.state() + s, _ = jax.lax.scan( + one_layer, + s, + ( + K.reshape(params, [nlayers, 3, n]), + K.reshape(structures, [nlayers, 3, n]), + ), + ) + c = tc.Circuit(n, inputs=s) + # e = tc.templates.measurements.heisenberg_measurements( + # c, g, hzz=1, hxx=1, hyy=1, hx=0, hy=0, hz=0 + # ) + e = tc.templates.measurements.operator_expectation(c, heih) + return K.real(e) + + vagf = K.jit(K.vvag(energy, argnums=0, vectorized_argnums=0), static_argnums=(2, 3)) + + structures = tc.array_to_tensor( + np.random.uniform(low=0.0, high=1.0, size=[3 * nlayers, n]), dtype="complex128" + ) + structures -= 1.0 * K.ones([3 * nlayers, n]) + params = tc.array_to_tensor( + np.random.uniform(low=-0.1, high=0.1, size=[ncircuits, 3 * nlayers, n]), + dtype="float64", + ) + + # opt = K.optimizer(tf.keras.optimizers.Adam(1e-2)) + opt = K.optimizer(optax.adam(1e-2)) + + for _ in range(50): + time0 = time.time() + e, grads = vagf(params, structures, n, nlayers) + time1 = time.time() + params = opt.update(grads, params) + print(K.numpy(e), time1 - time0) + + +if __name__ == "__main__": + main() diff --git a/examples/variational_dynamics.py b/examples/variational_dynamics.py index a6e8fc88..39015fbd 100644 --- a/examples/variational_dynamics.py +++ b/examples/variational_dynamics.py @@ -46,6 +46,8 @@ def lhs_matrix(theta, psi0): vij = tc.backend.vmap(ij, vectorized_argnums=0) vvij = tc.backend.vmap(vij, vectorized_argnums=1) jacobian = ppsioverptheta(theta, psi0=psi0) + # fim = tc.backend.adjoint(jacobian)@jacobian is also ok + # speed comparison? jacobian = tc.backend.transpose(jacobian) fim = vvij(jacobian, jacobian) fim = tc.backend.real(fim) @@ -62,12 +64,16 @@ def energy(theta, psi0): wl = tc.backend.reshape(wl, [1, -1]) wr = tc.backend.reshape(wr, [-1, 1]) e = wl @ h @ wr + # use sparse matrix if required return tc.backend.real(e)[0, 0] eg = tc.backend.grad(energy, argnums=0) rhs = eg(theta, psi0) rhs = tc.backend.imag(rhs) return rhs + # for ITE, imag is replace with real + # a simpler way to get rhs in ITE case is to directly evaluate + # 0.5*\nabla @tc.backend.jit diff --git a/examples/vqe_noisyopt.py b/examples/vqe_noisyopt.py new file mode 100644 index 00000000..8bd18948 --- /dev/null +++ b/examples/vqe_noisyopt.py @@ -0,0 +1,222 @@ +""" +VQE with finite measurement shot noise +""" + +from functools import partial +import numpy as np +import optax +from noisyopt import minimizeCompass, minimizeSPSA +from tabulate import tabulate # pip install tabulate +import tensorcircuit as tc +from tensorcircuit import experimental as E + +seed = 42 +np.random.seed(seed) + +K = tc.set_backend("jax") +# note this script only supports jax backend + +n = 6 +nlayers = 4 + +# initial value of the parameters +initial_value = np.random.uniform(size=[n * nlayers * 2]) + +result = { + "Algorithm / Optimization": ["Without Shot Noise", "With Shot Noise"], + "SPSA (Gradient Free)": [], + "Compass Search (Gradient Free)": [], + "Adam (Gradient based)": [], +} + +# We use OBC 1D TFIM Hamiltonian in this script + +ps = [] +for i in range(n): + l = [0 for _ in range(n)] + l[i] = 1 + ps.append(l) + # X_i +for i in range(n - 1): + l = [0 for _ in range(n)] + l[i] = 3 + l[i + 1] = 3 + ps.append(l) + # Z_i Z_i+1 +w = [-1.0 for _ in range(n)] + [1.0 for _ in range(n - 1)] + + +def generate_circuit(param): + # construct the circuit ansatz + c = tc.Circuit(n) + for i in range(n): + c.H(i) + for j in range(nlayers): + for i in range(n - 1): + c.rzz(i, i + 1, theta=param[i, j, 0]) + for i in range(n): + c.rx(i, theta=param[i, j, 1]) + return c + + +def ps2xyz(psi): + # ps2xyz([1, 2, 2, 0]) = {"x": [0], "y": [1, 2], "z": []} + xyz = {"x": [], "y": [], "z": []} + for i, j in enumerate(psi): + if j == 1: + xyz["x"].append(i) + if j == 2: + xyz["y"].append(i) + if j == 3: + xyz["z"].append(i) + return xyz + + +@partial(K.jit, static_argnums=(2)) +def exp_val(param, key, shots=1024): + # expectation with shot noise + # ps, w: H = \sum_i w_i ps_i + # describing the system Hamiltonian as a weighted sum of Pauli string + c = generate_circuit(param) + if isinstance(shots, int): + shots = [shots for _ in range(len(ps))] + loss = 0 + for psi, wi, shot in zip(ps, w, shots): + key, subkey = K.random_split(key) + xyz = ps2xyz(psi) + loss += wi * c.sample_expectation_ps(**xyz, shots=shot, random_generator=subkey) + return K.real(loss) + + +@K.jit +def exp_val_analytical(param): + param = param.reshape(n, nlayers, 2) + c = generate_circuit(param) + loss = 0 + for psi, wi in zip(ps, w): + xyz = ps2xyz(psi) + loss += wi * c.expectation_ps(**xyz) + return K.real(loss) + + +# 0. Exact result + +hm = tc.quantum.PauliStringSum2COO(ps, w, numpy=True) +hm = K.to_dense(hm) +e, v = np.linalg.eigh(hm) +exact_gs_energy = e[0] +print("==================================================================") +print("Exact ground state energy: ", exact_gs_energy) +print("==================================================================") + +# 1.1 VQE with numerically exact expectation: gradient free + +print(">>> VQE without shot noise") + + +r = minimizeSPSA( + func=exp_val_analytical, + x0=initial_value, + niter=6000, + paired=False, +) + +print(r) +print(">> SPSA converged as:", exp_val_analytical(r.x)) +result["SPSA (Gradient Free)"].append(exp_val_analytical(r.x)) + +r = minimizeCompass( + func=exp_val_analytical, + x0=initial_value, + deltatol=0.1, + feps=1e-3, + paired=False, +) + +print(r) +print(">> Compass converged as:", exp_val_analytical(r.x)) +result["Compass Search (Gradient Free)"].append(exp_val_analytical(r.x)) + +# 1.2 VQE with numerically exact expectation: gradient based + +exponential_decay_scheduler = optax.exponential_decay( + init_value=1e-2, transition_steps=500, decay_rate=0.9 +) +opt = K.optimizer(optax.adam(exponential_decay_scheduler)) +param = initial_value.reshape((n, nlayers, 2)) # zeros stall the gradient +exp_val_grad_analytical = K.jit(K.value_and_grad(exp_val_analytical)) +for i in range(1000): + e, g = exp_val_grad_analytical(param) + param = opt.update(g, param) + if i % 100 == 99: + print(f"Expectation value at iteration {i}: {e}") + +print(">> Adam converged as:", exp_val_grad_analytical(param)[0]) +result["Adam (Gradient based)"].append(exp_val_grad_analytical(param)[0]) + +# 2.1 VQE with finite shot noise: gradient free + +print("==================================================================") +print(">>> VQE with shot noise") + + +rkey = K.get_random_state(seed) + + +def exp_val_wrapper(param): + param = param.reshape(n, nlayers, 2) + global rkey + rkey, skey = K.random_split(rkey) + # maintain stateless randomness in scipy optimize interface + return exp_val(param, skey, shots=1024) + + +r = minimizeSPSA( + func=exp_val_wrapper, + x0=initial_value, + niter=6000, + paired=False, +) +print(r) +print(">> SPSA converged as:", exp_val_wrapper(r["x"])) +result["SPSA (Gradient Free)"].append(exp_val_wrapper(r["x"])) + +r = minimizeCompass( + func=exp_val_wrapper, + x0=initial_value, + deltatol=0.1, + feps=1e-2, + paired=False, +) + +print(r) +print(">> Compass converged as:", exp_val_wrapper(r["x"])) +result["Compass Search (Gradient Free)"].append(exp_val_wrapper(r["x"])) + + +# 2.2 VQE with finite shot noise: gradient based + +exponential_decay_scheduler = optax.exponential_decay( + init_value=1e-2, transition_steps=500, decay_rate=0.9 +) +opt = K.optimizer(optax.adam(exponential_decay_scheduler)) +param = initial_value.reshape((n, nlayers, 2)) # zeros stall the gradient +exp_grad = E.parameter_shift_grad_v2(exp_val, argnums=0, random_argnums=1) +rkey = K.get_random_state(seed) + +for i in range(1000): + rkey, skey = K.random_split(rkey) + g = exp_grad(param, skey) + param = opt.update(g, param) + if i % 100 == 99: + rkey, skey = K.random_split(rkey) + print(f"Expectation value at iteration {i}: {exp_val(param, skey)}") + +# the real energy position after optimization +print(">> Adam converged as:", exp_val_analytical(param)) +result["Adam (Gradient based)"].append(exp_val_analytical(param)) + +print("==================================================================") +print(">>> Benchmark") +print(">> Exact ground state energy: ", exact_gs_energy) +print(tabulate(result, headers="keys", tablefmt="github")) diff --git a/examples/vqe_parallel_pmap.py b/examples/vqe_parallel_pmap.py new file mode 100644 index 00000000..54ea6922 --- /dev/null +++ b/examples/vqe_parallel_pmap.py @@ -0,0 +1,68 @@ +""" +jax pmap paradigm for vqe on multiple gpus +""" + +import os + +os.environ["XLA_FLAGS"] = "--xla_force_host_platform_device_count=8" +from functools import partial +import jax +import optax +import tensorcircuit as tc + +K = tc.set_backend("jax") +tc.set_contractor("cotengra") + + +def vqef(param, measure, n, nlayers): + c = tc.Circuit(n) + c.h(range(n)) + for i in range(nlayers): + c.rzz(range(n - 1), range(1, n), theta=param[i, 0]) + c.rx(range(n), theta=param[i, 1]) + return K.real( + tc.templates.measurements.parameterized_measurements(c, measure, onehot=True) + ) + + +def get_tfim_ps(n): + tfim_ps = [] + for i in range(n): + tfim_ps.append(tc.quantum.xyz2ps({"x": [i]}, n=n)) + for i in range(n): + tfim_ps.append(tc.quantum.xyz2ps({"z": [i, (i + 1) % n]}, n=n)) + return K.convert_to_tensor(tfim_ps) + + +vqg_vgf = jax.vmap(K.value_and_grad(vqef), in_axes=(None, 0, None, None)) + + +@partial( + jax.pmap, + axis_name="pmap", + in_axes=(0, 0, None, None), + static_broadcasted_argnums=(2, 3), +) +def update(param, measure, n, nlayers): + # Compute the gradients on the given minibatch (individually on each device). + loss, grads = vqg_vgf(param, measure, n, nlayers) + grads = K.sum(grads, axis=0) + grads = jax.lax.psum(grads, axis_name="pmap") + loss = K.sum(loss, axis=0) + loss = jax.lax.psum(loss, axis_name="pmap") + param = opt.update(grads, param) + return param, loss + + +if __name__ == "__main__": + n = 8 + nlayers = 4 + ndevices = 8 + m = get_tfim_ps(n) + m = K.reshape(m, [ndevices, m.shape[0] // ndevices] + list(m.shape[1:])) + param = K.stateful_randn(jax.random.PRNGKey(43), shape=[nlayers, 2, n], stddev=0.1) + param = K.stack([param] * ndevices) + opt = K.optimizer(optax.adam(1e-2)) + for _ in range(100): + param, loss = update(param, m, n, nlayers) + print(loss[0]) diff --git a/experiments/README.md b/experiments/README.md new file mode 100644 index 00000000..c22ec332 --- /dev/null +++ b/experiments/README.md @@ -0,0 +1,127 @@ +# 在 Tensorcircuit 中使用参数化波形完成 Rabi 实验 + +## 下载安装 +``` +git clone https://github.com/tencent-quantum-lab/tensorcircuit.git +cd tensorcircuit +cd experiments +pip install -r requirements.txt +``` + +## 代码实现 + +在 rabi.py 文件中修改代码 +``` +vim rabi.py +``` + +#### 1. 配置量子云服务 + +```python +set_token("your_api_token") # 需替换为真实的量子云服务令牌 +``` + +#### 2. 自定义参数化波形 + + +```python +def gen_parametric_waveform_circuit(t): + """ + 参数: + t : 脉冲持续时间(dt) + + 返回: + Circuit: 包含自定义波形的量子电路 + """ + qc = Circuit(1) + + param0 = Param("a") + + builder = qc.calibrate("rabi_test", [param0]) + builder.new_frame("drive_frame", param0) + builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + qc.add_calibration('rabi_test', ['q[0]']) + + tqasm_code = qc.to_tqasm() + + print(tqasm_code) + return qc +``` + + +#### 3. 在量子设备中执行电路 + +通过以下输出获取可用的设备名称 +```python +ds = list_devices() +``` + +在其中一台设备上执行电路 +```python +def run_circuit(qc): + """ + 参数: + qc (Circuit): 待执行量子电路 + + 返回: + rf(Dict): 测量结果统计 + """ + device_name = "tianji_m2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + return rf +``` + +#### 4. Rabi 参数扫描 + +定义扫描周期,遍历不同的脉冲长度 +```python +def exp_rabi(): + result_lst = [] + for t in range(1, 400, 2): + qc = gen_parametric_waveform_circuit(t) + result = run_circuit(qc) + result['duration'] = t + result_lst.append(result) + return result_lst +``` + +#### 5. 绘制 Rabi 结果图 + +绘制 0/1 态的结果分布 +```python +def draw_rabi(result_lst): + data = { + 'duration': [], + '0': [], + '1': [] + } + + for result in result_lst: + data['0'].append(int(result['0']) / shots_const) + data['1'].append(int(result['1']) / shots_const) + data['duration'].append(result['duration']) + + plt.figure(figsize=(10,6)) + plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') + plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + plt.title('Rabi Oscillation Experiment') + plt.xlabel('Duration (dt)') + plt.ylabel('Probability') + plt.grid(alpha=0.3) + plt.legend() + plt.tight_layout() + + plt.savefig('rabi.png', dpi=300) + plt.show() +``` diff --git a/experiments/draw_rabi.py b/experiments/draw_rabi.py new file mode 100644 index 00000000..0c135b75 --- /dev/null +++ b/experiments/draw_rabi.py @@ -0,0 +1,35 @@ + +import csv +import matplotlib.pyplot as plt + +data = { + 'duration': [], + '0': [], + '1': [] +} +total_shots = 1000 + + +with open('rabi_data.csv') as f: + reader = csv.DictReader(f) + for row in reader: + data['duration'].append(float(row['duration'])) + data['0'].append(int(row['count0'])/total_shots) + data['1'].append(int(row['count1'])/total_shots) + + +plt.figure(figsize=(10,6)) +plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') +plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + +plt.title('Rabi Oscillation Experiment') +plt.xlabel('Duration (dt)') +plt.ylabel('Probability') +plt.grid(alpha=0.3) +plt.legend() +plt.tight_layout() + + +plt.savefig('rabi.png', dpi=300) +plt.show() \ No newline at end of file diff --git a/experiments/rabi.ipynb b/experiments/rabi.ipynb new file mode 100644 index 00000000..820735a4 --- /dev/null +++ b/experiments/rabi.ipynb @@ -0,0 +1,1220 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import os\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Add the directory containing your module to Python's search path\n", + "module_path = \"..\"\n", + "sys.path.insert(0, module_path)\n", + "\n", + "from tensorcircuit import Circuit, Param, gates, waveforms\n", + "from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices\n", + "import re" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ TEST FILE LOADED\n", + "[tencent::tianji_m2, tencent::tianji_m1v15s4, tencent::tianji_m1v15s2, tencent::tianxuan_s2v20s2, tencent::tianji_m2v16s1, tencent::simulator:tc, tencent::tianji_m2v15s3, tencent::tianxuan_s2, tencent::tianji_s2, tencent::tianji_m2v14s4, tencent::tianxuan_s2v20s1, tencent::tianji_m1v15s1, tencent::tianji_s2v6, tencent::tianji_m1v15s3, tencent::tianji_m2v14s2, tencent::tianji_m1, tencent::tianxuan_s1, tencent::tianji_s2v7]\n" + ] + } + ], + "source": [ + "shots_const = 1000\n", + "\n", + "print(\"✅ TEST FILE LOADED\")\n", + "set_token(\"xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=\")\n", + "set_provider(\"tencent\")\n", + "ds = list_devices()\n", + "print(ds)\n", + "\n", + "# TQASM 0.2;\n", + "# QREG a[1];\n", + "# defcal rabi_test a {\n", + "# frame drive_frame = newframe(a); \n", + "# play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); } \n", + "# rabi_test a[0];\n", + "# MEASZ a[0];" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_parametric_waveform_circuit(t):\n", + " qc = Circuit(1)\n", + "\n", + " param0 = Param(\"a\")\n", + "\n", + " builder = qc.calibrate(\"rabi_test\", [param0])\n", + " builder.new_frame(\"drive_frame\", param0)\n", + " builder.play(\"drive_frame\", waveforms.CosineDrag(t, 0.2, 0.0, 0.01))\n", + "\n", + " builder.build()\n", + " \n", + " tqasm_code = qc.to_tqasm()\n", + "\n", + " # print(tqasm_code)\n", + " return qc\n", + "\n", + "\n", + "def run_circuit(qc):\n", + " device_name = \"tianji_m2\" \n", + " d = get_device(device_name)\n", + " t = submit_task(\n", + " circuit=qc,\n", + " shots=shots_const,\n", + " device=d,\n", + " enable_qos_gate_decomposition=False,\n", + " enable_qos_qubit_mapping=False,\n", + " )\n", + " rs = t.results()\n", + " return rs\n", + "\n", + "\n", + "\n", + "def exp_rabi():\n", + " result_lst = []\n", + " for t in range(1, 400, 2):\n", + " qc = gen_parametric_waveform_circuit(t)\n", + " result = run_circuit(qc)\n", + " result['duration'] = t\n", + " result_lst.append(result)\n", + " return result_lst\n", + "\n", + "\n", + "\n", + "def draw_rabi(result_lst):\n", + " data = {\n", + " 'duration': [],\n", + " '0': [],\n", + " '1': []\n", + " }\n", + " \n", + " for result in result_lst:\n", + " data['0'].append(int(result['0']) / shots_const)\n", + " data['1'].append(int(result['1']) / shots_const)\n", + " data['duration'].append(result['duration'])\n", + "\n", + "\n", + " \n", + "\n", + " plt.figure(figsize=(10,6))\n", + " plt.plot(data['duration'], data['0'], 'b-o', label='State |0>')\n", + " plt.plot(data['duration'], data['1'], 'r--s', label='State |1>')\n", + "\n", + "\n", + " plt.title('Rabi Oscillation Experiment')\n", + " plt.xlabel('Duration (dt)')\n", + " plt.ylabel('Probability')\n", + " plt.grid(alpha=0.3)\n", + " plt.legend()\n", + " plt.tight_layout()\n", + "\n", + "\n", + " plt.savefig('rabi.png', dpi=300)\n", + " plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(1, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(3, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(5, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(7, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(9, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(11, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(13, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(15, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(17, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(19, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(21, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(23, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(25, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(27, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(29, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(31, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(33, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(35, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(37, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(39, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(41, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(43, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(45, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(47, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(49, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(51, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(53, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(55, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(57, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(59, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(61, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(63, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(65, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(67, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(69, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(71, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(73, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(75, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(77, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(79, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(81, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(83, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(85, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(87, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(89, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(91, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(93, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(95, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(97, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(99, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(101, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(103, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(105, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(107, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(109, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(111, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(113, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(115, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(117, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(119, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(121, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(123, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(125, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(127, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(129, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(131, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(133, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(135, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(137, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(139, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(141, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(143, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(145, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(147, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(149, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(151, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(153, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(155, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(157, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(159, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(161, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(163, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(165, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(167, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(169, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(171, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(173, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(175, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(177, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(179, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(181, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(183, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(185, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(187, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(189, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(191, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(193, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(195, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(197, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(199, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(201, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(203, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(205, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(207, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(209, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(211, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(213, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(215, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(217, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(219, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(221, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(223, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(225, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(227, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(229, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(231, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(233, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(235, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(237, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(239, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(241, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(243, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n", + "TQASM 0.2;\n", + "QREG q[1];\n", + "\n", + "defcal rabi_test a {\n", + " frame drive_frame = newframe(a);\n", + " play(drive_frame, cosine_drag(245, 0.2, 0.0, 0.01));\n", + "}\n", + "rabi_test q[0];\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Fails at fetching url: http://111.230.11.154/cloud/quk/task/detail. Try again.\n" + ] + }, + { + "ename": "ValueError", + "evalue": "{\"code\": 0, \"status\": \"502 Bad Gateway\", \"desc\": \"\\u672a\\u77e5\\u9519\\u8bef\", \"Contents\": [\"\\u672a\\u77e5\\u5f02\\u5e38\", \"\\u5982\\u9700\\u5e2e\\u52a9\\u8bf7\\u7acb\\u5373\\u81f4\\u75358000\\u70ed\\u7ebf\\u6216\\u4f01\\u4e1a\\u5fae\\u4fe1 8000\\u52a9\\u624b\\uff08IT\\u4e1a\\u52a1\\uff09 \\uff0c7x24\\u5c0f\\u65f6\\u4e3a\\u60a8\\u670d\\u52a1\"], \"version\": \"3.0.30.217\"}", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/tencent.py:361\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(task, device, token, prettify)\u001b[0m\n\u001b[1;32m 360\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 361\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresult\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m \u001b[43mr\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtask\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m:\n\u001b[1;32m 362\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcounts\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m r[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtask\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresult\u001b[39m\u001b[38;5;124m\"\u001b[39m]:\n", + "\u001b[0;31mKeyError\u001b[0m: 'task'", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[21], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[43mexp_rabi\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m draw_rabi(data)\n", + "Cell \u001b[0;32mIn[20], line 37\u001b[0m, in \u001b[0;36mexp_rabi\u001b[0;34m()\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m400\u001b[39m, \u001b[38;5;241m2\u001b[39m):\n\u001b[1;32m 36\u001b[0m qc \u001b[38;5;241m=\u001b[39m gen_parametric_waveform_circuit(t)\n\u001b[0;32m---> 37\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mrun_circuit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mqc\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 38\u001b[0m result[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mduration\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m t\n\u001b[1;32m 39\u001b[0m result_lst\u001b[38;5;241m.\u001b[39mappend(result)\n", + "Cell \u001b[0;32mIn[20], line 28\u001b[0m, in \u001b[0;36mrun_circuit\u001b[0;34m(qc)\u001b[0m\n\u001b[1;32m 20\u001b[0m d \u001b[38;5;241m=\u001b[39m get_device(device_name)\n\u001b[1;32m 21\u001b[0m t \u001b[38;5;241m=\u001b[39m submit_task(\n\u001b[1;32m 22\u001b[0m circuit\u001b[38;5;241m=\u001b[39mqc,\n\u001b[1;32m 23\u001b[0m shots\u001b[38;5;241m=\u001b[39mshots_const,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 26\u001b[0m enable_qos_qubit_mapping\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 27\u001b[0m )\n\u001b[0;32m---> 28\u001b[0m rs \u001b[38;5;241m=\u001b[39m \u001b[43mt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresults\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m rs\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:431\u001b[0m, in \u001b[0;36mTask.results\u001b[0;34m(self, format, blocked, mitigated, calibriation_options, readout_mit, mitigation_options)\u001b[0m\n\u001b[1;32m 429\u001b[0m tries \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 430\u001b[0m s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate()\n\u001b[0;32m--> 431\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresults\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mblocked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmitigated\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 432\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mitigated \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 433\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:419\u001b[0m, in \u001b[0;36mTask.results\u001b[0;34m(self, format, blocked, mitigated, calibriation_options, readout_mit, mitigation_options)\u001b[0m\n\u001b[1;32m 417\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcompleted\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m TaskUnfinished(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mid_, s)\n\u001b[0;32m--> 419\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdetails\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresults\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 420\u001b[0m r \u001b[38;5;241m=\u001b[39m counts\u001b[38;5;241m.\u001b[39msort_count(r) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 421\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/utils.py:155\u001b[0m, in \u001b[0;36marg_alias..wrapper\u001b[0;34m(*args, **kws)\u001b[0m\n\u001b[1;32m 153\u001b[0m kws[k] \u001b[38;5;241m=\u001b[39m kws[v]\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m kws[v]\n\u001b[0;32m--> 155\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkws\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/abstraction.py:336\u001b[0m, in \u001b[0;36mTask.details\u001b[0;34m(self, blocked, **kws)\u001b[0m\n\u001b[1;32m 333\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapis\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_task_details\n\u001b[1;32m 335\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m blocked \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[0;32m--> 336\u001b[0m dt \u001b[38;5;241m=\u001b[39m \u001b[43mget_task_details\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkws\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 337\u001b[0m dt\u001b[38;5;241m.\u001b[39mupdate(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmore_details)\n\u001b[1;32m 338\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m dt\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/apis.py:402\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(taskid, token, prettify)\u001b[0m\n\u001b[1;32m 399\u001b[0m provider \u001b[38;5;241m=\u001b[39m device\u001b[38;5;241m.\u001b[39mprovider\n\u001b[1;32m 401\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m provider\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtencent\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m--> 402\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtencent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_task_details\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtask\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprettify\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 403\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m provider\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mlocal\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 404\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m local\u001b[38;5;241m.\u001b[39mget_task_details(task, device, token, prettify) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n", + "File \u001b[0;32m~/tensorcircuit/experiments/../tensorcircuit/cloud/tencent.py:398\u001b[0m, in \u001b[0;36mget_task_details\u001b[0;34m(task, device, token, prettify)\u001b[0m\n\u001b[1;32m 396\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 397\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[0;32m--> 398\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(dumps(r))\n\u001b[1;32m 400\u001b[0m \u001b[38;5;66;03m# make the return at least contain the following terms across different providers\u001b[39;00m\n\u001b[1;32m 401\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;124;03m'id': 'd947cd76-a961-4c22-b295-76287c9fdaa3',\u001b[39;00m\n\u001b[1;32m 403\u001b[0m \u001b[38;5;124;03m'state': 'completed',\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[38;5;124;03m'111': 131}\u001b[39;00m\n\u001b[1;32m 416\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n", + "\u001b[0;31mValueError\u001b[0m: {\"code\": 0, \"status\": \"502 Bad Gateway\", \"desc\": \"\\u672a\\u77e5\\u9519\\u8bef\", \"Contents\": [\"\\u672a\\u77e5\\u5f02\\u5e38\", \"\\u5982\\u9700\\u5e2e\\u52a9\\u8bf7\\u7acb\\u5373\\u81f4\\u75358000\\u70ed\\u7ebf\\u6216\\u4f01\\u4e1a\\u5fae\\u4fe1 8000\\u52a9\\u624b\\uff08IT\\u4e1a\\u52a1\\uff09 \\uff0c7x24\\u5c0f\\u65f6\\u4e3a\\u60a8\\u670d\\u52a1\"], \"version\": \"3.0.30.217\"}" + ] + } + ], + "source": [ + "\n", + "data = exp_rabi()\n", + "draw_rabi(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJOCAYAAABBfN/cAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAADiyElEQVR4nOzdd3gU5doG8Ht2IQkdQhIIJCH0IjVBkBIpgqCIaEBURMGjWBECRz3iJ9XCsaABCx49BxBRj4p7EBUbCBK7ghSlQyAYQiiht5Dd+f54mWR3s2U22d2Znbl/17XXbGZnkxcmm5nnLc8jybIsg4iIiIiIiIhCwqJ1A4iIiIiIiIiMjIE3ERERERERUQgx8CYiIiIiIiIKIQbeRERERERERCHEwJuIiIiIiIgohBh4ExEREREREYUQA28iIiIiIiKiEGLgTURERERERBRCDLyJiIiIiIiIQoiBNxERRYS9e/dCkiS88MILfo+dMWMGJEkKQ6sqrm/fvujbt2/p18q/b9GiRaX7QvHvWLNmDSRJwpo1a4L6fc0gNTUVY8eO1boZREQUgRh4ExFR0C1atAiSJJU+qlSpgsaNG2Ps2LHIz8/XunnlfPrppxg8eDDq16+PmJgYtGrVCg8//DCOHj2qddMq7LXXXnMJ4vWgb9++Lr8Xzo82bdpo3TxD2LJlC2bMmIG9e/dq3RQiInJSResGEBGRcc2aNQtNmzbF+fPn8dNPP2HRokX47rvv8McffyAmJiZkP/eJJ57AY489purYhx9+GHPmzEGnTp3wj3/8A7GxsVi/fj1eeeUV/Pe//8WqVavQunXroLfxq6++Cvr3dPbaa68hLi6u3AjtlVdeiXPnziEqKiqkP9+bpKQkzJ49u9z+OnXqaNCawGzfvh0Wi77HLLZs2YKZM2eib9++SE1N1bo5RER0CQNvIiIKmWuuuQZdu3YFANx9992Ii4vDs88+i+XLl2PkyJEh+7lVqlRBlSr+L3Hvvfce5syZg5tvvhnvvPMOrFZr6Wtjx45Fv379cNNNN2H9+vWqvl8gtAp8LRZLSDs9/KlTpw5Gjx6t2c8PlCzLOH/+PKpVq4bo6Gitm0NERBFK3922RERkKBkZGQCA3bt3l+4rLi7GtGnTkJ6ejjp16qBGjRrIyMjA6tWrvX6fl156CU2aNEG1atXQp08f/PHHHy6vq10bPXPmTNSrVw9vvPGGS9ANAN26dcM//vEPbN68GUuXLi3dv3PnTgwfPhwNGzZETEwMkpKScMstt+DEiRMu71+yZAm6deuG6tWro169erjyyitdRrnd13irtXDhQvTv3x8JCQmIjo5Gu3btMH/+fJdjUlNT8eeff+Lbb78tncqt/Cxva7w//PBDpKeno1q1aoiLi8Po0aPLLQsYO3Ysatasifz8fNxwww2oWbMm4uPj8fDDD8Nutwf8b/Hk3LlzaNOmDdq0aYNz586V7i8qKkJiYiJ69uxZ+rOU9uzZsweDBg1CjRo10KhRI8yaNQuyLLt8X4fDgezsbFx22WWIiYlBgwYNcO+99+LYsWPl/u+uu+46fPnll+jatSuqVauGf/3rX6WvOc8gUJZUfPfdd5gwYQLi4+NRt25d3HvvvSguLsbx48dxxx13oF69eqhXrx4effTRSrfru+++Q7du3RATE4NmzZph8eLFLu256aabAAD9+vUrPfdcz09EpD0G3kREFDbKutN69eqV7jt58iT+/e9/o2/fvnj22WcxY8YMHD58GIMGDcKGDRvKfY/Fixdj3rx5ePDBBzFlyhT88ccf6N+/PwoLCwNqy86dO7F9+3YMGzYMtWvX9njMHXfcAUCsAQdEJ8GgQYPw008/4aGHHsKrr76Ke+65B3v27MHx48dL3zdz5kzcfvvtqFq1KmbNmoWZM2ciOTkZ33zzTUBt9GT+/Plo0qQJHn/8ccyZMwfJycl44IEH8Oqrr5Yek52djaSkJLRp0wZvv/023n77bfzf//2f1++5aNEijBw5ElarFbNnz8a4ceNgs9nQu3dvl38XANjtdgwaNAj169fHCy+8gD59+mDOnDl44403VLXfbrfjyJEj5R5nzpwBAFSrVg1vvfUWdu3a5dLmBx98ECdOnMCiRYtcOknsdjsGDx6MBg0a4LnnnkN6ejqmT5+O6dOnu/zce++9F4888gh69eqFuXPn4s4778Q777yDQYMG4eLFiy7Hbt++HbfeeisGDhyIuXPnonPnzj7/TQ899BB27tyJmTNn4vrrr8cbb7yBqVOnYujQobDb7XjmmWfQu3dvPP/883j77bcr3K5du3ZhxIgRGDhwIObMmYN69eph7Nix+PPPPwGIZQQTJkwAADz++OOl575t27YqzgwREYWUTEREFGQLFy6UAcgrV66UDx8+LO/fv19eunSpHB8fL0dHR8v79+8vPbakpES+cOGCy/uPHTsmN2jQQP7b3/5Wui83N1cGIFerVk3+66+/Svf//PPPMgB50qRJpfumT58u+7vELVu2TAYgv/TSSz6Pq127tpyWlibLsiz//vvvMgD5ww8/9Hr8zp07ZYvFIt94442y3W53ec3hcJQ+79Onj9ynT59y/76FCxf6/HecPXu23M8cNGiQ3KxZM5d9l112mcv3V6xevVoGIK9evVqWZVkuLi6WExIS5Pbt28vnzp0rPe7TTz+VAcjTpk0r3TdmzBgZgDxr1iyX79mlSxc5PT293M9y16dPHxmAx8e9997rcuyUKVNki8Uir127Vv7www9lAHJ2drbLMUp7HnroodJ9DodDHjJkiBwVFSUfPnxYlmVZzsnJkQHI77zzjsv7v/jii3L7mzRpIgOQv/jii3Ltb9KkiTxmzJjSr5Xf80GDBrmc2x49esiSJMn33Xdf6b6SkhI5KSnJ5ZxUpF1r164t3Xfo0CE5Ojpa/vvf/166T/m/Us4vERHpA0e8iYgoZAYMGID4+HgkJydjxIgRqFGjBpYvX46kpKTSY6xWa+l6Z4fDgaKiIpSUlKBr165Yv359ue95ww03oHHjxqVfd+vWDd27d8eKFSsCatupU6cAALVq1fJ5XK1atXDy5EkAZQnAvvzyS5w9e9bj8cuWLYPD4cC0adPKJeIKRmmwatWqlT4/ceIEjhw5gj59+mDPnj3lprur8dtvv+HQoUN44IEHXNZ+DxkyBG3atMFnn31W7j333Xefy9cZGRnYs2ePqp+XmpqKr7/+utwjKyvL5bgZM2bgsssuw5gxY/DAAw+gT58+paO57saPH1/6XJIkjB8/HsXFxVi5ciUAMY2+Tp06GDhwoMsoe3p6OmrWrFluWUPTpk0xaNAgVf8eALjrrrtczm337t0hyzLuuuuu0n1WqxVdu3Z1+X8KtF3t2rUrXa4BAPHx8WjdurXq/3siItIOk6sREVHIvPrqq2jVqhVOnDiBBQsWYO3atR4TVL311luYM2cOtm3b5jK9tmnTpuWObdmyZbl9rVq1wgcffBBQ25SAWwnAvTl16hQSEhJK2zN58mS8+OKLeOedd5CRkYHrr78eo0ePLg3Kd+/eDYvFgnbt2gXUHrW+//57TJ8+HT/++GO54P/EiRMBZwfft28fAHjM3N6mTRt89913LvtiYmIQHx/vsq9evXrl1iR7U6NGDQwYMMDvcVFRUViwYAEuv/xyxMTEYOHChR47LiwWC5o1a+ayr1WrVgDKljbs3LkTJ06cKD2P7g4dOuTytaffO19SUlJcvlbOQXJycrn9zv9PgbbL/ecAgf3fExGRdhh4ExFRyHTr1q00q/kNN9yA3r17Y9SoUdi+fTtq1qwJQCQhGzt2LG644QY88sgjSEhIKF1r7JyELdiUda+bNm3yesy+fftw8uRJlyB6zpw5GDt2LD7++GN89dVXmDBhAmbPno2ffvrJZSQ/FHbv3o2rrroKbdq0wYsvvojk5GRERUVhxYoVeOmll+BwOEL68wGUS0IXSl9++SUA4Pz589i5c2fAAbHC4XAgISEB77zzjsfX3TsSnGcVqOHt/8TTftkpuVqg7fL2c2S3hG1ERKQ/DLyJiCgslGC6X79+eOWVV0rrbC9duhTNmjWDzWZzGdF0T46l2LlzZ7l9O3bsCLhmcatWrdCqVSssW7YMc+fO9TjlXMkYfd1117ns79ChAzp06IAnnngCP/zwA3r16oXXX38dTz31FJo3bw6Hw4EtW7b4TcoVqE8++QQXLlzA8uXLXUY/PWWAVzutvUmTJgBEQrH+/fu7vLZ9+/bS18Nt06ZNmDVrFu68805s2LABd999NzZv3lxuRN/hcGDPnj2lo9yA+H0AUPo70bx5c6xcuRK9evUKOKgOpVC0KxjLGYiIKPi4xpuIiMKmb9++6NatG7Kzs3H+/HkAZaN4zqN2P//8M3788UeP32PZsmUuZa5++eUX/Pzzz7jmmmsCbs+0adNw7Ngx3HfffeXKYa1btw7PPvss2rdvj+HDhwMQGdhLSkpcjuvQoQMsFgsuXLgAQIzsWywWzJo1q9wIdGVHJj39X504cQILFy4sd2yNGjXKZST3pGvXrkhISMDrr79e+m8AgM8//xxbt27FkCFDKtXmirh48SLGjh2LRo0aYe7cuVi0aBEKCwsxadIkj8e/8sorpc9lWcYrr7yCqlWr4qqrrgIAjBw5Ena7HU8++WS595aUlKj6fwqFULSrRo0aAKDZv4mIiDzjiDcREYXVI488gptuugmLFi3Cfffdh+uuuw42mw033ngjhgwZgtzcXLz++uto164dTp8+Xe79LVq0QO/evXH//ffjwoULyM7ORv369fHoo48G3JbbbrsNv/76K+bOnYstW7bgtttuQ7169bB+/XosWLAA9evXx9KlS1G1alUAwDfffIPx48fjpptuQqtWrVBSUoK3334bVqu1NDhv0aIF/u///g9PPvkkMjIykJmZiejoaPz6669o1KgRZs+eXeH/u6uvvhpRUVEYOnQo7r33Xpw+fRpvvvkmEhISUFBQ4HJseno65s+fj6eeegotWrRAQkJCuRFtAKhatSqeffZZ3HnnnejTpw9uvfVWFBYWYu7cuUhNTfUa7FbUiRMnsGTJEo+vjR49GgDw1FNPYcOGDVi1ahVq1aqFjh07Ytq0aXjiiScwYsQIXHvttaXviYmJwRdffIExY8age/fu+Pzzz/HZZ5/h8ccfL52q3adPH9x7772YPXs2NmzYgKuvvhpVq1bFzp078eGHH2Lu3LkYMWJEUP+daoSiXZ07d4bVasWzzz6LEydOIDo6urTuOxERaUjDjOpERGRQSpmlX3/9tdxrdrtdbt68udy8eXO5pKREdjgc8jPPPCM3adJEjo6Olrt06SJ/+umn8pgxY+QmTZqUvk8pt/X888/Lc+bMkZOTk+Xo6Gg5IyND3rhxo8vPUFNOzNmyZcvkgQMHyvXq1ZOjo6PlFi1ayH//+99Ly1Ep9uzZI//tb3+TmzdvLsfExMixsbFyv3795JUrV5b7ngsWLJC7dOkiR0dHy/Xq1ZP79Okjf/3116WvV7Sc2PLly+WOHTvKMTExcmpqqvzss8/KCxYskAHIubm5pccdPHhQHjJkiFyrVi0ZQOnPci8npnj//fdL2xsbGyvfdtttLmXbZFmU76pRo0a5f6va/29f5cSU969bt06uUqWKS4kwWRbluC6//HK5UaNG8rFjx1zas3v3bvnqq6+Wq1evLjdo0ECePn16uVJusizLb7zxhpyeni5Xq1ZNrlWrltyhQwf50UcflQ8cOFB6TJMmTeQhQ4Z4bL+3cmLuv+fK/4f774+3/7/KtMv990iWZfnNN9+UmzVrJlutVpYWIyLSCUmWmZGDiIiIIs/YsWOxdOlSjzMjiIiI9IRrvImIiIiIiIhCiIE3ERERERERUQgx8CYiIiIiIiIKIa7xJiIiIiIiIgohjngTERERERERhRADbyIiIiIiIqIQqqJ1A8LN4XDgwIEDqFWrFiRJ0ro5REREREREFIFkWcapU6fQqFEjWCy+x7RNF3gfOHAAycnJWjeDiIiIiIiIDGD//v1ISkryeYzpAu9atWoBEP85tWvX1rg15TkcDhw+fBjx8fF+e01IGzxH+sdzpH88R/rHc6R/PEf6xvOjfzxH+qf3c3Ty5EkkJyeXxpi+mC7wVqaX165dW7eB9/nz51G7dm1d/nIRz1Ek4DnSP54j/eM50j+eI33j+dE/niP9i5RzpGYJs35bT0RERERERGQADLyJiIiIiIiIQoiBNxEREREREVEIMfAmIiIiIiIiCiEG3kREREREREQhxMCbiIiIiIiIKIQYeBMRERERERGFEANvIiIiIiIiohDSNPBeu3Ythg4dikaNGkGSJCxbtszve9asWYO0tDRER0ejRYsWWLRoUcjbSURERERERFRRmgbeZ86cQadOnfDqq6+qOj43NxdDhgxBv379sGHDBmRlZeHuu+/Gl19+GeKWEhEREREREVVMFS1/+DXXXINrrrlG9fGvv/46mjZtijlz5gAA2rZti++++w4vvfQSBg0aFKpmEhEREREREVWYpoF3oH788UcMGDDAZd+gQYOQlZXl9T0XLlzAhQsXSr8+efIkAMDhcMDhcISknZXhcDggy7Iu20YCz5H+8RzpH8+R/vEc6R/Pkb7x/Ogfz5H+6f0cBdKuiAq8Dx48iAYNGrjsa9CgAU6ePIlz586hWrVq5d4ze/ZszJw5s9z+w4cP4/z58yFra0U5HA6cOHECsizDYmHuOz3iOdI/niP94znSP54j/eM50jeeH/3jOdI/vZ+jU6dOqT42ogLvipgyZQomT55c+vXJkyeRnJyM+Ph41K5dW8OWeeZwOCBJEuLj43X5y0U8R5GA50j/eI70j+dI/3iO9I3nR/94jvRP7+coJiZG9bERFXg3bNgQhYWFLvsKCwtRu3Ztj6PdABAdHY3o6Ohy+y0Wiy5PHgBIkqTr9hHPUSTgOdI/niP94znSP54jfeP50T+eI/3T8zkKpE0RFXj36NEDK1ascNn39ddfo0ePHhq1iIiIiIzIbgdycoCCAiAxEcjIAKxWrVtFRESRStNug9OnT2PDhg3YsGEDAFEubMOGDcjLywMgponfcccdpcffd9992LNnDx599FFs27YNr732Gj744ANMmjRJi+YTERGRAdlsQGoq0K8fMGqU2Kamiv1EREQVoWng/dtvv6FLly7o0qULAGDy5Mno0qULpk2bBgAoKCgoDcIBoGnTpvjss8/w9ddfo1OnTpgzZw7+/e9/G76UmN0OrFkDvPee2NrtWreIiIjImGw2YMQI4K+/XPfn54v9DL6JiKgiNJ1q3rdvX8iy7PX1RYsWeXzP77//HsJW6YvNBkyc6HoDkJQEzJ0LZGZq1y4iIiK9qug0cbtdXHM93ZrIMiBJQFYWMGwYp50TEVFg9LdCnUpHuCdNAoYPZ687ERGRWpWZJp6TU/6a60yWgf37xXGcjUZERIGIqORqZmCzARMmxKOgwHufCHvdiYiIylOmibuPWCsd1kuX+p4tVlCg7ud8/DFw++2uQXrjxsA99wAtWzIZGxERlcfAW0dsNmDkSAmyLPk91rnXvW/f0LeNiIhIzwKZJg54noqemKjuZ2Vnl9+Xnw9Mn172NZeFERGRM0411wnXGwb/gbdCbe88ERGRkamdJv70096nomdkiIA5GLgsjIiInDHw1omyGwb1QTdQ1jvvvtasuJhrz4iIyDzUdkRPn14+QP/rL5FT5eGHgSuvDE57lJH3rCxeg4mIiFPNdSPQkWtJEr3yGRmeM59bra4Xek55IyIio7LbgcLCyn8f5ynkMTHA+fOV+35cFkZERAoG3jqhdl2ZQpZF7/zTTwMzZpRf0+beu642sQwRBUFeHnDkiPfX4+KAlJTwtYfIwDx1PgfD+fPA2LGAh8qmAeOyMCIiYuCtE8q6svx8WVVyNcBzchdvmAmdKEzy8oDWrX0PlcXEANu3M/gmqiRvWcyDQZKA5cuD872cl4VVpL44ERFFPq7x1gmrVUwFBwBJ8nwHcd11lfsZzlPeiChEjhzxPz/1/HnfI+JE5JevLObBIMtAUVHlv09srGjr0qUVry9ORESRjyPeOpKZCXzwgYwJE2QUFJR1gScnA3PmAJMnB+fncMobkQ4UFADr13t/ndPRiXzyl8U8WGJjgWPHKh7gFxUBAwZ4fo3LwIiIzIOBt85kZgI9ehzG9u0JKCy0lE5FC+YNRmGh6H3n9DYiDWVmivID3nA6OpFXdjuwalV4ftbEiSKXiiR5Dr6zsoB69YA33wz8Os1lYERE5sGp5jpktYrsp7feKrZWa3BHqSdN4vQ2Is35CroBTkcn8sJmE9ewp54K7c+RJDHj7P/+T4xIN27s+npyMvDRR8BLLwHTpgF79wIrV4oR8kAoy8Befpllx4iIjIwj3hEi0Kzn/nB6G1EAmKWcSBcCTaZmtQIOh/fja9YETp8uP5otXcpxmp0tvkdmphiR9pUYzWoVj4quC580SSwrY+lPIiJjYuAdIcqynqu74XCv4+2O09uIVFKTpTwqSkQEiYnA1q3haxuRiQSSTE0JnCdPBl54wXtg/dZbYutejiwpSQTdzgGwMhvNl8rOTvvrL1EqVLk2M+s5EZFxcKp5hHDNeu76mvL1zJnAu+8Cq1cDZ8+K6W++MMs5kQpqspQXF4uyA+npwOjR4WkXkckEkuskKUnM6HruOc/TxJXXMzPFY+9ece1UrqG5uRUbdQ7W7LTsbGY9JyIyGo54R5DMTHGjoKZnHgAaNFD3fZnlnCjMoqL8r/EmIgBlta8/+kjd8U88IZKhKSPFaqeJ+xvNViPQ2Wn+cFkYEZFxMPCOMGpuIBRqe94TE8tubPx9TyJS6ckngaZNgYsXgfh4YNcuYMoUoFo1YOpUsaCTiHyy2cp3Nvtz1VXlr1/BCqz9UWanjRjhPQt6ILgsjIjIOBh4RyC1NxD+et4lSbx+5IiYzuY+is4EL2RazsnUKrpme+rUsufR0eJDWFwMnDunPuj29bOZ0I0MLtBEaso1LSMjtO3yx9vstORkkTwtPz+wfjfnZWHh6DwgIqLQYOBtYP563mUZ6NQJuOmm8u/l9DYyDfeM5QUF/mtsB+rChYq9z9d6cdb5JgMLJJEaUD4LudZ8zU6z28sC8EBGxLksjIgosjHwNjhvPe+KTz/1/D5ObyNTUJOxPJyWLAHathUj3f6StCl1vhl4kwEFkkgN8J7rREveZqdVdDp6sMuKEhmemlKgSUnhaw+ZHgNvE3Duef/4Y3Fzogant5HhqclYHk5t2wLNm4vCw0QmpnZ0d/x4UX4r0vKS+OsUdxcbK0bK7fbI+ncSaUZtKdCPPkKVqCjxIUtIYGc2hRTLiZmE1SpuTJYuDfy9nN5GFCYTJ4oe+O3btW4JkabUju4OHy46hiMxGHUuY5aVJfa5lwtVFBUBAwawvBiRaipLgVqGDkXcoEGwXH65CNTz8sLTPjIljnibSKBT9xRbtgBr1kTeiAIRAN9TzSqaOC1ULBagpAT44Qd1xzu3n8nWKEJ5qqqhNjmo1onUKkuZjt63r/i3+BsBZ/4VohDytIRLzXR1XntJJQbeJlLRkeunnhIPZjqniJOXJ6Zvh2I6eSDrsdVq3hxYuxZYuVLd8c4/l8nWKAJ5KhemXGuUddDu9JZILViUZWFr1gAjR4pRbnfu+Ve8jZATURComa7Oay8FgFPNTaSyiVmUnnZlmpvdLm4Q3ntPbO32yraQKMhCuYa7bVsgLU1sg2XhQrHdsSPw9yo99UQRQikX5j7Cq1xrALGG211SknFHfK1W8fAUdCuU/Csvv8zrLpGLvDxg/XrxCMaMNjX3ELz2UgA44m0i/qbu+ePc0+5wiDqkrP1NphcXJ3q8fV2co6PFtqJlxYgimKep5ID3cmHO15qWLcW+v/1NrHF2LstlVGpnp02aBMyZI2HGjGjceWdo20QUdp6meBcUAMePi+d167qOKBUUiKQPlb3OOgfseluORhGPgbeJqClhMnw48NFH3r+H0tPO2t9kajExIuAGxPSy7dv9rwEDfK81D9Z0dSId8TaVfNw432uZlWvN/v3i66lTRWIxMwhkdlp+PjBuXF3UqSN7nJZPFJG0LPVZ2Wsx14STDwy8TcZbCZPkZLFe7sIF34G3L6z9TYYUFSWiB+e7YfcLZ0qKugspL7ZkIspUcvdO3vx8YPp09d/nyivNE3QDgc1Ok2UJkiRj8mQJN97I6y4ZhN5KfarFNeHkBwNvE3Ku6+089c9qFWu1K4O1v8kQlMRpAHuniSrAbvc9lTwQmzeLIN4sM6nUzE5zJssSr7tEehDImnDeV5gSA2+TUkqYuKvsOnAFa3+TZvLygEOHUKWoCDh0qGLfQ0mcRkQVUtHylZ4cP26+ZUzeZqf5osxWM/oaeCKiSMWs5uRC6WkHypcpCaRsSWUzqBNVyKVpXpbLL0fcoEGw3H671i0iMqVgdr4qncBZWebK4p2ZCezdC7z0krrjX3kF6NdPTMtXqo8QkZslS4B168RjyZLgfM+tW4OXSZ0MjYE3laP0tDdu7Lq/cWPggw/EiLi3IFySxHpxJWstUVhF6rqwYHBO+EaksUA6Xy0q7kSclzGZidUKPPSQ7+su4Do9zb30J1FECHYpMG+UGW3BLAc6ejSQns4kqeQXA2/ySOlp/+absnv5V14R2cznzvU8DV25KcjO5jQ3ooAoJcl8iY4GPv20rKf+l1+A+vXFay+9xGQtpCvKsiU1M6Vq1oTqjNxmXMbkayaaCLpdd5p1hgBFMCUpWXo6A1gyNAbe5JXVKqatKTdEX30ltpmZwA03lD++bl1zrcEjnQhXL3koKSXJlKDa02PHDmDIkLKe+ssvB0aNEu9ft45BN+mKEiyqyRVy6pS4dqhh1mVM3maiuQfdCrPOEKAIFa7ZapwZRhpjcjXy65prgNdfBz7/vOwmasMGsZ0xA/jjD3FD0Ls3g24Ks1DU+tTqwqy2JJmzm28GXn4Z+PlnwOFQN2eXKEwyM4HrrweWL/d9nHJdsVrFr7G3GVVJSeZexuRckeSjj8QsNH/MOEOAyIWvKiVxcZBjYiCZdYkahR0Db/Krf39Ryjg3Vwy6HT8upqHXqAE88giwc6cIvFeuBM6eBapX17rFZBoV7SV3vhC7i6TyYY0bA//6F9Cli+gNKygQH1BF3bq+648ThZhSWGDUKODdd30fq0yLdi+hxWVMZZwrkqgJvM06Q4AMKju7rGP8yBGxnsIfX1VKUlIgb92Kozt2IDY2FpbCQtHDVVwcrBaXx1F3U2PgTX7VrClGGVatEqPeeXli//XXiyC7Y0dxL5+XJ44ZOlTb9hL5ZYRyYXl54t8RSMdDTAzXglPYnDsnVkEAYmWEv8AbEPfRS5e6ltBKShL325xRVaas9KcMWfY83Tw2VnRm2O3ssCAdyMsTwbInapeJZWSUXbvXrw9Ou1JSUBITAyQkiFljO3f6bmdF15/fdBPw2GPsADc5Bt6kyjXXiKB6yRJgzx6xT1n7LUkiCH/lFTGlkIE3URhUZLT//HkxT9XbtDuiIPr1V+DiRTHq2qmTuvcMGwa88IL4NS0oEO9lXerylDX0I0YAkuQ5+C4qAgYMEAH63LnsuCANhWJZmJKU1Nf3rMjockWWfanx11+R3+FPlcbAm1Spcuk3RRm9AIAJE8RWWcf3yiti3VnfvmIGLG+WSJfMPs3LubeeI+AUQt9/L7a9ewNXXqmM0Ppfw+08nZq8y8wEPvhAxoQJMgoKvF9slfJiTH5KmglF8jQlKam30WlAP53L6eli3SaZHgNv8stmAyZNKr//wIGyi3lJibhxOnas7L6eveykG76Sq5jZ+fPipoX/HxQC330ntr16uY/Qcg13sGRmAj16HMaWLQm45RYLiorKHyPL4v84K0vMKAA4o4AMIlSj096oGWX35I03XEe7fU27V34Or8uGxMCbfLLbgYkTPY9QKBfze+4RU9rcj2EvO+mGEdZ0E0UQhwP44QfxvHdvsVVKYk2cyDXcwWS1ioenoFuhlBd7+mngzTfL//+zk5x0Tw+z1dxH2QsK/Cdjc2+3mmn3nI1mWAy8yaecHNcLtDtZBo4e9f6acy87e9SJiMxhyxaRYL9GDdf13c4lsTjiGjxqy4ZNn15+HzvJSbf0OFvNfZTdVzI2oKzdJ06I3rFjx/yPmHM2mmEx8CafKlsDVOllz8nhmj0KgVAlVyGiSlGmmV9xRVmOEAXXcAdfZcqGsZOcdCsSZqupme7+3nuipuJVVwHPPReedpEuMfAmn4JVA7SyATyRRykpwObNwMmTLrsdDgeKiopEXc6EBPYaE4WJ3S46WpcsEV/37Klte8yirLyY56Vh/rCTnCiEWrcW2/XrK/YBJcNg4E0+VfZirghWAE8G5y/hyIULQHR02deyDNx2mxjRfuQRoEsXEWQ7HCg5dKisLqcRVTTJC1GI2Gzl12/Pnw907swpzKHmK3ldINhJThQCl10mpv4cOwYcPKh1a0hDDLzJJ3+ZaGUZqF/fc3I15RilRAyRT5Wp87l9u6hdpCQkSUoKfvv0xlMplYICsbAWAHJzgalTNWkamY/NJq4T7teBo0e5fjhcvCWvCwQ7ySkk4uJEp/mFC1q3RBvR0SL43rgR2LZN69aQhgw6FETBpFzMGzd23Z+UJOp2v/GG+FopCeNMloHhw8X0Nbs99G2lCBaMOp9KQhKzSEkR69+Ux5AhYgbAbbcBd9whOiJ8iY4Wwfr69Z4feXnh+XdQRPNX/QIQ64d5DQi9zExg717gpZcCe58kAcnJ7CSnEElJKVvbfOWVZWtRzKRLF7Hdvl3bdpCmGHiTKsrFfPVq4N13xTY3V+z3FpgrsrOBfv2A1FQxKkJEYaCMiK9bV/Z46CHxWkYG8Omn4vl11wHp6Z4frVsz+Ca/1FS/UNYPU+hZrUCDBoG/j3XUKaRWrRLbK68sy1RuJkqSOI54mxqnmpNqvjLROpeI+fhjcQF3x5IlVI7zmu6tW7VtixF5yrb68svAhg1AfLz/aX8saUJulORpzqXA1K4L5vrh8Alkynjt2sDChbwuU5A5X99PnQJWrBDPO3QQfwz8TT03UkWSvDygenXx/M8/xXrvkhLvxxvp304uGHhT0Fit4ibs9ts9v86SJeSiMmu6qWI6dxZDYc2aicW3RAHwlDwtKQkYN07d+7l+OHzUJEatUQM4cwZo145BNwWZr+v7zTeLbXS0mHnl7Q+DXup2V5b7/0VRUfljrFbRq9m2rZiGb5R/O5XDwJuCKpAphyxZYnLBWNNNgbFYgH37xA3P+vVat4YiiLfkafn5wPTpTLKpN/4SowJiHfg99wC//CLOXWysNm0lA1Jzfb9wQQTdeq/TXVlq/i/sdvHB3LpVfBAZdBsW13hTUHHKIZHOOZdjI1LBX/I0T4k1FcprXD8cfr4Soy5dKmYqtG8POBzAV19p00YiukTpgFi5Utt2UEhxxJuCSu1Uwi1bgDVrxAgIb8aIwsR5zd26dere4772nlPgTEfNTKajR4GZM4FnnnFdtpmUJIJuTmXWhnP+Fed1+cp195prgD/+EMtvb7lF27YSmdoNNwCPPy4yEbvPSON11zAYeFNQqVlXBgBPPSUeSUliOhxvyigomJDEu4quqR892vVrpVY6bwJMQ+0MpWbNygK6f/4T6N6dnat64Csx6jXXAM8/D3zxhRj5tnAeJFWEc6cuwGSpFTF1qvfXeN01DAbeFFS+1pV5wkznVGlLlpSVJlF6hR0ObdukR8FaU89M56ajdibTmTPA2bNAnTrAI48wiIsEvXqJJGuHDwOzZ4uv2VlCfjkH2gUF4gauuFjbNhkZr7uGwcsiBZ2/ut7OlMA8K0usIyQKWNu2Ym1UWhovSkQhoMxk8raWW5KA5GTg3Dnxdc+eDLojxaefll17n3gC6NdPzHS12TRtFumZMnsqPV08rruOQTeRSrw0UkhkZgJ79wKrV4uLuS/Omc6JiEhflJlMnjgnT/vhB/G8d++wNIsqSclU7z4RRpmJxuCbPGJFEm1s3SrWfq9fLzo/KCJxqjmFjLKujJnOyaO4OLFuiRdwIt1TZjKNGuWaPC02FnjjDeDGG4GHHhL7GHjrn5pM9VlZIjEbp52bkPuabWfBWr9tlpwswbrXcc63wjXfEYuBN4Wc2vWBao8jg0hJERcOXxd398ReRKSZzEygQQNxT96mDbBtG3DllWJ/bi5w4ABQtSpw+eVat5T8UZOpXpmJ5i0xGxlURRNx+uOcjwUwT6buUNzrnD8vPpzu+W1I9xh4U8j5y3QuSeL1jIzwt400lpLi/WKhppfYLD3mRDpw7pwIxgAx9XzQIJEN+8wZ4Pvvxf70dKBaNe3aSOpwJhp5Faqp5Eo+FjPyda9TURwBj0gMvCnkfGU6d14fyOlsJrV4sZju0KsXUL162X5/vcQAe3mJwmjXLvH3u25dYOBAUT5szx7g88+B774Tx/TqpWkTSSW1M8y2bAHWrGGmcyJdY9bziMHAm8JCWR84caLr9LakJBF0s5SYSdntwP33ixpEW7a4TkMDQtNLbFZqZhBER4ut8yJed5xlYFo7doht69ai03TECOC554DXXgN27hSv9eihXftIPX8z0RRPPSUeSUmiA53XaoNyXtPNGtzhxXw3psLAm8ImM1Mkavn738UFvFs3kQWXvegmtm2bCLpr1ABatdK6NcamdgYBUHZMSYlY4HnuHPDuuyLi4iwD09q+XWyVj2r9+mK7enXZMQ89JIJyBmj65msmmidKpvOlS3luDSdUa7qdscPWO/drM/PbGBoDbworqxW46SZxwf/rLwbdprdundimpfGXIRzUziBwPqZfP2DFCpE569ZbQ9c20j1lxLtVK1Fq6rHHyh9z8CADtEjhbSaaJ8x0bmChWNMdFSX+SChrGthh6xtn95kG63hT2HXsKLYHDvgefCMT+O03sU1P17Yd5N1VV4ntqlXatoM0p4x4t2zpuxQVIAI0uz1sTaMKyswE9u4VsxaeeML3sc6ZzonQooXY/v3vohPd+bFzJzBkiOhUT0tjUEl0CUe8Kexq1SpLyrNxY9l9PZmQMuLNwFu/lA/o2rXAxYuiXhSZkjLifeoUS1EZidUqzhMznVNAdu0S0yAmTQIaN9a6NcbBNd+GxhFv0kSnTmK7caO27SANlZQAv/8unnftqm1byLsOHcTIxSOP8EbAxI4eBYqKxHO104wZoEUWtZnO1R5HBlbl0rhd794MuoNNWfOtzB5YskTrFlEQccSbNNG5M/C//zHwNrVt20TSrpo1mVhNzywW4NNPtW4FaUyZZp6cDDRtqu49DNAii79M55IkXs/ICH/bSAfq1gWOHwfuugv49lsx4t2zJ7B+PddwB5vzmm81I+BMXhcxGHiTJjjibVLOJUtKSoB33gEKC4ENG8Q+Xrz1x/mcecJzZgrOidUYoBmTr0znkiS22dlMrGZax4+L7X/+U7bv2WfFIyZG9M7xWhB8niqSfPUVMGUK0KaNuI/idThiMPAmTSiB95YtQHGxSIBJBqemZAkv3vrCc0aXONfwZoBmXN4ynScliXPKTPXk0fnzIjDkdSA03LOeN2wI5OaK3s20NO3aRQHjGm/SRJMmQJ06IlfT1q1at4bCQk3JEuXiTfqg9pzl5IjphuvXi2CdDMe9hrcSoLkv70xKYimxSKdkOh80SHx9553iHp/n1KCUqcwUORo1Av71L9b7jkAc8SZNSJIoK5aTI6abKyPgRBSBnC/+HAE3JOep5orMTFHTOSdHJFJLTBQDMBzpjnxWK9CnD/Dll2JWGs+pgXmayuxs61YGeERBwsCbNNOpU1ngrbDbeRNHFNE45dBwHA5RlhcQU82dKaWoyHiUc63MdiADO3kSeP99YPBgoF8/rVtDaly8KCrD5OcDN96odWtIJQbepBn3BGs2m+d1ZXPncopbxHJOzMU1BUQRKS8PuHBB5OJo0kTr1lC4OAfesly2fp8MaMUK4LnnxMlm4B0ZNm0CuncX2eaHDRMVSEj3GHiTZjp3FtuNG4GPPgJuuql8htz8fJHAh2sGI5CaxFxEpHvKNPMWLTgDyUxatBD38qdOAQcPsjycoa1eLbacvhI5OnYEqlcX2ea3bQPatdO6RaQCu0dIM5ddJnrQjxwB7r7bc1kaZV9WlpiGThFETWIuItI9T+u7yfiio8tqtnO6uYFdvCjW+AEc7Y4kVasC3bqJ5z/8oG1bSDWOeJNmPv9cjJ6UlJSVh/REloH9+8V1gZ2xOuKvvnNBQfjaQkQhYbcDq1eLOcYxMeJrjnqbR+vWwO7dIvDm9deg1q0DzpwBYmOBDh3Kv65kPfdXVjIuLnRtpPLy8oBmzYA1a4Dly8uXFWNtb11i4E2asNnEFHJPo9zeMI7TETXTyCtSnJ0Xb31Rc8NFhuKc4HLHDuBf/4pHQYEIvP/7X+C775h3w0xatxbLfznibSDuneZLlohtp07Ahg3lAzZ/Wc8BBnnh5n4P9skn4uGMFUZ0iYE3hZ3dLpKoBRJ0A1xfpitqppEXF6v7XkuWAG3biue8eOuL+w0Xy8oYWvkElxYArn+omXfDXJjZ3GB8dZqvXg2kp3sO2FJSeG3WEzX3YKwwoksMvCnscnJcM5f7I0kiu3lGRujaRBpq27b8FCnSD+cbLk45NCzvs5BcU1kr2a2zskQiXU47NzYG3gbDgM1cnKvJcGBDFxh4U9hVZMp4djZv8Ig052nK4f79wB13iDqw48eLOrBHjpQdw4u97gU6C4l5N8xDCbxzc0VJuehobdtDRAFwnqHGqee6wMCbwi7QKeM33igu+GvWiFFvBuBEGnIeAc/LA3r1KhtBeeUV8XDGi73uBToLScG8G8bXsCFQq5YoKbZ7NysWEUUszmTQBZYTo7DLyBBTxyXJ+zGxsUD//uK5zQaMGiWqXKSmiq8pQvhLsMZpyZEtkGmLpFsVDaCZd8P4JInTzYmIgoWBN4Wd1Sqy4gLlg29JEo+77hJ5PtwpiX0YfEcImw2oW1c8X7hQlC1xfnAklEhzgQbQkgQkJzPvhlkw8CYiCg7NA+9XX30VqampiImJQffu3fHLL7/4PD47OxutW7dGtWrVkJycjEmTJuE8S91EnMxMkRW3cWPX/UlJwPvvA++953m9obIvK0usSySdKy4WRdqjo4FbbxVJ1JwfDLqJNKfMQlJD6Sxl3g3z8BR42+1i+dd774ktr8dERP5pGni///77mDx5MqZPn47169ejU6dOGDRoEA4dOuTx+HfffRePPfYYpk+fjq1bt+I///kP3n//fTz++ONhbjkFQ2YmsHevGNl+912xzc0F4uN9rzd0TuxDGlGyW/sSEwPs2iWed+vGrDxmtnUrsH69eOTlad0acmO1AnPmeHvVtQc0KYmlxMzGPfC22cSyr379uAyMSBNq7sFIlzRNrvbiiy9i3LhxuPPOOwEAr7/+Oj777DMsWLAAjz32WLnjf/jhB/Tq1QujRo0CAKSmpuLWW2/Fzz//HNZ2U/BYreWz4qpdb8jEPhpyzm49Zgzwxx9A8+Yi+06/fsALL4gLw8yZ4vjevbVtL2nLU2ZVtUOsFBbK6LXFAjgcZfsTEx24914JrVpZkJjIBJdm5Bx4eys7x/ruEYIlIY3BvcLI1q2u11nSLc0C7+LiYqxbtw5Tpkwp3WexWDBgwAD8+OOPHt/Ts2dPLFmyBL/88gu6deuGPXv2YMWKFbj99tu9/pwLFy7gwoULpV+fPHkSAOBwOOBwvrvQCYfDAVmWddm2cGnQAFAzGaNBAwe0+G/iObokKQlo3BjSvn2QADimToVl7FjIv/4KuW1bIDoa0nffidd69EA4TxbPUZg4HIFPmzp/Ho5Dh+Bo1IjnSEf+/W8JgISHH5YxaJCMggKgYUMZrVsfQsOG8bA4nWieMv0Ix9+65s0BwIKiImD8ePlS0O2pvruMrCxg6FCZnTOX6O5alJQkgrRPPoFlwgTIcXGQP/sMLh/wuDhxnF7aHGK6O0dqJSWVdWCrvBY7HI6IPK96P0eBtEuzwPvIkSOw2+1oIKKsUg0aNMC2bds8vmfUqFE4cuQIevfuDVmWUVJSgvvuu8/nVPPZs2djpjLq5uTw4cO6XBvucDhw4sQJyLIMi0XzJfiaaN0aSEyMx8GDFshy+dTnkiQjMdGB1q0Pw8uqhJDiOSpjyc9HwqlTkKtUwaG+fRHfoAGshYU4tnw5ivv0geWDD1D1119R3Lo15DCeLJ6j8KhSVISKjIsUFRWh+NAhniON2e3Azz9HYds2K778sjYAYNiwI2jWzI527co+RxYLz5FehetvXaNG8ThwwIqCAu/lSGRZwv79wCefHEPPnsUha0sk0eW1KCYGtdavRw0A5wYPxklPuVa0uLnSiC7PUYAsAOKjoyE5DTS6k6OjcQSAIwLPrd7P0alTp1QfG1F1vNesWYNnnnkGr732Grp3745du3Zh4sSJePLJJzF16lSP75kyZQomT55c+vXJkyeRnJyM+Ph41K5dO1xNV83hcECSJMTHx+vylytc5s0DRo4UQbZr8C3mt82dKyExMUGTtvEcOVm/XmxbtUJCcjLw/PNw1KuHuv36AdWqAQkJQIcOYW8Wz1GYtGoFOSYGUoCdmLGxsXAkJPAchZndLnJjFBSI9AtvvikhP7/s72tUlIwDB+rjiivE1/wc6V84zpHNBhw96qP+p5t16+pi6FAuSQB0+hmSZUgrVwIAYkaOREyCNvdSeqHLcxSohATI27ZB9lW6My4OcRGa0Fbv5ygmgPX2mgXecXFxsFqtKCwsdNlfWFiIhg0benzP1KlTcfvtt+Puu+8GAHTo0AFnzpzBPffcg//7v//zeDKio6MR7SGpk8Vi0eXJAwBJknTdvnBQ1opNnOiaaK12bQkLFwKZmepvAkKB5+iSrVsBAFK7dpAsFsDHso9w4zkKg9TUCq0zs1gsgMXCcxRGNlv5v6fuiosljBwpuazT5TnSv1CeI5tNdIJ7qjLizTPPWLB4sSgbyvXeOvwMnT8PjB0LfPUVLAMGuE4zNyndnaOKSE0VD4PS8zkKpE2aBd5RUVFIT0/HqlWrcMMNNwAQPRqrVq3C+PHjPb7n7Nmz5f5x1ktdqnIgVwWKCJmZwLBhYoTmnXeAf/9bDJ7yQq4jFy4AdeoAl10mslU797bOmSNeGzZMpKqPi2P5MCNKSeF51TlvCbG8ycoSH1tJ2/5N0pjdLjprKnJ7xWRrOuJ+bQaAG28Uj61beW02qrw8oLAQ+PVXUTLo1ltdX+d514SmU80nT56MMWPGoGvXrujWrRuys7Nx5syZ0iznd9xxBxo3bozZs2cDAIYOHYoXX3wRXbp0KZ1qPnXqVAwdOrQ0ACdjUbKep6SIwPvnn4EzZ4AaNbRuGQEAHn8cmDJFZDNv3dpzptT588VWyWbNP/REYRNo8ORcrvHKK0PbNtK3nBzfMyR8EcnWyjpxeIumkbw879dmBa/NxuPpvL/wgusxUVGiVzYxUXzNQDwsNA28b775Zhw+fBjTpk3DwYMH0blzZ3zxxRelCdfy8vJcRrifeOIJSJKEJ554Avn5+YiPj8fQoUPx9NNPa/VPoDBp2hRo0gTYt0/cDAwerHWLqJQkASdP+r6wA+L1I0f4h50ojCoaPLFcI1X2d8C5E8e9bCiFyZEjvDabkZrzXlwMXHdd2dfsgAkLzZOrjR8/3uvU8jVr1rh8XaVKFUyfPh3Tp08PQ8tITyQJuOoqYMEC4JtvGHgT6RJrxOpORYMnZRCEzCtYvwPsxAkz56nll/KwEPnFDpiw0DzwJlKrf38ReK9apXVLCADw1VfA+PHAkCG6SqpGGkpJcU225okynU2n9TiNJtDgSZJEadiMjNC0hyJHRob4XcjPr9g6bwU7ccJIzdRyItIMA2+KGP37i+3vvwNFRUBsrLbtMb1Nm4CdO8VdGZHCU7I15xGYI0fEw+FAFeWDnJDAXvYQCSR4UpKpZWeLNbnsGzE3q1VkJh8xQvxuOP/+KF/Xry+ux55+t9iJowE1U4yJSDP6y8lO5EViItC2rbjAP/kksGaNSBxEGtmyRWwvu0zbdpC+KSMw6ekuD8vllyNu0CBYLr9cvJ6Xp3VLDUkJntRISmIWanKVmSl+Jxo3dt2flAR89BHwxhvia08Z8GUZGD5crPHmtZqIiIE3RRCbTSRqAcSITL9+omShzaZlq0zszz/FloE3+RJIch8KCSV4qlnTdX9SEjBzJvDuu8Dq1aLiDINucpeZCezdK35H3H9XvAXmCl6riYjKcKo5RQRvdWjz80WP+syZQMuWYlQ8I4OlS0JOlstGvNu149Q2Ip3LzAT+8x9gxQrgb38TaRn4t5LUUkp7epKZKUqG5eQAH38sgm13rOtNRMQRb4oAvurQKvumTwdGjWLPetjk5QGnTwNVq4oeDyWbtS/MZk2kqR07xHb0aBFEMeimYLFaRUfO0qWeX1eu1VlZnHauO7w2G4+aezLSBEe8SfcCrUPLnvUwUEa7W7USwXcg2ayJKOyKi8X0YEAsqScKNn/Xatb11pElS0TSHIDXZiNyvycrKBA3xMXF3t/DDpiwYOBNuhdoDVBZFolesrLE9DeO6gSJc2bqnTuBNm2AZs2A9evFvrg4IC1Nu/YRkVe7d4uRxpo1Wd6JQkPttZp1vXWgbVter43OvcLIzp3lB0eyskRP2NixYs0mO2BCjoE36V5FbhLZsx5k3mqDbtsGfPKJeB4TI3pY+YebSHe2bxfb1q09Z6Amqiy112p2/IRQXBwQFcWRTSrPPRDPywOuu07cKK9YATzwgGtgzpkQIcHAm3QvkDq07tizHiSBZKbmH2oi3dm2TWw5zZxCxd+1mnW9Q8R5NhoADBkC/O9/QKdOwCOPAHXruvZ2MKAi98GUQ4eAbt1cj+FgSkgw8CbdU+rQjhghLtyBBN/sWSfSmJLkxVfHDUdgQs55xJsoFNRcq7OzufwrqLzNRgOAjRtFJkUGUOSOgymaYeBNEUGpFTpxorpEa+xZJ9IJL4n3HA4HioqKEBsbC0tCAi/uIcbAm8LB27W6Xj3g3/9mwtOgcB7h3rqVARRRBGHgTRHDuVZoQYHIEzFjhnjNuWddWb/InnUinXBfWwYAFy5A/vlnkeDnr7/KkvR5wqmRlcbAm8LF+Vr90kvA8uXA8OEMuoPC1wg3EekeA2+KKFara7K09u3L96wnJYmgmxd5Ip3asQPSFVegviwDv/wCdOzofyo6p0pW2JEjQFGReN6ypbZtIXNQrtWHD4vAe8MGrVtkEGqmCBORblm0bgBRZWRmAnv3ivwhANC5s6hVy6CbSMeaNwesVliOHwe+/lr9VEmqEGW0OzkZqFFD27aQuaSni+2mTcDFi9q2hYhIawy8KeJZrcCtt4rne/cCFv5WE+lbfj7QowcAQFq2TNu2mACnmZNWmjYF6tQR1a3+/FPr1hARaYshChnCZZcBVasCx48D+/Zp3RoDiosDoqN9H8PM1KTGpTWK0qX679LXX2vcIONj4E1akSSRxgHwncaBiMgMGHiTIURFifXeAPD779q2xZBSUoC//10879ABWLeu/INrcEkNrlEMOwbepCVlurl74G23A2vWAO+9J7Z2e7hbRmRSSplPXziYEhJMrkaG0aWLCLrXrwduvFHr1hiAc8kSALjmGjGtoG5d8TUzTRNFBAbepCVlxHvdurJ9NpvnxKhz5zJHS9AxgCJ3nsp8yrK4ed6/H3jmGeC223iPFwIMvMkwunQRW/cRb7u9rARZYqKo7c0yY36oKVnCTNNEuldSAuzeLZ4z8CYtKIH3xo3i93H5cmDECNcyoIBI/TBihKgDzuC7kpYsAdq2Fc/ZSU6eeCrzOXo0MHu2GMGaMkWbdhkcp5qTYXgKvG02IDUV6NcPGDVKbFNTxX7yQc10YGaaJtIVT1N3c3NFNulq1URWc6Jwa9kSqFkTOHcO2LJFjHS7B91A2b6sLE4790rtFOGMDNHjkZbGoJvUGzFCbFesAM6c0bYtBsURbzKMTp1EIpcDB4DCQuD779mrTmQInCrpl7epu7ffLp63bMmKD6QNi0V0jOfkAP/9r+vvqDtZFjNdc3JEHXByo0wRfuMN4OmngZ49gZdfdj2GI9xUUfXri2zFLVsCP/wgvnbG361KY+BNhlGzJtCqlbgm/fab7151SRK96sOGcdo5kW499ZTILcCLvU82m+dOxr/+ErMGAaBePTGKyL93pIW0NBFMq01+WlAQ2vZEtJQUsf42Lg5o3LhsLj9RZeTlAW3aiNmMf/4JeCr1ySWGlcb+bzIUZbr5smXqe9WJSIeefRa4915OlfTDbvfeyejs22+5zIa0o8SGSqI/fxITQ9cWQ2jbVowe3HST1i0ho+ASw7Bg4E2GogTemzerO5696kRhpnaN4i23cHq5Cjk5vjsZnSnLbBh8U7gVFYltbq7v4yRJ5CLIyAh9m4iIwo1TzclQlMB7/351x7NXnSjMLq1RdBw6hKKiIsTGxsLivviYU8tVC6TzkMtsSAs2GzB5sv/jJElss7P5u+nT6dPAJ58A7dqJ5DZEFDEYeJOhKIH3gQNiTeOxY56PkySReIi96kQaSEkBkpJQcugQkJDgOevXzz8Dq1aJNd7KB5vKCbTzkMmrKJzULoUAxDU5O5tJT/364w9RpqVxY/XTXYhIFxh4k6GsXSt6yu1230E3wF51n+LigKgooLjY+zHMNE2hNHeuqItltzPw9iEjQwQsgd5/c5kNhYPapRCtW4t8Trwmq7Bli9i2a6dtO4goYFzjTYahZPb1V/8zMZGlxPxKSQE+/hi46irg+uuBdevKP5jZkkKpZ0+x/eEHbduhY3a7CGz69Qv8vVxmQ+GgtoPn2DEG3aox8CaKWBzxJkNQM51NGQl/8UUG3R7l5blmq0xIAJ57ruw/letuKZyUwPvHHwGHg0Wo3Xiq260Gl9lQOKnt4Dl8WEywiooKbXsMQQm827bVth1kTlu3lj3nfWHAGHiTIaiZzqaMhOfkADffHPo2RZS8PDHXz1cpCdZvpHDJywNKSsTv3IkTwEcfAc2bl71u8ou9t7rdiuuuAz79VATZzsdwmQ2Fm7IUIj/f8++r8jspy8DevUCrVmFtXmTiiDeFglJxxF9JsdGjy57zvjBgHEIgQwhkveLq1aFrR8Ri/UbSC6UTqHv3st/JkSOB9PSyR+vW4jgT8je7R5KAjRuBDz8UuZecJSVxmQ2Fl9Uq0jUAZUG2QvlauWfftSt87YpYp08D+/aJ5wy8KZguVRwpXU64ZIn/9/C+MGAc8SZDCGS94pYtgJJMmYh0JpBOIBP2svub3aNkLY+LEyOIOTmiYzIxUYw+cqSbwi0zU3T4uC+NULKYv/uuiCV37tSsiZFj2zaxTUgA6tfXti1kPCkppryuhhMDbzIENdPZkpKAunWBzZuBNWvEIBoRUSRRO7unoEAE2SwZRnqQmSlqx3vqCPr1V3EMR7xVaNkSWL4cOHlS65YQUQUw8CZDUKazjRjhe13j2rUi8F69moE3EUUetbN7mLWc9MZbR1CLFmLLEW8V6tQBhg7VuhVEVEFc402GoUxn87WuUSm7s2ZN2JtHRFRpyuwebyQJSE5m1nKKHC1bii1HvInI6Bh4k6FkZop1jatXi3Vjq1cDubllyYSuvFJst20DXntNBOD+6n4TEemFc7Iqd8xaTpFIGfHeuxe4eFHTpujfvHmiysOZM1q3hIgqgFPNyXB8rWtcvRqoWlVc3B98UOxLShI3ssz0SxRBTFxLdNgwMeP0xAnX/UqyKv4to0iSmAhUrw6cPSuCb2UE3JTy8lyzRBcUAMePi+fFxSJDHQB89ZVIrmayv31EkY6BN5mGt9q3+fliv6nL7Kip3xgTI44j0gMT1xL99lsRdNerB3zwAXD4MLOWU+SSJDHqvWmTWOdt2sBbKaXor6oDAFx9tdia7G8fhZGa+8KoKNE5tH592Xv4u+gTA28yBV+1b2VZXPizssRIkilvXJX6jfn5on7jFVcAFreVKPyDSuGg5mLvzmTlxd5/X2yHDwcGDNC2LUTB0LKlCLyd13nb7SYrh6emlKI7k/3tozBS7guVGRgFBWJ0qri47JjiYuC668q+ZkeQXwy8yRTU1r7NyTFx+R2lfmOPHlq3hMzM/WK/davr6LbJXbwolngCwM03a9sWomBxz2xus3mu+81lYURh5FzXe/1616DbE3YE+cXAm0whkNq3RKQx54s9ASgb/fviC+DoUTExwLSdhGQ4zpnNuSyMiIyKWc3JFFj71o/Nm4G2bYEZM7RuCRG5sdmA1FRRDvHZZ8W+c+eA5cs1bRZR0Cgj3jt2+F4WBohlYaxGQkSRiCPeZApK7dv8fM8XdEkSrxu29q2vTKkA8OWXosbaN98A11/P9dxEOuFt9O/MGY7+kXEoI9579wIOh/fjuCyMiCIZA28yBaX27YgRIsj2FHwbtvZtIJlSc3KA9HQmyCDSAV9JIRWmTgpJhuFcUkwNLgsjokjEqeZkGpmZYnSocWPX/bVqGXzUqDKZUolIM4EkhSSKZEpJMbVMuyyMiCIaA28ylcxMMZVt9Wrg/vvFvmbNDBx0E0U6pbyYLwatMc+kkGQmzZuLbfXq3o+RJCA52aDLwtT8rXNn0L99REbFqeZkOlarWBvWrh0wfz6wcWNZnVAi0hn38mIA8PTTwB9/ALNmicWhBs1JwKSQZBY2G7BypXjubbq5JImtYZeFOf+tGzRIbF94AWjYsOyYunVdP/AG/dtHOqR0DPmaQcmOIL8YeJNpJSQAXbsCv/0mSvTceafWLSIij9zLixUWivTHAJCWpk2bwsD0SSHJFLwlEHSXlCSCbkPPUEtJEevflI7GceOA2rW1bRMRUL4TvLAQuPZa0Qv2/fdA1arsCFKBU83J1K65Rmw//1zbdhBRAFq1Elsl+DYoJSmkJ4Yf/SNTUJNAEBC/7zt2GDzoVvz5p9gmJzPoJn1JSRGd3WlpwODBopPIbhfbtDQG3Sow8CZTUwLvr78GSkq0bQsRqaTUHjJ44A2IQGPBgvL7k5IMnhSSTMFfAkGFkkjQFA4eBKpVA9q317olRN5JEtCmjXi+dau2bYkgDLzJ1Lp1A+rVEyWtn3oKWLNGdN4RkY4pI947d2rbjjCJihLbpk2Bd98VySFzcxl0U+QLJDGgST7uYt796dPAO+9o3RIi39q2FVsG3qpxjTeZ2scfl+WJmDlTPJKSxPROw9zUqkmI4Y4JMkjPlMB7+3YxFKbMuzYoZSnMTTcBt96qbVuIgimQxIC7doWuHbpjsYhRASI9u+EGcdPct6/4Oi/PdylargFn4E3m5S2hS36+2G+YaZxKQowhQ0Qm6EcfBa68UgzzK5gplSKJUvD3+HHg6FFDdxI5HMCXX4rnytIYIqNQk0CwZk3g1CkTjXgTRYobbxQPQATdrVv7z3q+fbup7y8ZeJMp+UroogygZWUBw4YZJHGRwyGCbosFmDTJtTwJUaSpVk0E31WrGj7wXrcOOHxY5K7p1Uvr1hAFl5JAcMQIcd11viYrE1lGjxalP00x4n34MNC/P9CxI/D22+KaTRQJjhzxP7Py/HlxnIkDb36iyZT8JXRRErnk5ISvTSH1wQdi26cPg24yhh07gC1bRA+7gSnTzAcMEP0MREaTmSlmmDVu7LpfSSA4cqT42hQj3n/8IR4//cSgmyJDfj6wciVw8qTWLYkIHPEmU1Kb0CWQxC+64r7OpnZt4KqrgN69gfXrOZWcIp/B13Xb7aLj7+23xdeDBmnbHqJQyswUM8xycsR1NzFRTEO3WsV9PQDs3QtcvGjwDqg//hBbZjSnSDF4sPi99Vb7klww8CZTUpvQJZDEL7rha53NqlUigxzX2RDpls0mlsI4z8qZOROIjzdI3gkiD6zWshxNzhITxeqSc+dE8K1UEzQkpYY3A2+KFG3bisA7N1frlkQEzmMhU1ISungbNJMkIDlZHBdxAllnQxSpNmwALr9cJAo0ECXpo/tSmIMHxX6bTZt2EWnFYinLp2j4dd7KiPdll2nbDiK1lJJiDLxVYeBNpqQkdAG8B9/Z2QZJrEZkRDVqAL/9JrKPORxatyYo/CV9BETSR7s9rM0i0pwyym3odd6yzBFvijzt2oktA29VGHiTaXlL6BIdbaBSYkRGlZoqesbOngUOHNC6NUFhuqSPRCqZYsT7wAFRItFqNXzSSDIQjngHhGu8ydScE7ps2CAqbZWUiAzCRKRjVasCzZqJIbAdO8TakQhn+KSPRBVk2BFv50SoO3eKv2kWS9nINxOhkt61aiV+Z0+dEiNXFy54PzYmxtDlP9Vg4E2mpyR06dsXePVV0aO+erUIyIlIx1q1Kgu8+/fXujWVZuikj0SVYMgRb1+JUNPTxZaJUEnvYmKApk2B3buBt97ynf2QHUkMvImcXX21uLB/+WWEBd7OveZbt2rbFqJwadUK+OwzwwyDKUkf8/M9r/OWJPF6RCZ9JKoE5V4+N9dAJcUCSYRq8mCFdO7xx8U2I0NMG3X+fc3LE2ukVq4U00ndE/uaLBhn4E3kZNAg4LXXgK++0rolAfDVa05kZK1aie2OHeVr17uLgIu7kvRxxIjyrylJIJn0kczIVCXFiCKFct3t3Fl8/fnnwN13A717i4tVcbGYjabcn86YUf57mGxWBwNvIif9+gFVqogZM7t3A82ba90iFdT0mrvjOhsygjZtRPBdp47/zqcIubhnZgLTp5e/P0lKEvcxTPpIZqSUFNu8WcxKY+BNpDFfgz7ffQd07QpERYng2xeTzepgVnMiJ7VqAb16iecvvwy89x6wZo1ByvcsWSJKL61bFxEBCJFPeXlA7driQ3rNNYaqXa/cpwwYALz7rsg5kZvLoJvMTVnnbZCVJUSRTc2gj7+g24Q44k3kRikvptT5BsRo09y5EX7j27YtkJamdSuIKs/gyyu+/lpsR48Gbr1V27YQ6YUyyh3RCdaYj4XI1Bh4Ezmx2cQIk7v8fLHuculS4IYbwt4sInJWkeUVEaKoCPjtN/GcZQ2JykT8iLfBOwyJyD9ONSe6xG4HJk70/JqSYTgryyDTzolIl1avFn9v2rYtm31DRKLENQD8/nuELgEzcIchEanDwJvokpwc4K+/vL8uy6IiQk5O+NpEROaiTDMfOFDbdhDpic0G3H67eF5YKBKhpqaK/YbGRKhEhsLAm+iSgoLgHkdEpJbdLkbx/vc/8XX//po2h0g3bDax1Mv92qssATNc8M1EqESGxTXeRJckJgb3uLCJiwOio4ELF7wfw15zItdkRjqq622ziWUuzjNuHnhABOMRndCRqJKUJWDKci9nsizq22dlAcOGGai+PROhkpH4KylmsvtTBt5El2RkiOzl+fmeL/KSJF7PyACOHg1/+7xKSQEefhh4+mngssuAxYvLH6OjIINIM6NHlz3XSV1vZTTP/W9OQUFZQkcG32RWgSwB69s3bM0iorg4cR31lbcgJgb45hsxOOTr+5jo/pSBN9ElVqsoGTZihAiynW+EJUlss7N10qvuXJJEloF33hHPlZTrJvtDRhQwpa63Rp8TZWr5uHEmG80jCgCXgBHpVEqK6LxW7kU98XQvumAB8NFHwOTJwFVXhbaNOsTAm8hJZqYYYXKf9tm4cVkdb4dDu/YB8F2S5OmnxUMno3lEIaGmp13HPE0t94SjeWR2EbsEjMgMUlICv8/87jtgxQqgQwdTBt5MrkbkJjMT2LtXzI6pV0/smz9fR9M91ZQkUUbziIxI6WlXEhC5P5Ys0bqFXilTy/0F3c44mkdmpSwBU2aduZMkIDlZHKd7cXFivasvJlvvSibUp4/Yfvuttu3QCEe8iTywWkW5kptuAt54A/jiC+C667RuFRGVqkhPu8Z8JYryhaN5ZFa+loApdLMEzJO8PFTZsQOIjQUsFtFDsGoVcPnl4o9B3bquH3AuEyOjUwLv334DzpwBatTQtj1hxsCbyIfrrhOB96efAi+/7L3XnYjIH3+Jotw5J3QkMitvS8AA4IUXXGej2e3ic1ZQIOLZjAwNg/K8PEht2yLO0wy1X38VyR65LIzMJjVV/L7n5QE//AAMHKh1i8KKU82JfOjfXyRj3LcP2LJF69YQUSQLZMq47hI6EmlIWQK2ejXw7rtA795i/6FDZcfYbOKevl8/YNQosU1N1bDO95EjkLgsjKg8E08354g3kQ81aoiL9xdfiOlu/foBDRqI3GZERIEIZMp4UpIIunWTW4JIY1ZrWZLBqCiRo+ndd4FnngGWLfNcli8/P4Rl+Zyri3jC5AxE5eXliR4xAPjss/IfTIMvt2DgTeRHUpLYvvmmeAAWJCbGY948cUEnIp1RW180zEmMlERR+fne13nHxgIffCACDI50E3k2ZAhQu7bI+j9vHvDkk2Euy+eruojCXyI1IrNx/9xs2ACkp7seY/DlFwy8iXyw2YD//Kf8/oMHLRg5MkS96ERUORWtLxpizomi3ClTy99805QVVogCEhMj7tdXrwYmTfJ9bEjK8qmpLlJcHKQfRmQQgVTlMWjgzTXeRF74ykAsy+IuOStLHBdWymieLyxJQmaXkgKkpZU9du8G3n9ffC7S0jS7qGdmAvfdV35/UhI78ojUstlE0B0IzvwmIq1pHni/+uqrSE1NRUxMDLp3745ffvnF5/HHjx/Hgw8+iMTERERHR6NVq1ZYsWJFmFpLZuIvA7EsS6W96GGljObdfbf4etiw8nWMDTxNh6hCnn8eeO45kU1YYxcuiO1tt4k1qqtXA7m5DLqJ1FA6xQPFsnxEpDVNp5q///77mDx5Ml5//XV0794d2dnZGDRoELZv346EhIRyxxcXF2PgwIFISEjA0qVL0bhxY+zbtw9169YNf+PJ8NT2jmvSi56SAhw+LJ737y9G8IjIuw4dRNC9eTMwfLimTfnxR7G9+WZg6FBNm0IUcViWj4gilaaB94svvohx48bhzjvvBAC8/vrr+Oyzz7BgwQI89thj5Y5fsGABioqK8MMPP6Bq1aoAgFQlMx5RkKntHdesF33TJrHt2FGjBhBFkPbtxfaPPzRtxvHjwNat4vkVV2jaFKKIZKiyfFwWRmQqmgXexcXFWLduHaZMmVK6z2KxYMCAAfhRGQ5ws3z5cvTo0QMPPvggPv74Y8THx2PUqFH4xz/+AauXv6gXLlzABWVeH4CTJ08CABwOBxwORxD/RcHhcDggy7Iu22Y2vXoBSUnSpQzEUrnXJUlGUhLQq5eMsJ8uWQYefRTSpk2Q27dH+Bugb/wc6V/Yz1G7drAAkP/4A3KIf6bdLkblCgpEx1xGRtlNv7i8WdC8uYz69TX42xEAfo70z4znqEEDQO1KyaQkGS++KOOGG4J8mXQ4KrRW0/H220CbNmU74uLEcLyJzp/emPEzpBmVnxuHw+HymdD7OQqkXZoF3keOHIHdbkcD8Re0VIMGDbBt2zaP79mzZw+++eYb3HbbbVixYgV27dqFBx54ABcvXsT06dM9vmf27NmYOXNmuf2HDx/GeX+Z9TTgcDhw4sQJyLIMi0XzJfimN2NGNMaNqwtJkt2CbxmyDAwefAaffFKM7t2Lw9+bfsMN4lFSAhw6FOYfrm/8HOlfuM+RJTERCQCwcycO7dsHVKsWkp/z2WfRmDq1NgoKyv4gJCba8eSTJzFkyAV8800NALXQufN5HDp0IiRtCBZ+jvTPjOeodWsgMTEeBw9aPHaKAzIACb16XcD77x+D1Rr8S2SVoiJUZJy6KCEBJUqNUgWv35oy42dIK2o/N0VFRShx+lzo/RydOnVK9bERVU7M4XAgISEBb7zxBqxWK9LT05Gfn4/nn3/ea+A9ZcoUTJ48ufTrkydPIjk5GfHx8ahdu3a4mq6aw+GAJEmIj4/X5S+X2dx5J1CnjoxJkyS3NWXiYv/mmzXx5puiV/2ll2QmR9IJfo70L+znKD4ecv36kI4eRUJREdClS9B/hM0GjBsnlauEcPCgBePG1cUHH8jYtEn87ejXL9pjLhM94edI/8x6jubNA0aORLlOcfG1eH7xYhQSE0P0GWvVCnJMDKQAB3BiY2MBnX/uzcasnyFNqPjcyDExiG3VyuVzovdzFOOv0pATzQLvuLg4WK1WFBYWuuwvLCxEw4YNPb4nMTERVatWdZlW3rZtWxw8eBDFxcWIiooq957o6GhER0eX22+xWHR58gBAkiRdt89sRowAbrxRTB39+GMgO1v0pjvLz5cwcqQUvnJA338PVK0q1q1Wrx6GHxh5+DnSv7Cfo/btgW+/hWXrVlEEOIjsdlFP2Fv5QUkCJk+WcGm1E3r0sCASfjX5OdI/M56jESNE+b2JE10TrSUlScjKAv7+d2DXLgkWi6cR8SBITRXVQw4dAq68Ejh3TtXbLBYLIuKDbzJm/AxpQvncHDlStu+tt0RPWno68MYbkOLiIHmoyqPncxRImzRrfVRUFNLT07Fq1arSfQ6HA6tWrUKPHj08vqdXr17YtWuXy1z6HTt2IDEx0WPQTRQsVqtYp7l0qefXlZvtsNX1fuQRoHt30RNAROq89hqwb5+o4xVk/ssPAvv3AydOiFnuzIlIVDmZmcDevaIcn3NZvnvuEa8XFQHHjoWwASkpQN26IuiOjhaJ0nxhIjUi8blJSyt7TJok9q9fL5KiGLwUrqZTzSdPnowxY8aga9eu6NatG7Kzs3HmzJnSLOd33HEHGjdujNmzZwMA7r//frzyyiuYOHEiHnroIezcuRPPPPMMJkyYoOU/g0yi7Mbacw+6cmOdkwP07RvChjgcoiQSwLt3okC0axeybx1IpuXLLweqRNRCLyJ9slrLX29r1hQJ2AoLgd27ga5dQ9iADRvEtmNH0TPvPJIHMaBUVFSE2NhYWBISDB9UEAUsNRWYMkUE4fXqad2akNP00n/zzTfj8OHDmDZtGg4ePIjOnTvjiy++KE24lpeX5zJ8n5ycjC+//BKTJk1Cx44d0bhxY0ycOBH/+Mc/tPonkInopq733r3A6dNAVJTIMkNEmgukrGDjxmJmjC7LGxEZQIsWYQq8f/9dbDt3FkG1e2DtcIgkUQkJnGJO5Elenlg7AgBbtpR/Xcn8bxCa97mPHz8e48eP9/jamjVryu3r0aMHfvrppxC3iqg83dT1Vup3X3YZh82IAuFwALNmiRkj//mPmCYaJBkZ4t5AlB/0fex774mZMXPnhiknBJHJNG8uUqHs3h3iH3TmjJhm3rlziH8QkQHl5YkBJF9JCmNigK1b/S/liBDsfiNSSbmxliTPd9WSBCQni+NCSgm8Oc2cKDAWC7BggUg//scfQf3WVqsIpNXKzxed/DZbUJtBRBCBNwDs2hXiH5SdLWagXVoiSUQBOHLEd9ANiNfdlnBEMgbeRCo531i7B9/SpWXf2dlhmD7KwJsocHl5InlLcrL4esUK8bXyyMur9I/IzBTLPGvV8n9s2BMyEplIixZiG/IRb0DMPKtWLQw/iIgiHQNvogBkZgIffCCjYUOHy/5GjRC6UmJKwKA8fvlF7K9WLWgBA5GhKdPZ0tOBH34Q+2bPFl8rj9atgxZ8d+smnl97re9jnRMyElHwKCPeYQm8iSi0tm1DlU2bDHHPy8CbKECZmcCvvx7GqlUONG4s9mVnhzDoVgIG5bF/v3jtgQeCGjAQGVYYp7PJsrg3AIBevdS9J+QJGYlMRhnxzs9XXWI7cC+9BHTqJMoUElHIWG6/HXGDBsFy+eURf8/LwJuoApQSJtdfL77+7rsQ/SATrn8himS5uaJ2cFSUKBumRsgTMhKZTGwsUKeOeL5nT4h+yK+/iqVfJ06E6AcQUTkRfs/LwJuoEvr0Edtvvw3iN3WeWr51axC/MRGF2rp1YtuxI9C/v5KQ0fOxYUvISGQykhSG6eZKDW9mNCcilSoUeK9evTrY7SCKSErgvXGjGOWqNPep5aNHB+GbElG4/Pab2KanuydkdD0urAkZiUxImW4ekszmZ88C27eL5wy8iUilCgXegwcPRvPmzfHUU09hv7LelMiEGjYEWrUS6zq//z4I31DN1HIi0i1lxLtrV7FVMp0r+SAUSUkhTMhIRMEf8XaejbZ0KeBwAPXqAQcOGCLpE1HYxcUZpj63WlUq8qb8/Hy8/fbbeOuttzBz5kz0798fd911F2644QZERUUFu41EunbllcCOHWK6+XXXad0aItKKLJcF3unpZfszM4Fhw0T28oICsaY7I4Mj3UShFNRa3spsNPeO8WPHynrZYmLEKHhKShB+IJEJpKSIz4yyZnvrVsPP9KzQiHdcXBwmTZqEDRs24Oeff0arVq3wwAMPoFGjRpgwYQI2btwY7HYS6VZI1nkTUcTZswc4fhyIjgYuu8z1NSUh4623ii2DbqLQCmotbyY6JQqNlBQgLU082rbVujUhV+nkamlpaZgyZQrGjx+P06dPY8GCBUhPT0dGRgb+/PPPYLSRSNeUwHvdOmDBAmDNGqC4WGzfe09s7XYNG0hkdmqms8XEiOMqQVnf3bGjyGpORNpRRrz37QMuXtS2LUREQCUC74sXL2Lp0qW49tpr0aRJE3z55Zd45ZVXUFhYiF27dqFJkya46aabgtlWIl369VcxeuVwAHfdBfTrB1SvLrajRoltaipgs4WoAUEIGIgMTZnOtm5d2ePzz8te//TToEwRdV/fTUTaadRIXB5LSrj8migihKmTXEsVWuP90EMP4b333oMsy7j99tvx3HPPoX379qWv16hRAy+88AIaNWoUtIYS6ZHNBowYIdZ2OnMf4c7PF8cFLZnSkiVlU3Li4rimjMiflJTyn5N+/YDVq4HNm4EhQyr9I5wzmhORtiwWoFkzYMsWMd1cGQEnIp1yX/N9icPhQFFREWJjY2FJSIjoe94KBd5btmzByy+/jMzMTERHR3s8Ji4ujmXHyNDsdmDixPJBtyeyLMoHZWWJJEuVXt/Ztq1YD0NEFZOXB/TqJQLvf/8buPpqkfns+HHxet26IguaMy+dXHa7yPHw00/i6y5dQtpyIlJJCbz/+1+x/INJDYl0zlMnucOBkkOHgIQE0aMWwSoUeE+fPh09e/ZElSquby8pKcEPP/yAK6+8ElWqVEEfZfErkQHl5AB//aX+eFkG9u8X7+vb18tByjQbX0lcInyaDZHm3DMU796tbpjaQ9Zim010wDn/Lbj+emDePJYKI9KSzSZyrADAwoXikZQEzJ3LzyYRaaNC3Qb9+vVDUVFRuf0nTpxAv379Kt0ookhQUBCC9zmvRR04UMxP/+IL17WpLFdCVDlqMhR74pa1WFlq4t4Bd+CA2B+yvA5E5JPy2Tx92nW/suyLn00i0kKFRrxlWYYkSeX2Hz16FDVq1Kh0o4gigfss1KC9LyUFiI0Fvv5afD1/Pke4iXTG11KToC8tISLVQvLZ5Gw0qiCHw4Hi4mKtmxHRHA4HLl68iPPnz8OiwVTzqlWrwhqkC3lAgXfmpbk5kiRh7NixLuu77XY7Nm3ahJ49ewalYUR6l5Ehpq3l56tb5y1J4viMDBXfXCnF17AhL+REOuRvqYmqpSVEFHRB+2zm5bkmeZo8GXjmGaB2beDll4H69V170pnolNwUFxcjNzcXDodD66ZENFmW4XA4cOrUKY8Dv+FQt25dNGzYsNI/P6DAu06dOgDEf0CtWrVQrVq10teioqJwxRVXYNy4cZVqEFGksFrFWrERI0RQrSb4zs5W2cO+aZPYduhQmSYSUYioXWpS0SUpRFQxQflsuueBcHbyJDBmjMecD0QKWZZRUFAAq9WK5ORkTUZqjUKWZZSUlKBKlSphD7xlWcbZs2dx6NAhAEBiRae7XhJQ4L1w4UIAQGpqKh5++GFOKyfTy8wUJcLckytZra4lxapWFVlVVSd02bxZbDt2DFpbiSh41F57K3mNJqIABeWzqSYPhJLzgYE3eVBSUoKzZ8+iUaNGqF69utbNiWhaBt4ASgeaDx06hISEhEpNO69Q98v06dMZdBNdkpkJ7N0rqhK9+67Ynj0rtvPni2MuXgR69AjgmyqBN0e8iXRJWWri7R5AkoDkZJVLS4goaPx9NgGRRsVud+0gJwom+6VfrqioKI1bQsGgdJ5cvHixUt9H9Yh3WloaVq1ahXr16qFLly4+exzWr19fqUYRRRqrtfxasb59xWPhQuCXX4AVK4C77lLxzWSZgTeRzjkvNXGnXB5VLy0hoqBRswysqAgYMIDlxSj0tFqTTMEVrPOoOvAeNmxYaTK1G264ISg/nMgMhgwRgfenn6oMvE+cEGvHLBagbduQt4/IdNRkKPbELWuxstTkllvErBZFUpIIunkzT6QNb8vA3CnlxZYu5eeViEJPdeA9ffp0j8+JyLfrrgOmTxfVwS5cAJyKAXhWt664UzhxAnBKYEhEQZKSIpIiOWcsBkS2pePHxfPNm4EtW4D+/YErrxT7PGQtvvpqoKREPH/1VaBdOzHVlSPdRNrKzBQlw9asAUaOFKPc7lj6jygySZKE3NxcpKamat2UgFSojjcRqdeli0jiUlAAzJsnRsMSE1XcnF+qIkBEIZCSEpSkSL/9Jm7ek5KABx4IQruIKGisVvHwFHQrWPqP9MxuF7+bBQUq7x0r6fDhw5g2bRo+++wzFBYWol69eujUqROmTZuGXr16ARBB7//+97+AZ0CnpqYiKysLWVlZQW+3LMuYPn063nzzTRw/fhy9evXC/Pnz0bJly6D/rMpQHXjXq1dP9fz2Il9/4YhMRpLEKFhBAfDoo2X7ubaMKPL9/LPYXnGFtu0gIs9Y+o8ilc1WfrlEqO8dhw8fjuLiYrz11lto1qwZCgsLsWrVKhw9ejQ0PzBInnvuOcybNw9vvfUWmjZtiqlTp2LQoEHYsmULYmJiAAB5eXlI0bgKgerAOzs7O4TNIDIumw1Ytar8fq9rywYPBhwO4KWXgMsuC1s7ichNcTGwbRvQsCGQkODxECXw7t49jO0iItUqVF5MTR4It5wPRMFks4l7RPfkgKHMS3D8+HHk5ORgzZo16NOnDwCgSZMm6NatW+kxytTuG2+8sfT1vXv3Yvfu3Zg8eTJ++uknnDlzBm3btsXs2bMxYMAAAEDfvn2xb98+TJo0CZMmTQIgRqkB4LvvvsOUKVPw22+/IS4uDjfeeCNmz56tuoKWLMvIzs7GE088gWHDhgEAFi9ejAYNGmDZsmW45ZZbAAB9+vRBgwYNMGbMGNxyyy2oV69eJf/HAqc68B4zZkwo20FkSHa76K30xOPaspISsSDtwgWu7ybS2o03inIEr78O3Huvx0MYeBPpm1JeLD/fc4ZzSRKvu5T+U/JAfPstcMcdIvfKypWuNco85Hwg8kaWRalZNex2YMIEz7+vyr3jxIkiM7+aaefVq/sur6eoWbMmatasiWXLluGKK64oTart7Ndff0VCQgIWLlyIwYMHl9a0Pn36NK699lo8/fTTiI6OxuLFizF06FBs374dKSkpsNls6NSpE+655x6MGzeu9Pvt3r0bgwcPxlNPPYUFCxbg8OHDGD9+PMaPH4+FCxf6bzSA3NxcHDx4sDTIB4A6deqge/fu+PHHH0sD77Vr1+Ltt9/GvHnzMGnSJFx//fUYM2aMy78j1FQH3idPnkTt2rVLn/uiHEdkdjk55TOqJiMPcbiU1EkGsB/4/T9A164AcnNF0F2jBhBhCSOIDKd9exF4b9rk8eW//gIOHBA3PunpYW4bEamipryYx9J/KSllI96XX84POVXK2bNAzZrB+V6yLK4/alMBnT4tbiv9qVKlChYtWoRx48bh9ddfR1paGvr06YNbbrkFHTt2BADEx8cDAOrWrYuGDRuWvrdTp07o1KlT6ddPPvkk/ve//2H58uUYP348YmNjYbVaUatWLZf3zZ49G7fddlvpuu+WLVti3rx56NOnD+bPn186TdyXgwcPAgAaNGjgsr9BgwalrwFAcnIyHn/8cTz++OP45ZdfsHjxYowdOxZVqlTBbbfdhrFjx6J9+/b+/6MqIaA13gUFBUhISEDdunU9rveWZRmSJJUWjScyO/c1Y8nIw3a0RjW4TV9zH0xLSgI2bBDP2atOpA3lJsJL4P3TT2LboYMYUSAiffJWXiw6Gnj3XR9TdpXrcOfOIW4hkT4MHz4cQ4YMQU5ODn766Sd8/vnneO655/Dvf/8bY8eO9fq+06dPY8aMGfjss89QUFCAkpISnDt3Dnl5eT5/3saNG7Fp0ya88847pftkWYbD4UBubi7ahqisbrdu3dCtWze8+OKLmDJlCl588UWsXLkSG5TPfIioDry/+eYbxMbGAgBWr14dsgYRGYn72rI4HCkfdHuyfXtZ73pMjPiawTdReF3q4cemTWXz+5wwsRpR5FDKi+XkAL//DkyeDFy86DbF3B0DbwqS6tXFyLMaa9cC117r/7gVK8qqXfr72YGIiYnBwIEDMXDgQEydOhV33303pk+f7jPwfvjhh/H111/jhRdeQIsWLVCtWjWMGDECxcXFPn/W6dOnce+992LChAnlXlObCE0ZQS8sLESi0413YWEhOnv57G7fvh1vv/02lixZghMnTmDcuHG46667VP28ylAdeCuL7N2fE5F3/taWqXL+vKg3zMCbKLxatwaqVgVOngT27Su3/IPru4kii9UqSob17QssWQKsXy+SWDmncHAu3zSouAbqVa8OiYE3VZIkqZvuDQBXX60uL8HVV4en9ny7du2wbNmy0q+rVq1abnbz999/j7Fjx5YmXTt9+jT27t3rckxUVFS596WlpWHLli1o0aJFhdvXtGlTNGzYEKtWrSoNtE+ePImff/4Z999/f+lxR44cwX//+1+8/fbbWLduHQYOHIh//vOfuOGGG1RNaQ8GS0XfeOzYMbzwwgu46667cNddd2HOnDksI0bkRllbBqhLbEFEOlK1qqgFCJSbbl5SAqxbJ54z8CaKPDffLLbvv1+2z2YT/Wv9+gGjRgH1f/sKqfVOwraljSZtJHPyde+ofO0xL0ElHT16FP3798eSJUuwadMm5Obm4sMPP8Rzzz1Xmi0cEJnNV61ahYMHD+LYsWMAxNpsm82GDRs2YOPGjRg1ahQcDofL909NTcXatWuRn5+PI0dErqN//OMf+OGHHzB+/Hhs2LABO3fuxMcff4zx48erbrckScjKysJTTz2F5cuXY/PmzbjjjjvQqFEjl1rj3bt3x/z58zF8+HDs378fn3/+OW655ZawBd1ABQPvtWvXIjU1FfPmzcOxY8dw7NgxzJs3D02bNsXatWuD3UaiiKasLWvcWOuWEFHAPKzzttuBRYtEspwaNYBKdNQTkUZGjhTbNWuA+fOBWbNEAjb3hKj7D1gxYqQFNlvYm0gm5u3eMSkpNKXEAJHVvHv37njppZdw5ZVXon379pg6dSrGjRuHV155pfS4OXPm4Ouvv0ZycjK6dOkCAHjxxRdRr1499OzZE0OHDsWgQYOQlpbm8v1nzZqFvXv3onnz5qVJ2jp27Ihvv/0WO3bsQEZGBrp06YJp06ahUaNGAbX90UcfxUMPPYR77rkHl19+OU6fPo0vvvjCJaj+7LPP8Oeff+LRRx91mZIeTpIsBz4BtkOHDujRowfmz59fmn7dbrfjgQcewA8//IDNmzcHvaHBcvLkSdSpUwcnTpzQZfZ1h8OBQ4cOISEhARZLhSckUAhV9BzZ7cC/H1iPe9+oQGbUdesAtz9g5B0/R/oXMefos89E0H311UB6Omy28gmakpLE6EQoboS0FDHnyMR4jirOZgNuvRXwtgRVggPypfEpZWpvbm5go4w8P/oXqnN0/vx55ObmomnTppUaUXVe+pCYKJYwhqnylW7IsoySkhJUqVKlNLm3JEnIzc0trSsear7OZyCxZYV+w3bt2oW///3vLjXPrFYrJk+ejF27dlXkWxIZntUKOM14IaJIMGQI7I9OwZpT6Zg0CRg+vPyIWH6+GCnjiBhRZLDZxGfWV96njzEMf6IdBuBryDKwf78IgIjCSclLcOutYmu2oNtoVCdXc5aWloatW7eidevWLvu3bt3qUsONiFy5lRgkIj3Ly8M3HxzB888DhYfEri5OLx9BHPYjpTTheVaWyJrMGyMi/bLbxawVf/M907EOjVCA0ygrvuxeIpSIKBCqA+9NTuvbJkyYgIkTJ2LXrl244lIdlZ9++gmvvvoq/vnPfwa/lURGEReHYksMohwqSooRkXby8mBv0Rr9L55Hfy+HnEMMWmN7afCtjIj17RvOhhJRIHJyys9acZeAQjRCARyQsBkdSvdrtCyUiNxMnz4ddevW1boZAVMdeHfu3BmSJMF5Sfijjz5a7rhRo0bhZiVVJBG5SknBW49vR8xTj+N2vCMKNa5c6Xu+W0wMEBcXvjYSEeyFR2C96LuDrBrOozdysA1tAYgR8IIClv0j0rOCAiAZeYjDEa/HtMUWAMAOtMIZ1Cxd4+2z5jcRhc2MGTO0bkKFqA68c3NzQ9kOItO47JoU/P2pB1FYvTn+npUBaf58Uafbm7g41vAmCrPffwe6qjjuXYwufX4OMdhg2Q6An1civUq15GE7WqMavHesXbx0e7wBnUNavomIzEV14N2kSZNQtoPINNLSgHVVe+Cnsz2Q2RxolgIG1kQ646svzJtqOI9uzY6AgTeRfnVrdgRWH0E3AFRFCQDgEOIxOGE9Hn4Y6N81DvxsE1FlVCi5mmLLli3Iy8tDsds02euvv75SjSIyspgYEXz//DPw449As2Zat4iI3FV0dQdHxIj0LZDP6AS8ggmFrwCPAJgaA2zfzo5yIqqwCgXee/bswY033ojNmze7rPtWaqvZ7fbgtZDIaL7/HnclHMUu9MRPP8XhttvEbtZqJNKPLl38H0NEJnL+vJgKw8CbiCqoQnW8J06ciKZNm+LQoUOoXr06/vzzT6xduxZdu3bFmjVrgtxEIoN5+WWM+2QY7sW/8NVXwHvvAbNmAampQL9+wKhRYpuayrrARFphpxcREREFU4VGvH/88Ud88803iIuLg8VigcViQe/evTF79mxMmDABv//+e7DbSWQcP/0kNrgCO3aIQNuT/HxgxAhg6VIgMzOM7SMiIiIi0ilJkpCbm4vU1FStmxKQCo142+121KpVCwAQFxeHAwcOABAJ2LZv3x681hEZTUEBsG8f7LDgF3TzeahSuS8rS0xDJ6IwiosTCRmIiIjCLS8PWL/e+yMvLyQ/9vDhw7j//vuRkpKC6OhoNGzYEIMGDcL3339feowkSVi2bFnA3zs1NRXZ2dnBa6wTm82Gq6++GvXr14ckSdiwYUNIfk5lVWjEu3379ti4cSOaNm2K7t2747nnnkNUVBTeeOMNNGOmKCKv7N//CCuAP9Aep1HL7/GyDOzfL9Z+9+0b8uYRkSIlBdi+He/MPYI5LwK3d92KSb+N9v8+IiKiysjLA1q3FnkFvIkJTbK/4cOHo7i4GG+99RaaNWuGwsJCrFq1CkePHg3qzwm2M2fOoHfv3hg5ciTGjRvn8Zi8vDykaJyjoUIj3k888QQcDgcAYNasWcjNzUVGRgZWrFiBefPmBbWBRBHPqdfy0BsfAwB2oQW6YD26YD2S4b/XsqAg1I0konJSUrCyKA2/Iw3oneF/BDwmpuLp0IkoPDibhfTuyBHfQTdQluwviI4fP46cnBw8++yz6NevH5o0aYJu3bphypQppRWrlKndN954IyRJKv169+7dGDZsGBo0aICaNWvi8ssvx8qVK0u/d9++fbFv3z5MmjQJkiSVJuQGgO+++w4ZGRmoVq0akpOTMWHCBJw5cyagtt9+++2YNm0aBgwY4PWYMWPGoH379nj++edRoNGNdYUC70GDBiHz0qLTFi1aYNu2bThy5AgOHTqE/v37B7WBRBFN6bVMTwfS05H49WIAwHDYsB7pWI90bEdrv8F3YmI4GktE7jZtEtvUK8UIONatE4+ffwaiosSLNpvYx1JDRPqX4vZZXrcOWLJE61aRWZw54/3hL9iuyPcNQM2aNVGzZk0sW7YMFy5c8HjMr7/+CgBYuHAhCgoKSr8+ffo0rr32WqxatQq///47Bg8ejKFDhyLv0pR4m82GpKQkzJo1CwUFBaWB7+7duzF48GAMHz4cmzZtwvvvv4/vvvsO48ePr+j/hFcffPAB7rnnHrz//vtITk7Gtddei/fffx/nK/P/HqAKBd7O9u/fj/379yM2Ntal94KIoKrXshrOIw6eey0lCUhOFqXFiCi8SkqAP/8Uzzt2hLhhT0sTj27dgK5dxYunTol9DLqJIoPzZzktTVxkOaOFwqFmTe+P4cMr/n1TUz1/zwBUqVIFixYtwltvvYW6deuiV69eePzxx7FJ6YEGEB8fDwCoW7cuGjZsWPp1p06dcO+996J9+/Zo2bIlnnzySTRv3hzLly8HAMTGxsJqtaJWrVpo2LAhGjZsCACYPXs2brvtNmRlZaFly5bo2bMn5s2bh8WLFwc9II6Pj8eECRPw22+/YfPmzejYsSMefvhhJCYm4r777sNPl5Ifh1KFAu+SkhJMnToVderUQWpqKlJTU1GnTh088cQTuHjxYrDbSGRKSj9WdjZLGxFpYccO4MIFce/StKmHA664Qmx//jms7SKiSsrPB95/v2xE0NMo+Lp1GNNhHdKwDl/N5owWMofhw4fjwIEDWL58OQYPHow1a9YgLS0NixYt8vm+06dP4+GHH0bbtm1Rt25d1KxZE1u3bi0d8fZm48aNWLRoUeloe82aNTFo0CA4HA7k5uYG8V/mqm3btvjnP/+Jffv24bHHHsOCBQswePDgkP08RYWSqz300EOw2Wx47rnn0KNHDwCixNiMGTNw9OhRzJ8/P6iNJDKjpCQRdLOUGJE2lE7+Dh0Ai6du6u7dxZaBN5G+5eW5rod96y1g3jygRw/glVfESHZKSrnAunov4PfNwOoTwNWMuSkYTp/2/lplRln27q34e93ExMRg4MCBGDhwIKZOnYq7774b06dPx9ixY72+5+GHH8bXX3+NF154AS1atEC1atUwYsQIFBcX+/xZp0+fxr333osJEyaUey2UidD279+Pd955B2+//TZyc3Nx00034c477wzZz1NUKPB+99138d///hfXXHNN6b6OHTsiOTkZt956KwNvogpISgKGDQNefRWoVg3YsweoUqFPKBEFgxJ4d+zo5QAl8N64ETh3TnxwiUhffGWI/vFHkYPFS4bozp3FVqeViSgS1agRWd8XQLt27VzKh1WtWhV2tzq333//PcaOHYsbb7wRgAio97p1BkRFRZV7X1paGrZs2YIWLVqEpO3OTp06hY8++giLFy/Gt99+i549e2Ly5Mm46aabULt27ZD/fKCCgXd0dLTHguVNmzZFlJJshohUe+NfQJe7AIcDeOMNcQ//119iyQ4RacNv4J2SIu7MmzQBjh1j4E2kR4FkiPYSeP/+e2iaRqQnR48exU033YS//e1v6NixI2rVqoXffvsNzz33HIYNG1Z6XGpqKlatWoVevXohOjoa9erVQ8uWLWGz2TB06FBIkoSpU6eWVsByft/atWtxyy23IDo6GnFxcfjHP/6BK664AuPHj8fdd9+NGjVqYMuWLfj666/xyiuvqG57UVER8vLycODAAQDA9u3bAcBlPfkNN9yAPXv24Pbbb8ebb76J5s2bV/a/LGAVWuM9fvx4PPnkky4Z7y5cuICnn346JFnoiIyua1cxw6hqVaBtW7Fv82Zt20Rkdn4Db0kSd+TLlgGNGoWrWUQUJh06iI95YSEwfz6wZg3gNmBHFHxqSt6FINlfzZo10b17d7z00ku48sor0b59e0ydOhXjxo1zCYLnzJmDr7/+GsnJyejSpQsA4MUXX0S9evXQs2dPDB06FIMGDUJaWprL9581axb27t2L5s2blyZl69ixI7799lvs2LEDGRkZ6NKlC6ZNm4ZGAV5Tly9fji5dumDIkCEAgFtuuQVdunTB66+/XnrMa6+9hj179mDWrFmaBN1AACPemW4LTVeuXImkpCR06tQJgFgc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koTs7GzrMSO+lhh468T777+P6dOnY86cOdi3bx/S09MxePBglJSUaN20kHX99dejsLDQ+vXll19a75s2bRr+/e9/44MPPsDWrVvxv//9D1lZWRq21vguX76M9PR0LF261On9L730El599VW8/vrr2LVrFxo1aoTBgwejvLzces6ECRNw+PBhbNy4EZ9++im++OILPPDAA4H6FQzPUx8BwJAhQ+xeV6tWrbK7n33kX1u3bsUjjzyCr776Chs3bsTVq1dx++234/Lly9ZzPL2/VVdXY9iwYaisrMSOHTvwz3/+EytWrMCzzz6rxa9kKGr6BwAmT55s9zp66aWXrPexf/zLbDZj4cKF2Lt3L/bs2YOBAwdixIgROHz4MAC+fvTAUx8BfA3pye7du/HGG28gLS3N7rghX0sy6UKvXr3kRx55xPpzdXW13Lx5c3nBggUatip0zZkzR05PT3d63/nz5+UGDRrIH3zwgfVYfn6+DEDeuXNngFoY2gDIa9eutf5ssVjk5ORk+S9/+Yv12Pnz5+XIyEh51apVsizL8pEjR2QA8u7du63nrF+/XpYkST516lTA2h4qHPtIlmX5/vvvl0eMGOHyMeyjwCspKZEByFu3bpVlWd3723/+8x85LCxMLioqsp6zbNkyOSYmRq6oqAjsL2Bwjv0jy7J86623ylOnTnX5GPZP4DVr1kx+8803+frRMaWPZJmvIT0pKyuT27dvL2/cuNGuX4z6WuKMtw5UVlZi7969yMzMtB4LCwtDZmYmdu7cqWHLQtuxY8fQvHlzXHvttZgwYQIKCgoAAHv37sXVq1ft+uu6665Damoq+0sjJ06cQFFRkV2fNG3aFL1797b2yc6dOxEbG4uePXtaz8nMzERYWBh27doV8DaHqry8PCQmJqJjx454+OGHcfbsWet97KPAu3DhAgAgLi4OgLr3t507d6JLly5ISkqynjN48GBcvHjRbkaJ6s+xfxTvvvsu4uPjccMNN2DmzJm4cuWK9T72T+BUV1dj9erVuHz5MjIyMvj60SHHPlLwNaQPjzzyCIYNG2b3mgGMey0K17oBBJw5cwbV1dV2fzgAkJSUhO+++06jVoW23r17Y8WKFejYsSMKCwsxb9483HLLLTh06BCKiooQERGB2NhYu8ckJSWhqKhImwaHOOX/3dlrSLmvqKgIiYmJdveHh4cjLi6O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w4YNWLBgAYYPH4777rsPgFg63adPHyxcuBBt2rRBSUkJZs+erer527dvj5ycHNx5552QJAnPPPNMrRno1q1b44svvsDdd9+NyMhIxMfH13qeJ598EmPHjkW3bt2QmZmJf//738jJybHLkF4XgwcPxh/+8AdUV1fDZDIBAB577DH07dsXixYtwogRI/D5559jw4YNtdp84sQJHDhwAGazGU2aNEFkZCQAkbDtz3/+c73aRURE5E+c8SYiIgqgDRs2ICUlBa1bt8aQIUOwZcsWvPrqq1i3bp01EAWAt956C1VVVejRoweys7Ptsny78/LLL6NZs2a46aabcOedd2Lw4MHo3r273Tnz58/HyZMn0bZtW5dLtEeOHIklS5Zg0aJFuP766/HGG2/g7bffRv/+/ev8uwPA0KFDER4ebhfA9+nTB8uXL8eSJUuQnp6O//73v7UGGkaPHo0hQ4ZgwIABSEhIwKpVqwAAO3fuxIULFzBmzJh6tYuIiMifJNl2AxkRERGRny1duhSffPIJPv/883o/17hx45Ceno5Zs2b5oGVERET+waXmREREFFAPPvggzp8/j7KyMjRp0qTOz1NZWYkuXbpg2rRpPmwdERGR73HGm4iIiIiIiMiPuMebiIiIiIiIyI8YeBMRERERERH5EQNvIiIiIiIiIj9i4E1ERERERETkRwy8iYiIiIiIiPyIgTcRERERERGRHzHwJiIiIiIiIvIjBt5EREREREREfsTAm4iIiIiIiMiPGHgTERERERER+dH/By9hj+f04sliAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "draw_rabi(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/experiments/rabi.png b/experiments/rabi.png new file mode 100644 index 00000000..57da7ca1 Binary files /dev/null and b/experiments/rabi.png differ diff --git a/experiments/rabi.py b/experiments/rabi.py new file mode 100644 index 00000000..142007f6 --- /dev/null +++ b/experiments/rabi.py @@ -0,0 +1,106 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices +import re + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token("") +set_provider("tencent") +ds = list_devices() +print(ds) + +# TQASM 0.2; +# QREG a[1]; +# defcal rabi_test a { +# frame drive_frame = newframe(a); +# play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); } +# rabi_test a[0]; +# MEASZ a[0]; + +def gen_parametric_waveform_circuit(t): + qc = Circuit(1) + + param0 = Param("a") + + builder = qc.calibrate("rabi_test", [param0]) + builder.new_frame("drive_frame", param0) + builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + qc.add_calibration('rabi_test', ['q[0]']) + + tqasm_code = qc.to_tqasm() + + print(tqasm_code) + return qc + + +def run_circuit(qc): + device_name = "tianji_m2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + return rf + + + +def exp_rabi(): + result_lst = [] + for t in range(1, 4, 2): + qc = gen_parametric_waveform_circuit(t) + result = run_circuit(qc) + result['duration'] = t + result_lst.append(result) + return result_lst + + + +def draw_rabi(result_lst): + data = { + 'duration': [], + '0': [], + '1': [] + } + + for result in result_lst: + data['0'].append(int(result['0']) / shots_const) + data['1'].append(int(result['1']) / shots_const) + data['duration'].append(result['duration']) + + + + + plt.figure(figsize=(10,6)) + plt.plot(data['duration'], data['0'], 'b-o', label='State |0>') + plt.plot(data['duration'], data['1'], 'r--s', label='State |1>') + + + plt.title('Rabi Oscillation Experiment') + plt.xlabel('Duration (dt)') + plt.ylabel('Probability') + plt.grid(alpha=0.3) + plt.legend() + plt.tight_layout() + + + plt.savefig('rabi.png', dpi=300) + plt.show() + + +data = exp_rabi() +draw_rabi(data) diff --git a/experiments/rabi_grpc.sh b/experiments/rabi_grpc.sh new file mode 100644 index 00000000..7e3e6b0b --- /dev/null +++ b/experiments/rabi_grpc.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +echo "duration,count0,count1" > rabi_data.csv + +for t in $(seq 1.0 2.0 400.0); do + formatted_t=$(printf "%.1f" $t) + ./GRPCtest 127.0.0.1:2023 60GmonTa 15 1000 1 "TQASM 0.2;\\QREG a[1];\\defcal rabi_test a {frame drive_frame = newframe(a); \\play(drive_frame, cosine_drag($formatted_t, 0.2, 0.0, 0.0)); \\} rabi_test a[0];\\MEASZ a[0];" > tmp.log + + count0=$(grep -A1 'key: "0"' tmp.log | grep 'value:' | awk '{print $NF}') + count1=$(grep -A1 'key: "1"' tmp.log | grep 'value:' | awk '{print $NF}') + + echo "$t,$count0,$count1" >> rabi_data.csv + echo "已采集 duration=$t 的数据: 0: $count0 , 1: $count1" + + rm tmp.log +done \ No newline at end of file diff --git a/experiments/requirements.txt b/experiments/requirements.txt new file mode 100644 index 00000000..7664be2d --- /dev/null +++ b/experiments/requirements.txt @@ -0,0 +1,2 @@ +matplotlib==3.8.2 +tensorcircuit==0.12.0 diff --git a/nohup.out b/nohup.out new file mode 100644 index 00000000..9027e401 --- /dev/null +++ b/nohup.out @@ -0,0 +1,2467 @@ +[W 2025-06-06 18:35:36.833 ServerApp] A `_jupyter_server_extension_points` function was not found in notebook_shim. Instead, a `_jupyter_server_extension_paths` function was found and will be used for now. This function name will be deprecated in future releases of Jupyter Server. +[I 2025-06-06 18:35:36.834 ServerApp] jupyter_lsp | extension was successfully linked. +[I 2025-06-06 18:35:36.838 ServerApp] jupyter_server_terminals | extension was successfully linked. +[I 2025-06-06 18:35:36.841 ServerApp] jupyterlab | extension was successfully linked. +[I 2025-06-06 18:35:36.845 ServerApp] notebook | extension was successfully linked. +[I 2025-06-06 18:35:37.209 ServerApp] notebook_shim | extension was successfully linked. +[I 2025-06-06 18:35:37.250 ServerApp] notebook_shim | extension was successfully loaded. +[I 2025-06-06 18:35:37.252 ServerApp] jupyter_lsp | extension was successfully loaded. +[I 2025-06-06 18:35:37.253 ServerApp] jupyter_server_terminals | extension was successfully loaded. +[I 2025-06-06 18:35:37.255 LabApp] JupyterLab extension loaded from /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/jupyterlab +[I 2025-06-06 18:35:37.255 LabApp] JupyterLab application directory is /Library/Frameworks/Python.framework/Versions/3.10/share/jupyter/lab +[I 2025-06-06 18:35:37.255 LabApp] Extension Manager is 'pypi'. +[I 2025-06-06 18:35:37.258 ServerApp] jupyterlab | extension was successfully loaded. +[I 2025-06-06 18:35:37.260 ServerApp] notebook | extension was successfully loaded. +[I 2025-06-06 18:35:37.261 ServerApp] Serving notebooks from local directory: /Users/yuanhe/tensorcircuit +[I 2025-06-06 18:35:37.261 ServerApp] Jupyter Server 2.12.5 is running at: +[I 2025-06-06 18:35:37.261 ServerApp] http://V_ANYUHE-MC0:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.261 ServerApp] http://127.0.0.1:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.261 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). +[C 2025-06-06 18:35:37.265 ServerApp] + + To access the server, open this file in a browser: + file:///Users/yuanhe/Library/Jupyter/runtime/jpserver-11002-open.html + Or copy and paste one of these URLs: + http://V_ANYUHE-MC0:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 + http://127.0.0.1:8080/tree?token=dd8859251abd1568e7ad5fd9b9d3752eb044fe00d2629b01 +[I 2025-06-06 18:35:37.523 ServerApp] Skipped non-installed server(s): bash-language-server, dockerfile-language-server-nodejs, javascript-typescript-langserver, jedi-language-server, julia-language-server, pyright, python-language-server, python-lsp-server, r-languageserver, sql-language-server, texlab, typescript-language-server, unified-language-server, vscode-css-languageserver-bin, vscode-html-languageserver-bin, vscode-json-languageserver-bin, yaml-language-server +[I 2025-06-06 18:35:51.929 ServerApp] Kernel started: 49917d1f-ff43-4a11-89a9-94bf2d206d7d +[I 2025-06-06 18:35:52.390 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:37:08.420 ServerApp] 302 GET / (@10.96.56.35) 0.34ms +[I 2025-06-06 18:37:08.426 JupyterNotebookApp] 302 GET /tree? (@10.96.56.35) 0.37ms +[W 2025-06-06 18:37:17.452 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:19.121 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.88ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:30.322 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[W 2025-06-06 18:37:38.188 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.91ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:37:51.836 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:38:16.849 ServerApp] Kernel interrupted: 49917d1f-ff43-4a11-89a9-94bf2d206d7d +[I 2025-06-06 18:38:21.911 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:e26a9209-3bbf-4db4-b22f-5a2bbb453850 +[W 2025-06-06 18:38:36.795 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.95ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:38:42.885 ServerApp] 302 GET / (@10.96.56.35) 0.35ms +[I 2025-06-06 18:38:42.891 JupyterNotebookApp] 302 GET /tree? (@10.96.56.35) 0.42ms +[W 2025-06-06 18:38:44.357 ServerApp] 401 POST /login?next=%2Ftree%3F (@10.96.56.35) 0.93ms referer=http://10.96.56.18:8080/login?next=%2Ftree%3F +[I 2025-06-06 18:39:55.928 ServerApp] User 8a3ac88ad2984ca1a9015545763aa000 logged in. +[I 2025-06-06 18:39:55.929 ServerApp] 302 POST /login?next=%2Ftree%3F (8a3ac88ad2984ca1a9015545763aa000@10.96.56.35) 1.14ms +[I 2025-06-06 18:40:10.278 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:42:10.243 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:44:10.275 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:46:10.308 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:48:10.338 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:50:00.936 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:50:00.950 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:50:00.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:51:06.475 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:52:18.733 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 18:52:59.140 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:52:59.141 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:52:59.148 ServerApp] Replaying 16 buffered messages +[I 2025-06-06 18:53:37.941 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:53:37.952 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:53:37.952 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:54:34.164 ServerApp] 302 GET / (@10.96.56.17) 0.31ms +[I 2025-06-06 18:54:34.180 JupyterNotebookApp] 302 GET /tree? (@10.96.56.17) 0.38ms +[I 2025-06-06 18:55:01.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 18:55:03.755 ServerApp] User c83a602e3b2b49ab938fe23884616702 logged in. +[I 2025-06-06 18:55:03.755 ServerApp] 302 POST /login?next=%2Ftree%3F (c83a602e3b2b49ab938fe23884616702@10.96.56.17) 0.78ms +[I 2025-06-06 18:55:14.530 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 18:57:38.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:165040ce-03f4-44cf-ad52-8baf106e91c8 +[I 2025-06-06 19:10:19.624 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-06 19:10:23.602 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:11:47.415 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:27:29.684 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:27:29.685 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:28:53.494 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:44:21.186 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 19:44:21.187 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 19:45:45.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:01:27.156 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:01:27.157 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:02:50.982 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:36:48.118 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:36:48.118 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:38:41.939 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:53:34.081 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 20:53:34.082 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 20:54:57.927 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:10:08.085 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:10:08.085 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:11:31.935 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:27:36.142 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:27:36.143 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:28:59.964 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:44:29.143 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 21:44:29.144 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 21:45:52.962 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:11:12.266 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:11:12.267 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:12:36.094 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:29:10.872 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:29:10.872 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:30:34.694 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 22:46:25.940 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 22:46:25.940 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[W 2025-06-06 22:47:55.940 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-06 22:48:00.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:13:39.608 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:13:39.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:15:33.427 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:30:16.059 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:30:16.060 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:31:39.886 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:56:47.677 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-06 23:56:47.677 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-06 23:58:41.510 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:13:43.477 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:13:43.477 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:15:07.326 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:31:37.153 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:31:37.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:33:00.980 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:47:38.096 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 00:47:38.096 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 00:49:01.918 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:14:31.482 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:14:31.483 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:16:25.337 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:31:42.282 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:31:42.282 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:33:06.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:47:43.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:47:43.929 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:49:07.753 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 01:58:44.349 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 01:58:44.350 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:00:08.169 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:14:46.790 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 02:14:46.791 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:16:10.617 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:cafbe407-8345-461e-b7cc-c01cf8ad8bd5 +[I 2025-06-07 02:38:57.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 02:40:21.808 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:11:24.434 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:11:24.436 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:12:48.265 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:28:20.248 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:28:20.249 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:29:44.071 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:45:04.969 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 03:45:04.970 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 03:46:28.793 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:01:15.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:01:15.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:02:39.806 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:19:18.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:19:18.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:20:42.666 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:37:13.963 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:37:13.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:38:37.798 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:56:42.180 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 04:56:42.181 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 04:58:06.005 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:12:31.225 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:12:31.226 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 05:14:01.226 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 05:14:06.229 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:28:57.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:28:57.332 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:30:21.155 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:57:53.539 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 05:57:53.540 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 05:59:47.379 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:16:33.320 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:16:33.320 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:17:57.141 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:33:49.999 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:33:49.999 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:35:13.823 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 06:59:11.973 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 06:59:11.974 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:00:35.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:16:51.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:16:51.987 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:18:15.806 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:35:25.686 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:35:25.687 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:36:49.509 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:58:22.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 07:58:22.891 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 07:59:46.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:15:27.488 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 08:15:27.489 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:16:51.309 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:34:00.188 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 08:34:00.201 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 08:35:54.309 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:00:49.218 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:00:49.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:02:13.039 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:19:12.732 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:19:12.732 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:20:36.556 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:37:40.318 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:37:40.318 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:39:04.139 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 09:59:29.541 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 09:59:29.542 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:00:53.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:16:22.231 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 10:16:22.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:17:46.051 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:32:53.211 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 10:32:53.212 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 10:34:17.032 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:08:41.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:08:41.761 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:10:35.578 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:27:19.697 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:27:19.698 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:28:43.517 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:45:40.860 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 11:45:40.861 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 11:47:04.688 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:01:27.545 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:01:27.545 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:02:51.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:18:18.700 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:18:18.700 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:19:42.524 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:34:03.435 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:34:03.436 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:35:27.280 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:46:37.059 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 12:46:37.059 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 12:48:00.879 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:04:23.710 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:04:23.710 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:05:47.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:21:34.852 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:21:34.852 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:22:58.672 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:47:14.061 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 13:47:14.062 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 13:49:07.892 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:05:43.730 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:05:43.730 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:07:07.555 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:23:28.433 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:23:28.433 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:24:52.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:40:49.050 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 14:40:49.050 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 14:42:12.895 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:05:16.299 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:05:16.299 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:06:40.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:22:19.293 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:22:19.293 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:23:43.114 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:40:45.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 15:40:45.973 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 15:42:09.796 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:06:05.097 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:06:05.097 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:07:28.917 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:23:09.644 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:23:09.644 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:25:03.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:41:49.729 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 16:41:49.729 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 16:43:13.553 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:07:00.089 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:07:00.089 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:08:23.910 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:23:07.768 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:23:07.768 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:24:31.594 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:40:50.739 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:40:50.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:42:14.564 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:51:41.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 17:51:41.549 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 17:53:05.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:09:11.095 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 18:09:11.096 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:10:34.906 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:40:27.685 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 18:40:27.685 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 18:42:21.497 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:20:18.158 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:20:18.159 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:21:41.986 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:37:33.558 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:37:33.558 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:38:57.384 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:53:27.356 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 19:53:27.356 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 19:54:51.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:10:11.161 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:10:11.162 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 20:11:41.162 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 20:11:46.163 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:26:14.204 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:26:14.204 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 20:27:44.205 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 20:27:49.208 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:42:17.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 20:42:17.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 20:43:41.040 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:09:39.832 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 21:09:39.833 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:11:33.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:41:42.294 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 21:41:42.294 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 21:43:06.114 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:12:00.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:12:00.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-07 22:13:30.984 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-07 22:13:35.986 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:29:43.721 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:29:43.721 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:31:07.544 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:47:46.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 22:47:46.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 22:49:10.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:13:36.152 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:13:36.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:14:59.972 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:29:46.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:29:46.210 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:31:10.031 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:45:38.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-07 23:45:38.875 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-07 23:47:02.694 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:13:03.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:13:03.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:14:57.080 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:31:29.816 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:31:29.817 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:32:53.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:48:33.510 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:48:33.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:49:57.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 00:58:36.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 00:58:36.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:00:00.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:16:43.902 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:16:43.903 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:18:07.731 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:34:39.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:34:39.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:36:03.377 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:50:27.280 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 01:50:27.281 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 01:51:51.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:16:48.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:16:48.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:18:12.285 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:32:54.196 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:32:54.197 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:34:18.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:56:27.904 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 02:56:27.904 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 02:58:21.730 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:14:04.897 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:14:04.899 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:15:28.724 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:33:45.311 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:33:45.312 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:35:09.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:49:38.931 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 03:49:38.932 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 03:51:02.750 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:05:36.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:05:36.601 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:07:00.420 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:22:12.427 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:22:12.428 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:23:36.252 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:38:34.419 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:38:34.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:39:58.242 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:54:41.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 04:54:41.219 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 04:56:05.043 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:12:39.911 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:12:39.911 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:14:03.731 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:29:26.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:29:26.886 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:30:50.725 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:57:20.757 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 05:57:20.757 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 05:58:44.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:18:22.900 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:18:22.901 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:19:46.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:36:30.562 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:36:30.562 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:37:54.391 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:53:42.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 06:53:42.653 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 06:55:06.476 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:10:33.267 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:10:33.267 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:11:57.089 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:26:20.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:26:20.874 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:27:44.698 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:43:58.879 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 07:43:58.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 07:45:22.701 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:02:23.533 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:02:23.534 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:03:47.356 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:21:04.205 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:21:04.205 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:22:28.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:39:03.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:39:03.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:40:27.803 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:55:08.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 08:55:08.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 08:56:32.475 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:18:26.225 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:18:26.226 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:19:50.050 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:36:18.797 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:36:18.798 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:37:42.620 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:54:59.804 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 09:54:59.805 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 09:56:23.627 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:20:21.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:20:21.820 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:21:45.644 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:36:50.989 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:36:50.990 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:38:14.811 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:54:07.695 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 10:54:07.695 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 10:55:31.552 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:23:01.868 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 11:23:01.869 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:24:55.707 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 11:46:14.668 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 11:46:14.669 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 11:47:44.668 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-08 11:47:49.673 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:04:18.858 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:04:18.859 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:05:42.678 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:21:48.563 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:21:48.564 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:23:42.385 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:40:45.823 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:40:45.823 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:42:09.649 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 12:59:10.526 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 12:59:10.526 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:00:34.350 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:24:07.419 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:24:07.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:25:31.237 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:41:34.008 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:41:34.009 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:42:57.830 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 13:58:47.578 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 13:58:47.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:00:11.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:25:06.709 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 14:25:06.710 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:26:30.527 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:43:06.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 14:43:06.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 14:45:00.825 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:08:56.164 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:08:56.165 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:10:19.991 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:26:08.822 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:26:08.823 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:27:32.644 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:44:06.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 15:44:06.421 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 15:45:30.246 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:00:03.768 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:00:03.769 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:01:27.590 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:26:22.959 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:26:22.960 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:27:46.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:42:23.007 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 16:42:23.007 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 16:43:46.833 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:01:02.707 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:01:02.708 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:02:26.533 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:28:20.207 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:28:20.208 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:29:44.024 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:45:43.282 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 17:45:43.283 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 17:47:07.106 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:01:30.984 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:01:30.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:02:54.796 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:28:19.340 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:28:19.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:30:13.160 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:45:15.687 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 18:45:15.688 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 18:46:39.516 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:02:33.411 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:02:33.412 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:03:57.234 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:30:20.609 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:30:20.609 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:31:44.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 19:59:42.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 19:59:42.785 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:01:06.604 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:30:18.936 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 20:30:18.937 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:32:12.757 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 20:49:16.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 20:49:16.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 20:50:46.530 ServerApp] WebSocket ping timeout after 90002 ms. +[I 2025-06-08 20:50:47.996 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:05:10.669 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:05:10.670 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:06:34.491 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:32:27.142 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:32:27.142 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:33:50.961 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:49:55.605 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 21:49:55.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 21:51:19.432 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:08:20.107 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:08:20.107 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-08 22:09:50.109 ServerApp] WebSocket ping timeout after 90002 ms. +[I 2025-06-08 22:09:55.109 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:32:23.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:32:23.381 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:33:47.204 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:49:29.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 22:49:29.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 22:50:52.869 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:05:32.828 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:05:32.828 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:06:56.648 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:32:30.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:32:30.516 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:34:24.340 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:50:37.471 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-08 23:50:37.471 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-08 23:52:01.297 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:07:04.098 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:07:04.099 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:08:27.920 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:36:14.687 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:36:14.688 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:38:08.514 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:52:49.482 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 00:52:49.482 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 00:54:13.307 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:09:46.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:09:46.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:11:09.854 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:34:29.864 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:34:29.865 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:36:23.699 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:51:42.312 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 01:51:42.313 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 01:53:06.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:09:11.301 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:09:11.302 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:12:20.541 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:26:44.538 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:26:44.539 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:28:08.360 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:44:28.172 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 02:44:28.173 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 02:45:51.992 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:01:18.261 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:01:18.262 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-09 03:02:48.263 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-09 03:02:53.266 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:18:49.628 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:18:49.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:20:13.460 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:35:25.377 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:35:25.378 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:36:49.224 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:51:40.538 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 03:51:40.539 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 03:53:04.386 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:13:23.765 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:13:23.766 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:15:17.592 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:30:53.284 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:30:53.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:32:17.107 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:46:55.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 04:46:55.960 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 04:48:19.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:03:11.577 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:03:11.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:04:35.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:19:03.356 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:19:03.357 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:20:27.180 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:34:49.908 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:34:49.909 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:36:13.739 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:52:43.421 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 05:52:43.421 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 05:54:07.247 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:18:10.133 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:18:10.134 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:19:33.960 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:36:12.807 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:36:12.808 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:37:36.630 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:52:44.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 06:52:44.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 06:54:08.446 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:10:58.294 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:10:58.296 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:12:22.115 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:29:08.957 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:29:08.957 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:30:32.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:47:46.589 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 07:47:46.590 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 07:49:10.406 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:19:42.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 08:19:42.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:21:36.176 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:55:18.221 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 08:55:18.222 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 08:57:17.584 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:18:58.605 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:18:58.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:20:22.431 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 09:20:56.685 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:21:36.152 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:165040ce-03f4-44cf-ad52-8baf106e91c8 +[I 2025-06-09 09:51:11.265 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 09:53:36.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:20:16.614 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:20:16.615 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:21:40.432 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:36:24.652 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:36:24.653 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:37:48.474 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:52:17.625 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 10:52:17.626 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 10:53:41.441 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:22:37.598 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:22:37.598 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:24:01.412 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:39:56.971 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:39:56.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:41:20.787 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:47:48.628 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:47:48.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:49:02.792 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:49:02.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 11:49:02.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 11:50:26.620 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:06:38.190 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:06:38.191 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:08:02.058 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:25:50.415 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:25:50.415 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:27:14.240 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:41:53.724 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 12:41:53.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 12:43:17.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:31:58.913 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 13:31:58.914 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:33:22.738 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:49:05.361 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 13:49:05.361 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 13:50:29.175 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:05:11.342 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:05:11.343 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:06:35.157 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:25:22.706 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:25:22.707 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[W 2025-06-09 14:26:52.706 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-09 14:26:57.708 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:43:04.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 14:43:04.454 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 14:44:28.264 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:00:00.434 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:00:00.435 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:01:24.245 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:2cac7728-4025-4d0e-b927-88cb8258cca2 +[I 2025-06-09 15:22:36.901 ServerApp] 302 GET / (@10.96.56.32) 3.44ms +[I 2025-06-09 15:22:36.907 JupyterNotebookApp] 302 GET /tree? (@10.96.56.32) 1.65ms +[I 2025-06-09 15:23:47.599 ServerApp] User 463021115425478faae79675b159db20 logged in. +[I 2025-06-09 15:23:47.600 ServerApp] 302 POST /login?next=%2Ftree%3F (463021115425478faae79675b159db20@10.96.56.32) 5.47ms +[I 2025-06-09 15:24:01.964 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:26:01.906 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:26:02.613 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:30:02.664 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:32:03.667 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:34:03.696 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:36:03.724 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:38:03.752 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:40:03.780 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:42:03.838 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:43:03.252 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 15:44:04.682 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:46:05.677 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:48:06.702 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:50:07.690 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 15:58:18.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 16:25:25.268 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 16:41:38.843 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:00:04.309 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:26:27.017 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:43:00.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 17:49:54.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 18:16:45.519 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 18:24:44.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 19:08:32.774 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:12:32.875 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:18:32.941 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-09 19:23:50.318 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 19:49:54.155 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:08:35.216 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:41:00.315 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 20:57:53.355 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:15:11.037 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:42:45.258 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 21:59:40.832 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 22:17:30.444 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 22:44:06.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:01:06.452 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:20:27.670 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:28:28.484 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-09 23:45:08.910 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:01:44.554 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:19:02.882 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 00:44:50.403 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:01:13.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:19:52.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 01:47:23.384 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:03:12.090 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:20:49.489 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:38:04.163 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 02:56:03.810 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:13:49.563 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:29:49.092 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 03:47:56.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 04:07:56.445 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 04:26:13.013 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 04:27:43.015 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-10 04:51:33.393 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:09:14.998 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:26:16.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 05:44:31.068 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:01:33.785 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:19:49.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:38:29.504 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 06:56:57.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 07:15:20.583 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 07:16:50.585 ServerApp] WebSocket ping timeout after 90001 ms. +[I 2025-06-10 07:32:13.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 07:49:27.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 07:50:57.464 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-10 08:02:26.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:20:28.460 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:37:18.979 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 08:54:07.928 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 09:20:05.513 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 09:38:41.108 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:22:02.714 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:38:43.330 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 10:43:40.746 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 10:57:39.550 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[W 2025-06-10 11:00:09.551 ServerApp] WebSocket ping timeout after 119994 ms. +[I 2025-06-10 11:08:53.019 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:10:53.062 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:12:53.118 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:14:53.151 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:16:53.196 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:18:53.719 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:20:54.753 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:22:55.164 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:23:20.070 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:24:55.212 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:26:55.274 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 11:40:56.837 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:49:51.131 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 11:55:41.766 ServerApp] Saving file at /experiments/rabi.ipynb +[I 2025-06-10 12:07:26.215 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 13:02:00.801 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 16:10:22.117 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-10 16:10:22.143 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-10 16:10:22.143 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-11 10:08:45.978 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-11 10:13:07.204 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-11 10:13:07.205 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 11:55:51.065 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 11:55:51.117 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 11:55:51.118 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:40:32.807 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:40:32.836 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 15:40:32.837 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 15:41:56.663 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:00:15.116 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:00:15.116 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:01:38.938 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:02:25.953 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:02:25.954 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:12:07.023 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:12:07.040 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:12:07.041 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:35:26.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:35:26.847 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:35:26.847 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:37:20.667 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:38:36.286 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:38:36.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:40:00.110 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:56:36.745 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 16:56:36.746 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 16:59:00.569 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:15:47.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:15:47.886 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-12 17:18:17.887 ServerApp] WebSocket ping timeout after 119996 ms. +[I 2025-06-12 17:18:22.889 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:32:19.930 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:32:19.930 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:34:13.749 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:49:52.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 17:49:52.601 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 17:51:16.455 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:05:59.425 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:05:59.426 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:08:23.242 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:23:17.552 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:23:17.552 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:26:41.381 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:30:42.866 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:30:42.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:33:36.686 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:34:43.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:34:43.184 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:36:07.015 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:49:20.581 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:49:20.584 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:50:44.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:50:44.422 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 18:50:44.422 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 18:52:38.249 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:08:10.786 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:08:10.787 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:11:34.606 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:27:07.249 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:27:07.250 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:30:01.067 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:31:47.951 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:31:47.952 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:34:41.770 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:50:32.983 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 19:50:32.983 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 19:53:26.818 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:07:53.931 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:07:53.932 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:10:47.756 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:25:12.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:25:12.993 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:28:36.821 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:43:17.284 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 20:43:17.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 20:46:11.112 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:00:49.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:00:49.242 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:02:13.065 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:16:58.115 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:16:58.115 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:19:51.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:35:34.669 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:35:34.670 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:38:28.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:54:07.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 21:54:07.602 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 21:59:01.445 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:14:04.650 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:14:04.652 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:16:58.469 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:31:22.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:31:22.628 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:32:46.446 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:48:11.429 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 22:48:11.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 22:51:05.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:07:13.496 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:07:13.496 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:10:37.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:26:34.219 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:26:34.220 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:29:28.037 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:46:24.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-12 23:46:24.184 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-12 23:49:18.007 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:03:54.417 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:03:54.418 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:06:48.238 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:21:24.023 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:21:24.023 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:22:47.839 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:38:07.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:38:07.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:40:31.286 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:56:12.937 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 00:56:12.937 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 00:59:36.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:13:57.302 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:13:57.303 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:15:21.145 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:30:29.423 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:30:29.424 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:32:53.241 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:47:47.371 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 01:47:47.371 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 01:50:41.192 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:05:35.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:05:35.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:08:47.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:23:12.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:23:12.339 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:26:36.168 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:43:10.303 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 02:43:10.319 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 02:46:04.130 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:01:31.254 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:01:31.254 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:02:55.084 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:17:47.289 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:17:47.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:20:11.108 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:35:13.256 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:35:13.257 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:38:37.079 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:53:22.280 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 03:53:22.281 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 03:56:16.104 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:12:30.046 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:12:30.047 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:15:53.876 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:31:39.868 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:31:39.868 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:35:03.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:50:17.055 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 04:50:17.056 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 04:53:10.878 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:08:20.751 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:08:20.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:11:14.585 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:19:50.191 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:19:50.191 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:22:44.047 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:38:25.132 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:38:25.133 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:41:18.954 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 05:57:15.141 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 05:57:15.142 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:00:08.970 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:14:49.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:14:49.348 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:17:43.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:20:55.826 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:20:55.826 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:23:49.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:38:10.974 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:38:10.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:41:04.790 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:55:42.122 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 06:55:42.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 06:58:35.965 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:12:55.278 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:12:55.279 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:15:49.126 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:21:36.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:21:36.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:26:30.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:41:33.014 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 07:41:33.014 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 07:45:09.597 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:01:41.471 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:01:41.471 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:04:05.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:20:28.956 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:20:28.957 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:27:53.057 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:34:42.096 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:34:42.097 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:37:35.919 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:54:15.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 08:54:15.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 08:57:33.232 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:11:33.576 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:11:33.576 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:12:57.400 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:22:45.622 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:22:45.622 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-13 09:26:15.623 ServerApp] WebSocket ping timeout after 119962 ms. +[I 2025-06-13 09:26:20.625 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:37:32.085 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:37:32.086 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:52:01.962 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 09:52:01.987 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 09:52:01.987 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:24:43.645 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:24:43.654 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 10:24:43.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:47:17.956 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 10:47:17.971 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 10:47:17.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:04:17.315 ServerApp] 302 GET / (@10.96.56.21) 4.14ms +[I 2025-06-13 11:04:18.612 ServerApp] 302 GET / (@10.96.56.21) 0.36ms +[I 2025-06-13 11:22:42.235 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:22:42.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 11:22:42.248 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:55:53.872 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:55:53.885 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 11:55:53.885 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 11:57:47.702 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:12:22.016 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 12:12:22.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:15:15.849 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 12:30:01.982 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 12:30:01.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:12:31.919 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:27:57.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:27:57.602 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:29:51.429 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:45:01.632 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:45:01.633 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:46:25.465 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:52:07.510 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 13:52:07.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 13:55:31.330 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 14:11:33.180 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 14:11:33.181 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 15:29:24.216 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 15:29:24.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 15:29:24.241 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:05:56.786 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:05:56.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 17:05:56.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:57:52.485 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:57:52.524 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 17:57:52.525 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 17:59:46.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:15:52.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:15:52.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:18:46.083 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:33:47.348 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:33:47.349 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:40:11.162 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:55:36.668 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 18:55:36.669 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 18:59:30.505 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:15:13.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:15:13.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:18:07.505 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:33:07.913 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:33:07.914 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:36:44.561 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:52:02.704 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:52:02.705 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:54:56.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 19:58:32.509 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 19:58:32.510 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:01:26.331 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:15:45.518 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:15:45.519 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:19:09.369 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:34:13.738 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:34:13.739 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:37:37.562 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:52:42.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 20:52:42.585 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 20:55:06.405 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:09:34.373 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:09:34.374 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:10:58.188 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:26:17.442 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:26:17.442 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:29:11.271 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:43:44.706 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 21:43:44.706 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 21:46:38.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:01:07.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:01:07.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:04:01.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:19:35.783 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:19:35.783 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:20:59.603 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:36:01.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:36:01.512 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:38:55.335 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:53:32.748 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 22:53:32.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 22:54:56.572 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:09:16.891 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:09:16.892 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:12:40.713 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:27:13.759 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:27:13.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:30:07.579 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:45:01.763 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-13 23:45:01.764 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-13 23:47:25.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:04:16.648 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:04:16.648 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:09:10.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:25:29.817 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:25:29.818 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:28:53.641 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:44:21.699 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 00:44:21.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 00:47:45.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:02:45.699 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:02:45.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:05:39.534 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:22:26.569 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:22:26.570 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:25:20.567 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:41:21.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 01:41:21.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 01:44:15.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:01:10.411 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:01:10.411 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:04:04.232 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:07:47.345 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:07:47.345 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:10:41.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:26:46.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:26:46.878 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:30:10.698 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:44:43.644 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 02:44:43.644 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 02:47:37.462 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:02:07.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:02:07.516 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:05:01.336 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:21:55.001 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:21:55.002 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:26:48.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:41:38.124 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:41:38.125 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:44:31.945 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:47:36.948 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 03:47:36.949 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 03:50:30.766 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:06:50.230 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:06:50.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:09:44.057 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:25:15.485 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:25:15.486 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:32:09.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:47:09.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 04:47:09.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 04:50:03.291 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:06:31.670 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:06:31.671 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:09:55.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:26:18.444 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:26:18.444 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:29:12.264 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:45:13.406 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:45:13.407 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:47:37.250 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:48:20.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 05:48:20.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 05:51:14.713 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:06:22.890 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:06:22.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:09:16.709 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:23:55.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:23:55.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 06:27:55.287 ServerApp] WebSocket ping timeout after 119878 ms. +[I 2025-06-14 06:28:00.288 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:42:44.005 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:42:44.005 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:45:37.828 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:49:33.594 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 06:49:33.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 06:52:27.417 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:09:26.529 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:09:26.529 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:10:50.348 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:26:27.533 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:26:27.534 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:29:21.347 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:43:49.231 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:43:49.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:46:13.062 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:50:21.012 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 07:50:21.012 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 07:53:14.862 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:08:47.779 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:08:47.780 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:12:11.602 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:27:11.856 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:27:11.857 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:30:35.680 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:46:17.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:46:17.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:49:11.275 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:51:45.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:51:45.380 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:54:39.243 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:56:01.608 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 08:56:01.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 08:58:25.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:13:32.241 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:13:32.241 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:16:56.069 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:33:34.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:33:34.406 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:36:28.227 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:51:18.540 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 09:51:18.541 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 09:54:12.370 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:08:36.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:08:36.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:11:30.336 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:20:44.050 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:20:44.068 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:24:07.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:38:35.996 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:38:35.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:41:52.494 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:52:35.920 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 10:52:35.921 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 10:55:29.746 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:10:21.013 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:10:21.014 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:13:44.893 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:30:11.567 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:30:11.569 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:33:05.407 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:47:57.407 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:47:57.408 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:50:51.227 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:53:36.346 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 11:53:36.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 11:56:30.167 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:13:02.315 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:13:02.316 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:14:26.156 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:29:22.351 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:29:22.351 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:32:16.183 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:46:40.740 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:46:40.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:49:34.565 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 12:54:21.638 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 12:54:21.638 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:36:15.486 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:51:01.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 13:51:01.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:54:25.163 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:55:41.696 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 13:55:41.696 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 13:58:35.526 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:13:13.659 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:13:13.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:16:07.500 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:30:42.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:30:42.464 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:36:06.287 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:52:48.354 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:52:48.355 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:55:12.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:56:20.211 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 14:56:20.211 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 14:59:44.046 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:14:11.934 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:14:11.934 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:15:35.753 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:31:35.042 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:31:35.042 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:33:28.868 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:48:46.377 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:48:46.378 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:52:40.219 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 15:57:37.321 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 15:57:37.321 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:04:31.148 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:19:51.607 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:19:51.608 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 16:23:51.607 ServerApp] WebSocket ping timeout after 119994 ms. +[I 2025-06-14 16:23:56.609 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:38:53.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:38:53.247 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:40:47.070 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:52:28.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:52:28.655 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:54:52.474 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:58:24.306 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 16:58:24.306 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 16:59:48.122 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:14:22.245 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:14:22.245 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:17:46.076 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:33:07.000 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:33:07.001 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:36:00.823 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:50:45.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:50:45.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:53:39.800 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 17:58:36.012 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 17:58:36.013 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:01:29.825 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:16:18.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:16:18.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:17:42.811 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:33:09.795 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:33:09.795 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:34:33.604 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:50:16.586 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 18:50:16.587 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 18:52:10.402 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:06:54.599 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:06:54.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:09:48.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:24:56.621 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:24:56.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-14 19:28:56.623 ServerApp] WebSocket ping timeout after 119899 ms. +[I 2025-06-14 19:29:01.624 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:43:22.737 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 19:43:22.738 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 19:47:46.564 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:03:32.723 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:03:32.723 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:07:01.103 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:21:57.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:21:57.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:25:51.610 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:40:39.339 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:40:39.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:42:03.168 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 20:56:40.474 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 20:56:40.475 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:01:04.294 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:16:26.445 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:16:26.445 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:19:50.283 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:34:47.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:34:47.997 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:37:41.822 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:53:00.371 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 21:53:00.371 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 21:55:54.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:11:45.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:11:45.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:14:39.127 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:29:00.683 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:29:00.683 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:32:24.526 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:47:36.542 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 22:47:36.543 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 22:51:00.365 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:05:57.386 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:05:57.387 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:08:51.206 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:25:10.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:25:10.537 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:28:04.358 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:42:49.159 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-14 23:42:49.161 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-14 23:45:43.009 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:00:22.397 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:00:22.399 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:02:46.236 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:18:25.218 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:18:25.220 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:19:49.037 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:34:43.314 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:34:43.314 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:37:37.141 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:52:22.334 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 00:52:22.347 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 00:53:46.153 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:09:56.269 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:09:56.270 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-15 01:11:26.269 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-15 01:11:31.270 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:19:28.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:19:28.752 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:22:40.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:37:19.348 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:37:19.349 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:40:13.175 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:47:52.032 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 01:47:52.033 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 01:50:45.907 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:05:05.944 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:05:05.945 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:08:21.788 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:23:19.247 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:23:19.248 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:26:43.068 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:42:50.730 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:42:50.730 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:45:44.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:47:03.803 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 02:47:03.803 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 02:49:27.616 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:05:00.946 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:05:00.946 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:06:24.772 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:21:12.929 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:21:12.929 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:24:06.755 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:38:40.677 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:38:40.677 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:41:34.510 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:48:50.394 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 03:48:50.394 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 03:51:44.213 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:07:58.236 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:07:58.238 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:11:22.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:25:56.603 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:25:56.603 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:31:36.169 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:46:52.437 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 04:46:52.437 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 04:49:46.276 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:04:45.485 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:04:45.485 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:07:39.308 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:24:24.246 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:24:24.247 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:27:25.750 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:42:05.691 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 05:42:05.692 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 05:44:59.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:01:45.664 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:01:45.664 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:04:42.477 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:20:24.580 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:20:24.580 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:23:48.417 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:38:36.659 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:38:36.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:42:00.489 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 06:59:02.891 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 06:59:02.892 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:01:26.715 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:16:02.702 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:16:02.703 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:19:26.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:34:55.626 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:34:55.627 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:37:49.457 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:46:21.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 07:46:21.620 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 07:49:15.454 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:05:11.540 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:05:11.541 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:08:05.375 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:22:27.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:22:27.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:25:51.325 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:40:45.623 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 08:40:45.623 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 08:43:39.586 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:00:46.879 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:00:46.880 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:03:10.743 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:19:02.764 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:19:02.765 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:23:11.487 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:37:28.746 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:37:28.746 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:39:52.568 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:47:09.501 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 09:47:09.502 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 09:50:06.895 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:05:43.545 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:05:43.546 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:08:37.381 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:25:17.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:25:17.961 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:28:41.784 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:44:22.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:44:22.486 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:49:46.308 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 10:59:55.190 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 10:59:55.190 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:02:49.010 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:19:07.127 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:19:07.128 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:22:00.985 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:36:20.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:36:20.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:39:14.156 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:48:15.242 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 11:48:15.242 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 11:51:09.086 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:05:32.199 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 12:05:32.199 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:47:55.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:49:28.465 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 12:49:28.466 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 12:50:52.283 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:07:41.420 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:07:41.420 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:10:35.254 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:26:09.584 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:26:09.584 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:29:33.423 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:44:22.700 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:44:22.700 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:47:16.533 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:50:22.693 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 13:50:22.693 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 13:53:16.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:08:14.723 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:08:14.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:11:08.542 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:26:05.459 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:26:05.459 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:29:29.315 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:44:14.347 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:44:14.348 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:47:08.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:51:27.230 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 14:51:27.231 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 14:54:21.060 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:09:47.127 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:09:47.128 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:12:40.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:28:41.869 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:28:41.870 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:31:53.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:48:22.007 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:48:22.008 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:49:45.829 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:52:25.168 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 15:52:25.169 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 15:53:48.984 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:09:35.961 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:09:35.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:10:59.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:25:36.021 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:25:36.022 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:28:59.841 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:44:21.237 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:44:21.237 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:48:15.086 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:53:20.578 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 16:53:20.578 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 16:58:20.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:12:50.820 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:12:50.821 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:14:14.635 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:31:09.838 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:31:09.839 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:34:03.658 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:43:19.798 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:43:19.798 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:46:13.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:54:28.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 17:54:28.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 17:57:22.593 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:01:41.791 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:01:41.792 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:04:35.606 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:19:01.739 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:19:01.740 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:24:25.554 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:40:48.555 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:40:48.556 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:43:42.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 18:59:10.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 18:59:10.820 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:02:04.647 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:12:58.752 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:12:58.753 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:19:52.572 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:34:55.132 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:34:55.133 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:37:48.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:53:26.986 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 19:53:26.986 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 19:56:20.809 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:11:40.032 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:11:40.032 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-15 20:13:10.036 ServerApp] WebSocket ping timeout after 90003 ms. +[I 2025-06-15 20:13:14.639 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:27:31.323 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:27:31.323 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:30:55.144 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:46:31.084 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 20:46:31.085 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 20:49:24.902 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:05:05.887 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:05:05.887 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:07:59.722 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:23:55.831 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:23:55.831 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:26:49.657 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:41:32.412 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 21:41:32.413 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 21:46:26.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:01:52.770 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:01:52.770 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:05:00.406 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:20:23.839 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:20:23.839 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:23:52.752 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:40:06.819 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:40:06.819 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:43:30.649 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 22:58:05.745 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 22:58:05.745 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:00:29.560 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:15:00.528 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:15:00.528 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:18:24.384 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:34:05.998 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:34:05.999 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:38:59.817 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:53:39.090 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-15 23:53:39.090 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-15 23:56:32.915 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:11:05.302 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:11:05.302 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:14:29.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:29:19.051 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:29:19.051 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:32:42.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:48:48.049 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 00:48:48.050 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 00:51:41.873 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:06:25.202 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:06:25.202 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:09:51.055 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:24:28.627 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:24:28.627 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:27:22.445 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:42:03.594 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:42:03.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:44:27.435 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 01:59:09.631 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 01:59:09.631 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:02:03.451 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:18:13.614 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:18:13.614 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:21:37.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:36:21.801 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:36:21.801 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:39:15.640 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:54:02.939 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 02:54:02.939 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 02:56:57.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:12:23.028 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:12:23.028 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:13:46.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:25:50.074 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:25:50.075 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-16 03:29:20.074 ServerApp] WebSocket ping timeout after 119912 ms. +[I 2025-06-16 03:29:21.451 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:43:00.506 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 03:43:00.506 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 03:45:54.345 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:01:38.927 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:01:38.927 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:04:02.742 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:18:26.837 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:18:26.837 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:20:20.654 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:35:22.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:35:22.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:37:46.783 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:53:24.655 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 04:53:24.656 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 04:54:48.490 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:10:37.771 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:10:37.772 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:12:01.588 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:28:17.798 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:28:17.799 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:31:11.617 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:45:30.319 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 05:45:30.319 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 05:48:24.153 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:04:34.227 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:04:34.227 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:07:28.053 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:23:27.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:23:27.286 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:28:51.116 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:43:17.992 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 06:43:17.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 06:46:11.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:00:44.433 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:00:44.434 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:03:08.267 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:18:06.269 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:18:06.270 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:20:00.084 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:35:13.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:35:13.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:37:37.382 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:53:27.727 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 07:53:27.727 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 07:56:21.547 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:11:13.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:11:13.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:14:37.627 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:31:09.769 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:31:09.770 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:34:59.775 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:49:33.719 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 08:49:33.720 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 08:52:27.548 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:08:44.597 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:08:44.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:10:08.413 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:24:27.601 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:24:27.606 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:26:51.686 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:36:42.341 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:36:42.342 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:39:36.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:46:57.393 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:46:57.395 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:57:03.525 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:57:03.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 09:57:03.536 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 09:58:57.349 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 10:02:38.490 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 10:02:38.491 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:08:07.891 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:08:07.919 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:08:07.920 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:10:01.748 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:25:01.289 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:25:01.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:26:25.117 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:41:20.314 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:41:20.314 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:51:36.834 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:51:36.846 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 12:51:36.847 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 12:53:30.687 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:10:19.291 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:10:19.291 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:11:43.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:26:23.357 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:26:23.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:27:47.177 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:43:03.949 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 13:43:03.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 13:44:33.275 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:00:25.277 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:00:25.277 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:03:19.097 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:07:44.042 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:07:44.042 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:21:53.429 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:21:53.438 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:21:53.438 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:23:47.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 14:35:35.258 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 14:35:35.258 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:55:35.702 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:55:35.758 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 15:55:35.758 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:57:29.587 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 15:59:13.446 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 15:59:13.446 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:00:59.692 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:00:59.728 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:00:59.728 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:15:46.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:15:46.738 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:15:46.738 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:17:40.558 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:32:14.380 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:32:14.382 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:33:38.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:48:07.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 17:48:07.209 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 17:51:31.024 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:08:13.014 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:08:13.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:11:36.857 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:26:31.242 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:26:31.243 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:29:55.063 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:46:21.385 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 18:46:21.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 18:49:35.246 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:04:19.866 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:04:19.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:07:13.695 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:16:15.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:16:15.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:19:39.127 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:33:58.542 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:33:58.542 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:36:52.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:51:45.179 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 19:51:45.179 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 19:54:53.903 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:09:04.108 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:09:04.108 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:11:57.937 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:26:48.331 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:26:48.331 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:30:12.176 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:44:46.580 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 20:44:46.580 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 20:47:40.399 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:02:25.186 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:02:25.187 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-16 21:07:55.186 ServerApp] WebSocket ping timeout after 119886 ms. +[I 2025-06-16 21:08:00.187 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:22:40.161 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:22:40.161 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:25:33.985 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:40:24.889 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:40:24.890 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:43:48.716 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 21:58:09.414 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 21:58:09.415 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:01:03.249 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:15:36.201 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:15:36.202 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:18:30.040 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:32:53.790 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:32:53.791 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:34:47.646 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:51:15.693 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 22:51:15.694 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 22:53:39.845 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:09:08.493 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:09:08.494 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:12:32.323 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:29:25.620 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:29:25.621 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:32:19.449 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:46:43.703 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-16 23:46:43.705 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-16 23:49:37.518 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:04:31.553 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:04:31.554 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:07:25.404 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:22:48.653 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:22:48.654 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:24:12.480 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:40:28.103 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:40:28.104 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:42:51.927 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 00:58:45.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 00:58:45.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:02:09.798 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:17:49.583 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:17:49.583 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:21:13.425 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:35:44.183 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:35:44.183 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:38:38.029 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:45:12.030 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 01:45:12.030 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 01:48:05.846 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:04:29.024 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:04:29.024 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:06:52.848 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:22:51.841 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:22:51.841 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:26:15.660 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:41:33.153 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:41:33.153 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:44:26.978 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 02:59:08.487 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 02:59:08.489 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 03:02:08.514 ServerApp] WebSocket ping timeout after 90011 ms. +[I 2025-06-17 03:02:13.519 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:17:09.353 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:17:09.353 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:20:08.777 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:36:57.194 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:36:57.194 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:40:21.018 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:55:08.061 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 03:55:08.062 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 03:58:01.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:13:37.873 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:13:37.875 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:17:01.696 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:33:06.047 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:33:06.051 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:36:29.883 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:52:36.427 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 04:52:36.428 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 04:55:43.621 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:02:00.106 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:02:00.106 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:04:53.955 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:19:40.035 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:19:40.036 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:23:03.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:38:00.710 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:38:00.711 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:40:24.545 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:55:44.625 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 05:55:44.626 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 05:59:08.450 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:03:07.590 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:03:07.590 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:06:01.415 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:20:53.372 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:20:53.372 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:22:17.198 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:37:46.340 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:37:46.340 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:40:10.159 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:55:30.595 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 06:55:30.595 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 06:58:24.439 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:03:53.397 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:03:53.397 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:07:19.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:22:57.168 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:22:57.169 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:25:50.994 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:41:46.975 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 07:41:46.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 07:44:40.819 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:01:07.950 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:01:07.950 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:04:01.778 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:04:57.011 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:04:57.013 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:07:50.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:16:13.212 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:16:13.213 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:19:37.038 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:35:38.401 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:35:38.401 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:39:02.223 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:47:23.458 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 08:47:23.458 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 08:50:17.303 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:06:11.290 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:06:11.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 09:09:11.291 ServerApp] WebSocket ping timeout after 119890 ms. +[I 2025-06-17 09:09:15.699 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:24:09.358 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:24:09.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:29:33.193 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:45:06.149 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 09:45:06.149 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 09:47:59.980 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:03:05.960 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:03:05.961 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:05:59.780 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:07:13.724 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:07:13.724 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:09:37.550 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:26:26.872 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:26:26.872 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:29:50.693 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:44:13.666 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 10:44:13.666 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 10:49:07.491 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:05:37.516 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:05:37.517 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:08:31.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:24:19.335 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:24:19.336 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:27:13.172 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:43:16.088 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 11:43:16.088 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 11:46:09.911 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:00:29.281 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:00:29.282 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:03:23.108 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:08:06.162 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:08:06.162 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:10:59.987 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:25:22.568 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:25:22.569 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:29:16.385 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 12:44:44.561 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 12:44:44.562 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:30:38.395 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:44:57.959 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 13:44:57.959 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 13:46:21.776 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:03:23.984 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:03:23.984 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:04:47.810 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:08:58.123 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:08:58.124 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:11:51.942 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:27:46.810 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:27:46.810 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:31:10.632 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:47:21.067 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 14:47:21.078 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 14:50:14.887 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:05:33.400 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:05:33.400 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:08:27.237 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:10:09.683 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:10:09.683 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:11:33.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:27:21.703 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:27:21.703 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:30:18.026 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:45:18.997 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 15:45:18.998 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 15:48:12.820 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:02:56.489 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:02:56.490 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:05:20.347 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:10:46.115 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:10:46.115 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:14:10.118 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:29:53.802 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:29:53.802 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:32:47.623 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:48:11.323 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 16:48:11.337 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 16:51:05.170 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:06:47.224 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:06:47.225 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:09:11.038 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:11:48.125 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:11:48.125 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:14:41.946 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:30:52.082 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:30:52.083 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:33:45.915 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:48:42.862 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 17:48:42.863 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 17:50:06.680 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:05:13.909 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:05:13.910 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:07:03.821 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:12:52.483 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:12:52.484 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:14:16.473 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:28:58.633 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:28:58.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:31:52.455 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:46:37.006 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 18:46:37.006 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 18:48:30.827 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:04:08.002 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:04:08.002 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:07:31.819 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:22:11.130 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:22:11.130 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:23:34.951 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:38:13.060 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:38:13.061 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:41:06.922 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 19:55:36.437 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 19:55:36.437 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:00:30.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:17:10.759 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:17:10.760 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:20:34.575 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:34:59.122 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:34:59.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:36:22.952 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:39:27.290 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:39:27.290 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:42:21.123 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 20:57:10.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 20:57:10.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:00:34.957 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:14:25.756 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:14:25.756 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:17:49.330 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:32:01.298 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:32:01.298 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:35:47.691 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:51:25.480 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 21:51:25.480 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 21:54:19.304 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:10:01.462 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:10:01.463 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-17 22:13:31.464 ServerApp] WebSocket ping timeout after 119996 ms. +[I 2025-06-17 22:13:32.810 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:28:16.189 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:28:16.189 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:31:40.010 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:46:34.430 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 22:46:34.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 22:49:28.248 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:05:33.749 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:05:33.749 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:08:27.570 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:23:42.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:23:42.511 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:27:06.338 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:43:49.369 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-17 23:43:49.369 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-17 23:46:13.193 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:01:01.208 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:01:01.208 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:04:25.048 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:19:14.357 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:19:14.357 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:20:38.178 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:35:39.417 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:35:39.417 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:38:33.245 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:53:02.714 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 00:53:02.714 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 00:54:26.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:08:48.766 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:08:48.767 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:11:42.590 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:26:30.478 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:26:30.478 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:28:54.296 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:43:29.586 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 01:43:29.586 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 01:46:23.408 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:01:16.698 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:01:16.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:04:10.534 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:20:07.760 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:20:07.761 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:23:46.422 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:37:53.406 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:37:53.407 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:40:47.235 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:56:38.841 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 02:56:38.842 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 02:59:32.673 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:14:14.671 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:14:14.671 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:19:08.501 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:34:09.034 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:34:09.035 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:37:02.866 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:52:38.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 03:52:38.974 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 03:55:32.790 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:02:28.894 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:02:28.895 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:05:22.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:14:41.876 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:14:41.876 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:17:35.697 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:33:00.263 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:33:00.264 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:36:24.087 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:50:50.536 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 04:50:50.537 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 04:57:14.724 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:13:13.431 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:13:13.432 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:16:07.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:30:49.257 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:30:49.257 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:33:43.083 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:48:21.486 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 05:48:21.487 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 05:51:29.733 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:06:48.054 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:06:48.055 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:09:41.902 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:25:56.855 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:25:56.856 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:31:20.691 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:46:30.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 06:46:30.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 06:49:54.719 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:05:37.502 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:05:37.503 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:10:31.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:25:04.451 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:25:04.451 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:27:58.274 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:42:42.275 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:42:42.276 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:45:36.115 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:54:47.248 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 07:54:47.249 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 07:57:41.112 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:12:13.194 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:12:13.195 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:15:07.014 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:31:42.296 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:31:42.297 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:37:06.122 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:51:28.698 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 08:51:28.699 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 08:54:22.540 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:09:45.442 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:09:45.442 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:12:39.270 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:27:28.725 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:27:28.725 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:30:22.570 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 09:44:55.052 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 09:44:55.052 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:24:01.638 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:24:01.671 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:24:01.672 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:25:55.487 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:28:02.262 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:28:02.263 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:38:45.593 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:38:45.609 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:38:45.609 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:40:39.424 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 11:52:43.850 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 11:52:43.851 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:02:16.258 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:02:16.285 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:02:16.285 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:04:10.116 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:18:45.159 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:18:45.160 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:20:08.983 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:34:47.295 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:34:47.296 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:37:11.111 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:52:14.277 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 12:52:14.277 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 12:53:38.096 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:09:03.283 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 13:09:03.283 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:10:57.103 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 13:26:47.464 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 13:26:47.465 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:34:56.779 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:34:56.825 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 15:34:56.825 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:36:50.641 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 15:51:32.138 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 15:51:32.139 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:12:18.357 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:12:18.385 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 17:12:18.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:51:55.611 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:51:55.634 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 17:51:55.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 17:53:49.452 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:08:16.181 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:08:16.182 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:09:39.998 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:25:58.237 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:25:58.238 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:27:22.076 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 18:44:01.016 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 18:44:01.017 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-18 18:45:31.016 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-18 18:45:36.017 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:00:34.448 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:00:34.452 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:03:58.284 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:18:36.520 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:18:36.521 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:20:00.333 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:35:31.534 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:35:31.535 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:38:25.344 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:52:58.511 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 19:52:58.512 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 19:59:52.354 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:15:51.015 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 20:15:51.015 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:19:51.462 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:34:57.213 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 20:34:57.213 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 20:43:56.745 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:00:00.867 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:00:00.867 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:19:24.743 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:34:19.429 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:34:19.430 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:35:43.251 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:51:17.116 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 21:51:17.117 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 21:58:14.190 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:13:57.972 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:13:57.972 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:16:51.795 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:31:17.948 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:31:17.948 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:36:41.772 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 22:51:44.126 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 22:51:44.127 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:13:16.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:27:46.384 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 23:27:46.385 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:33:14.664 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:48:21.926 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-18 23:48:21.927 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-18 23:53:15.757 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:07:42.878 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:07:42.879 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 00:09:12.879 ServerApp] WebSocket ping timeout after 90000 ms. +[I 2025-06-19 00:09:17.882 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:24:42.087 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:24:42.087 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:28:05.912 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:43:03.479 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 00:43:03.480 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 00:50:27.717 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:06:07.734 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:06:07.739 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:19:01.566 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:34:01.011 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:34:01.011 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:37:24.841 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:50:26.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 01:50:26.548 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 01:55:25.530 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:10:12.358 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:10:12.358 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:17:06.191 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:34:06.599 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:34:06.599 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:37:00.592 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 02:52:00.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 02:52:00.962 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 02:55:30.963 ServerApp] WebSocket ping timeout after 119986 ms. +[I 2025-06-19 02:55:35.964 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:10:21.171 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:10:21.171 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:19:44.990 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:34:56.229 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:34:56.229 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:37:50.052 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:38:44.066 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:38:44.066 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:41:38.225 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 03:56:36.851 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 03:56:36.851 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 04:00:06.852 ServerApp] WebSocket ping timeout after 119899 ms. +[I 2025-06-19 04:00:11.853 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:15:15.835 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:15:15.836 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:18:39.684 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:33:53.977 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:33:53.978 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:39:58.304 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 04:54:43.548 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 04:54:43.549 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:01:37.383 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:17:55.405 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:17:55.406 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:32:49.255 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:39:49.658 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:39:49.659 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:42:43.508 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 05:57:40.403 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 05:57:40.403 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:00:34.221 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:15:37.273 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:15:37.274 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:18:01.095 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:32:56.222 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:32:56.223 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:34:50.035 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:40:51.346 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:40:51.346 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:43:45.166 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 06:58:08.634 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 06:58:08.634 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:01:02.503 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:15:38.502 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 07:15:38.503 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:26:32.332 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:41:46.942 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 07:41:46.943 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 07:44:40.759 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:00:05.121 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:00:05.122 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:03:16.368 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:18:42.991 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:18:42.992 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:20:06.804 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:23:58.970 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:23:58.971 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:26:52.788 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:41:29.977 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 08:41:29.978 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 08:50:23.835 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:05:22.134 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:05:22.135 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:08:15.954 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:24:50.010 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:24:50.010 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:27:43.851 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:42:36.974 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:42:36.975 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-19 09:46:06.975 ServerApp] WebSocket ping timeout after 119914 ms. +[I 2025-06-19 09:46:07.428 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:51:44.943 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:51:44.943 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:52:24.522 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 09:52:24.532 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 09:52:24.532 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 11:59:53.761 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 11:59:53.784 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 11:59:53.784 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:01:47.600 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:17:20.450 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:17:20.451 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:21:14.274 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:35:45.035 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:35:45.036 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:37:08.856 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 12:52:45.827 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 12:52:45.827 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 13:39:02.797 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-19 13:54:21.962 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-19 13:54:21.963 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-24 18:25:47.453 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-24 18:25:47.574 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-24 18:25:47.575 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-25 12:30:17.576 ServerApp] WebSocket ping timeout after 1829994 ms. +[I 2025-06-25 12:30:22.583 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 13:22:31.091 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-25 13:22:31.091 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[W 2025-06-25 13:47:01.090 ServerApp] WebSocket ping timeout after 1079993 ms. +[I 2025-06-25 13:47:06.090 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 14:12:47.395 ServerApp] Connecting to kernel 49917d1f-ff43-4a11-89a9-94bf2d206d7d. +[I 2025-06-25 14:12:47.396 ServerApp] Restoring connection for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +[I 2025-06-25 17:45:11.236 ServerApp] Starting buffering for 49917d1f-ff43-4a11-89a9-94bf2d206d7d:d65157b4-8ef0-4001-9653-438fa52bd5cc +Task exception was never retrieved +future: .wrapper() done, defined at /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py:1086> exception=WebSocketClosedError()> +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1088, in wrapper + await fut +tornado.iostream.StreamClosedError: Stream is closed + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1090, in wrapper + raise WebSocketClosedError() +tornado.websocket.WebSocketClosedError +Task exception was never retrieved +future: .wrapper() done, defined at /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py:1086> exception=WebSocketClosedError()> +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1088, in wrapper + await fut +tornado.iostream.StreamClosedError: Stream is closed + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/tornado/websocket.py", line 1090, in wrapper + raise WebSocketClosedError() +tornado.websocket.WebSocketClosedError diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index f4d974b8..e6b3e293 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -1,14 +1,14 @@ -mypy==1.2.0 +mypy==1.5.1 pytest==6.2.4 pytest-cov pytest-benchmark pytest-xdist -black==23.3.0 +black[jupyter] sphinx>=4.0 pytest-lazy-fixture -pylint==2.11.1 -numpy==1.21.5 +pylint==2.17.5 furo sphinx-copybutton nbsphinx -myst-parser \ No newline at end of file +myst-parser +sphinx-design \ No newline at end of file diff --git a/requirements/requirements-docker-v2.txt b/requirements/requirements-docker-v2.txt new file mode 100644 index 00000000..5a99a02d --- /dev/null +++ b/requirements/requirements-docker-v2.txt @@ -0,0 +1,47 @@ +torch>2.0 # 2.0.1 +jax[cuda11_pip]==0.4.7 +tensorflow==2.11 +# tf 2.12 can make torch 2 hangs with runtime error +# check with hybrid_gpu_pipeline.py example +cupy-cuda11x==12.0.0 +tensornetwork==0.4.6 +graphviz +numpy==1.23.5 +scipy==1.10.1 +sympy==1.12 +cirq==1.1.0 +qiskit +matplotlib +jupyter +cotengra +networkx +optax==0.1.5 +kahypar +optuna +baytune +nevergrad +scikit-learn==1.2.2 +scikit-optimize +openfermion +quimb +openfermionpyscf +pennylane==0.30.0 +mthree==1.1.0 +mitiq==0.26.0 +# below is for development +mypy==1.3.0 +pytest +pytest-cov +pytest-benchmark +pytest-xdist +pytest-lazy-fixture +black==23.3.0 +sphinx>=4.0 +sphinx-intl +sphinx-copybutton +nbsphinx +furo +myst-parser +pylint +sphinx-design +# made in 202306 diff --git a/requirements/requirements-extra.txt b/requirements/requirements-extra.txt index 09cacbba..63e1f992 100644 --- a/requirements/requirements-extra.txt +++ b/requirements/requirements-extra.txt @@ -1,6 +1,10 @@ # extra dependencies for ci -qiskit +qiskit<1.0 +qiskit-aer<1.0 qiskit-nature -torch -jupyter +mitiq +cirq +torch==2.2.2 +# jupyter mthree==1.1.0 +openfermion diff --git a/requirements/requirements-rtd.txt b/requirements/requirements-rtd.txt index cb334c99..8e93c419 100644 --- a/requirements/requirements-rtd.txt +++ b/requirements/requirements-rtd.txt @@ -13,4 +13,6 @@ ipykernel furo==2022.4.7 sphinx-copybutton nbsphinx -myst-parser \ No newline at end of file +myst-parser +urllib3==1.26.15 +sphinx-design \ No newline at end of file diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 69ddfea0..97de418f 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,8 +1,7 @@ numpy scipy -cirq==0.13.1 -tensorflow==2.7 -tensornetwork +tensorflow<2.16 # tf 2.16 with integration of keras 3 seems a disaster... +tensornetwork-ng graphviz jax jaxlib diff --git a/setup.py b/setup.py index 6495eed6..8e176a49 100644 --- a/setup.py +++ b/setup.py @@ -11,19 +11,19 @@ version=__version__, author=__author__, author_email="shixinzhang@tencent.com", - description="Quantum circuits on top of tensor network", + description="High performance unified quantum computing framework for the NISQ era", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/tencent-quantum-lab/tensorcircuit", packages=setuptools.find_packages(), include_package_data=True, - install_requires=["numpy", "scipy", "tensornetwork", "networkx"], + install_requires=["numpy", "scipy", "tensornetwork-ng", "networkx"], extras_require={ - "tensorflow": ["tensorflow"], + "tensorflow": ["tensorflow<2.16"], "jax": ["jax", "jaxlib"], "torch": ["torch"], - "qiskit": ["qiskit"], - "cloud": ["qiskit", "mthree"], + "qiskit": ["qiskit<1.0"], + "cloud": ["qiskit<1.0", "mthree"], }, classifiers=[ "Programming Language :: Python :: 3", diff --git a/tensorcircuit/__init__.py b/tensorcircuit/__init__.py index ef701d00..57646d0f 100644 --- a/tensorcircuit/__init__.py +++ b/tensorcircuit/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.9.0" +__version__ = "0.12.0" __author__ = "TensorCircuit Authors" __creator__ = "refraction-ray" @@ -24,8 +24,10 @@ ) # prerun of set hooks from . import gates from . import basecircuit +from . import waveforms from .gates import Gate from .circuit import Circuit, expectation +from .pulse import Param from .mpscircuit import MPSCircuit from .densitymatrix import DMCircuit as DMCircuit_reference from .densitymatrix import DMCircuit2 @@ -38,18 +40,33 @@ from . import results from . import quantum from .quantum import QuOperator, QuVector, QuAdjointVector, QuScalar +from . import compiler +from . import cloud +from . import fgs +from .fgs import FGSSimulator try: from . import keras - from .keras import QuantumLayer as KerasLayer + from .keras import KerasLayer, KerasHardwareLayer except ModuleNotFoundError: pass # in case tf is not installed try: from . import torchnn - from .torchnn import QuantumNet as TorchLayer + from .torchnn import TorchLayer, TorchHardwareLayer except ModuleNotFoundError: pass # in case torch is not installed +try: + import qiskit + + qiskit.QuantumCircuit.cnot = qiskit.QuantumCircuit.cx + qiskit.QuantumCircuit.toffoli = qiskit.QuantumCircuit.ccx + qiskit.QuantumCircuit.fredkin = qiskit.QuantumCircuit.cswap + + # amazing qiskit 1.0 nonsense... +except ModuleNotFoundError: + pass + # just for fun from .asciiart import set_ascii diff --git a/tensorcircuit/about.py b/tensorcircuit/about.py index 40f77c8f..d071c1dd 100644 --- a/tensorcircuit/about.py +++ b/tensorcircuit/about.py @@ -39,9 +39,12 @@ def about() -> None: print(f"TensorNetwork is not installed") try: - import cotengra as _ + import cotengra - print(f"Cotengra: installed") + try: + print(f"Cotengra version: {cotengra.__version__}") + except AttributeError: + print(f"Cotengra: installed") except ModuleNotFoundError: print(f"Cotengra is not installed") @@ -107,6 +110,10 @@ def about() -> None: except ModuleNotFoundError: print(f"Cirq is not installed") + from tensorcircuit import __version__ + + print(f"TensorCircuit version {__version__}") + if __name__ == "__main__": about() diff --git a/tensorcircuit/abstractcircuit.py b/tensorcircuit/abstractcircuit.py index b98c892f..7c2d119d 100644 --- a/tensorcircuit/abstractcircuit.py +++ b/tensorcircuit/abstractcircuit.py @@ -1,22 +1,24 @@ """ Methods for abstract circuits independent of nodes, edges and contractions """ + # pylint: disable=invalid-name -from typing import Any, Callable, Dict, List, Optional, Sequence, Union, Tuple +import json +import logging from copy import deepcopy from functools import reduce from operator import add -import json -import logging +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import numpy as np import tensornetwork as tn from . import gates from .cons import backend, dtypestr -from .vis import qir2tex from .quantum import QuOperator +from .utils import is_sequence +from .vis import qir2tex logger = logging.getLogger(__name__) @@ -77,6 +79,14 @@ class AbstractCircuit: mpogates = mpogates gate_aliases = gate_aliases + def __init__(self, nqubits: int, *args, **kwargs): + self._nqubits = nqubits + self._qir = [] + self._extra_qir = [] + self.inputs = None + self.circuit_param = {} + self.is_mps = False + def apply_general_gate( self, gate: Union[Gate, QuOperator], @@ -112,6 +122,7 @@ def apply(self: "AbstractCircuit", *index: int, **vars: Any) -> None: gate_dict = { "gatef": gatef, "index": index, + "target": list(index), "name": localname, "split": split, "mpo": mpo, @@ -128,7 +139,25 @@ def apply(self: "AbstractCircuit", *index: int, **vars: Any) -> None: ir_dict=gate_dict, ) - return apply + def apply_list(self: "AbstractCircuit", *index: int, **vars: Any) -> None: + if isinstance(index[0], int): + apply(self, *index, **vars) + elif is_sequence(index[0]) or isinstance(index[0], range): + for i, ind in enumerate(zip(*index)): + nvars = {} + for k, v in vars.items(): + try: + nvars[k] = v[i] + except Exception: # pylint: disable=W0703 + # (TypeError, IndexError) is not enough, + # tensorflow.python.framework.errors_impl.InvalidArgumentError + # not ideally captured here + nvars[k] = v + apply(self, *ind, **nvars) + else: + raise ValueError("Illegal index specification") + + return apply_list @staticmethod def apply_general_gate_delayed( @@ -167,7 +196,16 @@ def apply( ir_dict=gate_dict, ) - return apply + def apply_list(self: "AbstractCircuit", *index: int, **kws: Any) -> None: + if isinstance(index[0], int): + apply(self, *index, **kws) + elif is_sequence(index[0]) or isinstance(index[0], range): + for ind in zip(*index): + apply(self, *ind, **kws) + else: + raise ValueError("Illegal index specification") + + return apply_list @classmethod def _meta_apply(cls) -> None: @@ -406,13 +444,58 @@ def inverse( c = type(self)(**circuit_params) for d in reversed(self._qir): if "parameters" not in d: - self.apply_general_gate_delayed( - d["gatef"].adjoint(), d["name"], mpo=d["mpo"] - )(c, *d["index"], split=d["split"]) + if d["gatef"].n in self.sgates and d["gatef"].n not in [ + "wroot", + "sd", + "td", + ]: + self.apply_general_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], split=d["split"]) + elif d["gatef"].n in ["sd", "td"]: + self.apply_general_gate_delayed( + getattr(gates, d["gatef"].n[:-1]), d["name"], mpo=d["mpo"] + )(c, *d["index"], split=d["split"]) + else: + self.apply_general_gate_delayed( + d["gatef"].adjoint(), d["name"], mpo=d["mpo"] + )(c, *d["index"], split=d["split"]) else: - self.apply_general_variable_gate_delayed( - d["gatef"].adjoint(), d["name"], mpo=d["mpo"] - )(c, *d["index"], **d["parameters"], split=d["split"]) + if d["gatef"].n in ["r", "cr"]: + params = {k: v for k, v in d["parameters"].items()} + if "theta" in params: + params["theta"] = -params.get("theta", 0.0) + self.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **params, split=d["split"]) + elif d["gatef"].n in ["u", "cu"]: + params = {k: v for k, v in d["parameters"].items()} + # deepcopy fail with tf+jit + params["lbd"] = -d["parameters"].get("phi", 0) + np.pi + params["phi"] = -d["parameters"].get("lbd", 0) + np.pi + self.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **params, split=d["split"]) + elif d["gatef"].n in self.vgates and d["gatef"].n not in [ + "any", + "exp", + "exp1", + ]: + params = {k: v for k, v in d["parameters"].items()} + df = 0.0 + if d["gatef"].n == "iswap": + df = 1.0 + params["theta"] = -params.get("theta", df) + self.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **params, split=d["split"]) + + # TODO(@refraction-ray): multi control gate? + + else: + self.apply_general_variable_gate_delayed( + d["gatef"].adjoint(), d["name"], mpo=d["mpo"] + )(c, *d["index"], **d["parameters"], split=d["split"]) return c @@ -602,39 +685,41 @@ def gate_summary(self) -> Dict[str, int]: summary[d["name"]] = summary.get(d["name"], 0) + 1 return summary - def measure_instruction(self, index: int) -> None: + def measure_instruction(self, *index: int) -> None: """ add a measurement instruction flag, no effect on numerical simulation - :param index: the corresponding qubit + :param index: the corresponding qubits :type index: int """ l = len(self._qir) - d = { - "index": [index], - "name": "measure", - "gatef": "measure", - "instruction": True, - "pos": l, - } - self._extra_qir.append(d) + for ind in index: + d = { + "index": [ind], + "name": "measure", + "gatef": "measure", + "instruction": True, + "pos": l, + } + self._extra_qir.append(d) - def reset_instruction(self, index: int) -> None: + def reset_instruction(self, *index: int) -> None: """ add a reset instruction flag, no effect on numerical simulation - :param index: the corresponding qubit + :param index: the corresponding qubits :type index: int """ l = len(self._qir) - d = { - "index": [index], - "name": "reset", - "gatef": "reset", - "instruction": True, - "pos": l, - } - self._extra_qir.append(d) + for ind in index: + d = { + "index": [ind], + "name": "reset", + "gatef": "reset", + "instruction": True, + "pos": l, + } + self._extra_qir.append(d) def barrier_instruction(self, *index: List[int]) -> None: """ @@ -680,7 +765,7 @@ def to_qiskit( :type enable_inputs: bool, defaults to False :return: A qiskit object of this circuit. """ - from .translation import qir2qiskit, perm_matrix + from .translation import perm_matrix, qir2qiskit qir = self.to_qir() if enable_instruction: @@ -752,6 +837,7 @@ def draw(self, **kws: Any) -> Any: Visualise the circuit. This method recevies the keywords as same as qiskit.circuit.QuantumCircuit.draw. More details can be found here: https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.draw.html. + Interesting kws options include: ``idle_wires``(bool) :Example: >>> c = tc.Circuit(3) @@ -810,7 +896,7 @@ def from_qiskit( n = qc.num_qubits return qiskit2tc( # type: ignore - qc.data, + qc, n, inputs, circuit_constructor=cls, @@ -1096,6 +1182,11 @@ def append( self.__dict__.update(newc.__dict__) return self + def copy(self) -> "AbstractCircuit": + qir = self.to_qir() + c = type(self).from_qir(qir, self.circuit_param) + return c + def expectation( self, *ops: Tuple[tn.Node, List[int]], @@ -1112,6 +1203,7 @@ def expectation_ps( x: Optional[Sequence[int]] = None, y: Optional[Sequence[int]] = None, z: Optional[Sequence[int]] = None, + ps: Optional[Sequence[int]] = None, reuse: bool = True, noise_conf: Optional[Any] = None, nmc: int = 1000, @@ -1150,6 +1242,10 @@ def expectation_ps( :type y: Optional[Sequence[int]], optional :param z: sites to apply Z gate, defaults to None :type z: Optional[Sequence[int]], optional + :param ps: or one can apply a ps structures instead of ``x``, ``y``, ``z``, + e.g. [0, 1, 3, 0, 2, 2] for X_1Z_2Y_4Y_5 + defaults to None, ``ps`` can overwrite ``x``, ``y`` and ``z`` + :type ps: Optional[Sequence[int]], optional :param reuse: whether to cache and reuse the wavefunction, defaults to True :type reuse: bool, optional :param noise_conf: Noise Configuration, defaults to None @@ -1163,6 +1259,14 @@ def expectation_ps( :rtype: Tensor """ obs = [] + if ps is not None: + from .quantum import ps2xyz + + d = ps2xyz(ps) # type: ignore + x = d.get("x", None) + y = d.get("y", None) + z = d.get("z", None) + if x is not None: for i in x: obs.append([gates.x(), [i]]) # type: ignore diff --git a/tensorcircuit/applications/README.md b/tensorcircuit/applications/README.md index c63ef6cf..202e06cf 100644 --- a/tensorcircuit/applications/README.md +++ b/tensorcircuit/applications/README.md @@ -1,3 +1,6 @@ +Code implementation in this submodule `applications` are not very well maintained and extensively tested. There are indeed many interesting pieces, but try on your own risk. + + ## Differentiable Quantum Architecture Search In `applications`, framework and relevant applications of DQAS are implemented, mainly in `vags.py` and `dqas.py`. diff --git a/tensorcircuit/applications/__init__.py b/tensorcircuit/applications/__init__.py index 99d7c732..70d128b0 100644 --- a/tensorcircuit/applications/__init__.py +++ b/tensorcircuit/applications/__init__.py @@ -1,5 +1,5 @@ """ The application codebase is related to research and previous version of tensorcircuit, the code inside is subject to change, be caution to use. -Most of the useful code is refactored and copied to other parts of tensorcircuit. +Most of the useful code is and will be refactored and copied to other parts of tensorcircuit. """ diff --git a/tensorcircuit/applications/ai/__init__.py b/tensorcircuit/applications/ai/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tensorcircuit/templates/ensemble.py b/tensorcircuit/applications/ai/ensemble.py similarity index 93% rename from tensorcircuit/templates/ensemble.py rename to tensorcircuit/applications/ai/ensemble.py index f8b97aee..a9d6b0d7 100644 --- a/tensorcircuit/templates/ensemble.py +++ b/tensorcircuit/applications/ai/ensemble.py @@ -4,24 +4,22 @@ from typing import Any, List, Optional import tensorflow as tf -import keras import numpy as np NDArray = Any kwargus = Any +model_type = Any class bagging: # A.K.A. voting def __init__(self) -> None: - self.models: List[keras.engine.functional.Functional] = [] + self.models: List[model_type] = [] self.model_trained: List[bool] = [] self.count = 0 self.need_confidence = True # Help in reducing numbers of get_confidence runs self.permit_train = False - def append( - self, model: keras.engine.functional.Functional, model_trained: bool - ) -> None: + def append(self, model: model_type, model_trained: bool) -> None: """ Add model to the voting method """ @@ -55,9 +53,13 @@ def train(self, **kwargs: kwargus) -> None: def compile(self, **kwargs: kwargus) -> None: self.permit_train = True + for i in range(self.count): if not self.model_trained[i]: - self.models[i].compile(**kwargs) + dict_kwargs = kwargs.copy() + # TODO(@refraction-ray): still not compatible with new optimizer + # https://github.com/tensorflow/tensorflow/issues/58973 + self.models[i].compile(**dict_kwargs) def __get_confidence(self, model_index: int, input: NDArray) -> NDArray: """ diff --git a/tensorcircuit/applications/dqas.py b/tensorcircuit/applications/dqas.py index d139fe01..161a2c73 100644 --- a/tensorcircuit/applications/dqas.py +++ b/tensorcircuit/applications/dqas.py @@ -1,6 +1,7 @@ """ Modules for DQAS framework """ + # possibly deprecated, multiprocessing is not the recommended way to do DQAS task now, using vmap! import sys @@ -486,9 +487,9 @@ def qaoa_simple_train( if "prob_model_func" in kws: pmf = kws["prob_model_func"] del kws["prob_model_func"] - kws[ - "prob_model" - ] = pmf() # in case keras model cannot pickled for multiprocessing map + kws["prob_model"] = ( + pmf() + ) # in case keras model cannot pickled for multiprocessing map if isinstance(graph, list): def graph_generator() -> Iterator[Graph]: diff --git a/tensorcircuit/applications/finance/__init__.py b/tensorcircuit/applications/finance/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tensorcircuit/applications/finance/portfolio.py b/tensorcircuit/applications/finance/portfolio.py new file mode 100644 index 00000000..a9097241 --- /dev/null +++ b/tensorcircuit/applications/finance/portfolio.py @@ -0,0 +1,89 @@ +""" +Supplementary functions for portfolio optimization +""" + +from typing import Any + +import numpy as np + +Array = Any +Tensor = Any + + +def QUBO_from_portfolio(cov: Array, mean: Array, q: float, B: int, t: float) -> Tensor: + """ + convert portfolio parameters to a Q matrix + :param cov: n-by-n covariance numpy array + :param mean: numpy array of means + :param q: the risk preference of investor + :param B: budget + :param t: penalty factor + :return Q: n-by-n symmetric Q matrix + """ + n = cov.shape[0] + R = np.diag(mean) + S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n)) + + Q = q * cov - R + t * S + return Q + + +class StockData: + """ + A class for converting real-world stock data to an annualized covariance matrix and annualized return. + + Attributes: + - data: A list of continuous stock data in the same time span. + - n_stocks: The number of stocks in the data. + - n_days: The number of trading days in the data. + + Methods: + - __init__(self, data): Initializes the StockData object. + - get_return(self, decimals=5): Calculates the annualized return. + - get_covariance(self, decimals=5): Calculates the annualized covariance matrix. + """ + + def __init__(self, data: Tensor): + """ + Initializes the StockData object. + + :param data: A list of continuous stock data in the same time span. + """ + self.data = data + self.n_stocks = len(data) + + # Check the number of days + n_days = [len(i) for i in data] + if max(n_days) != (sum(n_days) / len(n_days)): + raise Exception("Timespan of stocks should be the same") + self.n_days = len(data[1]) + + # Calculate the daily percentage price change + self.daily_change = [ + np.diff(data[i][:]) / data[i][:-1] for i in range(self.n_stocks) + ] + + def get_return(self, decimals: int = 5) -> Any: + """ + Calculates the annualized return (mu). + + :param decimals: Number of decimal places to round the result to (default: 5). + :return: The annualized return as an array rounded to the specified number of decimals. + """ + change = [[j + 1 for j in i] for i in self.daily_change] + ret = np.prod(change, axis=1) ** (252 / self.n_days) + return ret.round(decimals) + + def get_covariance(self, decimals: int = 5) -> Tensor: + """ + Calculates the annualized covariance matrix (sigma). + + :param decimals: Number of decimal places to round the result to (default: 5). + :return: The annualized covariance matrix rounded to the specified number of decimals. + """ + mean = np.mean(self.daily_change, axis=1) + relative_change = [ + [j - mean[i] for j in self.daily_change[i]] for i in range(6) + ] + cov = 252 / self.n_days * np.dot(relative_change, np.transpose(relative_change)) + return cov.round(decimals) diff --git a/tensorcircuit/applications/layers.py b/tensorcircuit/applications/layers.py index 18f53db6..64eef546 100644 --- a/tensorcircuit/applications/layers.py +++ b/tensorcircuit/applications/layers.py @@ -1,6 +1,7 @@ """ Module for functions adding layers of circuits """ + import itertools import logging import sys diff --git a/tensorcircuit/applications/optimization.py b/tensorcircuit/applications/optimization.py new file mode 100644 index 00000000..28c5c81a --- /dev/null +++ b/tensorcircuit/applications/optimization.py @@ -0,0 +1,364 @@ +""" +modules for QUBO problems in QAOA +""" + +from typing import List, Callable, Any, Optional, Tuple +from functools import partial + +import tensorflow as tf +import scipy.optimize as optimize + +from ..cons import backend +from ..quantum import measurement_results +from ..interfaces import scipy_interface +from ..templates.ansatz import QAOA_ansatz_for_Ising +from ..templates.conversions import QUBO_to_Ising + +Circuit = Any +Tensor = Any +Array = Any + + +def Ising_loss(c: Circuit, pauli_terms: Tensor, weights: List[float]) -> Any: + """ + computes the loss function for the Ising model based on a given quantum circuit, + a list of Pauli terms, and corresponding weights. + The offset is ignored. + + :param c: A quantum circuit object generating the state. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :return loss: A real number representing the computed loss value. + """ + loss = 0.0 + for k in range(len(pauli_terms)): + term = pauli_terms[k] + index_of_ones = [] + + for l in range(len(term)): + if term[l] == 1: + index_of_ones.append(l) + + # Compute expectation value based on the number of qubits involved in the Pauli term + if len(index_of_ones) == 1: + delta_loss = weights[k] * c.expectation_ps(z=[index_of_ones[0]]) + # Compute expectation value for a single-qubit Pauli term + else: + delta_loss = weights[k] * c.expectation_ps( + z=[index_of_ones[0], index_of_ones[1]] + ) + # Compute expectation value for a two-qubit Pauli term + + loss += delta_loss + + return backend.real(loss) + + +def QAOA_loss( + nlayers: int, + pauli_terms: Tensor, + weights: List[float], + params: List[float], + full_coupling: bool = False, + mixer: str = "X", +) -> Any: + """ + computes the loss function for the Quantum Approximate Optimization Algorithm (QAOA) applied to the Ising model. + + :param nlayers: The number of layers in the QAOA ansatz. + :param pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :param params: A list of parameter values used in the QAOA ansatz. + :param full_coupling (optional): A flag indicating whether to use all-to-all coupling in mixers. Default is False. + :paran mixer (optional): The mixer operator to use. Default is "X". The other options are "XY" and "ZZ". + :return: The computed loss value. + """ + c = QAOA_ansatz_for_Ising( + params, nlayers, pauli_terms, weights, mixer=mixer, full_coupling=full_coupling + ) + # Obtain the quantum circuit using QAOA_from_Ising function + + return Ising_loss(c, pauli_terms, weights) + # Compute the Ising loss using Ising_loss function on the obtained circuit + + +def QUBO_QAOA( + Q: Tensor, + nlayers: int, + iterations: int, + vvag: bool = False, + ncircuits: int = 10, + init_params: Optional[List[float]] = None, + mixer: str = "X", + learning_rate: float = 1e-2, + callback: Optional[Optional[Callable[[List[float], float], None]]] = None, + full_coupling: bool = False, +) -> Array: + """ + Performs the QAOA on a given QUBO problem. + Adam optimizer from TensorFlow is used. + + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param iterations: The number of iterations to run the optimization. + :param vvag (optional): A flag indicating whether to use vectorized variational adjoint gradient. Default is False. + :param ncircuits (optional): The number of circuits when using vectorized variational adjoint gradient. + Default is 10. + :param init_params (optional): The initial parameters for the ansatz circuit. + Default is None, which initializes the parameters randomly. + :paran mixer (optional): The mixer operator to use. Default is "X". The other options are "XY" and "ZZ". + :param learning_rate (optional): The learning rate for the Adam optimizer. Default is 1e-2. + :param callback (optional): A callback function that is executed during each iteration. Default is None. + :param full_coupling (optional): A flag indicating whether to use all-to-all coupling in mixers. Default is False. + :return params: The optimized parameters for the ansatz circuit. + """ + + pauli_terms, weights, _ = QUBO_to_Ising(Q) + + loss_val_grad = backend.value_and_grad( + partial( + QAOA_loss, + nlayers, + pauli_terms, + weights, + mixer=mixer, + full_coupling=full_coupling, + ) + ) + loss_val_grad = backend.jit(loss_val_grad, static_argnums=(1, 2)) + # Define the loss and gradients function using value_and_grad, which calculates both the loss value and gradients. + + if init_params is None: + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + if vvag is True: + loss_val_grad = backend.vvag(loss_val_grad, argnums=0, vectorized_argnums=0) + params = backend.implicit_randn(shape=[ncircuits, 2 * nlayers], stddev=0.1) + # If init_params is not provided, initialize the parameters randomly. + # If vvag flag is set to True, use vectorized variational adjoint gradient (vvag) with multiple circuits. + else: + params = init_params + # If init_params is provided, use the provided parameters. + # Initialize the parameters for the ansatz circuit. + + # This can improve the performance by pre-compiling the loss and gradients function. + + opt = backend.optimizer(tf.keras.optimizers.Adam(learning_rate)) + # Define the optimizer (Adam optimizer) with the specified learning rate. + + for _ in range(iterations): + loss, grads = loss_val_grad(params) + # Calculate the loss and gradients using the loss_val_grad_jit function. + + params = opt.update(grads, params) + # Update the parameters using the optimizer and gradients. + + if callback is not None: + callback(loss, params) + # Execute the callback function with the current loss and parameters. + + return params + # Return the optimized parameters for the ansatz circuit. + + +def cvar_value(r: List[float], p: List[float], percent: float) -> Any: + """ + Compute the Conditional Value at Risk (CVaR) based on the measurement results. + + :param r: The observed outcomes after measurements. + :param p: Probabilities associated with each observed outcome. + :param percent: The cut-off percentage for CVaR computation. + :return: The calculated CVaR value. + """ + sorted_indices = tf.argsort(r) + p_sorted = tf.cast(tf.gather(p, sorted_indices), dtype=tf.float32) + r_sorted = tf.cast(tf.gather(r, sorted_indices), dtype=tf.float32) + + # Calculate the cumulative sum of sorted probabilities. + cumsum_p = tf.math.cumsum(p_sorted) + + # Create a tensor that evaluates to 1 if the condition is met, otherwise 0. + mask = tf.cast(tf.math.less(cumsum_p, percent), dtype=tf.float32) + + # Use mask to filter and sum the required elements for CVaR. + cvar_numerator = tf.reduce_sum(mask * p_sorted * r_sorted) + + # Compute the last remaining portion that exceeds the cut-off percentage. + last_portion_index = tf.math.argmax(tf.math.greater_equal(cumsum_p, percent)) + last_portion = (percent - cumsum_p[last_portion_index - 1]) * r_sorted[ + last_portion_index + ] + + # Calculate the final CVaR. + cvar_result = (cvar_numerator + last_portion) / percent + + return cvar_result + + +def cvar_from_circuit(circuit: Circuit, nsamples: int, Q: Tensor, alpha: float) -> Any: + """ + Directly calculate the Conditional Value at Risk (CVaR) from a circuit. + The CVaR depends on a bunch of measurements. + + :param circuit: The quantum circuit used to prepare the state. + :param nsamples: The number of samples to take for measurements. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param alpha: The cut-off percentage for CVaR. + :return: The calculated CVaR value. + """ + # Obtain and normalize measurement results + measurement_data = circuit.state() + results = measurement_results( + measurement_data, counts=nsamples, format="sample_int", jittable=True + ) + n_counts = tf.shape(results)[0] + + # Determine the number of qubits in the circuit and generate all possible states + n_qubits = len(Q) + all_states = tf.constant([format(i, f"0{n_qubits}b") for i in range(2**n_qubits)]) + all_binary = tf.reshape( + tf.strings.to_number(tf.strings.bytes_split(all_states), tf.float32), + (2**n_qubits, n_qubits), + ) + all_decimal = tf.range(2**n_qubits, dtype=tf.int32) + + # Convert the Q matrix to a TensorFlow tensor + Q_tensor = tf.convert_to_tensor(Q, dtype=tf.float32) + + # calculate cost values + values = tf.reduce_sum(all_binary * tf.matmul(all_binary, Q_tensor), axis=1) + + # Count the occurrences of each state and calculate probabilities + state_counts = tf.reduce_sum( + tf.cast(tf.equal(tf.reshape(results, [-1, 1]), all_decimal), tf.int32), axis=0 + ) + probabilities = tf.cast(state_counts, dtype=tf.float32) / tf.cast( + n_counts, dtype=tf.float32 + ) + + # Calculate CVaR + cvar_result = cvar_value(values, probabilities, alpha) + + return cvar_result + + +def cvar_from_expectation(circuit: Circuit, Q: Tensor, alpha: float) -> Any: + """ + Calculate the Conditional Value at Risk (CVaR) from the expectation values of a quantum circuit. + + :param circuit: The quantum circuit. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param alpha: The cut-off percentage for CVaR. + :return: The calculated CVaR value. + """ + + # Calculate the probability amplitudes for quantum circuit outcomes. + prob = tf.convert_to_tensor(circuit.probability(), dtype=tf.float32) + + # Generate all possible binary states for the given Q-matrix. + n_qubits = len(Q) + all_states = tf.constant( + [format(i, "0" + str(n_qubits) + "b") for i in range(2 ** len(Q))] + ) + all_binary = tf.reshape( + tf.strings.to_number(tf.strings.bytes_split(all_states), tf.float32), + (2**n_qubits, n_qubits), + ) + + # Convert the Q-matrix to a TensorFlow tensor. + Q_tensor = tf.convert_to_tensor(Q, dtype=tf.float32) + + # calculate cost values + elementwise_product = tf.multiply(all_binary, tf.matmul(all_binary, Q_tensor)) + values = tf.reduce_sum(elementwise_product, axis=1) + + # Calculate the CVaR value using the computed values and the probability distribution. + cvar_result = cvar_value(values, prob, alpha) + + return cvar_result + + +def cvar_loss( + nlayers: int, + Q: Tensor, + nsamples: int, + alpha: float, + expectation_based: bool, + params: List[float], +) -> Any: + """ + Calculate the CVaR loss for a given QUBO problem using the QAOA ansatz. + + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param Q: The Q-matrix representing the Quadratic Unconstrained Binary Optimization (QUBO) problem. + :param nsamples: The number of samples to take for measurements in the CVaR calculation. + :param alpha: The cut-off percentage for CVaR. + :param expectation_based: A flag indicating the type of CVaR ansatz (measurement-based or expectation-based). + :param params: The parameters for the QAOA ansatz circuit. + :return: The calculated CVaR loss. + """ + + pauli_terms, weights, _ = QUBO_to_Ising(Q) + + c = QAOA_ansatz_for_Ising(params, nlayers, pauli_terms, weights) + # Generate the QAOA ansatz circuit for the given parameters. + + if expectation_based is False: + return cvar_from_circuit(c, nsamples, Q, alpha) + # Calculate CVaR using circuit-based measurement results. + elif expectation_based is True: + return cvar_from_expectation(c, Q, alpha) + # Calculate CVaR using expectation values of the circuit. + else: + raise ValueError("Invalid CVaR ansatz type.") + # Raise an error if an invalid CVaR ansatz type is provided. + + +def QUBO_QAOA_cvar( + Q: Tensor, + nlayers: int, + alpha: float, + nsamples: int = 1000, + callback: Optional[Callable[[List[float], float], None]] = None, + expectation_based: bool = False, + maxiter: int = 1000, + init_params: Optional[Tuple[float,]] = None, +) -> Array: + """ + Perform the QUBO QAOA optimization with CVaR as the loss function. + + :param Q: The n-by-n square and symmetric Q-matrix representing the QUBO problem. + :param ansatz: The ansatz function to be used for QAOA. + :param nlayers: The number of layers (depth) in the QAOA ansatz. + :param alpha: The cut-off percentage for CVaR. + :param nsamples: The number of samples for measurements in the CVaR calculation. Default is 1000. + :param callback: A callback function to be called after each iteration. Default is None. + :param expectation_based: A flag indicating the type of CVaR ansatz (measurement-based or expectation-based). + Default is False. + :param maxiter: The maximum number of iterations for the optimization. Default is 1000. + :return: The optimized parameters for the ansatz circuit. + """ + loss = partial(cvar_loss, nlayers, Q, nsamples, alpha, expectation_based) + + f_scipy = scipy_interface(loss, shape=(2 * nlayers,), jit=True, gradient=False) + + if init_params is None: + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + # If init_params is not provided, initialize the parameters randomly. + else: + params = init_params + # If init_params is provided, use the provided parameters. + + # Initialize the parameters for the ansatz circuit. + params = backend.implicit_randn(shape=[2 * nlayers], stddev=0.5) + + r = optimize.minimize( + f_scipy, + params, + method="COBYLA", + callback=callback, + options={"maxiter": maxiter}, + ) + # Perform the optimization using the COBYLA method from scipy.optimize. + + return r.x + # Return the optimized parameters for the ansatz circuit. diff --git a/tensorcircuit/applications/physics/__init__.py b/tensorcircuit/applications/physics/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tensorcircuit/applications/physics/baseline.py b/tensorcircuit/applications/physics/baseline.py new file mode 100644 index 00000000..9105abaf --- /dev/null +++ b/tensorcircuit/applications/physics/baseline.py @@ -0,0 +1,57 @@ +""" +baseline calculators for physical systems +""" + +import numpy as np + + +def TFIM1Denergy( + L: int, Jzz: float = 1.0, Jx: float = 1.0, Pauli: bool = True +) -> float: + # PBC + # nice tutorial: https://arxiv.org/pdf/2009.09208.pdf + # further investigation on 1 TFIM solution structure is required + # will fail on AFM phase Jzz>Jx and Jzz>0 and odd sites (frustration in boundary) + e = 0 + if Pauli: + Jx *= 2 + Jzz *= 4 + for i in range(L): + q = np.pi * (2 * i - (1 + (-1) ** L) / 2) / L + e -= np.abs(Jx) / 2 * np.sqrt(1 + Jzz**2 / 4 / Jx**2 - Jzz / Jx * np.cos(q)) + return e + + +def Heisenberg1Denergy(L: int, Pauli: bool = True, maxiters: int = 1000) -> float: + # PBC + error = 1e-15 + eps = 1e-20 # avoid zero division + phi = np.zeros([L // 2, L // 2]) + phi2 = np.zeros([L // 2, L // 2]) + lamb = np.array([2 * i + 1 for i in range(L // 2)]) + for _ in range(maxiters): + k = 1 / L * (2 * np.pi * lamb + np.sum(phi, axis=-1) - np.diag(phi)) + for i in range(L // 2): + for j in range(L // 2): + phi2[i, j] = ( + np.arctan( + 2 + / ( + 1 / (np.tan(k[i] / 2) + eps) + - 1 / (np.tan(k[j] / 2) + eps) + + eps + ) + ) + * 2 + ) + if np.allclose(phi, phi2, rtol=error): # converged + break + phi = phi2.copy() + else: + raise ValueError( + "the maxiters %s is too small for bethe ansatz to converge" % maxiters + ) + e = -np.sum(1 - np.cos(k)) + L / 4 + if Pauli is True: + e *= 4 + return e # type: ignore diff --git a/tensorcircuit/applications/physics/fss.py b/tensorcircuit/applications/physics/fss.py new file mode 100644 index 00000000..f0490509 --- /dev/null +++ b/tensorcircuit/applications/physics/fss.py @@ -0,0 +1,110 @@ +""" +finite size scaling tools +""" + +from typing import List, Tuple, Optional + +import numpy as np + + +def data_collapse( + n: List[int], + p: List[float], + obs: List[List[float]], + pc: float, + nu: float, + beta: float = 0, + obs_type: int = 1, + fit_type: int = 0, + dobs: Optional[List[List[float]]] = None, +) -> Tuple[List[float], List[List[float]], List[List[float]], float]: + xL: List[List[float]] = [] # x=(p-pc)L^(1/\nv) + yL: List[List[float]] = [] # y=S(p,L)-S(pc,L) or S(p,L) + pc_list = [] + if not isinstance(p[0], list): + p = [p for _ in n] # type: ignore + for n0 in range(len(n)): + xL.append([]) + yL.append([]) + for p0 in range(len(p[n0])): # type: ignore + xL[n0].append((p[n0][p0] - pc) * (n[n0] ** (1 / nu))) # type: ignore + pc_L = pc_linear_interpolation(p[n0], obs[n0], pc) # type: ignore + if obs_type == 0: + yL[n0].append((obs[n0][p0] - pc_L) * n[n0] ** beta) + # entanglement with only collapse and no crossing + else: + yL[n0].append(obs[n0][p0] * n[n0] ** beta) + # tripartite mutual information + pc_list.append(pc_L) + if fit_type == 0: + xL_all = [] + for i in range(len(xL)): + xL_all.extend(xL[i]) + yL_ave = [] + loss = [] + for x0 in range(len(xL_all)): + ybar_list = [] + for n0 in range(len(n)): + if xL_all[x0] >= xL[n0][0] and xL_all[x0] <= xL[n0][-1]: + yinsert = pc_linear_interpolation(xL[n0], yL[n0], xL_all[x0]) + ybar_list.append(yinsert) + + ybar = np.mean(ybar_list) + mean_squared = [(ybar_list[i] - ybar) ** 2 for i in range(len(ybar_list))] + loss.append(np.sum(mean_squared)) + yL_ave.append(ybar) + loss = np.sum(loss) + + return pc_list, xL, yL, loss # type: ignore + + # fit_type == 1 + if dobs is None: + raise ValueError("uncertainty of each y has to be specified in `dobs`") + + datas = [] + for n0 in range(len(n)): + for i in range(len(xL[n0])): + datas.append([xL[n0][i], yL[n0][i], dobs[n0][i]]) + datas = sorted(datas, key=lambda x: x[0]) + loss = _quality_objective_v2(datas) # type: ignore + return pc_list, xL, yL, loss # type: ignore + + +def _quality_objective_v2(datas: List[List[float]]) -> float: + # https://journals.aps.org/prb/supplemental/10.1103/PhysRevB.101.060301/Supplement.pdf + loss = [] + for i in range(len(datas) - 2): + # i, i+1, i+2 + x, y, d = datas[i + 1] + x1, y1, d1 = datas[i] + x2, y2, d2 = datas[i + 2] + if np.abs(x - x1) < 1e-4 or np.abs(x - x2) < 1e-4: + continue + ybar = ((x2 - x) * y1 - (x1 - x) * y2) / (x2 - x1) + delta = ( + d**2 + + d1**2 * (x2 - x) ** 2 / (x2 - x1) ** 2 + + d2**2 * (x1 - x) ** 2 / (x2 - x1) ** 2 + ) + w = (y - ybar) ** 2 / delta + loss.append(w) + return np.mean(loss) # type: ignore + + +def pc_linear_interpolation(p: List[float], SA: List[float], pc_input: float) -> float: + if pc_input in p: + pc_index = p.index(pc_input) + pc = SA[pc_index] + else: + pr_index = 0 + for p0 in range(len(p)): + if p[p0] > pc_input: + pr_index = p0 + break + + x = [p[pr_index - 1], p[pr_index]] + y = [SA[pr_index - 1], SA[pr_index]] + linear_model = np.polyfit(x, y, 1) + linear_model_fn = np.poly1d(linear_model) + pc = linear_model_fn(pc_input) + return pc diff --git a/tensorcircuit/applications/utils.py b/tensorcircuit/applications/utils.py index a2db4fee..3ca54ff2 100644 --- a/tensorcircuit/applications/utils.py +++ b/tensorcircuit/applications/utils.py @@ -2,6 +2,7 @@ A collection of useful function snippets that irrelevant with the main modules or await for further refactor """ + import logging from typing import Any, Callable, Iterator, Optional, Sequence, Tuple @@ -388,6 +389,8 @@ def repr2array(inputs: str) -> Array: return np.array(outputs) +# duplicated, will remove later +# use the version in applications.physics.baseline.py def TFIM1Denergy( L: int, Jzz: float = 1.0, Jx: float = 1.0, Pauli: bool = True ) -> float: diff --git a/tensorcircuit/applications/vags.py b/tensorcircuit/applications/vags.py index 80e5b74a..b2b5a612 100644 --- a/tensorcircuit/applications/vags.py +++ b/tensorcircuit/applications/vags.py @@ -1,6 +1,7 @@ """ DQAS application kernels as vag functions """ + from functools import lru_cache, partial, reduce import logging import operator diff --git a/tensorcircuit/applications/vqes.py b/tensorcircuit/applications/vqes.py index 8eb6c510..a542268b 100644 --- a/tensorcircuit/applications/vqes.py +++ b/tensorcircuit/applications/vqes.py @@ -1,6 +1,7 @@ """ VQNHE application """ + from functools import lru_cache from itertools import product import time @@ -28,6 +29,9 @@ dtype = np.complex128 # only guarantee compatible with float64 mode # only support tf backend +# i.e. use the following setup in the code +# tc.set_backend("tensorflow") +# tc.set_dtype("complex128") x = np.array([[0, 1.0], [1.0, 0]], dtype=dtype) y = np.array([[0, -1j], [1j, 0]], dtype=dtype) @@ -376,7 +380,11 @@ def create_circuit( return self.create_hea2_circuit(**kws) if choose == "hn": return self.create_hn_circuit(**kws) - raise ValueError("no such choose option: %s" % choose) + return self.create_functional_circuit(**kws) # type: ignore + + def create_functional_circuit(self, **kws: Any) -> Callable[[Tensor], Tensor]: + func = kws.get("func") + return func # type: ignore def create_hn_circuit(self, **kws: Any) -> Callable[[Tensor], Tensor]: def circuit(a: Tensor) -> Tensor: diff --git a/tensorcircuit/asciiart.py b/tensorcircuit/asciiart.py index b63b317e..b5c9e3b4 100644 --- a/tensorcircuit/asciiart.py +++ b/tensorcircuit/asciiart.py @@ -1,6 +1,7 @@ """ Some ascii art from https://www.asciiart.eu/, have fun! """ + # pylint: disable=invalid-name import hashlib diff --git a/tensorcircuit/backends/abstract_backend.py b/tensorcircuit/backends/abstract_backend.py index e6f69f97..4a7ccecd 100644 --- a/tensorcircuit/backends/abstract_backend.py +++ b/tensorcircuit/backends/abstract_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: abstract backend """ + # pylint: disable=invalid-name # pylint: disable=unused-variable @@ -25,7 +26,7 @@ def copy(self: Any, a: Tensor) -> Tensor: :param a: tensor in matrix form :type a: Tensor - :return: matrix exponential of matrix ``a`` + :return: the copy tensor of ``a`` :rtype: Tensor """ raise NotImplementedError( @@ -345,6 +346,34 @@ def adjoint(self: Any, a: Tensor) -> Tensor: """ return self.conj(self.transpose(a)) + def det(self: Any, a: Tensor) -> Tensor: + """ + Return the determinant scalar of a tensor ``a`` + + :param a: Input tensor + :type a: Tensor + :return: determinant of ``a`` + :rtype: Tensor + """ + raise NotImplementedError( + "Backend '{}' has not implemented `det`.".format(self.name) + ) + + def schur(self: Any, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + """ + Compute Schur decomposition of a matrix. + + :param a: _description_ + :type a: Tensor + :param output: _description_, defaults to "real" + :type output: str, optional + :return: T, Z so that ZTZ^H = a + :rtype: Tuple[Tensor, Tensor] + """ + raise NotImplementedError( + "Backend '{}' has not implemented `schur`.".format(self.name) + ) + def i(self: Any, dtype: str) -> Tensor: """ Return 1.j in as a tensor compatible with the backend. @@ -1511,16 +1540,19 @@ def wrapper(*args: Any, **kws: Any) -> Any: args, tuple( [ - self.reshape( - self.eye(self.sizen(arg), dtype=arg.dtype), - [-1] + list(self.shape_tuple(arg)), - ) - if i == argnum - else self.reshape( - self.zeros( - [self.sizen(arg), self.sizen(arg)], dtype=arg.dtype - ), - [-1] + list(self.shape_tuple(arg)), + ( + self.reshape( + self.eye(self.sizen(arg), dtype=arg.dtype), + [-1] + list(self.shape_tuple(arg)), + ) + if i == argnum + else self.reshape( + self.zeros( + [self.sizen(arg), self.sizen(arg)], + dtype=arg.dtype, + ), + [-1] + list(self.shape_tuple(arg)), + ) ) for i, arg in enumerate(args) ] @@ -1579,16 +1611,18 @@ def _first(x: Sequence[Any]) -> Any: args, collect( [ - self.reshape( - self.eye(self.sizen(v), dtype=v.dtype), - [-1] + list(self.shape_tuple(v)), - ) - if i == k - else self.reshape( - self.zeros( - [self.sizen(v), self.sizen(v)], dtype=v.dtype - ), - [-1] + list(self.shape_tuple(v)), + ( + self.reshape( + self.eye(self.sizen(v), dtype=v.dtype), + [-1] + list(self.shape_tuple(v)), + ) + if i == k + else self.reshape( + self.zeros( + [self.sizen(v), self.sizen(v)], dtype=v.dtype + ), + [-1] + list(self.shape_tuple(v)), + ) ) for i, v in enumerate(values) ] diff --git a/tensorcircuit/backends/cupy_backend.py b/tensorcircuit/backends/cupy_backend.py index 4aa58d06..11260d19 100644 --- a/tensorcircuit/backends/cupy_backend.py +++ b/tensorcircuit/backends/cupy_backend.py @@ -1,6 +1,7 @@ """ CuPy backend. Not in the tensornetwork package and highly experimental. """ + # pylint: disable=invalid-name import logging diff --git a/tensorcircuit/backends/jax_backend.py b/tensorcircuit/backends/jax_backend.py index 472066ea..33be28fd 100644 --- a/tensorcircuit/backends/jax_backend.py +++ b/tensorcircuit/backends/jax_backend.py @@ -1,17 +1,19 @@ """ Backend magic inherited from tensornetwork: jax backend """ + # pylint: disable=invalid-name -from functools import partial import logging import warnings +from functools import partial from typing import Any, Callable, Optional, Sequence, Tuple, Union import numpy as np -from scipy.sparse import coo_matrix import tensornetwork +from scipy.sparse import coo_matrix from tensornetwork.backends.jax import jax_backend + from .abstract_backend import ExtendedBackend logger = logging.getLogger(__name__) @@ -156,12 +158,19 @@ def _rq_jax( return r, q +def _eigh_jax(self: Any, tensor: Tensor) -> Tensor: + from .jax_ops import adaware_eigh_jit as adaware_eigh + + return adaware_eigh(tensor) + + tensornetwork.backends.jax.jax_backend.JaxBackend.convert_to_tensor = ( _convert_to_tensor_jax ) tensornetwork.backends.jax.jax_backend.JaxBackend.svd = _svd_jax tensornetwork.backends.jax.jax_backend.JaxBackend.qr = _qr_jax tensornetwork.backends.jax.jax_backend.JaxBackend.rq = _rq_jax +tensornetwork.backends.jax.jax_backend.JaxBackend.eigh = _eigh_jax class JaxBackend(jax_backend.JaxBackend, ExtendedBackend): # type: ignore @@ -188,8 +197,8 @@ def __init__(self) -> None: "Jax not installed, please switch to a different " "backend or install Jax." ) - from jax.experimental import sparse import jax.scipy + from jax.experimental import sparse try: import optax @@ -295,7 +304,13 @@ def i(self, dtype: Any = None) -> Tensor: dtype = npdtype # type: ignore if isinstance(dtype, str): dtype = getattr(jnp, dtype) - return np.array(1j, dtype=dtype) + return jnp.array(1j, dtype=dtype) + + def det(self, a: Tensor) -> Tensor: + return jnp.linalg.det(a) + + def schur(self, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + return jsp.linalg.schur(a, output=output) # type: ignore def real(self, a: Tensor) -> Tensor: return jnp.real(a) @@ -405,7 +420,7 @@ def searchsorted(self, a: Tensor, v: Tensor, side: str = "left") -> Tensor: return jnp.searchsorted(a, v, side) def tree_map(self, f: Callable[..., Any], *pytrees: Any) -> Any: - return libjax.tree_map(f, *pytrees) + return libjax.tree_util.tree_map(f, *pytrees) def tree_flatten(self, pytree: Any) -> Tuple[Any, Any]: return libjax.tree_util.tree_flatten(pytree) # type: ignore @@ -616,7 +631,7 @@ def is_sparse(self, a: Tensor) -> bool: return isinstance(a, sparse.BCOO) # type: ignore def device(self, a: Tensor) -> str: - dev = a.device() + (dev,) = a.devices() return self._dev2str(dev) def device_move(self, a: Tensor, dev: Any) -> Tensor: @@ -743,7 +758,7 @@ def wrapper( gs = list(gs) for i, (j, g) in enumerate(zip(argnums_list, gs)): if j not in vectorized_argnums: # type: ignore - gs[i] = libjax.tree_map(partial(jnp.sum, axis=0), g) + gs[i] = libjax.tree_util.tree_map(partial(jnp.sum, axis=0), g) if isinstance(argnums, int): gs = gs[0] else: diff --git a/tensorcircuit/backends/jax_ops.py b/tensorcircuit/backends/jax_ops.py index e9e6c2cf..2eaf2f1b 100644 --- a/tensorcircuit/backends/jax_ops.py +++ b/tensorcircuit/backends/jax_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any, Tuple, Sequence @@ -13,7 +14,8 @@ @jax.custom_vjp def adaware_svd(A: Array) -> Any: - return jnp.linalg.svd(A, full_matrices=False) + u, s, v = jnp.linalg.svd(A, full_matrices=False) + return (u, s, v) def _safe_reciprocal(x: Array, epsilon: float = 1e-15) -> Array: @@ -66,7 +68,7 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: return (grad_a,) -adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) +adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd) # type: ignore adaware_svd_jit = jax.jit(adaware_svd) @@ -76,8 +78,8 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: @jax.custom_vjp def adaware_qr(A: Array) -> Any: - # q, r = jnp.linalg.qr(A) - return jnp.linalg.qr(A) + q, r = jnp.linalg.qr(A) + return (q, r) def jaxqr_fwd(A: Array) -> Any: @@ -92,7 +94,7 @@ def jaxqr_bwd(res: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]: dr = dr.conj() def _TriangularSolve(x: Array, r: Array) -> Array: - return jax.scipy.linalg.solve_triangular( + return jax.scipy.linalg.solve_triangular( # type: ignore r, x.T.conj(), lower=False, trans=0 ).T.conj() @@ -142,6 +144,32 @@ def _QrGradSquareAndDeepMatrices(q: Array, r: Array, dq: Array, dr: Array) -> Ar return (result,) -adaware_qr.defvjp(jaxqr_fwd, jaxqr_bwd) +adaware_qr.defvjp(jaxqr_fwd, jaxqr_bwd) # type: ignore adaware_qr_jit = jax.jit(adaware_qr) + + +@jax.custom_vjp +def adaware_eigh(A: Array) -> Array: + return jnp.linalg.eigh(A) + + +def jaxeigh_fwd(A: Array) -> Array: + e, v = jnp.linalg.eigh(A) + return (e, v), (A, e, v) + + +def jaxeigh_bwd(r: Array, tangents: Array) -> Array: + a, e, v = r + de, dv = tangents + eye_n = jnp.eye(a.shape[-1], dtype=a.dtype) + f = _safe_reciprocal(e[..., jnp.newaxis, :] - e[..., jnp.newaxis] + eye_n) - eye_n + middle = jnp.diag(de) + jnp.multiply(f, (v.T @ dv)) + grad_a = jnp.conj(v) @ middle @ v.T + return (grad_a,) + + +# denegerate eigev values lead nan in eigh gradients, while tf has fixed that long ago + +adaware_eigh.defvjp(jaxeigh_fwd, jaxeigh_bwd) +adaware_eigh_jit = jax.jit(adaware_eigh) diff --git a/tensorcircuit/backends/numpy_backend.py b/tensorcircuit/backends/numpy_backend.py index 2d22b94d..87052275 100644 --- a/tensorcircuit/backends/numpy_backend.py +++ b/tensorcircuit/backends/numpy_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: numpy backend """ + # pylint: disable=invalid-name import logging @@ -9,7 +10,7 @@ import numpy as np import tensornetwork -from scipy.linalg import expm, solve +from scipy.linalg import expm, solve, schur from scipy.special import softmax, expit from scipy.sparse import coo_matrix, issparse from tensornetwork.backends.numpy import numpy_backend @@ -131,6 +132,12 @@ def dtype(self, a: Tensor) -> str: def numpy(self, a: Tensor) -> Tensor: return a + def det(self, a: Tensor) -> Tensor: + return np.linalg.det(a) + + def schur(self, a: Tensor, output: str = "real") -> Tuple[Tensor, Tensor]: + return schur(a, output=output) # type: ignore + def i(self, dtype: Any = None) -> Tensor: if not dtype: dtype = npdtype # type: ignore @@ -207,7 +214,8 @@ def imag(self, a: Tensor) -> Tensor: def cast(self, a: Tensor, dtype: str) -> Tensor: with warnings.catch_warnings(): - warnings.simplefilter("ignore", np.ComplexWarning) + #warnings.simplefilter("ignore", np.ComplexWarning) + warnings.simplefilter("ignore", DeprecationWarning) if isinstance(dtype, str): return a.astype(getattr(np, dtype)) return a.astype(dtype) diff --git a/tensorcircuit/backends/pytorch_backend.py b/tensorcircuit/backends/pytorch_backend.py index 7362cc47..3214c72c 100644 --- a/tensorcircuit/backends/pytorch_backend.py +++ b/tensorcircuit/backends/pytorch_backend.py @@ -1,6 +1,7 @@ """ Backend magic inherited from tensornetwork: pytorch backend """ + # pylint: disable=invalid-name import logging @@ -306,6 +307,9 @@ def i(self, dtype: Any = None) -> Tensor: dtype = getattr(torchlib, dtype) return torchlib.tensor(1j, dtype=dtype) + def det(self, a: Tensor) -> Tensor: + return torchlib.linalg.det(a) + def real(self, a: Tensor) -> Tensor: try: a = torchlib.real(a) diff --git a/tensorcircuit/backends/pytorch_ops.py b/tensorcircuit/backends/pytorch_ops.py index 182101fd..e801a4ca 100644 --- a/tensorcircuit/backends/pytorch_ops.py +++ b/tensorcircuit/backends/pytorch_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any diff --git a/tensorcircuit/backends/tensorflow_backend.py b/tensorcircuit/backends/tensorflow_backend.py index a77ea1d7..365bd521 100644 --- a/tensorcircuit/backends/tensorflow_backend.py +++ b/tensorcircuit/backends/tensorflow_backend.py @@ -1,8 +1,11 @@ """ Backend magic inherited from tensornetwork: tensorflow backend """ + # pylint: disable=invalid-name +import os +import re from functools import reduce, partial from operator import mul from typing import Any, Callable, Optional, Sequence, Tuple, Union @@ -225,6 +228,120 @@ def _rq_tf( return r, q +def _svd_tf( + self: Any, + tensor: Tensor, + pivot_axis: int = -1, + max_singular_values: Optional[int] = None, + max_truncation_error: Optional[float] = None, + relative: Optional[bool] = False, +) -> Tuple[Tensor, Tensor, Tensor, Tensor]: + """Computes the singular value decomposition (SVD) of a tensor. + + The SVD is performed by treating the tensor as a matrix, with an effective + left (row) index resulting from combining the axes `tensor.shape[:pivot_axis]` + and an effective right (column) index resulting from combining the axes + `tensor.shape[pivot_axis:]`. + + For example, if `tensor` had a shape (2, 3, 4, 5) and `pivot_axis` was 2, then + `u` would have shape (2, 3, 6), `s` would have shape (6), and `vh` would + have shape (6, 4, 5). + + If `max_singular_values` is set to an integer, the SVD is truncated to keep + at most this many singular values. + + If `max_truncation_error > 0`, as many singular values will be truncated as + possible, so that the truncation error (the norm of discarded singular + values) is at most `max_truncation_error`. + If `relative` is set `True` then `max_truncation_err` is understood + relative to the largest singular value. + + If both `max_singular_values` snd `max_truncation_error` are specified, the + number of retained singular values will be + `min(max_singular_values, nsv_auto_trunc)`, where `nsv_auto_trunc` is the + number of singular values that must be kept to maintain a truncation error + smaller than `max_truncation_error`. + + The output consists of three tensors `u, s, vh` such that: + ```python + u[i1,...,iN, j] * s[j] * vh[j, k1,...,kM] == tensor[i1,...,iN, k1,...,kM] + ``` + Note that the output ordering matches numpy.linalg.svd rather than tf.svd. + + Args: + tf: The tensorflow module. + tensor: A tensor to be decomposed. + pivot_axis: Where to split the tensor's axes before flattening into a + matrix. + max_singular_values: The number of singular values to keep, or `None` to + keep them all. + max_truncation_error: The maximum allowed truncation error or `None` to not + do any truncation. + relative: Multiply `max_truncation_err` with the largest singular value. + + Returns: + u: Left tensor factor. + s: Vector of ordered singular values from largest to smallest. + vh: Right tensor factor. + s_rest: Vector of discarded singular values (length zero if no + truncation). + """ + left_dims = tf.shape(tensor)[:pivot_axis] + right_dims = tf.shape(tensor)[pivot_axis:] + + tensor = tf.reshape(tensor, [tf.reduce_prod(left_dims), tf.reduce_prod(right_dims)]) + + eps = os.environ.get("TC_BACKENDS_TENSORFLOW_BACKEND__SVD_TF_EPS") + if eps is not None: + eps = 10 ** (-int(eps)) + tensor += eps * tf.ones(tensor.shape, dtype=tensor.dtype) + # for numerical stability at least in tf+cpu + s, u, v = tf.linalg.svd(tensor) + + if max_singular_values is None: + max_singular_values = tf.size(s, out_type=tf.int64) + else: + max_singular_values = tf.constant(max_singular_values, dtype=tf.int64) + + if max_truncation_error is not None: + # Cumulative norms of singular values in ascending order. + trunc_errs = tf.sqrt(tf.cumsum(tf.square(s), reverse=True)) + # If relative is true, rescale max_truncation error with the largest + # singular value to yield the absolute maximal truncation error. + if relative: + abs_max_truncation_error = max_truncation_error * s[0] + else: + abs_max_truncation_error = max_truncation_error + # We must keep at least this many singular values to ensure the + # truncation error is <= abs_max_truncation_error. + num_sing_vals_err = tf.math.count_nonzero( + tf.cast(trunc_errs > abs_max_truncation_error, dtype=tf.int32) + ) + else: + num_sing_vals_err = max_singular_values + + num_sing_vals_keep = tf.minimum(max_singular_values, num_sing_vals_err) + + # tf.svd() always returns the singular values as a vector of float{32,64}. + # since tf.math_ops.real is automatically applied to s. This causes + # s to possibly not be the same dtype as the original tensor, which can cause + # issues for later contractions. To fix it, we recast to the original dtype. + s = tf.cast(s, tensor.dtype) + + s_rest = s[num_sing_vals_keep:] + s = s[:num_sing_vals_keep] + u = u[:, :num_sing_vals_keep] + v = v[:, :num_sing_vals_keep] + + vh = tf.linalg.adjoint(v) + + dim_s = tf.shape(s)[0] # must use tf.shape (not s.shape) to compile + u = tf.reshape(u, tf.concat([left_dims, [dim_s]], axis=-1)) + vh = tf.reshape(vh, tf.concat([[dim_s], right_dims], axis=-1)) + + return u, s, vh, s_rest + + # temporary hot replace until new version of tensorflow is released, # see issue: https://github.com/google/TensorNetwork/issues/940 # avoid buggy tensordot2 in tensornetwork @@ -240,6 +357,7 @@ def _rq_tf( ) tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.qr = _qr_tf tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.rq = _rq_tf +tensornetwork.backends.tensorflow.tensorflow_backend.TensorFlowBackend.svd = _svd_tf class TensorFlowBackend(tensorflow_backend.TensorFlowBackend, ExtendedBackend): # type: ignore @@ -262,6 +380,9 @@ def __init__(self) -> None: tf.sparse.SparseTensor.__add__ = tf.sparse.add self.minor = int(tf.__version__.split(".")[1]) self.name = "tensorflow" + logger = tf.get_logger() # .setLevel('ERROR') + logger.addFilter(lambda s: not re.match(".*You are casting.*", s.getMessage())) + # ignore casting warning by logger def eye( self, N: int, dtype: Optional[str] = None, M: Optional[int] = None @@ -360,6 +481,9 @@ def i(self, dtype: Any = None) -> Tensor: dtype = getattr(tf, dtype) return tf.constant(1j, dtype=dtype) + def det(self, a: Tensor) -> Tensor: + return tf.linalg.det(a) + def min(self, a: Tensor, axis: Optional[int] = None) -> Tensor: return tf.reduce_min(a, axis=axis) diff --git a/tensorcircuit/backends/tf_ops.py b/tensorcircuit/backends/tf_ops.py index 27327722..d7b6d380 100644 --- a/tensorcircuit/backends/tf_ops.py +++ b/tensorcircuit/backends/tf_ops.py @@ -1,6 +1,7 @@ """ Customized ops for ML framework """ + # pylint: disable=invalid-name from typing import Any diff --git a/tensorcircuit/basecircuit.py b/tensorcircuit/basecircuit.py index bad32b0f..cc9c5d7d 100644 --- a/tensorcircuit/basecircuit.py +++ b/tensorcircuit/basecircuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: common methods for all circuit classes as MixIn """ + # pylint: disable=invalid-name from typing import Any, Dict, List, Optional, Sequence, Tuple, Union @@ -39,6 +40,9 @@ class BaseCircuit(AbstractCircuit): is_mps = False + def __init__(self, nqubits: int, *args, **kwargs): + super().__init__(nqubits, *args, **kwargs) + @staticmethod def all_zero_nodes(n: int, d: int = 2, prefix: str = "qb-") -> List[tn.Node]: l = [0.0 for _ in range(d)] @@ -81,7 +85,7 @@ def coloring_copied_nodes( node.id = getattr(n0, "id", id(n0)) @staticmethod - def copy( + def copy_nodes( nodes: Sequence[tn.Node], dangling: Optional[Sequence[tn.Edge]] = None, conj: Optional[bool] = False, @@ -111,7 +115,7 @@ def copy( def _copy( self, conj: Optional[bool] = False ) -> Tuple[List[tn.Node], List[tn.Edge]]: - return self.copy(self._nodes, self._front, conj) + return self.copy_nodes(self._nodes, self._front, conj) def apply_general_gate( self, @@ -171,7 +175,7 @@ def apply_general_gate( self._front[index[0]] = n1[0] self._front[index[1]] = n2[1] if self.is_dm: - [n1l, n2l], _ = self.copy([n1, n2], conj=True) + [n1l, n2l], _ = self.copy_nodes([n1, n2], conj=True) n1l[1] ^ self._front[index[0] + nq] n2l[2] ^ self._front[index[1] + nq] self._nodes.append(n1l) @@ -186,7 +190,7 @@ def apply_general_gate( self._front[index[0]] = n1[0] self._front[index[1]] = n2[1] if self.is_dm: - [n1l, n2l], _ = self.copy([n1, n2], conj=True) + [n1l, n2l], _ = self.copy_nodes([n1, n2], conj=True) n2l[1] ^ self._front[index[0] + nq] n1l[2] ^ self._front[index[1] + nq] self._nodes.append(n1l) @@ -203,7 +207,7 @@ def apply_general_gate( # gate.id = id(gate) self._nodes.append(gate) if self.is_dm: - lgates, _ = self.copy([gate], conj=True) + lgates, _ = self.copy_nodes([gate], conj=True) lgate = lgates[0] self._nodes.append(lgate) for i, ind in enumerate(index): diff --git a/tensorcircuit/circuit.py b/tensorcircuit/circuit.py index ade0cafa..f510142f 100644 --- a/tensorcircuit/circuit.py +++ b/tensorcircuit/circuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: the state simulator """ + # pylint: disable=invalid-name from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple @@ -16,6 +17,7 @@ from .quantum import QuOperator, identity from .simplify import _full_light_cone_cancel from .basecircuit import BaseCircuit +from .pulse import DefcalBuilder, Param, Frame Gate = gates.Gate Tensor = Any @@ -59,6 +61,13 @@ def __init__( ``max_singular_values`` and ``max_truncation_err``. :type split: Optional[Dict[str, Any]] """ + super().__init__( + nqubits=nqubits, inputs=inputs, mps_inputs=mps_inputs, split=split + ) + self.calibrations = [] + self.calibration_invokes = [] + self.measz_invokes = [] + self.inputs = inputs self.mps_inputs = mps_inputs self.split = split @@ -110,6 +119,108 @@ def __init__( # self._qcode += str(self._nqubits) + "\n" self._qir: List[Dict[str, Any]] = [] self._extra_qir: List[Dict[str, Any]] = [] + + def def_calibration( + self, name: str, parameters: List[str], instructions: List[Dict] + ) -> None: + self.calibrations.append({ + "name": name, + "parameters": parameters, + "instructions": instructions + }) + + def add_calibration( + self, builder: DefcalBuilder, parameters: List[str] + ) -> None: + self.calibration_invokes.append({ + "name": builder.name, + "parameters": parameters, + "pos": len(self._qir) + }) + + def measz(self, *index: int) -> None: + self.measz_invokes.append({ + "name": "measz", + "index": index, + "pos": len(self._qir) + }) + return + + + def to_tqasm(self, pragma: Optional[str]= None) -> str: + qasm_lines = [] + + qasm_lines.append("TQASM 0.2;") + + if pragma: + qasm_lines.append(pragma) + + qasm_lines.append(f"QREG q[{self._nqubits}];") + + for cal in getattr(self, "calibrations", []): + pname = ", ".join(cal["parameters"]) + qasm_lines.append(f"defcal {cal['name']} {pname} {{") + for inst in cal["instructions"]: + if inst["type"] == "frame": + qasm_lines.append(f" frame {inst['frame'].name} = newframe({inst['qubit']});") + elif inst["type"] == "play": + args_str = ", ".join(str(x) for x in inst["args"]) + wf_type = inst["waveform_type"] + qasm_lines.append(f" play({inst['frame']}, {wf_type}({args_str}));") + qasm_lines.append("}") + + + # 先把 calibration_invokes 按 pos 分组,并保留同 pos 内的插入顺序 + from collections import defaultdict + cals_by_pos = defaultdict(list) + for cal in getattr(self, "calibration_invokes", []): + # pos 记录的是加入时的 len(self._qir) + pos = cal.get("pos", len(self._qir)) + cals_by_pos[pos].append(cal) + + measz_by_pos = defaultdict(list) + for m in getattr(self, "measz_invokes", []): + # pos 记录的是加入时的 len(self._qir) + pos = m.get("pos", len(self._qir)) + measz_by_pos[pos].append(m) + + # 交错输出:在第 i 个门之前输出所有 pos == i 的校准 + for i, gate in enumerate(self._qir): + for m in measz_by_pos.get(i, []): + targets = ", ".join(f"q[{idx}]" for idx in m["index"]) + qasm_lines.append(f"MEASZ {targets};") + + for cal in cals_by_pos.get(i, []): + # print(cal) + pname = ", ".join(f"q[{x}]" for x in cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + # print(gate) + gname = gate["name"] + gname = gname.upper() + if gname == "CNOT": + gname = "CX" + targets = ", ".join(f"q[{idx}]" for idx in gate["index"]) + if (gname == "RX") or (gname == "RY") or (gname == "RZ"): + theta = gate["parameters"]["theta"] + qasm_lines.append(f"{gname} ({theta}) {targets};") + else: + qasm_lines.append(f"{gname} {targets};") + + for m in measz_by_pos.get(len(self._qir), []): + targets = ", ".join(f"q[{idx}]" for idx in m["index"]) + qasm_lines.append(f"MEASZ {targets};") + + # 收尾:把 pos == len(self._qir) 的校准放在最后 + for cal in cals_by_pos.get(len(self._qir), []): + # print(cal) + pname = ", ".join(f"q[{x}]" for x in cal.get("parameters", [])) + qasm_lines.append(f"{cal['name']} {pname};") + + return ("\n".join(qasm_lines)) + + def calibrate(self, name: str, parameters: List["Param"]) -> "DefcalBuilder": + return DefcalBuilder(self, name, parameters) def replace_mps_inputs(self, mps_inputs: QuOperator) -> None: """ @@ -507,6 +618,7 @@ def _general_kraus_2( kraus: Sequence[Gate], *index: int, status: Optional[float] = None, + with_prob: bool = False, name: Optional[str] = None, ) -> Tensor: # the graph building time is frustratingly slow, several minutes @@ -554,16 +666,20 @@ def calculate_kraus_p(i: int) -> Tensor: k / backend.cast(backend.sqrt(w) + eps, dtypestr) for w, k in zip(prob, kraus_tensor) ] - - return self.unitary_kraus( + pick = self.unitary_kraus( new_kraus, *index, prob=prob, status=status, name=name ) + if with_prob is False: + return pick + else: + return pick, prob def general_kraus( self, kraus: Sequence[Gate], *index: int, status: Optional[float] = None, + with_prob: bool = False, name: Optional[str] = None, ) -> Tensor: """ @@ -583,7 +699,9 @@ def general_kraus( when the random number will be generated automatically :type status: Optional[float], optional """ - return self._general_kraus_2(kraus, *index, status=status, name=name) + return self._general_kraus_2( + kraus, *index, status=status, with_prob=with_prob, name=name + ) apply_general_kraus = general_kraus diff --git a/tensorcircuit/cloud/__init__.py b/tensorcircuit/cloud/__init__.py index e69de29b..eb14f9d6 100644 --- a/tensorcircuit/cloud/__init__.py +++ b/tensorcircuit/cloud/__init__.py @@ -0,0 +1,6 @@ +from . import apis +from . import abstraction +from . import wrapper +from .wrapper import batch_expectation_ps +from .apis import submit_task +from .tencent import Topology diff --git a/tensorcircuit/cloud/abstraction.py b/tensorcircuit/cloud/abstraction.py index b94e2a69..be07790c 100644 --- a/tensorcircuit/cloud/abstraction.py +++ b/tensorcircuit/cloud/abstraction.py @@ -380,6 +380,56 @@ def resubmit(self) -> "Task": from .apis import resubmit_task return resubmit_task(self) + + @partial(arg_alias, alias_dict={"format": ["format_"], "blocked": ["wait"]}) + def m_results( + self, + format: Optional[str] = None, + blocked: bool = True, + mitigated: bool = False, + calibriation_options: Optional[Dict[str, Any]] = None, + readout_mit: Optional[rem.ReadoutMit] = None, + mitigation_options: Optional[Dict[str, Any]] = None, + ) -> counts.ct: + """ + get task results of the qjob + + :param format: unsupported now, defaults to None, which is "count_dict_bin" + :type format: Optional[str], optional + :param blocked: whether blocked to wait until the result is returned, defaults to False, + which raise error when the task is unfinished + :type blocked: bool, optional + :param mitigated: whether enable readout error mitigation, defaults to False + :type mitigated: bool, optional + :param calibriation_options: option dict for ``ReadoutMit.cals_from_system``, + defaults to None + :type calibriation_options: Optional[Dict[str, Any]], optional + :param readout_mit: if given, directly use the calibriation info on ``readout_mit``, + defaults to None + :type readout_mit: Optional[rem.ReadoutMit], optional + :param mitigation_options: option dict for ``ReadoutMit.apply_correction``, defaults to None + :type mitigation_options: Optional[Dict[str, Any]], optional + :return: count dict results + :rtype: Any + """ + if not blocked: + s = self.state() + if s != "completed": + raise TaskUnfinished(self.id_, s) + r = self.details()["multi_result"] + else: + s = self.state() + tries = 0 + while s != "completed": + if s in ["failed"]: + err = self.details().get("err", "") + raise TaskFailed(self.id_, s, err) + time.sleep(0.5 + tries / 10) + tries += 1 + s = self.state() + r = self.m_results(format=format, blocked=False, mitigated=False) + + return r # type: ignore @partial(arg_alias, alias_dict={"format": ["format_"], "blocked": ["wait"]}) def results( diff --git a/tensorcircuit/cloud/apis.py b/tensorcircuit/cloud/apis.py index 24441731..0e4f6eb6 100644 --- a/tensorcircuit/cloud/apis.py +++ b/tensorcircuit/cloud/apis.py @@ -41,7 +41,7 @@ def list_providers() -> List[Provider]: """ - list all providers that tensorcircuit supports + list all cloud providers that tensorcircuit supports :return: _description_ :rtype: List[Provider] @@ -85,7 +85,7 @@ def set_device( set_global: bool = True, ) -> Device: """ - _summary_ + set the default device :param provider: provider of the device, defaults to None :type provider: Optional[Union[str, Provider]], optional @@ -205,10 +205,15 @@ def set_token( saved_token = {} if token is None: if cached and os.path.exists(authpath): - with open(authpath, "r") as f: - file_token = json.load(f) - file_token = {k: b64decode_s(v) for k, v in file_token.items()} - # file_token = backend.tree_map(b64decode_s, file_token) + try: + with open(authpath, "r") as f: + file_token = json.load(f) + file_token = {k: b64decode_s(v) for k, v in file_token.items()} + # file_token = backend.tree_map(b64decode_s, file_token) + except json.JSONDecodeError: + logger.warning("token file loading failure, set empty token instead") + # TODO(@refraction-ray): better conflict solve with multiprocessing + file_token = {} else: file_token = {} file_token.update(saved_token) @@ -232,9 +237,9 @@ def set_token( if cached: # file_token = backend.tree_map(b64encode_s, saved_token) file_token = {k: b64encode_s(v) for k, v in saved_token.items()} - - with open(authpath, "w") as f: - json.dump(file_token, f) + if file_token: + with open(authpath, "w") as f: + json.dump(file_token, f) return saved_token @@ -413,6 +418,10 @@ def submit_task( """ submit task to the cloud platform, batch submission default enabled + .. seealso:: + + :py:meth:`tensorcircuit.cloud.tencent.submit_task` + :param provider: _description_, defaults to None :type provider: Optional[Union[str, Provider]], optional :param device: _description_, defaults to None diff --git a/tensorcircuit/cloud/local.py b/tensorcircuit/cloud/local.py index aa11681a..6d48f8e6 100644 --- a/tensorcircuit/cloud/local.py +++ b/tensorcircuit/cloud/local.py @@ -39,7 +39,7 @@ def submit_task( **kws: Any ) -> List[Task]: def _circuit2result(c: AbstractCircuit) -> Dict[str, Any]: - if device.name == "testing": + if device.name in ["testing", "default"]: count = c.sample(batch=shots, allow_state=True, format="count_dict_bin") # type: ignore else: raise ValueError("Unsupported device from local provider: %s" % device.name) diff --git a/tensorcircuit/cloud/quafu_provider.py b/tensorcircuit/cloud/quafu_provider.py index a852b905..f1d1f9bf 100644 --- a/tensorcircuit/cloud/quafu_provider.py +++ b/tensorcircuit/cloud/quafu_provider.py @@ -10,6 +10,7 @@ from .abstraction import Device, sep, Task from ..abstractcircuit import AbstractCircuit +from ..utils import is_sequence logger = logging.getLogger(__name__) @@ -43,18 +44,28 @@ def c2qasm(c: Any) -> str: s = c.to_openqasm() return s # type: ignore - source = c2qasm(circuit) + if not is_sequence(circuit): + source = c2qasm(circuit) + else: + source = [c2qasm(c) for c in circuit] # type: ignore user = User() user.save_apitoken(token) - nq = int(source.split("\n")[2].split("[")[1].split("]")[0]) # type: ignore - qc = QuantumCircuit(nq) - qc.from_openqasm(source) - task = Task_() - device_name = device.name.split(sep)[-1] - task.config(backend=device_name, shots=shots, compile=compile) - res = task.send(qc, wait=False) - wrapper = Task(res.taskid, device=device) - return wrapper + + def c2task(source: str) -> Task: + nq = int(source.split("\n")[2].split("[")[1].split("]")[0]) # type: ignore + qc = QuantumCircuit(nq) + qc.from_openqasm(source) + task = Task_() + device_name = device.name.split(sep)[-1] + task.config(backend=device_name, shots=shots, compile=compile) + res = task.send(qc, wait=False) + wrapper = Task(res.taskid, device=device) + return wrapper + + if not is_sequence(source): + return c2task(source) # type: ignore + else: + return [c2task(s) for s in source] # type: ignore def resubmit_task(task: Task, token: str) -> Task: diff --git a/tensorcircuit/cloud/tencent.py b/tensorcircuit/cloud/tencent.py index 95497779..9fc8bd02 100644 --- a/tensorcircuit/cloud/tencent.py +++ b/tensorcircuit/cloud/tencent.py @@ -19,6 +19,84 @@ logger = logging.getLogger(__name__) +class Topology: + def __init__(self, device: Device) -> None: + topology = device.topology() + + self._qubits = list(set(num for row in topology for num in row)) + self._qubit_pairs = topology + + self._used_chip_qubits = [] + self._used_user_qubits = [] + self._used_user_pairs = [] + + def map_qubits(self, chip_addrs: Optional[List[int]], user_addrs: List[int] = None) -> None: + """ + Map chip address to user address, and remove other unused chip addresses. + """ + if user_addrs is None: + user_addrs = range(len(chip_addrs)) + if len(user_addrs) != len(chip_addrs): + raise ValueError("user_addrs and chip_addrs should have the same length") + for addr in chip_addrs: + if addr not in self._qubits: + raise ValueError(f"chip_addr {addr} not in the device") + + self._used_chip_qubits = chip_addrs + self._used_user_qubits = user_addrs + inherited_pairs = [e for e in self._qubit_pairs if e[0] in chip_addrs and e[1] in chip_addrs] + self._used_user_pairs = [(user_addrs[chip_addrs.index(e[0])], user_addrs[chip_addrs.index(e[1])]) for e in inherited_pairs] + + def map_qubit(self, chip_addr: int, user_addr: int) -> None: + if chip_addr not in self._qubits: + raise ValueError(f"chip_addr {chip_addr} not in the device") + try: + subscript = self._used_chip_qubits.index(chip_addr) + if self._used_user_qubits[subscript] != user_addr: + raise ValueError(f"chip_addr {chip_addr} is already mapped to user_addr {self._used_user_qubits[subscript]}") + except ValueError: # not found, so add it. + self._used_chip_qubits.append(chip_addr) + self._used_user_qubits.append(user_addr) + return + + def pair_qubit(self, user_addr1: int, user_addr2: int, dual: bool = True, add_remove: bool = True) -> None: + def update_pairs(user_addr1: int, user_addr2: int, add_remove: bool = True): + original_pair = (user_addr1, user_addr2) + if add_remove: + if original_pair in getattr(self, "_used_user_pairs", []): + return + self._used_user_pairs = getattr(self, "_used_user_pairs", []) + [original_pair] + else: + try: + self._used_user_pairs = getattr(self, "_used_user_pairs", []) - [original_pair] + except ValueError: + raise ValueError(f"Qubit pair {user_addr1}-{user_addr2} does not exist to remove") + update_pairs(user_addr1, user_addr2, add_remove) + if dual: + update_pairs(user_addr2, user_addr1, add_remove) + return + + def pragma(self) -> str: + lines = [] + if self._used_chip_qubits == [] or self._used_user_qubits == []: + return None + if len(self._used_user_pairs) == 0: + raise ValueError("No qubit pairs are defined, please use pair_qubit to define qubit pairs") + + pragma = "#pragma qubits.mapping [" + for c, u in zip(self._used_chip_qubits, self._used_user_qubits): + pragma += f"[{u}, {c}], " + pragma = pragma[:-2] + "]" + lines.append(pragma) + + pragma = "#pragma qubits.coupling [" + for u1, u2 in getattr(self, "_used_user_pairs", []): + pragma += f"[{u1}, {u2}], " + pragma = pragma[:-2] + "]" + lines.append(pragma) + + return "\n".join(lines) + def tencent_headers(token: Optional[str] = None) -> Dict[str, str]: if token is None: token = "ANY;0" @@ -65,7 +143,7 @@ def list_properties(device: Device, token: Optional[str] = None) -> Dict[str, An for bit in r["bits"]: bits_dict[bit["Qubit"]] = bit r["bits"] = bits_dict - r["native_gates"] = ["h", "rz", "x", "y", "z", "cz"] # handcoded + r["native_gates"] = ["h", "rz", "x", "y", "z", "cz", "cx"] # handcoded return r # type: ignore else: raise ValueError("No device with the name: %s" % device) @@ -124,6 +202,7 @@ def submit_task( circuit: Optional[Union[AbstractCircuit, Sequence[AbstractCircuit]]] = None, source: Optional[Union[str, Sequence[str]]] = None, remarks: Optional[str] = None, + group: Optional[str] = None, compiling: bool = False, compiled_options: Optional[Dict[str, Any]] = None, enable_qiskit_initial_mapping: bool = False, @@ -132,6 +211,7 @@ def submit_task( enable_qos_gate_decomposition: bool = True, enable_qos_initial_mapping: bool = False, qos_dry_run: bool = False, + topology: Optional[Topology] = None, **kws: Any ) -> List[Task]: """ @@ -210,9 +290,15 @@ def c2qasm(c: Any, compiling: bool) -> str: else: if isinstance(c, QuantumCircuit): s = c.qasm() + lang = "OPENQASM" # nq = c.num_qubits else: - s = c.to_openqasm() + prag = None + if topology is not None: + prag = topology.pragma() + s = c.to_tqasm(prag) + lang = "TQASM" + #s = c.to_openqasm() # nq = c._nqubits # s = _free_pi(s) # tQuk translation now supports this # if measure is not None: # ad hoc partial measurement @@ -224,13 +310,12 @@ def c2qasm(c: Any, compiling: bool) -> str: # slist.append("") # s = "\n".join(slist) s = _replace_rz_to_st(s) - return s # type: ignore + return s, lang # type: ignore if is_sequence(circuit): source = [c2qasm(c, compiling) for c in circuit] # type: ignore else: - source = c2qasm(circuit, compiling) - lang = "OPENQASM" + source, lang = c2qasm(circuit, compiling) if len(device.name.split("?")) > 1: device_str = device.name @@ -261,6 +346,7 @@ def c2qasm(c: Any, compiling: bool) -> str: "lang": lang, "prior": prior, "remarks": remarks, + "group": group, } ) @@ -273,6 +359,7 @@ def c2qasm(c: Any, compiling: bool) -> str: "lang": lang, "prior": prior, "remarks": remarks, + "group": group, } r = rpost_json( tencent_base_url + "task/submit", json=json, headers=tencent_headers(token) @@ -288,7 +375,7 @@ def c2qasm(c: Any, compiling: bool) -> str: else: ti = Task(id_=t["id"], device=device) rtn.append(ti) - if len(rtn) == 1: + if not is_sequence(source): return rtn[0] # type: ignore elif len(rtn) == 0: raise ValueError("All tasks submitted failed") @@ -358,6 +445,10 @@ def get_task_details( r["task"]["results"] = r["task"]["result"]["counts"] else: r["task"]["results"] = r["task"]["result"] + if "multi_results" in r["task"]: + for i, res in enumerate(r["task"]["multi_results"]): + if "counts" in res: + r["task"]["multi_results"][i] = counts.sort_count(res["counts"]) if "optimization" in r["task"]: if ( "pairs" in r["task"]["optimization"] @@ -408,4 +499,5 @@ def get_task_details( '101': 135, '110': 128, '111': 131} + 'multi_results': [{'000': 123, '001': 126, ...}, {...}, ...] """ diff --git a/tensorcircuit/cloud/utils.py b/tensorcircuit/cloud/utils.py index 296e66df..fe15a56f 100644 --- a/tensorcircuit/cloud/utils.py +++ b/tensorcircuit/cloud/utils.py @@ -1,6 +1,7 @@ """ utility functions for cloud connection """ + from typing import Any, Callable, Optional from functools import wraps import inspect diff --git a/tensorcircuit/cloud/wrapper.py b/tensorcircuit/cloud/wrapper.py index 2c8140a8..f43f9ea9 100644 --- a/tensorcircuit/cloud/wrapper.py +++ b/tensorcircuit/cloud/wrapper.py @@ -1,7 +1,8 @@ """ higher level wrapper shortcut for submit_task """ -from typing import Any, Callable, Dict, List, Optional, Sequence, Union + +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import logging import time @@ -13,7 +14,8 @@ from ..utils import is_sequence from ..cons import backend from ..quantum import ps2xyz -from ..compiler.qiskit_compiler import qiskit_compile +from ..compiler import DefaultCompiler +from ..compiler.simple_compiler import simple_compile from .apis import submit_task, get_device from .abstraction import Device @@ -22,9 +24,12 @@ Tensor = Any -def batch_submit_template(device: str) -> Callable[..., List[counts.ct]]: - # TODO(@refraction-ray): fixed when batch submission really works - def run(cs: Union[Circuit, Sequence[Circuit]], shots: int) -> List[counts.ct]: +def batch_submit_template( + device: str, batch_limit: int = 64, **kws: Any +) -> Callable[..., List[counts.ct]]: + def run( + cs: Union[Circuit, Sequence[Circuit]], shots: int = 8192, **nkws: Any + ) -> List[counts.ct]: """ batch circuit running alternative """ @@ -32,12 +37,38 @@ def run(cs: Union[Circuit, Sequence[Circuit]], shots: int) -> List[counts.ct]: if not is_sequence(cs): cs = [cs] # type: ignore single = True - ts = [] # for c in cs: # type: ignore # ts.append(submit_task(circuit=c, shots=shots, device=device)) # time.sleep(0.3) - ts = submit_task(circuit=cs, shots=shots, device=device) - l = [t.results(blocked=True) for t in ts] # type: ignore + kws.update(nkws) + if len(cs) <= batch_limit: # type: ignore + css = [cs] + else: + ntimes = len(cs) // batch_limit # type: ignore + if ntimes * batch_limit == len(cs): # type: ignore + css = [ + cs[i * batch_limit : (i + 1) * batch_limit] for i in range(ntimes) # type: ignore + ] + else: + css = [ + cs[i * batch_limit : (i + 1) * batch_limit] for i in range(ntimes) # type: ignore + ] + [ + cs[ntimes * batch_limit :] # type: ignore + ] + tss = [] + logger.info(f"submit task on {device} for {len(cs)} circuits") # type: ignore + time0 = time.time() + for i, cssi in enumerate(css): + tss += submit_task(circuit=cssi, shots=shots, device=device, **kws) + if i < len(css) - 1: + time.sleep(1.5) + # TODO(@refraction-ray) whether the sleep time is enough for tquk? + # incase duplicae request error protection + l = [t.results() for t in tss] + time1 = time.time() + logger.info( + f"finished collecting count results of {len(cs)} tasks in {round(time1-time0, 4)} seconds" # type: ignore + ) if single is False: return l return l[0] # type: ignore @@ -54,8 +85,13 @@ def sample_expectation_ps( device: Optional[Device] = None, **kws: Any, ) -> float: - # deprecated - # TODO(@refraction-ray): integrated error mitigation + """ + Deprecated, please use :py:meth:`tensorcircuit.cloud.wrapper.batch_expectation_ps`. + """ + logger.warning( + "This method is deprecated and not maintained, \ + please use `tensorcircuit.cloud.wrapper.batch_expectation_ps` instead" + ) c1 = Circuit.from_qir(c.to_qir()) if x is None: x = [] @@ -75,6 +111,39 @@ def sample_expectation_ps( return counts.expectation(raw_counts, x + y + z) +def reduce_and_evaluate( + cs: List[Circuit], shots: int, run: Callable[..., Any] +) -> List[counts.ct]: + reduced_cs = [] + reduced_dict = {} + recover_dict = {} + # merge the same circuit + for j, c in enumerate(cs): + key = hash(c.to_openqasm()) + if key not in reduced_dict: + reduced_dict[key] = [j] + reduced_cs.append(c) + recover_dict[key] = len(reduced_cs) - 1 + else: + reduced_dict[key].append(j) + + # for j, ps in enumerate(pss): + # ps = [i if i in [1, 2] else 0 for i in ps] + # if tuple(ps) not in reduced_dict: + # reduced_dict[tuple(ps)] = [j] + # reduced_cs.append(cs[j]) + # recover_dict[tuple(ps)] = len(reduced_cs) - 1 + # else: + # reduced_dict[tuple(ps)].append(j) + + reduced_raw_counts = run(reduced_cs, shots) + raw_counts: List[Dict[str, int]] = [None] * len(cs) # type: ignore + for i, c in enumerate(cs): + key = hash(c.to_openqasm()) + raw_counts[i] = reduced_raw_counts[recover_dict[key]] + return raw_counts + + def batch_expectation_ps( c: Circuit, pss: List[List[int]], @@ -82,82 +151,149 @@ def batch_expectation_ps( ws: Optional[List[float]] = None, shots: int = 8192, with_rem: bool = True, + compile_func: Optional[Callable[[Circuit], Tuple[Circuit, Dict[str, Any]]]] = None, + batch_limit: int = 64, + batch_submit_func: Optional[Callable[..., List[counts.ct]]] = None, ) -> Union[Any, List[Any]]: + """ + Unified interface to compute the Pauli string expectation lists or sums via simulation or on real qpu. + Error mitigation, circuit compilation and Pauli string grouping are all built-in. + + One line access to unlock the whole power or real quantum hardware on quantum cloud. + + :Example: + + .. code-block:: python + + c = tc.Circuit(2) + c.h(0) + c.x(1) + tc.cloud.wrapper.batch_expectation_ps(c, [[1, 0], [0, 3]], device=None) + # array([ 0.99999994, -0.99999994], dtype=float32) + tc.cloud.wrapper.batch_expectation_ps(c, [[1, 0], [0, 3]], device="tencent::9gmon") + # array([ 1.03093477, -1.11715944]) + + :param c: The target circuit to compute expectation + :type c: Circuit + :param pss: List of Pauli string list, eg. [[0, 1, 0], [2, 3, 3]] represents [X1, Y0Z1Z2]. + :type pss: List[List[int]] + :param device: The device str or object for quantum cloud module, + defaults to None, None is for analytical exact simulation + :type device: Any, optional + :param ws: List of float to indicate the final return is the weighted sum of Pauli string expectations, + e.g. [2., -0.3] represents the final results is 2* ``pss`` [0]-0.3* ``pss`` [1] + defaults to None, None indicate the list of expectations for ``pss`` are all returned + :type ws: Optional[List[float]], optional + :param shots: measurement shots for each expectation estimation, defaults to 8192 + :type shots: int, optional + :param with_rem: whether enable readout error mitigation for the result, defaults to True + :type with_rem: bool, optional + :return: List of Pauli string expectation or a weighted sum float for Pauli strings, depending on ``ws`` + :rtype: Union[Any, List[Any]] + """ if device is None: results = [] for ps in pss: results.append(c.expectation_ps(**ps2xyz(ps))) # type: ignore if ws is None: - return backend.stack(results) + return backend.real(backend.stack(results)) else: - return backend.sum([w * r for w, r in zip(ws, results)]) + sumr = sum([w * r for w, r in zip(ws, results)]) + return backend.convert_to_tensor(sumr) cs = [] infos = [] exps = [] if isinstance(device, str): device = get_device(device) + + if compile_func is None: + try: + coupling_map = device.topology() + compile_func = DefaultCompiler( + { + "coupling_map": coupling_map, + } + ) + except (AttributeError, ValueError): + compile_func = DefaultCompiler() + c1, info = compile_func(c) # type: ignore + if not info.get("logical_physical_mapping", None): + info["logical_physical_mapping"] = {i: i for i in range(c._nqubits)} for ps in pss: # TODO(@refraction-ray): Pauli string grouping - c1 = Circuit.from_qir(c.to_qir()) + # https://docs.pennylane.ai/en/stable/_modules/pennylane/pauli/grouping/group_observables.html + c2 = Circuit.from_qir(c1.to_qir()) exp = [] for j, i in enumerate(ps): if i == 1: - c1.H(j) # type: ignore + c2.H(info["logical_physical_mapping"][j]) # type: ignore + c2, _ = simple_compile(c2) exp.append(j) + elif i == 2: - c1.rx(j, theta=np.pi / 2) # type: ignore + c2.rx(info["logical_physical_mapping"][j], theta=np.pi / 2) # type: ignore + c2, _ = simple_compile(c2) exp.append(j) elif i == 3: exp.append(j) - c1, info = qiskit_compile( - c1, - compiled_options={ - "basis_gates": device.native_gates(), - "optimization_level": 3, - "coupling_map": device.topology(), - }, - ) - cs.append(c1) + for i in range(c._nqubits): + c2.measure_instruction(info["logical_physical_mapping"][i]) + # c1, info = compile_func(c1) # type: ignore + # TODO(@refraction-ray): two steps compiling with pre compilation: + # basically done, require some fine tuning for performance + cs.append(c2) infos.append(info) exps.append(exp) - reduced_cs = [] - reduced_dict = {} - recover_dict = {} - # merge the same circuit - for j, ps in enumerate(pss): - ps = [i if i in [1, 2] else 0 for i in ps] - if tuple(ps) not in reduced_dict: - reduced_dict[tuple(ps)] = [j] - reduced_cs.append(cs[j]) - recover_dict[tuple(ps)] = len(reduced_cs) - 1 - else: - reduced_dict[tuple(ps)].append(j) + # reduced_cs = [] + # reduced_dict = {} + # recover_dict = {} + # # merge the same circuit + # for j, ps in enumerate(pss): + # ps = [i if i in [1, 2] else 0 for i in ps] + # if tuple(ps) not in reduced_dict: + # reduced_dict[tuple(ps)] = [j] + # reduced_cs.append(cs[j]) + # recover_dict[tuple(ps)] = len(reduced_cs) - 1 + # else: + # reduced_dict[tuple(ps)].append(j) - def run(cs: List[Any], shots: int) -> List[Dict[str, int]]: - logger.info(f"submit task on {device.name} for {len(cs)} circuits") - time0 = time.time() - ts = submit_task( - circuit=cs, - device=device, - shots=shots, + if batch_submit_func is None: + run = batch_submit_template( + device, + batch_limit, enable_qos_qubit_mapping=False, enable_qos_gate_decomposition=False, ) - if not is_sequence(ts): - ts = [ts] # type: ignore - raw_counts = [t.results(blocked=True) for t in ts] - time1 = time.time() - logger.info( - f"finished collecting count results of {len(cs)} tasks in {round(time1-time0, 4)} seconds" - ) - return raw_counts + else: + run = batch_submit_func - reduced_raw_counts = run(reduced_cs, shots) - raw_counts: List[Dict[str, int]] = [None] * len(cs) # type: ignore - for i in range(len(cs)): - ps = [i if i in [1, 2] else 0 for i in pss[i]] - raw_counts[i] = reduced_raw_counts[recover_dict[tuple(ps)]] + raw_counts = reduce_and_evaluate(cs, shots, run) # type: ignore + + # def run(cs: List[Any], shots: int) -> List[Dict[str, int]]: + # logger.info(f"submit task on {device.name} for {len(cs)} circuits") + # time0 = time.time() + # ts = submit_task( + # circuit=cs, + # device=device, + # shots=shots, + # enable_qos_qubit_mapping=False, + # enable_qos_gate_decomposition=False, + # ) + # if not is_sequence(ts): + # ts = [ts] # type: ignore + # raw_counts = [t.results(blocked=True) for t in ts] + # time1 = time.time() + # logger.info( + # f"finished collecting count results of {len(cs)} tasks in {round(time1-time0, 4)} seconds" + # ) + # return raw_counts + + # reduced_raw_counts = run(reduced_cs, shots) + # raw_counts: List[Dict[str, int]] = [None] * len(cs) # type: ignore + # for i in range(len(cs)): + # ps = [i if i in [1, 2] else 0 for i in pss[i]] + # raw_counts[i] = reduced_raw_counts[recover_dict[tuple(ps)]] if with_rem: if getattr(device, "readout_mit", None) is None: @@ -181,5 +317,5 @@ def run(cs: List[Any], shots: int) -> List[Dict[str, int]]: ] if ws is not None: sumr = sum([w * r for w, r in zip(ws, results)]) - return sumr - return results + return backend.convert_to_tensor(sumr) + return backend.stack(results) diff --git a/tensorcircuit/compiler/__init__.py b/tensorcircuit/compiler/__init__.py index 9d8f25a0..d5f812fe 100644 --- a/tensorcircuit/compiler/__init__.py +++ b/tensorcircuit/compiler/__init__.py @@ -2,4 +2,7 @@ Experimental module, no software agnostic unified interface for now, only reserve for internal use """ -from .composed_compiler import Compiler, default_compiler + +from .composed_compiler import Compiler, DefaultCompiler, default_compile +from . import simple_compiler +from . import qiskit_compiler diff --git a/tensorcircuit/compiler/composed_compiler.py b/tensorcircuit/compiler/composed_compiler.py index 30c30057..d49c4fe4 100644 --- a/tensorcircuit/compiler/composed_compiler.py +++ b/tensorcircuit/compiler/composed_compiler.py @@ -2,11 +2,12 @@ object oriented compiler pipeline """ -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Callable, Dict, List, Optional, Tuple, Union from ..utils import is_sequence from ..abstractcircuit import AbstractCircuit from .qiskit_compiler import qiskit_compile +from .simple_compiler import simple_compile class Compiler: @@ -24,20 +25,60 @@ def __init__( def add_options( self, compiled_options: Optional[List[Dict[str, Any]]] = None ) -> None: - if not is_sequence(compiled_options): - self.compiled_options = [compiled_options for _ in self.compile_funcs] + if compiled_options is None: + self.compiled_options = [{} for _ in range(len(self.compile_funcs))] # type: ignore + elif not is_sequence(compiled_options): + self.compiled_options = [compiled_options for _ in self.compile_funcs] # type: ignore else: assert len(compiled_options) == len( # type: ignore self.compile_funcs ), "`compiled_options` must have the same list length as `compile_funcs`" self.compiled_options = list(compiled_options) # type: ignore + for i, c in enumerate(self.compiled_options): + if c is None: + self.compiled_options[i] = {} def __call__( self, circuit: AbstractCircuit, info: Optional[Dict[str, Any]] = None ) -> Any: for f, d in zip(self.compile_funcs, self.compiled_options): - circuit, info = f(circuit, info, compiled_options=d) # type: ignore + result = f(circuit, info, compiled_options=d) # type: ignore + if not isinstance(result, tuple): + result = (result, info) + circuit, info = result return circuit, info -default_compiler = Compiler(qiskit_compile) +class DefaultCompiler(Compiler): + def __init__(self, qiskit_compiled_options: Optional[Dict[str, Any]] = None): + """ + A fallback choice to compile circuit running on tencent quantum cloud with rz as native gate + + :param qiskit_compiled_options: qiskit compiled options to be added + options documented in `qiskit.transpile` method, + to use tencent quantum cloud, `{"coupling_map": d.topology()}` is in general enough, + where d is a device object, + defaults to None, i.e. no qubit mapping is applied + :type qiskit_compiled_options: Optional[Dict[str, Any]], optional + """ + compiled_options = { + "optimization_level": 3, + "basis_gates": ["u3", "h", "cx", "cz"], + } + # rz target is bad for qiskit + if qiskit_compiled_options: + compiled_options.update(qiskit_compiled_options) + super().__init__( + [qiskit_compile, simple_compile], + [compiled_options, None], # type: ignore + ) + + +def default_compile( + circuit: AbstractCircuit, + info: Optional[Dict[str, Any]] = None, + compiled_options: Optional[Dict[str, Any]] = None, +) -> Tuple[AbstractCircuit, Dict[str, Any]]: + dc = DefaultCompiler(compiled_options) + c, info = dc(circuit, info) + return c, info # type: ignore diff --git a/tensorcircuit/compiler/qiskit_compiler.py b/tensorcircuit/compiler/qiskit_compiler.py index 9a56b5b4..1f946359 100644 --- a/tensorcircuit/compiler/qiskit_compiler.py +++ b/tensorcircuit/compiler/qiskit_compiler.py @@ -2,8 +2,8 @@ compiler interface via qiskit """ -from typing import Any, Dict, Optional import re +from typing import Any, Dict, Optional from ..abstractcircuit import AbstractCircuit from ..circuit import Circuit @@ -22,7 +22,10 @@ def _free_pi(s: str) -> str: else: v = r[inc.start() : inc.end()] v = eval(v) - r = r[: inc.start()] + "(" + str(v) + ")" + r[inc.end() :] + if not isinstance(v, tuple): + r = r[: inc.start()] + "(" + str(v) + ")" + r[inc.end() :] + else: # u gate case + r = r[: inc.start()] + str(v) + r[inc.end() :] rs.append(r) return "\n".join(rs) @@ -68,7 +71,7 @@ def _get_positional_logical_mapping_from_qiskit(qc: Any) -> Dict[int, int]: positional_logical_mapping = {} for inst in qc.data: if inst[0].name == "measure": - positional_logical_mapping[i] = inst[1][0].index + positional_logical_mapping[i] = qc.find_bit(inst[1][0]).index i += 1 return positional_logical_mapping @@ -92,16 +95,17 @@ def _get_logical_physical_mapping_from_qiskit( for inst in qc_after.data: if inst[0].name == "measure": if qc_before is None: - logical_q = inst[2][0].index + logical_q = qc_after.find_bit(inst[2][0]).index else: for instb in qc_before.data: if ( instb[0].name == "measure" - and instb[2][0].index == inst[2][0].index + and qc_before.find_bit(instb[2][0]).index + == qc_after.find_bit(inst[2][0]).index ): - logical_q = instb[1][0].index + logical_q = qc_before.find_bit(instb[1][0]).index break - logical_physical_mapping[logical_q] = inst[1][0].index + logical_physical_mapping[logical_q] = qc_after.find_bit(inst[1][0]).index return logical_physical_mapping @@ -120,6 +124,20 @@ def qiskit_compile( output: str = "tc", compiled_options: Optional[Dict[str, Any]] = None, ) -> Any: + """ + compile the circuit using ``qiskit.transpile`` method with some tricks and hacks + + :param circuit: circuit in ``tc.Circuit`` or ``qiskit.QuantumCircuit`` form + :type circuit: Any + :param info: info for qubit mappings, defaults to None + :type info: Optional[Dict[str, Any]], optional + :param output: output circuit format, defaults to "tc" + :type output: str, optional + :param compiled_options: ``qiskit.transpile`` options in a dict, defaults to None + :type compiled_options: Optional[Dict[str, Any]], optional + :return: Tuple containing the output circuit and the qubit mapping info dict + :rtype: Any + """ from qiskit.compiler import transpile from qiskit.transpiler.passes import RemoveBarriers @@ -132,7 +150,7 @@ def qiskit_compile( if compiled_options is None: compiled_options = { "basis_gates": ["h", "rz", "cx"], - "optimization_level": 2, + "optimization_level": 2, # 3 can induce bugs... } ncircuit = transpile(circuit, **compiled_options) ncircuit = RemoveBarriers()(ncircuit) diff --git a/tensorcircuit/compiler/simple_compiler.py b/tensorcircuit/compiler/simple_compiler.py new file mode 100644 index 00000000..868a678e --- /dev/null +++ b/tensorcircuit/compiler/simple_compiler.py @@ -0,0 +1,311 @@ +""" +Very simple transformations that qiskit may even fail or hard to control +""" + +from typing import Any, Dict, List, Optional, Tuple, Union +from copy import copy + +import numpy as np + +from ..abstractcircuit import AbstractCircuit +from ..cons import backend +from ..quantum import QuOperator +from .. import gates +from ..utils import is_sequence + + +def replace_r(circuit: AbstractCircuit, **kws: Any) -> AbstractCircuit: + qir = circuit.to_qir() + c: Any = type(circuit)(**circuit.circuit_param) + for d in qir: + if "parameters" not in d: + c.apply_general_gate_delayed(d["gatef"], d["name"], mpo=d["mpo"])( + c, *d["index"], split=d["split"] + ) + else: + if d["gatef"].n == "rx": + c.h(*d["index"]) + c.rz(*d["index"], theta=d["parameters"].get("theta", 0.0)) + c.h(*d["index"]) + + elif d["gatef"].n == "ry": + c.sd(*d["index"]) + c.h(*d["index"]) + c.rz(*d["index"], theta=d["parameters"].get("theta", 0.0)) + c.h(*d["index"]) + c.s(*d["index"]) + + elif d["gatef"].n == "rzz": + c.cx(*d["index"]) + c.rz(d["index"][1], theta=d["parameters"].get("theta", 0.0)) + c.cx(*d["index"]) + + elif d["gatef"].n == "rxx": + c.h(d["index"][0]) + c.h(d["index"][1]) + c.cx(*d["index"]) + c.rz(d["index"][1], theta=d["parameters"].get("theta", 0.0)) + c.cx(*d["index"]) + c.h(d["index"][0]) + c.h(d["index"][1]) + + elif d["gatef"].n == "ryy": + c.sd(d["index"][0]) + c.sd(d["index"][1]) + c.h(d["index"][0]) + c.h(d["index"][1]) + c.cx(*d["index"]) + c.rz(d["index"][1], theta=d["parameters"].get("theta", 0.0)) + c.cx(*d["index"]) + c.h(d["index"][0]) + c.h(d["index"][1]) + c.s(d["index"][0]) + c.s(d["index"][1]) + + else: + c.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **d["parameters"], split=d["split"]) + + return c # type: ignore + + +def replace_u(circuit: AbstractCircuit, **kws: Any) -> AbstractCircuit: + qir = circuit.to_qir() + c: Any = type(circuit)(**circuit.circuit_param) + for d in qir: + if "parameters" not in d: + c.apply_general_gate_delayed(d["gatef"], d["name"], mpo=d["mpo"])( + c, *d["index"], split=d["split"] + ) + else: + if d["gatef"].n == "u": + c.rz(*d["index"], theta=d["parameters"].get("lbd", 0) - np.pi / 2) + c.h(*d["index"]) + c.rz(*d["index"], theta=d["parameters"].get("theta", 0)) + c.h(*d["index"]) + c.rz(*d["index"], theta=np.pi / 2 + d["parameters"].get("phi", 0)) + else: + c.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **d["parameters"], split=d["split"]) + + return c # type: ignore + + +def _get_matrix(qir_item: Dict[str, Any]) -> Any: + if "gate" in qir_item: + op = qir_item["gate"] + else: + op = qir_item["gatef"](**qir_item["parameters"]) + if isinstance(op, QuOperator): + m = backend.numpy(op.eval_matrix()) + else: + m = backend.numpy(backend.reshapem(op.tensor)) + return m + + +def prune( + circuit: Union[AbstractCircuit, List[Dict[str, Any]]], + rtol: float = 1e-3, + atol: float = 1e-3, + **kws: Any +) -> Any: + if isinstance(circuit, list): + qir = circuit + output = "qir" + else: + qir = circuit.to_qir() + output = "tc" + if output in ["tc", "circuit"]: + c: Any = type(circuit)(**circuit.circuit_param) # type: ignore + for d in qir: + m = _get_matrix(d) + + if not np.allclose( + m / (m[0, 0] + 1e-8), np.eye(m.shape[0]), rtol=rtol, atol=atol + ): + # upto a phase + if "parameters" not in d: + c.apply_general_gate_delayed(d["gatef"], d["name"], mpo=d["mpo"])( + c, *d["index"], split=d["split"] + ) + else: + c.apply_general_variable_gate_delayed( + d["gatef"], d["name"], mpo=d["mpo"] + )(c, *d["index"], **d["parameters"], split=d["split"]) + return c + + elif output in ["qir"]: + nqir = [] + for d in qir: + m = _get_matrix(d) + + if not np.allclose( + m / (m[0, 0] + 1e-8), np.eye(m.shape[0]), rtol=rtol, atol=atol + ): + nqir.append(d) + # upto a phase + + return nqir + + +# upto global phase +default_merge_rules = { + ("s", "s"): "z", + ("sd", "sd"): "z", + ("t", "t"): "s", + ("td", "td"): "sd", + ("x", "y"): "z", + ("y", "x"): "z", + ("x", "z"): "y", + ("z", "x"): "y", + ("z", "y"): "x", + ("y", "z"): "x", + ("x", "x"): "i", + ("y", "y"): "i", + ("z", "z"): "i", + ("h", "h"): "i", + ("rz", "rz"): "rz", + ("rx", "rx"): "rx", + ("ry", "ry"): "rx", + ("rzz", "rzz"): "rzz", + ("rxx", "rxx"): "rxx", + ("ryy", "ryy"): "ryy", + ("crz", "crz"): "crz", + ("crx", "crx"): "crx", + ("cry", "cry"): "crx", + ("cnot", "cnot"): "i", + ("cz", "cz"): "i", + ("cy", "cy"): "i", +} + + +def _find_next(qir: List[Dict[str, Any]], i: int) -> Optional[int]: + # if qir[i] is None: + # return None + index = qir[i]["index"] + for j, item in enumerate(qir[i + 1 :]): + # if item is not None: + if item["index"] == index: + return j + i + 1 + for ind in item["index"]: + if ind in index: + return None + return None + + +def _get_theta(qir_item: Dict[str, Any]) -> float: + theta = qir_item["parameters"].get("theta", 0.0) + if is_sequence(theta) and len(theta) == 1: + return theta[0] # type: ignore + return theta # type: ignore + + +def _merge( + qir: List[Dict[str, Any]], rules: Dict[Tuple[str, ...], str] +) -> Tuple[List[Dict[str, Any]], bool]: + i = 0 + flg = False + while i < len(qir) - 1: + j = _find_next(qir, i) + + if j is not None: + if (qir[i]["gatef"].n, qir[j]["gatef"].n) in rules: + nn = rules[(qir[i]["gatef"].n, qir[j]["gatef"].n)] + if nn == "i": + del qir[i] + del qir[j - 1] + # qir[i] = None + # qir[j] = None + else: + param = {} + if nn.startswith("r") or nn.startswith("cr"): + param = {"theta": _get_theta(qir[i]) + _get_theta(qir[j])} + qir[i] = { + "gatef": getattr(gates, nn), + "name": nn, + "mpo": False, + "split": False, + "parameters": param, + "index": qir[i]["index"], + } + del qir[j] + # qir[j] = None + flg = True + # return qir, flg + elif ( + qir[i]["gatef"].n == qir[j]["gatef"].n + "d" + or qir[i]["gatef"].n + "d" == qir[j]["gatef"].n + ): + del qir[i] + del qir[j - 1] + # qir[i] = None + # qir[j] = None + flg = True + # return qir, True + i += 1 + return qir, flg + + +def merge( + circuit: Union[AbstractCircuit, List[Dict[str, Any]]], + rules: Optional[Dict[Tuple[str, ...], str]] = None, + **kws: Any +) -> Any: + merge_rules = copy(default_merge_rules) + if rules is not None: + merge_rules.update(rules) # type: ignore + if isinstance(circuit, list): + qir = circuit + output = "qir" + else: + qir = circuit.to_qir() + output = "tc" + flg = True + while flg: + qir, flg = _merge(qir, merge_rules) # type: ignore + if output in ["qir"]: + return qir + elif output in ["tc", "circuit"]: + c: Any = type(circuit).from_qir(qir, circuit.circuit_param) # type: ignore + return c + + +def simple_compile( + circuit: Any, + info: Optional[Dict[str, Any]] = None, + output: str = "tc", + compiled_options: Optional[Dict[str, Any]] = None, +) -> Any: + if compiled_options is None: + compiled_options = {} + len0 = len(circuit.to_qir()) + for d in circuit._extra_qir: + if d["pos"] < len0 - 1: + raise ValueError( + "TC's simple compiler doesn't support measurement/reset instructions \ + in the middle of the circuit" + ) + + c = replace_r(circuit, **compiled_options) + c = replace_u(c, **compiled_options) + qir = c.to_qir() + len0 = len(qir) + qir = merge(qir, **compiled_options) + qir = prune(qir, **compiled_options) + len1 = len(qir) + while len1 != len0: + len0 = len1 + qir = merge(qir, **compiled_options) + if len(qir) == len0: + break + qir = prune(qir, **compiled_options) + len1 = len(qir) + + c = type(circuit).from_qir(qir, circuit.circuit_param) + + for d in circuit._extra_qir: + d["pos"] = len1 + c._extra_qir.append(d) + return (c, info) diff --git a/tensorcircuit/cons.py b/tensorcircuit/cons.py index c733d8e0..c2ffa8f8 100644 --- a/tensorcircuit/cons.py +++ b/tensorcircuit/cons.py @@ -1,6 +1,7 @@ """ Constants and setups """ + # pylint: disable=invalid-name import logging @@ -152,7 +153,7 @@ def set_dtype(dtype: Optional[str] = None, set_global: bool = True) -> Tuple[str raise ValueError(f"Unsupported data type: {dtype}") try: - from jax.config import config + from jax import config except ImportError: config = None # type: ignore @@ -758,6 +759,32 @@ def set_contractor( method = "greedy" # auto for small size fallbacks to dp, which has bug for now # see: https://github.com/dgasmith/opt_einsum/issues/172 + if method.startswith("cotengra"): + # cotengra shortcut + import cotengra + + if method == "cotengra": + method = "custom" + optimizer = cotengra.ReusableHyperOptimizer( + methods=["greedy", "kahypar"], + parallel=True, + minimize="combo", + max_time=30, + max_repeats=64, + progbar=True, + ) + else: # "cotengra-30-64" + _, mt, mr = method.split("-") + method = "custom" + optimizer = cotengra.ReusableHyperOptimizer( + methods=["greedy", "kahypar"], + parallel=True, + minimize="combo", + max_time=int(mt), + max_repeats=int(mr), + progbar=True, + ) + if method == "plain": cf = plain_contractor elif method == "plain-experimental": diff --git a/tensorcircuit/densitymatrix.py b/tensorcircuit/densitymatrix.py index ec0277a6..dc52fe4a 100644 --- a/tensorcircuit/densitymatrix.py +++ b/tensorcircuit/densitymatrix.py @@ -1,6 +1,7 @@ """ Quantum circuit class but with density matrix simulator """ + # pylint: disable=invalid-name from functools import reduce @@ -86,7 +87,7 @@ def __init__( for i, n in enumerate(mps_nodes): mps_nodes[i].tensor = backend.cast(n.tensor, dtypestr) # type: ignore mps_edges = mps_inputs.out_edges + mps_inputs.in_edges - self._nodes, self._front = self.copy(mps_nodes, mps_edges) + self._nodes, self._front = self.copy_nodes(mps_nodes, mps_edges) self.coloring_nodes(self._nodes) self._double_nodes_front() @@ -131,7 +132,7 @@ def __init__( self._extra_qir: List[Dict[str, Any]] = [] def _double_nodes_front(self) -> None: - lnodes, lfront = self.copy(self._nodes, self._front, conj=True) + lnodes, lfront = self.copy_nodes(self._nodes, self._front, conj=True) self._front.extend(lfront) self._nodes.extend(lnodes) @@ -333,9 +334,11 @@ def apply_general_kraus( ) -> None: # incompatible API for now kraus = [ - k - if isinstance(k, tn.Node) - else Gate(backend.cast(backend.convert_to_tensor(k), dtypestr)) + ( + k + if isinstance(k, tn.Node) + else Gate(backend.cast(backend.convert_to_tensor(k), dtypestr)) + ) for k in kraus ] self.check_kraus(kraus) diff --git a/tensorcircuit/experimental.py b/tensorcircuit/experimental.py index b2de6451..8eba9a43 100644 --- a/tensorcircuit/experimental.py +++ b/tensorcircuit/experimental.py @@ -7,14 +7,17 @@ import numpy as np -from .cons import backend, dtypestr +from .cons import backend, dtypestr, contractor, rdtypestr +from .gates import Gate Tensor = Any +Circuit = Any def adaptive_vmap( f: Callable[..., Any], vectorized_argnums: Union[int, Sequence[int]] = 0, + static_argnums: Optional[Union[int, Sequence[int]]] = None, chunk_size: Optional[int] = None, ) -> Callable[..., Any]: if chunk_size is None: @@ -44,7 +47,10 @@ def wrapper(*args: Any, **kws: Any) -> Tensor: reshape_args.append(arg) if s2 != 0: rest_args.append(arg_rest) - _vmap = backend.vmap(f, vectorized_argnums) + _vmap = backend.jit( + backend.vmap(f, vectorized_argnums=vectorized_argnums), + static_argnums=static_argnums, + ) r = [] for i in range(s1): # currently using naive python loop for simplicity @@ -53,16 +59,16 @@ def wrapper(*args: Any, **kws: Any) -> Tensor: for j, a in enumerate(reshape_args) ] r.append(_vmap(*nreshape_args, **kws)) - r = backend.stack(r) - rshape = list(backend.shape_tuple(r)) - if len(rshape) == 2: - nshape = [rshape[0] * rshape[1]] - else: - nshape = [rshape[0] * rshape[1], -1] - r = backend.reshape(r, nshape) + r = backend.tree_map(lambda *x: backend.concat(x), *r) + # rshape = list(backend.shape_tuple(r)) + # if len(rshape) == 2: + # nshape = [rshape[0] * rshape[1]] + # else: + # nshape = [rshape[0] * rshape[1], -1] + # r = backend.reshape(r, nshape) if s2 != 0: rest_r = _vmap(*rest_args, **kws) - return backend.concat([r, rest_r]) + return backend.tree_map(lambda *x: backend.concat(x), r, rest_r) return r return wrapper @@ -345,6 +351,7 @@ def grad_f(*args: Any, **kws: Any) -> Any: # TODO(@refraction-ray): add SPSA gradient wrapper similar to parameter shift +# -- using noisyopt package instead def finite_difference_differentiator( @@ -433,3 +440,88 @@ def _evol(t: Tensor) -> Tensor: return callback(psi_exact) return backend.stack([_evol(t) for t in tlist]) + + +def evol_local( + c: Circuit, + index: Sequence[int], + h_fun: Callable[..., Tensor], + t: float, + *args: Any, + **solver_kws: Any +) -> Circuit: + """ + ode evolution of time dependent Hamiltonian on circuit of given indices + [only jax backend support for now] + + :param c: _description_ + :type c: Circuit + :param index: _description_ + :type index: Sequence[int] + :param h_fun: h_fun should return a dense Hamiltonian matrix + with input arguments time and *args + :type h_fun: Callable[..., Tensor] + :param t: evolution time + :type t: float + :return: _description_ + :rtype: Circuit + """ + from jax.experimental.ode import odeint + + s = c.state() + n = c._nqubits + l = len(index) + + def f(y: Tensor, t: Tensor, *args: Any) -> Tensor: + y = backend.reshape2(y) + y = Gate(y) + h = -1.0j * h_fun(t, *args) + h = backend.reshape2(h) + h = Gate(h) + edges = [] + for i in range(n): + if i not in index: + edges.append(y[i]) + else: + j = index.index(i) + edges.append(h[j]) + h[j + l] ^ y[i] + y = contractor([y, h], output_edge_order=edges) + return backend.reshape(y.tensor, [-1]) + + ts = backend.stack([0.0, t]) + ts = backend.cast(ts, dtype=rdtypestr) + s1 = odeint(f, s, ts, *args, **solver_kws) + return type(c)(n, inputs=s1[-1]) + + +def evol_global( + c: Circuit, h_fun: Callable[..., Tensor], t: float, *args: Any, **solver_kws: Any +) -> Circuit: + """ + ode evolution of time dependent Hamiltonian on circuit of all qubits + [only jax backend support for now] + + :param c: _description_ + :type c: Circuit + :param h_fun: h_fun should return a **SPARSE** Hamiltonian matrix + with input arguments time and *args + :type h_fun: Callable[..., Tensor] + :param t: _description_ + :type t: float + :return: _description_ + :rtype: Circuit + """ + from jax.experimental.ode import odeint + + s = c.state() + n = c._nqubits + + def f(y: Tensor, t: Tensor, *args: Any) -> Tensor: + h = -1.0j * h_fun(t, *args) + return backend.sparse_dense_matmul(h, y) + + ts = backend.stack([0.0, t]) + ts = backend.cast(ts, dtype=rdtypestr) + s1 = odeint(f, s, ts, *args, **solver_kws) + return type(c)(n, inputs=s1[-1]) diff --git a/tensorcircuit/fgs.py b/tensorcircuit/fgs.py new file mode 100644 index 00000000..a7012701 --- /dev/null +++ b/tensorcircuit/fgs.py @@ -0,0 +1,931 @@ +""" +Fermion Gaussian state simulator +""" + +from typing import Any, Dict, List, Optional, Tuple + +import numpy as np + +try: + import openfermion +except ModuleNotFoundError: + pass + +from .cons import backend, dtypestr, rdtypestr, get_backend +from .circuit import Circuit +from . import quantum + +Tensor = Any + + +def onehot_matrix(i: int, j: int, N: int) -> Tensor: + m = np.zeros([N, N]) + m[i, j] = 1 + m = backend.convert_to_tensor(m) + m = backend.cast(m, dtypestr) + return m + + +# TODO(@refraction-ray): efficiency benchmark with jit +# TODO(@refraction-ray): FGS mixed state support? +# TODO(@refraction-ray): overlap? + + +class FGSSimulator: + r""" + main refs: https://arxiv.org/pdf/2306.16595.pdf, + https://arxiv.org/abs/2209.06945, + https://scipost.org/SciPostPhysLectNotes.54/pdf + + convention: + for Hamiltonian (c^dagger, c)H(c, c^\dagger) + for correlation <(c, c^\dagger)(c^\dagger, c)> + c' = \alpha^\dagger (c, c^\dagger) + """ + + def __init__( + self, + L: int, + filled: Optional[List[int]] = None, + alpha: Optional[Tensor] = None, + hc: Optional[Tensor] = None, + cmatrix: Optional[Tensor] = None, + ): + """ + _summary_ + + :param L: system size + :type L: int + :param filled: the fermion site that is fully occupied, defaults to None + :type filled: Optional[List[int]], optional + :param alpha: directly specify the alpha tensor as the input + :type alpha: Optional[Tensor], optional + :param hc: the input is given as the ground state of quadratic Hamiltonian ``hc`` + :type hc: Optional[Tensor], optional + :param cmatrix: only used for debug, defaults to None + :type cmatrix: Optional[Tensor], optional + """ + if filled is None: + filled = [] + self.L = L + if alpha is None: + if hc is None: + self.alpha = self.init_alpha(filled, L) + else: + _, _, self.alpha = self.fermion_diagonalization(hc, L) + else: + self.alpha = alpha + self.alpha0 = self.alpha + self.wtransform = self.wmatrix(L) + self.cmatrix = cmatrix + self.otcmatrix: Dict[Tuple[int, int], Tensor] = {} + + @classmethod + def fermion_diagonalization( + cls, hc: Tensor, L: int + ) -> Tuple[Tensor, Tensor, Tensor]: + es, u = backend.eigh(hc) + es = es[::-1] + u = u[:, ::-1] + alpha = u[:, :L] + return es, u, alpha + + @classmethod + def fermion_diagonalization_2( + cls, hc: Tensor, L: int + ) -> Tuple[Tensor, Tensor, Tensor]: + w = cls.wmatrix(L) + hm = 0.25 * w @ hc @ backend.adjoint(w) + hm = backend.real((-1.0j) * hm) + hd, om = backend.schur(hm, output="real") + # order not kept + # eps = 1e-10 + # idm = backend.convert_to_tensor(np.array([[1.0, 0], [0, 1.0]])) + # idm = backend.cast(idm, dtypestr) + # xm = backend.convert_to_tensor(np.array([[0, 1.0], [1.0, 0]])) + # xm = backend.cast(xm, dtypestr) + # for i in range(0, 2 * L, 2): + # (backend.sign(hd[i, i + 1] + eps) + 1) / 2 * idm - ( + # backend.sign(hd[i, i + 1] + eps) - 1 + # ) / 2 * xm + # print(hd) + + es = backend.adjoint(w) @ (1.0j * hd) @ w + u = 0.5 * backend.adjoint(w) @ backend.transpose(om) @ w + alpha = backend.adjoint(u)[:, :L] + # c' = u@c + # e_k (c^\dagger_k c_k - c_k c^\dagger_k) + return es, u, alpha + + @staticmethod + def wmatrix(L: int) -> Tensor: + w = np.zeros([2 * L, 2 * L], dtype=complex) + for i in range(2 * L): + if i % 2 == 1: + w[i, (i - 1) // 2] = 1.0j + w[i, (i - 1) // 2 + L] = -1.0j + else: + w[i, i // 2] = 1 + w[i, i // 2 + L] = 1 + return backend.convert_to_tensor(w) + + @staticmethod + def init_alpha(filled: List[int], L: int) -> Tensor: + alpha = np.zeros([2 * L, L]) + for i in range(L): + if i not in filled: + alpha[i, i] = 1 + else: + alpha[i + L, i] = 1 + alpha = backend.convert_to_tensor(alpha) + alpha = backend.cast(alpha, dtypestr) + return alpha + + def get_alpha(self) -> Tensor: + return self.alpha + + def get_cmatrix(self, now_i: bool = True, now_j: bool = True) -> Tensor: + # otoc in FGS language, see: https://arxiv.org/pdf/1908.03292.pdf + # https://journals.aps.org/prb/pdf/10.1103/PhysRevB.99.054205 + # otoc for non=hermitian system is more subtle due to the undefined normalization + # of operator and not considered here, see: https://arxiv.org/pdf/2305.12054.pdf + if self.cmatrix is not None and now_i is True and now_j is True: + return self.cmatrix + elif now_i is True and now_j is True: + cmatrix = self.alpha @ backend.adjoint(self.alpha) + self.cmatrix = cmatrix + return cmatrix + elif now_i is True: # new i old j + if (1, 0) in self.otcmatrix: + return self.otcmatrix[(1, 0)] + cmatrix = self.alpha @ backend.adjoint(self.alpha0) + self.otcmatrix[(1, 0)] = cmatrix + return cmatrix + elif now_j is True: # old i new j + if (0, 1) in self.otcmatrix: + return self.otcmatrix[(0, 1)] + cmatrix = self.alpha0 @ backend.adjoint(self.alpha) + self.otcmatrix[(0, 1)] = cmatrix + return cmatrix + else: # initial cmatrix + if (0, 0) in self.otcmatrix: + return self.otcmatrix[(0, 0)] + cmatrix = self.alpha0 @ backend.adjoint(self.alpha0) + self.otcmatrix[(0, 0)] = cmatrix + return cmatrix + + def get_reduced_cmatrix(self, subsystems_to_trace_out: List[int]) -> Tensor: + m = self.get_cmatrix() + if subsystems_to_trace_out is None: + subsystems_to_trace_out = [] + keep = [i for i in range(self.L) if i not in subsystems_to_trace_out] + keep += [i + self.L for i in range(self.L) if i not in subsystems_to_trace_out] + keep = backend.convert_to_tensor(keep) + + def slice_(a: Tensor) -> Tensor: + return backend.gather1d(a, keep) + + slice_ = backend.vmap(slice_) + m = backend.gather1d(slice_(m), keep) + return m + + def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor: + """ + compute renyi_entropy of order ``n`` for the fermion state + + :param n: _description_ + :type n: int + :param subsystems_to_trace_out: system sites to be traced out + :type subsystems_to_trace_out: List[int] + :return: _description_ + :rtype: Tensor + """ + m = self.get_reduced_cmatrix(subsystems_to_trace_out) + lbd, _ = backend.eigh(m) + lbd = backend.real(lbd) + lbd = backend.relu(lbd) + eps = 1e-6 + + entropy = backend.sum(backend.log(lbd**n + (1 - lbd) ** n + eps)) + s = 1 / (2 * (1 - n)) * entropy + return s + + def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor: + """ + compute von Neumann entropy for the fermion state + + :param subsystems_to_trace_out: _description_, defaults to None + :type subsystems_to_trace_out: Optional[List[int]], optional + :return: _description_ + :rtype: Tensor + """ + m = self.get_reduced_cmatrix(subsystems_to_trace_out) # type: ignore + lbd, _ = backend.eigh(m) + lbd = backend.real(lbd) + lbd = backend.relu(lbd) + # lbd /= backend.sum(lbd) + eps = 1e-6 + entropy = -backend.sum( + lbd * backend.log(lbd + eps) + (1 - lbd) * backend.log(1 - lbd + eps) + ) + return entropy / 2 + + def evol_hamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-i/2 \hat{h}}` + + :param h: _description_ + :type h: Tensor + """ + # e^{-i/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(-1.0j * h) @ self.alpha + self.cmatrix = None + self.otcmatrix = {} + + def evol_ihamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-1/2 \hat{h}}` + + :param h: _description_ + :type h: Tensor + """ + # e^{-1/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(h) @ self.alpha + self.orthogonal() + self.cmatrix = None + self.otcmatrix = {} + + def evol_ghamiltonian(self, h: Tensor) -> None: + r""" + Evolve as :math:`e^{-1/2 i \hat{h}}` with h generally non-Hermitian + + :param h: _description_ + :type h: Tensor + """ + # e^{-1/2 H} + h = backend.cast(h, dtype=dtypestr) + self.alpha = backend.expm(-1.0j * backend.adjoint(h)) @ self.alpha + self.orthogonal() + self.cmatrix = None + self.otcmatrix = {} + + def orthogonal(self) -> None: + q, _ = backend.qr(self.alpha) + self.alpha = q + + @staticmethod + def hopping(chi: Tensor, i: int, j: int, L: int) -> Tensor: + # chi * ci dagger cj + hc. + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, j, 2 * L) + m += -chi / 2 * onehot_matrix(j + L, i + L, 2 * L) + m += backend.adjoint(m) + return m + + def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`\chi c_i^\dagger c_j +h.c.` + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.hopping(chi, i, j, self.L)) + + @staticmethod + def chemical_potential(chi: Tensor, i: int, L: int) -> Tensor: + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, i, 2 * L) + m += -chi / 2 * onehot_matrix(i + L, i + L, 2 * L) + return m + + @staticmethod + def sc_pairing(chi: Tensor, i: int, j: int, L: int) -> Tensor: + chi = backend.convert_to_tensor(chi) + chi = backend.cast(chi, dtypestr) + m = chi / 2 * onehot_matrix(i, j + L, 2 * L) + m += -chi / 2 * onehot_matrix(j, i + L, 2 * L) + m += backend.adjoint(m) + return m + + def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_j^\dagger +h.c.` + + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.sc_pairing(chi, i, j, self.L)) + + def evol_cp(self, i: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` + + :param i: _description_ + :type i: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_hamiltonian(self.chemical_potential(chi, i, self.L)) + + def evol_icp(self, i: int, chi: Tensor = 0) -> None: + r""" + The evolve Hamiltonian is :math:`chi c_i^\dagger c_i` with :math:`\exp^{-H/2}` + + :param i: _description_ + :type i: int + :param chi: _description_, defaults to 0 + :type chi: Tensor, optional + """ + self.evol_ihamiltonian(self.chemical_potential(chi, i, self.L)) + + def get_bogoliubov_uv(self) -> Tuple[Tensor, Tensor]: + return ( + backend.gather1d( + self.alpha, backend.convert_to_tensor([i for i in range(self.L)]) + ), + backend.gather1d( + self.alpha, + backend.convert_to_tensor([i + self.L for i in range(self.L)]), + ), + ) + + def get_cmatrix_majorana(self) -> Tensor: + r""" + correlation matrix defined in majorana basis + convention: :math:`gamma_0 = c_0 + c_0^\dagger` + :math:`gamma_1 = i(c_0 - c_0^\dagger)` + + :return: _description_ + :rtype: Tensor + """ + c = self.get_cmatrix() + return self.wtransform @ c @ backend.adjoint(self.wtransform) + + def get_covariance_matrix(self) -> Tensor: + m = self.get_cmatrix_majorana() + return -1.0j * (2 * m - backend.eye(self.L * 2)) + + def expectation_2body( + self, i: int, j: int, now_i: bool = True, now_j: bool = True + ) -> Tensor: + """ + expectation of two fermion terms + convention: (c, c^\dagger) + for i>L, c_{i-L}^\dagger is assumed + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :return: _description_ + :rtype: Tensor + """ + return self.get_cmatrix(now_i, now_j)[i][(j + self.L) % (2 * self.L)] + + def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: + """ + expectation of four fermion terms using Wick Thm + convention: (c, c^\dagger) + for i>L, c_{i-L}^\dagger is assumed + + :param i: _description_ + :type i: int + :param j: _description_ + :type j: int + :param k: _description_ + :type k: int + :param l: _description_ + :type l: int + :return: _description_ + :rtype: Tensor + """ + e = ( + self.expectation_2body(i, j) * self.expectation_2body(k, l) + - self.expectation_2body(i, k) * self.expectation_2body(j, l) + + self.expectation_2body(i, l) * self.expectation_2body(j, k) + ) + return e + + def post_select(self, i: int, keep: int = 1) -> None: + """ + post select (project) the fermion state to occupation eigenstate + = ``keep`` + + :param i: _description_ + :type i: int + :param keep: _description_, defaults to 1 + :type keep: int, optional + """ + # i is not jittable, keep is jittable + L = backend.convert_to_tensor(self.L) + i = backend.convert_to_tensor(i) + L = backend.cast(L, "int32") + i = backend.cast(i, "int32") + keep = backend.convert_to_tensor(keep) + keep = backend.cast(keep, "int32") + alpha = self.alpha + # if keep == 0: + i = i + L * (1 - keep) + i0 = backend.argmax(backend.abs(alpha[(i + L) % (2 * L), :])) + i0 = backend.cast(i0, "int32") + alpha1 = alpha - backend.reshape(alpha[:, i0], [-1, 1]) @ backend.reshape( + alpha[(i + L) % (2 * L), :] / alpha[(i + L) % (2 * L), i0], [1, -1] + ) + mask1 = backend.onehot(i0, alpha.shape[1]) + mask1 = backend.cast(mask1, dtypestr) + mask0 = backend.ones(alpha.shape[1]) - mask1 + mask12d = backend.tile(mask1[None, :], [alpha.shape[0], 1]) + mask02d = backend.tile(mask0[None, :], [alpha.shape[0], 1]) + alpha1 = mask02d * alpha1 + mask12d * alpha + r = [] + for j in range(2 * self.L): + indicator = ( + backend.sign(backend.cast((i - j), rdtypestr) ** 2 - 0.5) + 1 + ) / 2 + # i=j indicator = 0, i!=j indicator = 1 + indicator = backend.cast(indicator, dtypestr) + r.append( + backend.ones([self.L]) * indicator + + backend.ones([self.L]) * mask1 * (1 - indicator) + ) + # if j != i: + # r.append(backend.ones([L])) + # else: + # r.append(backend.ones([L]) * mask1) + mask2 = backend.stack(r) + alpha1 = alpha1 * mask2 + r = [] + for j in range(2 * self.L): + indicator = ( + backend.sign( + (backend.cast((i + L) % (2 * L) - j, rdtypestr)) ** 2 - 0.5 + ) + + 1 + ) / 2 + r.append(1 - indicator) + newcol = backend.stack(r) + # newcol = np.zeros([2 * self.L]) + # newcol[(i + L) % (2 * L)] = 1 + # newcol = backend.convert_to_tensor(newcol) + newcol = backend.cast(newcol, dtypestr) + alpha1 = alpha1 * mask02d + backend.tile(newcol[:, None], [1, self.L]) * mask12d + q, _ = backend.qr(alpha1) + self.alpha = q + + def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor: + p0 = backend.real(self.get_cmatrix()[ind, ind]) + prob = backend.convert_to_tensor([p0, 1 - p0]) + status = backend.convert_to_tensor(status) + status = backend.cast(status, rdtypestr) + eps = 1e-12 + keep = (backend.sign(status - p0 + eps) + 1) / 2 + self.post_select(ind, keep) + if with_prob is False: + return keep + else: + return keep, prob + + # def product(self, other): + # # self@other + # gamma1 = self.get_covariance_matrix() + # gamma2 = other.get_covariance_matrix() + # den = backend.inv(1 + gamma1 @ gamma2) + # idm = backend.eye(2 * self.L) + # covm = idm - (idm - gamma2) @ den @ (idm - gamma1) + # cm = (1.0j * covm + idm) / 2 + # cmatrix = backend.adjoint(self.wtransform) @ cm @ self.wtransform * 0.25 + # return type(self)(self.L, cmatrix=cmatrix) + + def overlap(self, other: "FGSSimulator") -> Tensor: + """ + overlap upto a U(1) phase + + :param other: _description_ + :type other: FGSSimulator + :return: _description_ + :rtype: _type_ + """ + u, v = self.get_bogoliubov_uv() + u1, v1 = other.get_bogoliubov_uv() + return backend.sqrt( + backend.abs(backend.det(backend.adjoint(u1) @ u + backend.adjoint(v1) @ v)) + ) + + +npb = get_backend("numpy") + + +class FGSTestSimulator: + """ + Never use, only for correctness testing + stick to numpy backend and no jit/ad/vmap is available + """ + + def __init__( + self, + L: int, + filled: Optional[List[int]] = None, + state: Optional[Tensor] = None, + hc: Optional[Tensor] = None, + ): + if filled is None: + filled = [] + self.L = L + if state is not None: + self.state = state + elif hc is not None: + self.state = self.fermion_diagonalization(hc, L) + else: + self.state = self.init_state(filled, L) + self.state0 = self.state + + @staticmethod + def init_state(filled: List[int], L: int) -> Tensor: + c = Circuit(L) + for i in filled: + c.x(i) # type: ignore + return c.state() + + @classmethod + def fermion_diagonalization(cls, hc: Tensor, L: int) -> Tensor: + h = cls.get_hmatrix(hc, L) + _, u = np.linalg.eigh(h) + return u[:, 0] + + @staticmethod + def get_hmatrix(hc: Tensor, L: int) -> Tensor: + hm = np.zeros([2**L, 2**L], dtype=complex) + for i in range(L): + for j in range(L): + op = openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L, 2 * L): + for j in range(L): + op = openfermion.FermionOperator(f"{str(i-L)} {str(j)}") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L): + for j in range(L, 2 * L): + op = openfermion.FermionOperator(f"{str(i)}^ {str(j-L)}^") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + for i in range(L, 2 * L): + for j in range(L, 2 * L): + op = openfermion.FermionOperator(f"{str(i-L)} {str(j-L)}^") + hm += ( + hc[i, j] * openfermion.get_sparse_operator(op, n_qubits=L).todense() + ) + + return hm + + @staticmethod + def hopping_jw(chi: Tensor, i: int, j: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + np.conj( + chi + ) * openfermion.FermionOperator(f"{str(j)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + @staticmethod + def chemical_potential_jw(chi: Tensor, i: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + def evol_hamiltonian(self, h: Tensor) -> None: + self.state = npb.expm(-1 / 2 * 1.0j * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) + + def evol_ihamiltonian(self, h: Tensor) -> None: + self.state = npb.expm(-1 / 2 * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) + self.orthogonal() + + def evol_ghamiltonian(self, h: Tensor) -> None: + self.state = npb.expm(-1 / 2 * 1.0j * h) @ npb.reshape(self.state, [-1, 1]) + self.state = npb.reshape(self.state, [-1]) + self.orthogonal() + + def evol_hp(self, i: int, j: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.hopping_jw(chi, i, j, self.L)) + + def evol_cp(self, i: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.chemical_potential_jw(chi, i, self.L)) + + def evol_icp(self, i: int, chi: Tensor = 0) -> None: + self.evol_ihamiltonian(self.chemical_potential_jw(chi, i, self.L)) + + @staticmethod + def sc_pairing_jw(chi: Tensor, i: int, j: int, L: int) -> Tensor: + op = chi * openfermion.FermionOperator(f"{str(i)}^ {str(j)}^") + np.conj( + chi + ) * openfermion.FermionOperator(f"{str(j)} {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + def evol_sp(self, i: int, j: int, chi: Tensor = 0) -> None: + self.evol_hamiltonian(self.sc_pairing_jw(chi, i, j, self.L)) + + def orthogonal(self) -> None: + self.state /= backend.norm(self.state) + + def get_ot_cmatrix(self, h: Tensor, now_i: bool = True) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(self.L): + for j in range(self.L): + op1 = openfermion.FermionOperator(f"{str(i)}") + op2 = openfermion.FermionOperator(f"{str(j)}^") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L): + op1 = openfermion.FermionOperator(f"{str(i-self.L)}^") + op2 = openfermion.FermionOperator(f"{str(j)}^") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + for i in range(self.L): + for j in range(self.L, 2 * self.L): + op1 = openfermion.FermionOperator(f"{str(i)}") + op2 = openfermion.FermionOperator(f"{str(j-self.L)}") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L, 2 * self.L): + op1 = openfermion.FermionOperator(f"{str(i-self.L)}^ ") + op2 = openfermion.FermionOperator(f"{str(j-self.L)}") + + m1 = openfermion.get_sparse_operator(op1, n_qubits=self.L).todense() + m2 = openfermion.get_sparse_operator(op2, n_qubits=self.L).todense() + eh = npb.expm(-1 / 2 * 1.0j * h) + eh1 = npb.expm(1 / 2 * 1.0j * h) + + if now_i is True: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ eh1 + @ m1 + @ eh + @ m2 + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + else: + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m1 + @ eh1 + @ m2 + @ eh + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + return cmatrix + + def get_cmatrix(self) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(self.L): + for j in range(self.L): + op = openfermion.FermionOperator(f"{str(i)} {str(j)}^") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L): + op = openfermion.FermionOperator(f"{str(i-self.L)}^ {str(j)}^") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L): + for j in range(self.L, 2 * self.L): + op = openfermion.FermionOperator(f"{str(i)} {str(j-self.L)}") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + for i in range(self.L, 2 * self.L): + for j in range(self.L, 2 * self.L): + op = openfermion.FermionOperator(f"{str(i-self.L)}^ {str(j-self.L)}") + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + return cmatrix + + def get_cmatrix_majorana(self) -> Tensor: + alpha1_jw = self.state + cmatrix = np.zeros([2 * self.L, 2 * self.L], dtype=complex) + for i in range(2 * self.L): + for j in range(2 * self.L): + op = openfermion.MajoranaOperator((i,)) * openfermion.MajoranaOperator( + (j,) + ) + if j % 2 + i % 2 == 1: + op *= -1 + # convention diff in jordan wigner + # c\dagger = X\pm iY + + op = openfermion.jordan_wigner(op) + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + cmatrix[i, j] = backend.item( + ( + backend.reshape(backend.adjoint(alpha1_jw), [1, -1]) + @ m + @ backend.reshape(alpha1_jw, [-1, 1]) + )[0, 0] + ) + + return cmatrix + + def expectation_4body(self, i: int, j: int, k: int, l: int) -> Tensor: + s = "" + if i < self.L: + s += str(i) + "" + else: + s += str(i - self.L) + "^ " + if j < self.L: + s += str(j) + "" + else: + s += str(j - self.L) + "^ " + if k < self.L: + s += str(k) + "" + else: + s += str(k - self.L) + "^ " + if l < self.L: + s += str(l) + "" + else: + s += str(l - self.L) + "^ " + op = openfermion.FermionOperator(s) + m = openfermion.get_sparse_operator(op, n_qubits=self.L).todense() + return ( + npb.reshape(npb.adjoint(self.state), [1, -1]) + @ m + @ npb.reshape(self.state, [-1, 1]) + )[0, 0] + + def entropy(self, subsystems_to_trace_out: Optional[List[int]] = None) -> Tensor: + rm = quantum.reduced_density_matrix(self.state, subsystems_to_trace_out) # type: ignore + return quantum.entropy(rm) + + def renyi_entropy(self, n: int, subsystems_to_trace_out: List[int]) -> Tensor: + rm = quantum.reduced_density_matrix(self.state, subsystems_to_trace_out) + return quantum.renyi_entropy(rm, n) + + def overlap(self, other: "FGSTestSimulator") -> Tensor: + return backend.tensordot(backend.conj(self.state), other.state, 1) + + def get_dm(self) -> Tensor: + s = backend.reshape(self.state, [-1, 1]) + return s @ backend.adjoint(s) + + def product(self, other: "FGSTestSimulator") -> Tensor: + rho1 = self.get_dm() + rho2 = other.get_dm() + rho = rho1 @ rho2 + rho /= backend.trace(rho) + return rho + + def post_select(self, i: int, keep: int = 1) -> None: + c = Circuit(self.L, inputs=self.state) + c.post_select(i, keep) + s = c.state() + s /= backend.norm(s) + self.state = s + + def cond_measure(self, ind: int, status: float, with_prob: bool = False) -> Tensor: + p0 = self.get_cmatrix()[ind, ind] + prob = [p0, 1 - p0] + if status < p0: + self.post_select(ind, 0) + keep = 0 + else: + self.post_select(ind, 1) + keep = 1 + + if with_prob is False: + return keep + else: + return keep, prob diff --git a/tensorcircuit/gates.py b/tensorcircuit/gates.py index 40fa9b26..412230e2 100644 --- a/tensorcircuit/gates.py +++ b/tensorcircuit/gates.py @@ -13,7 +13,7 @@ import tensornetwork as tn from scipy.stats import unitary_group -from .cons import backend, dtypestr, npdtype +from .cons import backend, dtypestr, npdtype, runtime_backend from .utils import arg_alias thismodule = sys.modules[__name__] @@ -389,6 +389,9 @@ def meta_gate() -> None: setattr(thismodule, n + "_gate", temp) setattr(thismodule, n, temp) + with runtime_backend("numpy"): # backward compatibility + setattr(thismodule, "pauli_gates", [i(), x(), y(), z()]) # type: ignore + meta_gate() @@ -544,7 +547,7 @@ def r_gate(theta: float = 0, alpha: float = 0, phi: float = 0) -> Gate: General single qubit rotation gate .. math:: - R(\theta, \alpha, \phi) = j \cos(\theta) I + R(\theta, \alpha, \phi) = \cos(\theta) I - j \cos(\phi) \sin(\alpha) \sin(\theta) X - j \sin(\phi) \sin(\alpha) \sin(\theta) Y - j \sin(\theta) \cos(\alpha) Z diff --git a/tensorcircuit/interfaces/__init__.py b/tensorcircuit/interfaces/__init__.py index f257d387..1f8cc608 100644 --- a/tensorcircuit/interfaces/__init__.py +++ b/tensorcircuit/interfaces/__init__.py @@ -14,3 +14,6 @@ from .scipy import scipy_interface, scipy_optimize_interface from .torch import torch_interface, pytorch_interface, torch_interface_kws from .tensorflow import tensorflow_interface, tf_interface + + +# TODO(@refraction-ray): jax interface using puer_callback and custom_vjp diff --git a/tensorcircuit/interfaces/torch.py b/tensorcircuit/interfaces/torch.py index e346b757..8fcdb2e2 100644 --- a/tensorcircuit/interfaces/torch.py +++ b/tensorcircuit/interfaces/torch.py @@ -12,6 +12,8 @@ Tensor = Any +# TODO(@refraction-ray): new paradigm compatible with torch functional trasnformation + def torch_interface( fun: Callable[..., Any], jit: bool = False, enable_dlpack: bool = False diff --git a/tensorcircuit/keras.py b/tensorcircuit/keras.py index 7aafdd15..ed947b8c 100644 --- a/tensorcircuit/keras.py +++ b/tensorcircuit/keras.py @@ -143,6 +143,11 @@ def call( class HardwareLayer(QuantumLayer): + """ + Keras Layer wrapping quantum function with cloud qpu access + (using :py:mod:`tensorcircuit.cloud` module) + """ + @tf.autograph.experimental.do_not_convert # type: ignore def call( self, @@ -170,6 +175,9 @@ def call( return result +KerasHardwareLayer = HardwareLayer + + def output_asis_loss(y_true: tf.Tensor, y_pred: tf.Tensor) -> tf.Tensor: """ The keras loss function that directly taking the model output as the loss. diff --git a/tensorcircuit/mps_base.py b/tensorcircuit/mps_base.py index 1b09b5a8..d8234c2b 100644 --- a/tensorcircuit/mps_base.py +++ b/tensorcircuit/mps_base.py @@ -1,12 +1,21 @@ """ FiniteMPS from tensornetwork with bug fixed """ + # pylint: disable=invalid-name from typing import Any, Optional, List, Sequence import numpy as np -from tensornetwork.linalg.node_linalg import conj + +try: + from tensornetwork.linalg.node_linalg import conj + + # google tn +except ModuleNotFoundError: + # tc tn + from tensornetwork.matrixproductstates.utils import conj + import tensornetwork as tn import tensornetwork.ncon_interface as ncon from tensornetwork.network_components import Node @@ -127,7 +136,6 @@ def set_center_position(site: int) -> None: if center_position is None: center_position = site1 - if use_svd: U, S, V, tw = self.backend.svd( tensor, @@ -136,6 +144,7 @@ def set_center_position(site: int) -> None: max_truncation_error=max_truncation_err, relative=relative, ) + # Note: fix the center position bug here if center_position == site2: left_tensor = U diff --git a/tensorcircuit/mpscircuit.py b/tensorcircuit/mpscircuit.py index 8a37b3ed..7fc4052e 100644 --- a/tensorcircuit/mpscircuit.py +++ b/tensorcircuit/mpscircuit.py @@ -1,6 +1,7 @@ """ Quantum circuit: MPS state simulator """ + # pylint: disable=invalid-name from functools import reduce @@ -52,6 +53,11 @@ def split_tensor( return backend.qr(tensor) # type: ignore +# AD + MPS can lead to numerical stability issue +# E ./tensorflow/core/kernels/linalg/svd_op_impl.h:110] Eigen::BDCSVD failed with error code 3 +# this is now solved by setting os.environ["TC_BACKENDS_TENSORFLOW_BACKEND__SVD_TF_EPS"]="10" + + class MPSCircuit(AbstractCircuit): """ ``MPSCircuit`` class. diff --git a/tensorcircuit/noisemodel.py b/tensorcircuit/noisemodel.py index 0b03d966..9a1d85ac 100644 --- a/tensorcircuit/noisemodel.py +++ b/tensorcircuit/noisemodel.py @@ -1,6 +1,7 @@ """ General Noise Model Construction. """ + import logging from functools import partial from typing import Any, Sequence, Optional, List, Dict, Tuple, Callable, Union diff --git a/tensorcircuit/pulse.py b/tensorcircuit/pulse.py new file mode 100644 index 00000000..a09ddac6 --- /dev/null +++ b/tensorcircuit/pulse.py @@ -0,0 +1,50 @@ +from typing import List, Dict, Any + + +class Param: + def __init__(self, name: str): + self.name = name + +class Frame: + def __init__(self, name: str): + self.name = name + +class DefcalBuilder: + def __init__(self, circuit, name: str, parameters: List["Param"]): + self.circuit = circuit + self.name = name + self.parameters = parameters + self.instructions = [] + + def new_frame(self, frame_name: str, param: "Param"): + frame = Frame(frame_name) + self.instructions.append({ + "type": "frame", + "frame": frame, + "qubit": param.name, + }) + return frame + + def play(self, frame: Frame, waveform: Any, start_time: int = None): + if not hasattr(waveform, "__dataclass_fields__"): + raise TypeError("Unsupported waveform type") + + waveform_type = waveform.qasm_name() + args = waveform.to_args() + if start_time is not None: + args = [start_time] + args + + self.instructions.append({ + "type": "play", + "frame": frame.name, + "waveform_type": waveform_type, + "args": args, + }) + return self + + def build(self): + self.circuit.def_calibration( + name=self.name, + parameters=[p.name for p in self.parameters], + instructions=self.instructions, + ) diff --git a/tensorcircuit/quantum.py b/tensorcircuit/quantum.py index ab837c7f..b6ed4eab 100644 --- a/tensorcircuit/quantum.py +++ b/tensorcircuit/quantum.py @@ -7,11 +7,13 @@ import tensorcircuit.quantum as qu """ + # pylint: disable=invalid-name -from functools import reduce, partial import logging -from operator import or_, mul, matmul +import os +from functools import partial, reduce +from operator import matmul, mul, or_ from typing import ( Any, Callable, @@ -26,19 +28,18 @@ ) import numpy as np -from tensornetwork.network_components import AbstractNode, Node, Edge, connect -from tensornetwork.network_components import CopyNode -from tensornetwork.network_operations import get_all_nodes, copy, reachable -from tensornetwork.network_operations import get_subgraph_dangling, remove_node - -try: - import tensorflow as tf -except ImportError: - pass +from tensornetwork.network_components import AbstractNode, CopyNode, Edge, Node, connect +from tensornetwork.network_operations import ( + copy, + get_all_nodes, + get_subgraph_dangling, + reachable, + remove_node, +) from .cons import backend, contractor, dtypestr, npdtype, rdtypestr -from .backends import get_backend -from .utils import is_m1mac, arg_alias +from .gates import Gate, num_to_tensor +from .utils import arg_alias Tensor = Any Graph = Any @@ -1159,318 +1160,327 @@ def quimb2qop(qb_mpo: Any) -> QuOperator: return qop -try: +def heisenberg_hamiltonian( + g: Graph, + hzz: float = 1.0, + hxx: float = 1.0, + hyy: float = 1.0, + hz: float = 0.0, + hx: float = 0.0, + hy: float = 0.0, + sparse: bool = True, + numpy: bool = False, +) -> Tensor: + """ + Generate Heisenberg Hamiltonian with possible external fields. + Currently requires tensorflow installed + + :Example: + + >>> g = tc.templates.graphs.Line1D(6) + >>> h = qu.heisenberg_hamiltonian(g, sparse=False) + >>> tc.backend.eigh(h)[0][:10] + array([-11.2111025, -8.4721365, -8.472136 , -8.472136 , -6. , + -5.123106 , -5.123106 , -5.1231055, -5.1231055, -5.1231055], + dtype=float32) + + :param g: input circuit graph + :type g: Graph + :param hzz: zz coupling, default is 1.0 + :type hzz: float + :param hxx: xx coupling, default is 1.0 + :type hxx: float + :param hyy: yy coupling, default is 1.0 + :type hyy: float + :param hz: External field on z direction, default is 0.0 + :type hz: float + :param hx: External field on y direction, default is 0.0 + :type hx: float + :param hy: External field on x direction, default is 0.0 + :type hy: float + :param sparse: Whether to return sparse Hamiltonian operator, default is True. + :type sparse: bool, defalts True + :param numpy: whether return the matrix in numpy or tensorflow form + :type numpy: bool, defaults False, + + :return: Hamiltonian measurements + :rtype: Tensor + """ + n = len(g.nodes) + ls = [] + weight = [] + for e in g.edges: + if hzz != 0: + r = [0 for _ in range(n)] + r[e[0]] = 3 + r[e[1]] = 3 + ls.append(r) + weight.append(hzz) + if hxx != 0: + r = [0 for _ in range(n)] + r[e[0]] = 1 + r[e[1]] = 1 + ls.append(r) + weight.append(hxx) + if hyy != 0: + r = [0 for _ in range(n)] + r[e[0]] = 2 + r[e[1]] = 2 + ls.append(r) + weight.append(hyy) + for node in g.nodes: + if hz != 0: + r = [0 for _ in range(n)] + r[node] = 3 + ls.append(r) + weight.append(hz) + if hx != 0: + r = [0 for _ in range(n)] + r[node] = 1 + ls.append(r) + weight.append(hx) + if hy != 0: + r = [0 for _ in range(n)] + r[node] = 2 + ls.append(r) + weight.append(hy) + ls = num_to_tensor(ls) + weight = num_to_tensor(weight) + if sparse: + r = PauliStringSum2COO_numpy(ls, weight) + if numpy: + return r + return backend.coo_sparse_matrix_from_numpy(r) + return PauliStringSum2Dense(ls, weight, numpy=numpy) + + +def PauliStringSum2Dense( + ls: Sequence[Sequence[int]], + weight: Optional[Sequence[float]] = None, + numpy: bool = False, +) -> Tensor: + """ + Generate dense matrix from Pauli string sum. + Currently requires tensorflow installed. + - def _id(x: Any) -> Any: - return x + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :param numpy: default False. If True, return numpy coo + else return backend compatible sparse tensor + :type numpy: bool + :return: the tensorflow dense matrix + :rtype: Tensor + """ + sparsem = PauliStringSum2COO_numpy(ls, weight) + if numpy: + return sparsem.todense() + sparsem = backend.coo_sparse_matrix_from_numpy(sparsem) + densem = backend.to_dense(sparsem) + return densem + + +# already implemented as backend method +# +# def _tf2numpy_sparse(a: Tensor) -> Tensor: +# return get_backend("numpy").coo_sparse_matrix( +# indices=a.indices, +# values=a.values, +# shape=a.get_shape(), +# ) + +# def _numpy2tf_sparse(a: Tensor) -> Tensor: +# return get_backend("tensorflow").coo_sparse_matrix( +# indices=np.array([a.row, a.col]).T, +# values=a.data, +# shape=a.shape, +# ) + + +def PauliStringSum2COO( + ls: Sequence[Sequence[int]], + weight: Optional[Sequence[float]] = None, + numpy: bool = False, +) -> Tensor: + """ + Generate sparse tensor from Pauli string sum. + Currently requires tensorflow installed + + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :param numpy: default False. If True, return numpy coo + else return backend compatible sparse tensor + :type numpy: bool + :return: the scipy coo sparse matrix + :rtype: Tensor + """ + # numpy version is 3* faster! + + nterms = len(ls) + # n = len(ls[0]) + # s = 0b1 << n + if weight is None: + weight = [1.0 for _ in range(nterms)] + weight = num_to_tensor(weight) + ls = num_to_tensor(ls) + # rsparse = get_backend("numpy").coo_sparse_matrix( + # indices=np.array([[0, 0]], dtype=np.int64), + # values=np.array([0.0], dtype=getattr(np, dtypestr)), + # shape=(s, s), + # ) + global PauliString2COO_jit + if backend.name not in PauliString2COO_jit: + PauliString2COO_jit[backend.name] = backend.jit( + PauliString2COO, jit_compile=True + ) + rsparses = [ + backend.numpy(PauliString2COO_jit[backend.name](ls[i], weight[i])) # type: ignore + for i in range(nterms) + ] + rsparse = _dc_sum(rsparses) + # auto transformed into csr format!! + + # for i in range(nterms): + # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) + rsparse = rsparse.tocoo() + if numpy: + return rsparse + return backend.coo_sparse_matrix_from_numpy(rsparse) - if is_m1mac(): - compiled_jit = _id + +def _dc_sum(l: List[Any]) -> Any: + """ + For the sparse sum, the speed is determined by the non zero terms, + so the DC way to do the sum can indeed bring some speed advantage (several times) + + :param l: _description_ + :type l: List[Any] + :return: _description_ + :rtype: Any + """ + n = len(l) + if n > 2: + return _dc_sum(l[: n // 2]) + _dc_sum(l[n // 2 :]) else: - compiled_jit = partial(get_backend("tensorflow").jit, jit_compile=True) - - def heisenberg_hamiltonian( - g: Graph, - hzz: float = 1.0, - hxx: float = 1.0, - hyy: float = 1.0, - hz: float = 0.0, - hx: float = 0.0, - hy: float = 0.0, - sparse: bool = True, - numpy: bool = False, - ) -> Tensor: - """ - Generate Heisenberg Hamiltonian with possible external fields. - Currently requires tensorflow installed + return sum(l) - :Example: - >>> g = tc.templates.graphs.Line1D(6) - >>> h = qu.heisenberg_hamiltonian(g, sparse=False) - >>> tc.backend.eigh(h)[0][:10] - array([-11.2111025, -8.4721365, -8.472136 , -8.472136 , -6. , - -5.123106 , -5.123106 , -5.1231055, -5.1231055, -5.1231055], - dtype=float32) - - :param g: input circuit graph - :type g: Graph - :param hzz: zz coupling, default is 1.0 - :type hzz: float - :param hxx: xx coupling, default is 1.0 - :type hxx: float - :param hyy: yy coupling, default is 1.0 - :type hyy: float - :param hz: External field on z direction, default is 0.0 - :type hz: float - :param hx: External field on y direction, default is 0.0 - :type hx: float - :param hy: External field on x direction, default is 0.0 - :type hy: float - :param sparse: Whether to return sparse Hamiltonian operator, default is True. - :type sparse: bool, defalts True - :param numpy: whether return the matrix in numpy or tensorflow form - :type numpy: bool, defaults False, - - :return: Hamiltonian measurements - :rtype: Tensor - """ - n = len(g.nodes) - ls = [] - weight = [] - for e in g.edges: - if hzz != 0: - r = [0 for _ in range(n)] - r[e[0]] = 3 - r[e[1]] = 3 - ls.append(r) - weight.append(hzz) - if hxx != 0: - r = [0 for _ in range(n)] - r[e[0]] = 1 - r[e[1]] = 1 - ls.append(r) - weight.append(hxx) - if hyy != 0: - r = [0 for _ in range(n)] - r[e[0]] = 2 - r[e[1]] = 2 - ls.append(r) - weight.append(hyy) - for node in g.nodes: - if hz != 0: - r = [0 for _ in range(n)] - r[node] = 3 - ls.append(r) - weight.append(hz) - if hx != 0: - r = [0 for _ in range(n)] - r[node] = 1 - ls.append(r) - weight.append(hx) - if hy != 0: - r = [0 for _ in range(n)] - r[node] = 2 - ls.append(r) - weight.append(hy) - ls = tf.constant(ls) - weight = tf.constant(weight) - ls = get_backend("tensorflow").cast(ls, dtypestr) - weight = get_backend("tensorflow").cast(weight, dtypestr) - if sparse: - r = PauliStringSum2COO_numpy(ls, weight) - if numpy: - return r - return backend.coo_sparse_matrix_from_numpy(r) - return PauliStringSum2Dense(ls, weight, numpy=numpy) - - def PauliStringSum2Dense( - ls: Sequence[Sequence[int]], - weight: Optional[Sequence[float]] = None, - numpy: bool = False, - ) -> Tensor: - """ - Generate dense matrix from Pauli string sum. - Currently requires tensorflow installed. - - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :param numpy: default False. If True, return numpy coo - else return backend compatible sparse tensor - :type numpy: bool - :return: the tensorflow dense matrix - :rtype: Tensor - """ - sparsem = PauliStringSum2COO_numpy(ls, weight) - if numpy: - return sparsem.todense() - sparsem = backend.coo_sparse_matrix_from_numpy(sparsem) - densem = backend.to_dense(sparsem) - return densem - - # already implemented as backend method - # - # def _tf2numpy_sparse(a: Tensor) -> Tensor: - # return get_backend("numpy").coo_sparse_matrix( - # indices=a.indices, - # values=a.values, - # shape=a.get_shape(), - # ) - - # def _numpy2tf_sparse(a: Tensor) -> Tensor: - # return get_backend("tensorflow").coo_sparse_matrix( - # indices=np.array([a.row, a.col]).T, - # values=a.data, - # shape=a.shape, - # ) - - def PauliStringSum2COO( - ls: Sequence[Sequence[int]], - weight: Optional[Sequence[float]] = None, - numpy: bool = False, - ) -> Tensor: - """ - Generate sparse tensor from Pauli string sum. - Currently requires tensorflow installed - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :param numpy: default False. If True, return numpy coo - else return backend compatible sparse tensor - :type numpy: bool - :return: the scipy coo sparse matrix - :rtype: Tensor - """ - # numpy version is 3* faster! - - nterms = len(ls) - # n = len(ls[0]) - # s = 0b1 << n - if weight is None: - weight = [1.0 for _ in range(nterms)] - if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): - weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) - # rsparse = get_backend("numpy").coo_sparse_matrix( - # indices=np.array([[0, 0]], dtype=np.int64), - # values=np.array([0.0], dtype=getattr(np, dtypestr)), - # shape=(s, s), - # ) - rsparses = [ - get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore - for i in range(nterms) - ] - rsparse = _dc_sum(rsparses) - # auto transformed into csr format!! +PauliStringSum2COO_numpy = partial(PauliStringSum2COO, numpy=True) - # for i in range(nterms): - # rsparse += get_backend("tensorflow").numpy(PauliString2COO(ls[i], weight[i])) # type: ignore - rsparse = rsparse.tocoo() - if numpy: - return rsparse - return backend.coo_sparse_matrix_from_numpy(rsparse) - def _dc_sum(l: List[Any]) -> Any: - """ - For the sparse sum, the speed is determined by the non zero terms, - so the DC way to do the sum can indeed bring some speed advantage (several times) +def PauliStringSum2COO_tf( + ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None +) -> Tensor: + """ + Generate tensorflow sparse matrix from Pauli string sum + [deprecated] - :param l: _description_ - :type l: List[Any] - :return: _description_ - :rtype: Any - """ - n = len(l) - if n > 2: - return _dc_sum(l[: n // 2]) + _dc_sum(l[n // 2 :]) - else: - return sum(l) + :param ls: 2D Tensor, each row is for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type ls: Sequence[Sequence[int]] + :param weight: 1D Tensor, each element corresponds the weight for each Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[Sequence[float]], optional + :return: the tensorflow coo sparse matrix + :rtype: Tensor + """ + import tensorflow as tf - PauliStringSum2COO_numpy = partial(PauliStringSum2COO, numpy=True) + nterms = len(ls) + n = len(ls[0]) + s = 0b1 << n + if weight is None: + weight = [1.0 for _ in range(nterms)] + if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): + weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) + rsparse = tf.SparseTensor( + indices=tf.constant([[0, 0]], dtype=tf.int64), + values=tf.constant([0.0], dtype=weight.dtype), # type: ignore + dense_shape=(s, s), + ) + for i in range(nterms): + rsparse = tf.sparse.add(rsparse, PauliString2COO(ls[i], weight[i])) # type: ignore + # very slow sparse.add? + return rsparse - def PauliStringSum2COO_tf( - ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None - ) -> Tensor: - """ - Generate tensorflow sparse matrix from Pauli string sum - - :param ls: 2D Tensor, each row is for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type ls: Sequence[Sequence[int]] - :param weight: 1D Tensor, each element corresponds the weight for each Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[Sequence[float]], optional - :return: the tensorflow coo sparse matrix - :rtype: Tensor - """ - nterms = len(ls) - n = len(ls[0]) - s = 0b1 << n - if weight is None: - weight = [1.0 for _ in range(nterms)] - if not (isinstance(weight, tf.Tensor) or isinstance(weight, tf.Variable)): - weight = tf.constant(weight, dtype=getattr(tf, dtypestr)) - rsparse = tf.SparseTensor( - indices=tf.constant([[0, 0]], dtype=tf.int64), - values=tf.constant([0.0], dtype=weight.dtype), # type: ignore - dense_shape=(s, s), - ) - for i in range(nterms): - rsparse = tf.sparse.add(rsparse, PauliString2COO(ls[i], weight[i])) # type: ignore - # very slow sparse.add? - return rsparse - @compiled_jit - def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: - """ - Generate tensorflow sparse matrix from Pauli string sum - - :param l: 1D Tensor representing for a Pauli string, - e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` - :type l: Sequence[int] - :param weight: the weight for the Pauli string - defaults to None (all Pauli strings weight 1.0) - :type weight: Optional[float], optional - :return: the tensorflow sparse matrix - :rtype: Tensor - """ - n = len(l) - one = tf.constant(0b1, dtype=tf.int64) - idx_x = tf.constant(0b0, dtype=tf.int64) - idx_y = tf.constant(0b0, dtype=tf.int64) - idx_z = tf.constant(0b0, dtype=tf.int64) - i = tf.constant(0, dtype=tf.int64) - for j in l: - # i, j from enumerate is python, non jittable when cond using tensor - if j == 1: # xi - idx_x += tf.bitwise.left_shift(one, n - i - 1) - elif j == 2: # yi - idx_y += tf.bitwise.left_shift(one, n - i - 1) - elif j == 3: # zi - idx_z += tf.bitwise.left_shift(one, n - i - 1) - i += 1 - - if weight is None: - weight = tf.constant(1.0, dtype=tf.complex64) - return ps2coo_core(idx_x, idx_y, idx_z, weight, n) - - @compiled_jit - def ps2coo_core( - idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int - ) -> Tuple[Tensor, Tensor]: - dtype = weight.dtype - s = 0b1 << nqubits - idx1 = tf.cast(tf.range(s), dtype=tf.int64) - idx2 = (idx1 ^ idx_x) ^ (idx_y) - indices = tf.transpose(tf.stack([idx1, idx2])) - tmp = idx1 & (idx_y | idx_z) - e = idx1 * 0 - ny = 0 - for i in range(nqubits): - # if tmp[i] is power of 2 (non zero), then e[i] = 1 - e ^= tf.bitwise.right_shift(tmp, i) & 0b1 - # how many 1 contained in idx_y - ny += tf.bitwise.right_shift(idx_y, i) & 0b1 - ny = tf.math.mod(ny, 4) - values = ( - tf.cast((1 - 2 * e), dtype) - * tf.math.pow(tf.constant(-1.0j, dtype=dtype), tf.cast(ny, dtype)) - * weight - ) - return tf.SparseTensor(indices=indices, values=values, dense_shape=(s, s)) # type: ignore +def PauliString2COO(l: Sequence[int], weight: Optional[float] = None) -> Tensor: + """ + Generate sparse matrix from Pauli string sum -except (NameError, ImportError): - logger.info( - "tensorflow is not installed, and sparse Hamiltonian generation utilities are disabled" + :param l: 1D Tensor representing for a Pauli string, + e.g. [1, 0, 0, 3, 2] is for :math:`X_0Z_3Y_4` + :type l: Sequence[int] + :param weight: the weight for the Pauli string + defaults to None (all Pauli strings weight 1.0) + :type weight: Optional[float], optional + :return: the tensorflow sparse matrix + :rtype: Tensor + """ + n = len(l) + l = num_to_tensor(l, dtype="int64") + # l = backend.cast(l, dtype="int64") + one = num_to_tensor(0b1, dtype="int64") + idx_x = num_to_tensor(0b0, dtype="int64") + idx_y = num_to_tensor(0b0, dtype="int64") + idx_z = num_to_tensor(0b0, dtype="int64") + i = num_to_tensor(0, dtype="int64") + # for j in l: + for j in range(n): + oh = backend.onehot(l[j], 4) + s = backend.left_shift(one, n - i - 1) + oh = backend.cast(oh, dtype="int64") + idx_x += oh[1] * s + idx_y += oh[2] * s + idx_z += oh[3] * s + + # if j == 1: # xi + # idx_x += backend.left_shift(one, n - i - 1) + # elif j == 2: # yi + # idx_y += backend.left_shift(one, n - i - 1) + # elif j == 3: # zi + # idx_z += backend.left_shift(one, n - i - 1) + i += 1 + + if weight is None: + weight = num_to_tensor(1.0, dtype="complex64") + return ps2coo_core(idx_x, idx_y, idx_z, weight, n) + + +PauliString2COO_jit = {"numpy": PauliString2COO} + + +def ps2coo_core( + idx_x: Tensor, idx_y: Tensor, idx_z: Tensor, weight: Tensor, nqubits: int +) -> Tuple[Tensor, Tensor]: + s = 0b1 << nqubits + idx1 = num_to_tensor(backend.arange(s), dtype="int64") + idx2 = (idx1 ^ idx_x) ^ (idx_y) + indices = backend.transpose(backend.stack([idx1, idx2])) + tmp = idx1 & (idx_y | idx_z) + e = idx1 * 0 + ny = 0 + for i in range(nqubits): + # if tmp[i] is power of 2 (non zero), then e[i] = 1 + e ^= backend.right_shift(tmp, i) & 0b1 + # how many 1 contained in idx_y + ny += backend.right_shift(idx_y, i) & 0b1 + ny = backend.mod(ny, 4) + values = ( + num_to_tensor(1 - 2 * e) + * ((num_to_tensor(-1.0j) ** num_to_tensor(ny))) + * weight ) + return backend.coo_sparse_matrix(indices=indices, values=values, shape=(s, s)) # type: ignore + # some quantum quatities below @@ -1502,7 +1512,7 @@ def op2tensor( @op2tensor -def entropy(rho: Union[Tensor, QuOperator], eps: float = 1e-12) -> Tensor: +def entropy(rho: Union[Tensor, QuOperator], eps: Optional[float] = None) -> Tensor: """ Compute the entropy from the given density matrix ``rho``. @@ -1540,9 +1550,15 @@ def entanglement2(param, n, nlayers): :return: Entropy on the given density matrix. :rtype: Tensor """ + eps_env = os.environ.get("TC_QUANTUM_ENTROPY_EPS") + if eps is None and eps_env is None: + eps = 1e-12 + elif eps is None and eps_env is not None: + eps = 10 ** (-int(eps_env)) rho += eps * backend.cast(backend.eye(rho.shape[-1]), rho.dtype) # type: ignore lbd = backend.real(backend.eigh(rho)[0]) lbd = backend.relu(lbd) + lbd /= backend.sum(lbd) # we need the matrix anyway for AD. entropy = -backend.sum(lbd * backend.log(lbd + eps)) return backend.real(entropy) @@ -1580,10 +1596,56 @@ def trace_product(*o: Union[Tensor, QuOperator]) -> Tensor: return backend.trace(prod) +@op2tensor +def entanglement_entropy(state: Tensor, cut: Union[int, List[int]]) -> Tensor: + rho = reduced_density_matrix(state, cut) + return entropy(rho) + + +def reduced_wavefunction( + state: Tensor, cut: List[int], measure: Optional[List[int]] = None +) -> Tensor: + """ + Compute the reduced wavefunction from the quantum state ``state``. + The fixed measure result is guaranteed by users, + otherwise final normalization may required in the return + + :param state: _description_ + :type state: Tensor + :param cut: the list of position for qubit to be reduced + :type cut: List[int] + :param measure: the fixed results of given qubits in the same shape list as ``cut`` + :type measure: List[int] + :return: _description_ + :rtype: Tensor + """ + if measure is None: + measure = [0 for _ in cut] + s = backend.reshape2(state) + n = len(backend.shape_tuple(s)) + s_node = Gate(s) + end_nodes = [] + for c, m in zip(cut, measure): + rt = backend.cast(backend.convert_to_tensor(1 - m), dtypestr) * backend.cast( + backend.convert_to_tensor(np.array([1.0, 0.0])), dtypestr + ) + backend.cast(backend.convert_to_tensor(m), dtypestr) * backend.cast( + backend.convert_to_tensor(np.array([0.0, 1.0])), dtypestr + ) + end_node = Gate(rt) + end_nodes.append(end_node) + s_node[c] ^ end_node[0] + new_node = contractor( + [s_node] + end_nodes, + output_edge_order=[s_node[i] for i in range(n) if i not in cut], + ) + return backend.reshape(new_node.tensor, [-1]) + + def reduced_density_matrix( state: Union[Tensor, QuOperator], cut: Union[int, List[int]], p: Optional[Tensor] = None, + normalize: bool = True, ) -> Union[Tensor, QuOperator]: """ Compute the reduced density matrix from the quantum state ``state``. @@ -1597,6 +1659,7 @@ def reduced_density_matrix( :type p: Optional[Tensor] :return: The reduced density matrix. :rtype: Union[Tensor, QuOperator] + :normalize: if True, returns a trace 1 density matrix. Otherwise does not normalize. """ if isinstance(cut, list) or isinstance(cut, tuple) or isinstance(cut, set): traceout = list(cut) @@ -1639,7 +1702,9 @@ def reduced_density_matrix( rho = backend.reshape( rho, [2 ** (freedom - len(traceout)), 2 ** (freedom - len(traceout))] ) - rho /= backend.trace(rho) + if normalize: + rho /= backend.trace(rho) + else: w = state / backend.norm(state) @@ -1654,7 +1719,9 @@ def reduced_density_matrix( rho = w @ backend.adjoint(w) else: rho = w @ backend.diagflat(p) @ backend.adjoint(w) - rho /= backend.trace(rho) + if normalize: + rho /= backend.trace(rho) + return rho @@ -1789,6 +1856,76 @@ def truncated_free_energy( return energy - renyi / beta +@op2tensor +def partial_transpose(rho: Tensor, transposed_sites: List[int]) -> Tensor: + """ + _summary_ + + :param rho: density matrix + :type rho: Tensor + :param transposed_sites: sites int list to be transposed + :type transposed_sites: List[int] + :return: _description_ + :rtype: Tensor + """ + rho = backend.reshape2(rho) + rho_node = Gate(rho) + n = len(rho.shape) // 2 + left_edges = [] + right_edges = [] + for i in range(n): + if i not in transposed_sites: + left_edges.append(rho_node[i]) + right_edges.append(rho_node[i + n]) + else: + left_edges.append(rho_node[i + n]) + right_edges.append(rho_node[i]) + rhot_op = QuOperator(out_edges=left_edges, in_edges=right_edges) + rhot = rhot_op.eval_matrix() + return rhot + + +@op2tensor +def entanglement_negativity(rho: Tensor, transposed_sites: List[int]) -> Tensor: + """ + _summary_ + + :param rho: _description_ + :type rho: Tensor + :param transposed_sites: _description_ + :type transposed_sites: List[int] + :return: _description_ + :rtype: Tensor + """ + rhot = partial_transpose(rho, transposed_sites) + es = backend.eigvalsh(rhot) + rhot_m = backend.sum(backend.abs(es)) + return (backend.log(rhot_m) - 1.0) / 2.0 + + +@op2tensor +def log_negativity(rho: Tensor, transposed_sites: List[int], base: str = "e") -> Tensor: + """ + _summary_ + + :param rho: _description_ + :type rho: Tensor + :param transposed_sites: _description_ + :type transposed_sites: List[int] + :param base: whether use 2 based log or e based log, defaults to "e" + :type base: str, optional + :return: _description_ + :rtype: Tensor + """ + rhot = partial_transpose(rho, transposed_sites) + es = backend.eigvalsh(rhot) + rhot_m = backend.sum(backend.abs(es)) + een = backend.log(rhot_m) + if base in ["2", 2]: + return een / backend.cast(backend.log(2.0), rdtypestr) + return een + + @partial(op2tensor, op_argnums=(0, 1)) def trace_distance(rho: Tensor, rho0: Tensor, eps: float = 1e-12) -> Tensor: """ @@ -2033,7 +2170,10 @@ def count_vector2dict(count: Tensor, n: int, key: str = "bin") -> Dict[Any, int] :return: _description_ :rtype: _type_ """ - d = {i: backend.numpy(count[i]).item() for i in range(2**n)} + from .interfaces import which_backend + + b = which_backend(count) + d = {i: b.numpy(count[i]).item() for i in range(2**n)} if key == "int": return d else: diff --git a/tensorcircuit/results/counts.py b/tensorcircuit/results/counts.py index 78695734..a4800cc4 100644 --- a/tensorcircuit/results/counts.py +++ b/tensorcircuit/results/counts.py @@ -1,6 +1,7 @@ """ dict related functionalities """ + from typing import Any, Dict, Optional, Sequence import numpy as np @@ -9,6 +10,8 @@ Tensor = Any ct = Dict[str, int] +# TODO(@refraction-ray): merge_count + def reverse_count(count: ct) -> ct: ncount = {} @@ -109,6 +112,8 @@ def plot_histogram(data: Any, **kws: Any) -> Any: See ``qiskit.visualization.plot_histogram``: https://qiskit.org/documentation/stubs/qiskit.visualization.plot_histogram.html + interesting kw options include: ``number_to_keep`` (int) + :param data: _description_ :type data: Any :return: _description_ @@ -116,4 +121,4 @@ def plot_histogram(data: Any, **kws: Any) -> Any: """ from qiskit.visualization import plot_histogram - return plot_histogram(data) + return plot_histogram(data, **kws) diff --git a/tensorcircuit/results/qem/__init__.py b/tensorcircuit/results/qem/__init__.py new file mode 100644 index 00000000..c895d370 --- /dev/null +++ b/tensorcircuit/results/qem/__init__.py @@ -0,0 +1,14 @@ +from . import qem_methods + +apply_zne = qem_methods.apply_zne +zne_option = qem_methods.zne_option # type: ignore + +apply_dd = qem_methods.apply_dd +dd_option = qem_methods.dd_option # type: ignore +used_qubits = qem_methods.used_qubits +prune_ddcircuit = qem_methods.prune_ddcircuit +add_dd = qem_methods.add_dd + +apply_rc = qem_methods.apply_rc +rc_circuit = qem_methods.rc_circuit +rc_candidates = qem_methods.rc_candidates diff --git a/tensorcircuit/results/qem/benchmark_circuits.py b/tensorcircuit/results/qem/benchmark_circuits.py new file mode 100644 index 00000000..368cc828 --- /dev/null +++ b/tensorcircuit/results/qem/benchmark_circuits.py @@ -0,0 +1,107 @@ +""" +circuits for quantum chip benchmark +""" + +from typing import Any, List, Dict, Tuple +import logging + +logger = logging.getLogger(__name__) + +import networkx as nx + +try: + from mitiq.benchmarks import ( + generate_ghz_circuit, + generate_mirror_circuit, + generate_rb_circuits, + generate_w_circuit, + ) + from mitiq.interface import convert_from_mitiq +except ModuleNotFoundError: + logger.warning("mitiq is not installed, please ``pip install mitiq`` first") + + +from ... import Circuit + + +def ghz_circuit(num_qubits: int) -> Tuple[Any, Dict[str, float]]: + cirq = generate_ghz_circuit(num_qubits) + ideal = {"0" * num_qubits: 0.5, "1" * num_qubits: 0.5} + qisc = convert_from_mitiq(cirq, "qiskit") + circuit = Circuit.from_qiskit(qisc, qisc.num_qubits) + return circuit, ideal + + +def w_circuit(num_qubits: int) -> Tuple[Any, Dict[str, float]]: + # Efficient quantum algorithms for GHZ and W states https://arxiv.org/abs/1807.05572 + # Werner-state with linear complexity {'1000': 0.25, '0100': 0.25, '0010': 0.25, '0001': 0.25} + cirq = generate_w_circuit(num_qubits) + + ideal = {} + for i in range(num_qubits): + bitstring = "0" * i + "1" + "0" * (num_qubits - i - 1) + ideal[bitstring] = 1 / num_qubits + + qisc = convert_from_mitiq(cirq, "qiskit") + circuit = Circuit.from_qiskit(qisc, qisc.num_qubits) + return circuit, ideal + + +def rb_circuit(num_qubits: int, depth: int) -> Tuple[Any, Dict[str, float]]: + # num_qubits limited to 1 or 2 + cirq = generate_rb_circuits(num_qubits, depth)[0] + ideal = {"0" * num_qubits: 1.0} + qisc = convert_from_mitiq(cirq, "qiskit") + circuit = Circuit.from_qiskit(qisc, qisc.num_qubits) + return circuit, ideal + + +def mirror_circuit( + depth: int, + two_qubit_gate_prob: float, + connectivity_graph: nx.Graph, + seed: int, + two_qubit_gate_name: str = "CNOT", +) -> Tuple[Any, Dict[str, float]]: + # Measuring the Capabilities of Quantum Computers https://arxiv.org/pdf/2008.11294.pdf + cirq, bitstring_list = generate_mirror_circuit( + nlayers=depth, + two_qubit_gate_prob=two_qubit_gate_prob, + connectivity_graph=connectivity_graph, + two_qubit_gate_name=two_qubit_gate_name, + seed=seed, + ) + ideal_bitstring = "".join(map(str, bitstring_list)) + ideal = {ideal_bitstring: 1.0} + qisc = convert_from_mitiq(cirq, "qiskit") + circuit = Circuit.from_qiskit(qisc, qisc.num_qubits) + return circuit, ideal + + +def QAOA_circuit( + graph: List[Tuple[int]], weight: List[float], params: List[float] +) -> Any: # internal API don't use + nlayers = len(params) + + qlist = [] + for i in range(len(graph)): + for j in range(2): + qlist.append(graph[i][j]) + qlist = list(set(qlist)) + + nqubit = max(qlist) + 1 + + c = Circuit(nqubit) + for i in qlist: + c.h(i) # type: ignore + + for i in range(nlayers): + for e in range(len(graph)): + c.cnot(graph[e][0], graph[e][1]) # type: ignore + c.rz(graph[e][1], theta=params[i, 0] * weight[e]) # type: ignore + c.cnot(graph[e][0], graph[e][1]) # type: ignore + + for k in qlist: + c.rx(k, theta=params[i, 1] * 2) # type: ignore + + return c diff --git a/tensorcircuit/results/qem/qem_methods.py b/tensorcircuit/results/qem/qem_methods.py new file mode 100644 index 00000000..68199e49 --- /dev/null +++ b/tensorcircuit/results/qem/qem_methods.py @@ -0,0 +1,383 @@ +""" +quantum error mitigation functionalities +""" + +from typing import Any, List, Union, Optional, Dict, Tuple, Callable, Sequence +from itertools import product +import functools +from functools import partial +import collections +import operator +from random import choice +import logging + +logger = logging.getLogger(__name__) + +import numpy as np + +try: + from mitiq import zne, ddd + from mitiq.zne.scaling import fold_gates_at_random + + zne_option = zne + dd_option = ddd +except ModuleNotFoundError: + logger.warning("mitiq is not installed, please ``pip install mitiq`` first") + zne_option = None + dd_option = None + +from ... import Circuit +from ... import backend, gates +from ...compiler import simple_compiler + +Gate = gates.Gate + + +def apply_zne( + circuit: Any, + executor: Callable[[Union[Any, Sequence[Any]]], Any], + factory: Optional[Any], + scale_noise: Optional[Callable[[Any, float], Any]] = None, + num_to_average: int = 1, + **kws: Any, +) -> Any: + """ + Apply zero-noise extrapolation (ZNE) and return the mitigated results. + + :param circuit: The aim circuit. + :type circuit: Any + :param executor: A executor that executes a single circuit or a batch of circuits and return results. + :type executor: Callable[[Union[Any, Sequence[Any]]], Any] + :param factory: Determines the extropolation method. + :type factory: Optional[Factory] + :param scale_noise: The scaling function for the aim circuit, defaults to fold_gates_at_random + :type scale_noise: Callable[[Any, float], Any], optional + :param num_to_average: Number of times expectation values are computed by + the executor, average each point, defaults to 1. + :type num_to_average: int, optional + :return: Mitigated average value by ZNE. + :rtype: float + """ + if scale_noise is None: + scale_noise = fold_gates_at_random + + def executortc(c): # type: ignore + c = Circuit.from_qiskit(c, c.num_qubits) + return executor(c) + + circuit = circuit.to_qiskit(enable_instruction=True) + result = zne.execute_with_zne( + circuit=circuit, + executor=executortc, + factory=factory, + scale_noise=scale_noise, + num_to_average=num_to_average, + **kws, + ) + return result + + +def prune_ddcircuit(c: Any, qlist: List[int]) -> Any: + """ + Discard DD sequence on idle qubits and Discard identity gate + (no identity/idle gate on device now) filled in DD sequence. + + :param c: circuit + :type c: Any + :param qlist: qubit list to apply DD sequence + :type qlist: list + :return: new circuit + :rtype: Any + """ + qir = c.to_qir() + cnew = Circuit(c.circuit_param["nqubits"]) + for d in qir: + if d["index"][0] in qlist: + if_iden = np.sum(abs(np.array([[1, 0], [0, 1]]) - d["gate"].get_tensor())) + if if_iden > 1e-4: + if "parameters" not in d: + cnew.apply_general_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"] + ) + else: + cnew.apply_general_variable_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"], **d["parameters"] + ) + return cnew + + +def used_qubits(c: Any) -> List[int]: + """ + Create a qubit list that includes all qubits having gate manipulation. + + :param c: a circuit + :type c: Any + :return: qubit list + :rtype: List + """ + qir = c.to_qir() + qlist = [] + for d in qir: + for i in range(len(d["index"])): + if d["index"][i] not in qlist: + qlist.append(d["index"][i]) + return qlist + + +def add_dd(c: Any, rule: Callable[[int], Any]) -> Any: + """ + Add DD sequence to A circuit + + :param c: circuit + :type c: Any + :param rule: The rule to conduct the DD sequence + :type rule: Callable[[int], Any] + :return: new circuit + :rtype: Any + """ + nqubit = c.circuit_param["nqubits"] + input_circuit = c.to_qiskit() + circuit_dd = dd_option.insert_ddd_sequences(input_circuit, rule=rule) + circuit_dd = Circuit.from_qiskit(circuit_dd, nqubit) + return circuit_dd + + +def apply_dd( + circuit: Any, + executor: Callable[[Any], Any], + rule: Union[Callable[[int], Any], List[str]], + rule_args: Optional[Dict[str, Any]] = None, + num_trials: int = 1, + full_output: bool = False, + ignore_idle_qubit: bool = True, + fulldd: bool = False, + iscount: bool = False, +) -> Union[ + float, Tuple[float, List[Any]], Dict[str, float], Tuple[Dict[str, float], List[Any]] +]: + """ + Apply dynamic decoupling (DD) and return the mitigated results. + + + :param circuit: The aim circuit. + :type circuit: Any + :param executor: A executor that executes a circuit and return results. + :type executor: Callable[[Any], Any] + :param rule: The rule to construct DD sequence, can use default rule "dd_option.rules.xx" + or custom rule "['X','X']" + :type rule: Union[Callable[[int], Any], List[str]] + :param rule_args:An optional dictionary of keyword arguments for ``rule``, defaults to {}. + :type rule_args: Dict[str, Any], optional + :param num_trials: The number of independent experiments to average over, defaults to 1 + :type num_trials: int, optional + :param full_output: If ``False`` only the mitigated expectation value is + returned. If ``True`` a dictionary containing all DD data is + returned too, defaults to False + :type full_output: bool, optional + :param ig_idle_qubit: ignore the DD sequences that added to unused qubits, defaults to True + :type ig_idle_qubit: bool, optional + :param fulldd: dd sequence full fill the idle circuits, defaults to False + :type fulldd: bool, optional + :param iscount: whether the output is bit string, defaults to False + :type iscount: bool, optional + :return: mitigated expectation value or mitigated expectation value and DD circuit information + :rtype: Union[float, Tuple[float, Dict[str, Any]]] + """ + if rule_args is None: + rule_args = {} + + def dd_rule(slack_length: int, spacing: int = -1) -> Any: + """ + Set DD rule. + + :param slack_length: Length of idle window to fill. Automatically calculated for a circuit. + :type slack_length: int + :param spacing: How many identity spacing gates to apply between dynamical + decoupling gates, defaults to -1 + :type spacing: int, optional + """ + dd_sequence = dd_option.rules.general_rule( + slack_length=slack_length, + spacing=spacing, + gates=gates, + ) + return dd_sequence + + if isinstance(rule, list): + import cirq + + gates = [] + for i in rule: + gates.append(getattr(cirq, i)) + rule = dd_rule + + if ignore_idle_qubit is True: + qlist = used_qubits(circuit) + else: + qlist = list(range(circuit.circuit_param["nqubits"])) + + rule_partial = partial( + rule, **rule_args + ) # rule_args influence the finall DD sequence + c2 = circuit + c3 = add_dd(c2, rule_partial) + c3 = prune_ddcircuit(c3, qlist) + if fulldd is True: + while c2.to_openqasm() != c3.to_openqasm(): + c2 = c3 + c3 = add_dd(c2, rule_partial) + c3 = prune_ddcircuit(c3, qlist) + + exp = [] + for i in range(num_trials): # type: ignore + exp.append(executor(c3)) + + if iscount is True: + sumcount = dict( + functools.reduce(operator.add, map(collections.Counter, exp)) # type:ignore + ) # type:ignore + result = {k: sumcount[k] / num_trials for k in sumcount.keys()} + else: + result = np.mean(exp) # type:ignore + + if full_output is True: + result = [result, c3] # type:ignore + + # def executortc(c): + # c = Circuit.from_qiskit(c, c.num_qubits) + # c = prune_ddcircuit(c,qlist) + # return executor(c) + # circuit = circuit.to_qiskit() + # result = ddd.execute_with_ddd( + # circuit=circuit, + # executor=executortc, + # rule=rule, + # rule_args=rule_args, + # num_trials=num_trials, + # full_output=full_output, + # ) + + return result # type:ignore + + +def rc_candidates(gate: Gate) -> List[Any]: + pauli = [m.tensor for m in gates.pauli_gates] + if isinstance(gate, gates.Gate): + gate = gate.tensor + gatem = backend.reshapem(gate) + r = [] + for combo in product(*[range(4) for _ in range(4)]): + i = ( + np.kron(pauli[combo[0]], pauli[combo[1]]) + @ gatem + @ np.kron(pauli[combo[2]], pauli[combo[3]]) + ) + if np.allclose(i, gatem, atol=1e-4): + r.append(combo) + elif np.allclose(i, -gatem, atol=1e-4): + r.append(combo) + return r + + +def _apply_gate(c: Any, i: int, j: int) -> Any: + if i == 0: + c.i(j) + elif i == 1: + c.x(j) + elif i == 2: + c.y(j) + elif i == 3: + c.z(j) + return c + + +candidate_dict = {} # type: ignore + + +def rc_circuit(c: Any) -> Any: + qir = c.to_qir() + cnew = Circuit(c.circuit_param["nqubits"]) + for d in qir: + if len(d["index"]) == 2: + if d["gate"].name in candidate_dict: + rc_cand = candidate_dict[d["gate"].name] + rc_list = choice(rc_cand) + else: + rc_cand = rc_candidates(d["gate"]) + rc_list = choice(rc_cand) + candidate_dict[d["gate"].name] = rc_cand + + cnew = _apply_gate(cnew, rc_list[0], d["index"][0]) + cnew = _apply_gate(cnew, rc_list[1], d["index"][1]) + if "parameters" not in d: + cnew.apply_general_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"] + ) + else: + cnew.apply_general_variable_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"], **d["parameters"] + ) + cnew = _apply_gate(cnew, rc_list[2], d["index"][0]) + cnew = _apply_gate(cnew, rc_list[3], d["index"][1]) + else: + if "parameters" not in d: + cnew.apply_general_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"] + ) + else: + cnew.apply_general_variable_gate_delayed(d["gatef"], d["name"])( + cnew, *d["index"], **d["parameters"] + ) + return cnew + + +def apply_rc( + circuit: Any, + executor: Callable[[Any], Any], + num_to_average: int = 1, + simplify: bool = True, + iscount: bool = False, + **kws: Any, +) -> Tuple[float, List[Any]]: + """ + Apply Randomized Compiling or Pauli twirling on two-qubit gates. + + :param circuit: Input circuit + :type circuit: Any + :param executor: A executor that executes a circuit and return results. + :type executor: Callable[[Any], Any] + :param num_to_average: Number of circuits for RC, defaults to 1 + :type num_to_average: int, optional + :param simplify: Whether simplify the circuits by merging single qubit gates, defaults to True + :type simplify: bool, optional + :param iscount: whether the output is bit string, defaults to False + :type iscount: bool, optional + :return: Mitigated results by RC + :rtype: float + """ + exp = [] + circuit_list = [] + for _ in range(num_to_average): + circuit1 = rc_circuit(circuit) + + if simplify is True: + circuit1 = prune_ddcircuit( + circuit1, qlist=list(range(circuit1.circuit_param["nqubits"])) + ) + circuit1 = simple_compiler.merge(circuit1) + + exp.append(executor(circuit1)) + circuit_list.append(circuit1) + + if iscount is True: + sumcount = dict( + functools.reduce(operator.add, map(collections.Counter, exp)) # type:ignore + ) # type:ignore + result = {k: sumcount[k] / num_to_average for k in sumcount.keys()} + else: + result = np.mean(exp) # type:ignore + + return result, circuit_list # type:ignore + + +# TODO(yuqinchen) add executor with batch ability diff --git a/tensorcircuit/results/readout_mitigation.py b/tensorcircuit/results/readout_mitigation.py index ef205800..d701dcc1 100644 --- a/tensorcircuit/results/readout_mitigation.py +++ b/tensorcircuit/results/readout_mitigation.py @@ -1,6 +1,7 @@ """ readout error mitigation functionalities """ + # Part of the code in this file is from mthree: https://github.com/Qiskit-Partners/mthree (Apache2) # https://journals.aps.org/prxquantum/pdf/10.1103/PRXQuantum.2.040326 @@ -811,9 +812,11 @@ def expectation( ] else: diagonal_op = [ - [1, -1] @ inv_single_qubit_cals[i] - if i in z1 - else [1, 1] @ inv_single_qubit_cals[i] + ( + [1, -1] @ inv_single_qubit_cals[i] + if i in z1 + else [1, 1] @ inv_single_qubit_cals[i] + ) for i in range(n) ] diff --git a/tensorcircuit/shadows.py b/tensorcircuit/shadows.py new file mode 100644 index 00000000..63cad7f6 --- /dev/null +++ b/tensorcircuit/shadows.py @@ -0,0 +1,485 @@ +""" +Classical shadows functions +""" + +from typing import Any, Union, Optional, Sequence, Tuple, List +from string import ascii_letters as ABC + +import numpy as np + +from .cons import backend, dtypestr, rdtypestr +from .circuit import Circuit + +Tensor = Any + + +def shadow_bound( + observables: Union[Tensor, Sequence[int]], epsilon: float, delta: float = 0.01 +) -> Tuple[int, int]: + r"""Calculate the shadow bound of the Pauli observables, please refer to the Theorem S1 and Lemma S3 in + Huang, H.-Y., R. Kueng, and J. Preskill, 2020, Nat. Phys. 16, 1050. + + :param observables: shape = (nq,) or (M, nq), where nq is the number of qubits, M is the number of observables + :type: Union[Tensor, Sequence[int]] + :param epsilon: error on the estimator + :type: float + :param delta: rate of failure for the bound to hold + :type: float + + :return Nk: number of snapshots + :rtype: int + :return k: number of equal parts to split the shadow snapshot states to compute the median of means. + k=1 (default) corresponds to simply taking the mean over all shadow snapshot states. + :rtype: int + """ + count = np.sign(np.asarray(observables)) + if len(count.shape) == 1: + count = count[None, :] + M = count.shape[0] + k = np.ceil(2 * np.log(2 * M / delta)) + max_length = np.max(np.sum(count, axis=1)) + N = np.ceil((34 / epsilon**2) * 3**max_length) + return int(N * k), int(k) + + +def shadow_snapshots( + psi: Tensor, + pauli_strings: Tensor, + status: Optional[Tensor] = None, + sub: Optional[Sequence[int]] = None, + measurement_only: bool = False, +) -> Tensor: + r"""To generate the shadow snapshots from given pauli string observables on psi + + :param psi: shape = (2 ** nq,), where nq is the number of qubits + :type: Tensor + :param pauli_strings: shape = (ns, nq), where ns is the number of pauli strings + :type: Tensor + :param status: shape = None or (ns, repeat), where repeat is the times to measure on one pauli string + :type: Optional[Tensor] + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + :param measurement_only: return snapshots (True) or snapshot states (False), default=False + :type: bool + + :return snapshots: shape = (ns, repeat, nq) if measurement_only=True otherwise (ns, repeat, nq, 2, 2) + :rtype: Tensor + """ + pauli_strings = backend.cast(pauli_strings, dtype="int32") - 1 + ns, nq = pauli_strings.shape + if 2**nq != len(psi): + raise ValueError( + f"The number of qubits of psi and pauli_strings should be the same, " + f"but got {nq} and {int(np.log2(len(psi)))}." + ) + if status is None: + status = backend.convert_to_tensor(np.random.rand(ns, 1)) + elif status.shape[0] != ns: + raise ValueError(f"status.shape[0] should be {ns}, but got {status.shape[0]}.") + status = backend.cast(status, dtype=rdtypestr) + repeat = status.shape[1] + + angles = backend.cast( + backend.convert_to_tensor( + [ + [-np.pi / 2, np.pi / 4, 0], + [np.pi / 4, np.pi / 2, 0], + [0, 0, 0], + ] + ), + dtype=rdtypestr, + ) # (3, 3) + + def proj_measure(pauli_string: Tensor, st: Tensor) -> Tensor: + c_ = Circuit(nq, inputs=psi) + for i in range(nq): + c_.r( # type: ignore + i, + theta=backend.gather1d( + backend.gather1d(angles, backend.gather1d(pauli_string, i)), 0 + ), + alpha=backend.gather1d( + backend.gather1d(angles, backend.gather1d(pauli_string, i)), 1 + ), + phi=backend.gather1d( + backend.gather1d(angles, backend.gather1d(pauli_string, i)), 2 + ), + ) + return c_.sample(batch=repeat, format="sample_bin", allow_state=True, status=st) + + vpm = backend.vmap(proj_measure, vectorized_argnums=(0, 1)) + snapshots = vpm(pauli_strings, status) # (ns, repeat, nq) + if measurement_only: + return snapshots if sub is None else slice_sub(snapshots, sub) + else: + return local_snapshot_states(snapshots, pauli_strings + 1, sub) + + +def local_snapshot_states( + snapshots: Tensor, pauli_strings: Tensor, sub: Optional[Sequence[int]] = None +) -> Tensor: + r"""To generate the local snapshots states from snapshots and pauli strings + + :param snapshots: shape = (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = (ns, nq) or (ns, repeat, nq) + :type: Tensor + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + + :return lss_states: shape = (ns, repeat, nq, 2, 2) + :rtype: Tensor + """ + pauli_strings = backend.cast(pauli_strings, dtype="int32") - 1 + if len(pauli_strings.shape) < len(snapshots.shape): + pauli_strings = backend.tile( + pauli_strings[:, None, :], (1, snapshots.shape[1], 1) + ) # (ns, repeat, nq) + + X_dm = backend.cast( + backend.convert_to_tensor([[[1, 1], [1, 1]], [[1, -1], [-1, 1]]]) / 2, + dtype=dtypestr, + ) + Y_dm = backend.cast( + backend.convert_to_tensor( + np.array([[[1, -1j], [1j, 1]], [[1, 1j], [-1j, 1]]]) / 2 + ), + dtype=dtypestr, + ) + Z_dm = backend.cast( + backend.convert_to_tensor([[[1, 0], [0, 0]], [[0, 0], [0, 1]]]), dtype=dtypestr + ) + pauli_dm = backend.stack((X_dm, Y_dm, Z_dm), axis=0) # (3, 2, 2, 2) + + def dm(p: Tensor, s: Tensor) -> Tensor: + return backend.gather1d(backend.gather1d(pauli_dm, p), s) + + v = backend.vmap(dm, vectorized_argnums=(0, 1)) + vv = backend.vmap(v, vectorized_argnums=(0, 1)) + vvv = backend.vmap(vv, vectorized_argnums=(0, 1)) + + lss_states = vvv(pauli_strings, snapshots) + if sub is not None: + lss_states = slice_sub(lss_states, sub) + return 3 * lss_states - backend.eye(2)[None, None, None, :, :] + + +def global_shadow_state( + snapshots: Tensor, + pauli_strings: Optional[Tensor] = None, + sub: Optional[Sequence[int]] = None, +) -> Tensor: + r"""To generate the global shadow state from local snapshot states or snapshots and pauli strings + + :param snapshots: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = None or (ns, nq) or (ns, repeat, nq) + :type: Optional[Tensor] + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + + :return gsdw_state: shape = (2 ** nq, 2 ** nq) + :rtype: Tensor + """ + if pauli_strings is not None: + if len(snapshots.shape) != 3: + raise ValueError( + f"snapshots should be 3-d if pauli_strings is not None, got {len(snapshots.shape)}-d instead." + ) + lss_states = local_snapshot_states( + snapshots, pauli_strings, sub + ) # (ns, repeat, nq_sub, 2, 2) + else: + if sub is not None: + lss_states = slice_sub(snapshots, sub) + else: + lss_states = snapshots # (ns, repeat, nq, 2, 2) + + nq = lss_states.shape[2] + + def tensor_prod(dms: Tensor) -> Tensor: + res = backend.gather1d(dms, 0) + for i in range(1, nq): + res = backend.kron(res, backend.gather1d(dms, i)) + return res + + v = backend.vmap(tensor_prod, vectorized_argnums=0) + vv = backend.vmap(v, vectorized_argnums=0) + gss_states = vv(lss_states) + return backend.mean(gss_states, axis=(0, 1)) + + +def expectation_ps_shadow( + snapshots: Tensor, + pauli_strings: Optional[Tensor] = None, + x: Optional[Sequence[int]] = None, + y: Optional[Sequence[int]] = None, + z: Optional[Sequence[int]] = None, + ps: Optional[Sequence[int]] = None, + k: int = 1, +) -> List[Tensor]: + r"""To calculate the expectation value of an observable on shadow snapshot states + + :param snapshots: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = None or (ns, nq) or (ns, repeat, nq) + :type: Optional[Tensor] + :param x: sites to apply X gate, defaults to None + :type: Optional[Sequence[int]] + :param y: sites to apply Y gate, defaults to None + :type: Optional[Sequence[int]] + :param z: sites to apply Z gate, defaults to None + :type: Optional[Sequence[int]] + :param ps: or one can apply a ps structures instead of x, y, z, e.g. [1, 1, 0, 2, 3, 0] for X_0X_1Y_3Z_4 + defaults to None, ps can overwrite x, y and z + :type: Optional[Sequence[int]] + :param k: Number of equal parts to split the shadow snapshot states to compute the median of means. + k=1 (default) corresponds to simply taking the mean over all shadow snapshot states. + :type: int + + :return expectation values: shape = (k,) + :rtype: List[Tensor] + """ + if pauli_strings is not None: + if len(snapshots.shape) != 3: + raise ValueError( + f"snapshots should be 3-d if pauli_strings is not None, got {len(snapshots.shape)}-d instead." + ) + lss_states = local_snapshot_states( + snapshots, pauli_strings + ) # (ns, repeat, nq, 2, 2) + else: + lss_states = snapshots # (ns, repeat, nq, 2, 2) + ns, repeat, nq, _, _ = lss_states.shape + ns *= repeat + ss_states = backend.reshape(lss_states, (ns, nq, 2, 2)) + + if ps is None: + ps = [0] * nq + if x is not None: + for i in x: + ps[i] = 1 + if y is not None: + for i in y: + ps[i] = 2 + if z is not None: + for i in z: + ps[i] = 3 + elif len(ps) != nq: + raise ValueError( + f"The number of qubits of the shadow state is {nq}, but got a {len(ps)}-qubit pauli string observable." + ) + ps = backend.cast(backend.convert_to_tensor(ps), dtype="int32") # (nq,) + + paulis = backend.convert_to_tensor( + backend.cast( + np.array( + [ + [[1, 0], [0, 1]], + [[0, 1], [1, 0]], + [[0, -1j], [1j, 0]], + [[1, 0], [0, -1]], + ] + ), + dtype=dtypestr, + ) + ) # (4, 2, 2) + + def trace_paulis_prod(dm: Tensor, idx: Tensor) -> Tensor: + return backend.real(backend.trace(backend.gather1d(paulis, idx) @ dm)) + + v = backend.vmap(trace_paulis_prod, vectorized_argnums=(0, 1)) # (nq,) + + def prod(dm: Tensor) -> Tensor: + return backend.shape_prod(v(dm, ps)) + + vv = backend.vmap(prod, vectorized_argnums=0) # (ns,) + + batch = int(np.ceil(ns / k)) + return [backend.mean(vv(ss_states[i : i + batch])) for i in range(0, ns, batch)] + + +def entropy_shadow( + snapshots: Tensor, + pauli_strings: Optional[Tensor] = None, + sub: Optional[Sequence[int]] = None, + alpha: int = 2, +) -> Tensor: + r"""To calculate the Renyi entropy of a subsystem from shadow state or shadow snapshot states + + :param snapshots: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = None or (ns, nq) or (ns, repeat, nq) + :type: Optional[Tensor] + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + :param alpha: order of the Renyi entropy, alpha=1 corresponds to the von Neumann entropy + :type: int + + :return Renyi entropy: shape = () + :rtype: Tensor + """ + if alpha <= 0: + raise ValueError("Alpha should not be less than 1!") + + sdw_rdm = global_shadow_state(snapshots, pauli_strings, sub) # (2 ** nq, 2 ** nq) + + evs = backend.relu(backend.real(backend.eigvalsh(sdw_rdm))) + evs /= backend.sum(evs) + if alpha == 1: + return -backend.sum(evs * backend.log(evs + 1e-12)) + else: + return backend.log(backend.sum(backend.power(evs, alpha))) / (1 - alpha) + + +def renyi_entropy_2(snapshots: Tensor, sub: Optional[Sequence[int]] = None) -> Tensor: + r"""To calculate the second order Renyi entropy of a subsystem from snapshot, please refer to + Brydges, T. et al. Science 364, 260–263 (2019). This function is not jitable. + + :param snapshots: shape = (ns, repeat, nq) + :type: Tensor + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + + :return second order Renyi entropy: shape = () + :rtype: Tensor + """ + if sub is not None: + snapshots = slice_sub(snapshots, sub) + snapshots = backend.cast(snapshots, dtype="int32") + ns, repeat, nq = snapshots.shape + + count = {} + for i, ss in enumerate(snapshots): + for s in ss: + s = tuple(backend.numpy(s)) + if s not in count: + count[s] = np.zeros(ns) + count[s][i] += 1 + + tr = 0.0 + for x in count: + for y in count: + h = np.sum((np.asarray(x) + np.asarray(y)) % 2) + pp_mean = np.mean(count[x] * count[y]) / repeat / repeat + tr += pp_mean * (-2.0) ** (-h) + return -np.log(tr * 2**nq) + + +def global_shadow_state1( + snapshots: Tensor, + pauli_strings: Optional[Tensor] = None, + sub: Optional[Sequence[int]] = None, +) -> Tensor: + r"""To generate the global snapshots states from local snapshot states or snapshots and pauli strings + + :param snapshots: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = None or (ns, nq) or (ns, repeat, nq) + :type: Optional[Tensor] + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + + :return gsdw_state: shape = (2 ** nq, 2 ** nq) + :rtype: Tensor + """ + if pauli_strings is not None: + if len(snapshots.shape) != 3: + raise ValueError( + f"snapshots should be 3-d if pauli_strings is not None, got {len(snapshots.shape)}-d instead." + ) + lss_states = local_snapshot_states( + snapshots, pauli_strings, sub + ) # (ns, repeat, nq_sub, 2, 2) + else: + if sub is not None: + lss_states = slice_sub(snapshots, sub) + else: + lss_states = snapshots # (ns, repeat, nq, 2, 2) + lss_states = backend.transpose( + lss_states, (2, 0, 1, 3, 4) + ) # (nq, ns, repeat, 2, 2) + nq, ns, repeat, _, _ = lss_states.shape + + old_indices = [f"ab{ABC[2 + 2 * i: 4 + 2 * i]}" for i in range(nq)] + new_indices = f"ab{ABC[2:2 * nq + 2:2]}{ABC[3:2 * nq + 2:2]}" + + gss_states = backend.reshape( + backend.einsum( + f'{",".join(old_indices)}->{new_indices}', *lss_states, optimize=True + ), + (ns, repeat, 2**nq, 2**nq), + ) + return backend.mean(gss_states, axis=(0, 1)) + + +def global_shadow_state2( + snapshots: Tensor, + pauli_strings: Optional[Tensor] = None, + sub: Optional[Sequence[int]] = None, +) -> Tensor: + r"""To generate the global snapshots states from local snapshot states or snapshots and pauli strings + + :param snapshots: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param pauli_strings: shape = None or (ns, nq) or (ns, repeat, nq) + :type: Optional[Tensor] + :param sub: qubit indices of subsystem + :type: Optional[Sequence[int]] + + :return gsdw_state: shape = (2 ** nq, 2 ** nq) + :rtype: Tensor + """ + if pauli_strings is not None: + if len(snapshots.shape) != 3: + raise ValueError( + f"snapshots should be 3-d if pauli_strings is not None, got {len(snapshots.shape)}-d instead." + ) + lss_states = local_snapshot_states( + snapshots, pauli_strings, sub + ) # (ns, repeat, nq_sub, 2, 2) + else: + if sub is not None: + lss_states = slice_sub(snapshots, sub) + else: + lss_states = snapshots # (ns, repeat, nq, 2, 2) + nq = lss_states.shape[2] + + old_indices = [f"{ABC[2 * i: 2 + 2 * i]}" for i in range(nq)] + new_indices = f"{ABC[0:2 * nq:2]}{ABC[1:2 * nq:2]}" + + def tensor_prod(dms: Tensor) -> Tensor: + return backend.reshape( + backend.einsum( + f'{",".join(old_indices)}->{new_indices}', *dms, optimize=True + ), + (2**nq, 2**nq), + ) + + v = backend.vmap(tensor_prod, vectorized_argnums=0) + vv = backend.vmap(v, vectorized_argnums=0) + gss_states = vv(lss_states) + return backend.mean(gss_states, axis=(0, 1)) + + +def slice_sub(entirety: Tensor, sub: Sequence[int]) -> Tensor: + r"""To slice off the subsystem + + :param entirety: shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq) + :type: Tensor + :param sub: qubit indices of subsystem + :type: Sequence[int] + + :return subsystem: shape = (ns, repeat, nq_sub, 2, 2) + :rtype: Tensor + """ + if len(entirety.shape) < 3: + entirety = entirety[:, None, :] + + def slc(x: Tensor, idx: Tensor) -> Tensor: + return backend.gather1d(x, idx) + + v = backend.vmap(slc, vectorized_argnums=(1,)) + vv = backend.vmap(v, vectorized_argnums=(0,)) + vvv = backend.vmap(vv, vectorized_argnums=(0,)) + return vvv(entirety, backend.convert_to_tensor(sub)) diff --git a/tensorcircuit/simplify.py b/tensorcircuit/simplify.py index 6123c8dd..1cbcfc6a 100644 --- a/tensorcircuit/simplify.py +++ b/tensorcircuit/simplify.py @@ -1,6 +1,7 @@ """ Tensornetwork Simplification """ + # part of the implementations and ideas are inspired from # https://github.com/jcmgray/quimb/blob/a2968050eba5a8a04ced4bdaa5e43c4fb89edc33/quimb/tensor/tensor_core.py#L7309-L8293 # (Apache 2.0) diff --git a/tensorcircuit/templates/__init__.py b/tensorcircuit/templates/__init__.py index e40637e3..be2236ab 100644 --- a/tensorcircuit/templates/__init__.py +++ b/tensorcircuit/templates/__init__.py @@ -1,5 +1,9 @@ +from . import ansatz from . import blocks from . import chems from . import dataset from . import graphs from . import measurements +from . import conversions + +costfunctions = measurements diff --git a/tensorcircuit/templates/ansatz.py b/tensorcircuit/templates/ansatz.py new file mode 100644 index 00000000..0bb96258 --- /dev/null +++ b/tensorcircuit/templates/ansatz.py @@ -0,0 +1,93 @@ +""" +Shortcuts for reusable circuit ansatz +""" + +from typing import Any, List + +from ..circuit import Circuit as Circ + +Tensor = Any +Circuit = Any + + +def QAOA_ansatz_for_Ising( + params: List[float], + nlayers: int, + pauli_terms: Tensor, + weights: List[float], + full_coupling: bool = False, + mixer: str = "X", +) -> Circuit: + """ + Construct the QAOA ansatz for the Ising Model. + The number of qubits is determined by `pauli_terms`. + + :param params: A list of parameter values used in the QAOA ansatz. + :param nlayers: The number of layers in the QAOA ansatz. + :pauli_terms: A list of Pauli terms, where each term is represented as a list of 0/1 series. + :param weights: A list of weights corresponding to each Pauli term. + :param full_coupling (optional): A flag indicating whether to use all-to-all coupling in mixers. Default is False. + :paran mixer (optional): The mixer operator to use. Default is "X". The other options are "XY" and "ZZ". + :return: QAOA ansatz for Ising model. + """ + nqubits = len(pauli_terms[0]) + c: Any = Circ(nqubits) + for i in range(nqubits): + c.h(i) # Apply Hadamard gate to each qubit + + for j in range(nlayers): + # cost terms + for k, term in enumerate(pauli_terms): + index_of_ones = [] + for l in range(len(term)): + if term[l] == 1: + index_of_ones.append(l) + if len(index_of_ones) == 1: + c.rz(index_of_ones[0], theta=2 * weights[k] * params[2 * j]) + # Apply Rz gate with angle determined by weight and current parameter value + elif len(index_of_ones) == 2: + c.rzz( + index_of_ones[0], + index_of_ones[1], + theta=weights[k] * params[2 * j], + ) + # Apply exp1 gate with a custom unitary (zz_matrix) + # and angle determined by weight and current parameter value + else: + raise ValueError("Invalid number of Z terms") + + # prepare the coupling map for mixer terms + pairs = [] + if full_coupling is False: + for q0 in list(range(0, nqubits - 1, 2)) + list(range(1, nqubits - 1, 2)): + pairs.append([q0, q0 + 1]) + pairs.append([nqubits - 1, 0]) + elif full_coupling is True: + for q0 in range(nqubits - 1): + for q1 in range(q0 + 1, nqubits): + pairs.append([q0, q1]) + else: + raise ValueError("Invalid input.") + + # standard mixer + if mixer == "X": + for i in range(nqubits): + c.rx( + i, theta=params[2 * j + 1] + ) # Apply Rx gate with angle determined by current parameter value + + # XY mixer + elif mixer == "XY": + for [q0, q1] in pairs: + c.rxx(q0, q1, theta=params[2 * j + 1]) + c.ryy(q0, q1, theta=params[2 * j + 1]) + + # ZZ mixer + elif mixer == "ZZ": + for [q0, q1] in pairs: + c.rzz(q0, q1, theta=params[2 * j + 1]) + + else: + raise ValueError("Invalid mixer type.") + + return c diff --git a/tensorcircuit/templates/blocks.py b/tensorcircuit/templates/blocks.py index eacc2b42..1e376903 100644 --- a/tensorcircuit/templates/blocks.py +++ b/tensorcircuit/templates/blocks.py @@ -1,6 +1,7 @@ """ Shortcuts for measurement patterns on circuit """ + # circuit in, circuit out # pylint: disable=invalid-name diff --git a/tensorcircuit/templates/chems.py b/tensorcircuit/templates/chems.py index 0ac3a0da..bc0a2184 100644 --- a/tensorcircuit/templates/chems.py +++ b/tensorcircuit/templates/chems.py @@ -2,37 +2,6 @@ Useful utilities for quantum chemistry related task """ -from typing import Any, Tuple +from .conversions import get_ps # pylint:disable=unused-import -import numpy as np - -Tensor = Any - - -def get_ps(qo: Any, n: int) -> Tuple[Tensor, Tensor]: - """ - Get Pauli string array and weights array for a qubit Hamiltonian - as a sum of Pauli strings defined in openfermion ``QubitOperator``. - - :param qo: ``openfermion.ops.operators.qubit_operator.QubitOperator`` - :type qo: ``openfermion.ops.operators.qubit_operator.QubitOperator`` - :param n: The number of qubits - :type n: int - :return: Pauli String array and weights array - :rtype: Tuple[Tensor, Tensor] - """ - value = {"X": 1, "Y": 2, "Z": 3} - terms = qo.terms - res = [] - wts = [] - for key in terms: - bit = np.zeros(n, dtype=int) - for i in range(len(key)): - bit[key[i][0]] = value[key[i][1]] - w = terms[key] - res_t = tuple() # type: ignore - for i in range(n): - res_t = res_t + (bit[i],) - res.append(res_t) - wts.append(w) - return np.array(res), np.array(wts) +# backward compatibility for the entry point diff --git a/tensorcircuit/templates/conversions.py b/tensorcircuit/templates/conversions.py new file mode 100644 index 00000000..d848e405 --- /dev/null +++ b/tensorcircuit/templates/conversions.py @@ -0,0 +1,94 @@ +""" +helper functions for conversions +""" + +from typing import Any, Tuple, List + +import numpy as np + +Tensor = Any +Array = Any + + +def get_ps(qo: Any, n: int) -> Tuple[Tensor, Tensor]: + """ + Get Pauli string array and weights array for a qubit Hamiltonian + as a sum of Pauli strings defined in openfermion ``QubitOperator``. + + :param qo: ``openfermion.ops.operators.qubit_operator.QubitOperator`` + :type qo: ``openfermion.ops.operators.qubit_operator.QubitOperator`` + :param n: The number of qubits + :type n: int + :return: Pauli String array and weights array + :rtype: Tuple[Tensor, Tensor] + """ + value = {"X": 1, "Y": 2, "Z": 3} + terms = qo.terms + res = [] + wts = [] + for key in terms: + bit = np.zeros(n, dtype=int) + for i in range(len(key)): + bit[key[i][0]] = value[key[i][1]] + w = terms[key] + res_t = tuple() # type: ignore + for i in range(n): + res_t = res_t + (bit[i],) + res.append(res_t) + wts.append(w) + return np.array(res), np.array(wts) + + +def QUBO_to_Ising(Q: Tensor) -> Tuple[Tensor, List[float], float]: + """ + Cnvert the Q matrix into a the indication of pauli terms, the corresponding weights, and the offset. + The outputs are used to construct an Ising Hamiltonian for QAOA. + + :param Q: The n-by-n square and symmetric Q-matrix. + :return pauli_terms: A list of 0/1 series, where each element represents a Pauli term. + A value of 1 indicates the presence of a Pauli-Z operator, while a value of 0 indicates its absence. + :return weights: A list of weights corresponding to each Pauli term. + :return offset: A float representing the offset term of the Ising Hamiltonian. + """ + + # input is n-by-n symmetric numpy array corresponding to Q-matrix + # output is the components of Ising Hamiltonian + + n = Q.shape[0] + + # square matrix check + if Q[0].shape[0] != n: + raise ValueError("Matrix is not a square matrix.") + + offset = ( + np.triu(Q, 0).sum() / 2 + ) # Calculate the offset term of the Ising Hamiltonian + pauli_terms = [] # List to store the Pauli terms + weights = ( + -np.sum(Q, axis=1) / 2 + ) # Calculate the weights corresponding to each Pauli term + + for i in range(n): + term = np.zeros(n) + term[i] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a single qubit + + for i in range(n - 1): + for j in range(i + 1, n): + term = np.zeros(n) + term[i] = 1 + term[j] = 1 + pauli_terms.append( + term.tolist() + ) # Add a Pauli term corresponding to a two-qubit interaction + + weight = ( + Q[i][j] / 2 + ) # Calculate the weight for the two-qubit interaction term + weights = np.concatenate( + (weights, weight), axis=None + ) # Add the weight to the weights list + + return pauli_terms, weights, offset diff --git a/tensorcircuit/templates/graphs.py b/tensorcircuit/templates/graphs.py index 4b2e1c9c..e382085c 100644 --- a/tensorcircuit/templates/graphs.py +++ b/tensorcircuit/templates/graphs.py @@ -1,6 +1,7 @@ """ Some common graphs and lattices """ + # pylint: disable=invalid-name from functools import partial diff --git a/tensorcircuit/templates/measurements.py b/tensorcircuit/templates/measurements.py index aca804d9..63f5c5b7 100644 --- a/tensorcircuit/templates/measurements.py +++ b/tensorcircuit/templates/measurements.py @@ -1,6 +1,7 @@ """ Shortcuts for measurement patterns on circuit """ + # circuit in, scalar out from typing import Any diff --git a/tensorcircuit/torchnn.py b/tensorcircuit/torchnn.py index f284e5e7..0cda7f0f 100644 --- a/tensorcircuit/torchnn.py +++ b/tensorcircuit/torchnn.py @@ -97,3 +97,42 @@ def forward(self, *inputs: Tensor) -> Tensor: TorchLayer = QuantumNet + + +class HardwareNet(QuantumNet): + """ + PyTorch Layer wrapping quantum function with cloud qpu access + (using :py:mod:`tensorcircuit.cloud` module) + """ + + def __init__( + self, + f: Callable[..., Any], + weights_shape: Sequence[Tuple[int, ...]], + initializer: Union[Any, Sequence[Any]] = None, + use_vmap: bool = True, + ): + super().__init__( + f, + weights_shape, + initializer, + use_vmap=False, + use_interface=False, + use_jit=False, + ) + self.batch_support = use_vmap + + def forward(self, *inputs: Tensor) -> Tensor: + if self.batch_support: + ypred = [] + batch = inputs[0].shape[0] + for i in range(batch): + inp = tuple([a[i] for a in inputs]) + ypred.append(self.f(*inp, *self.q_weights)) + ypred = torch.stack(ypred) # type: ignore + else: + ypred = self.f(*inputs, *self.q_weights) + return ypred + + +TorchHardwareLayer = HardwareNet diff --git a/tensorcircuit/translation.py b/tensorcircuit/translation.py index 6e867fd5..73b973b6 100644 --- a/tensorcircuit/translation.py +++ b/tensorcircuit/translation.py @@ -2,43 +2,45 @@ Circuit object translation in different packages """ -from typing import Any, Dict, List, Optional, Tuple, Union, Sequence -from copy import deepcopy import logging +from copy import deepcopy +from typing import Any, Dict, List, Optional, Sequence, Tuple, Union + import numpy as np logger = logging.getLogger(__name__) try: - from qiskit import QuantumCircuit - from qiskit.circuit.library import XXPlusYYGate - from qiskit.extensions import UnitaryGate import qiskit.quantum_info as qi - from qiskit.extensions.exceptions import ExtensionError - from qiskit.circuit.quantumcircuitdata import CircuitInstruction - from qiskit.circuit.parametervector import ParameterVectorElement + import symengine + import sympy + from qiskit import QuantumCircuit from qiskit.circuit import Parameter, ParameterExpression + from qiskit.circuit.exceptions import CircuitError + from qiskit.circuit.library import HamiltonianGate, UnitaryGate, XXPlusYYGate + from qiskit.circuit.parametervector import ParameterVectorElement + from qiskit.circuit.quantumcircuitdata import CircuitInstruction except ImportError: logger.warning( "Please first ``pip install -U qiskit`` to enable related functionality in translation module" ) CircuitInstruction = Any + QuantumCircuit = Any try: import cirq except ImportError: - logger.warning( + logger.info( "Please first ``pip install -U cirq`` to enable related functionality in translation module" ) from . import gates from .circuit import Circuit -from .densitymatrix import DMCircuit2 from .cons import backend +from .densitymatrix import DMCircuit2 from .interfaces.tensortrans import tensor_to_numpy - Tensor = Any @@ -125,7 +127,7 @@ def qir2cirq( support more element in qir, e.g. barrier, measure... """ - class CustomizedCirqGate(cirq.Gate): + class CustomizedCirqGate(cirq.Gate): # type: ignore def __init__(self, uMatrix: Any, name: str, nqubit: int): super(CustomizedCirqGate, self) self.uMatrix = uMatrix @@ -138,7 +140,9 @@ def _num_qubits_(self) -> int: def _unitary_(self) -> Any: return self.uMatrix - def _circuit_diagram_info_(self) -> List[str]: + def _circuit_diagram_info_( + self, *args: Optional[cirq.CircuitDiagramInfoArgs] + ) -> List[str]: return [self.name] * self.nqubit if extra_qir is not None and len(extra_qir) > 0: @@ -235,6 +239,7 @@ def qir2qiskit( qiskit_circ = QuantumCircuit(n) if initialization is not None: qiskit_circ.initialize(initialization) + measure_cbit = 0 for gate_info in qir: index = gate_info["index"] gate_name = str(gate_info["gatef"]) @@ -306,9 +311,8 @@ def qir2qiskit( # Error can be presented if theta is actually complex in this procedure. exp_op = qi.Operator(unitary) index_reversed = [x for x in index[::-1]] - qiskit_circ.hamiltonian( - exp_op, time=theta, qubits=index_reversed, label=qis_name - ) + gate = HamiltonianGate(data=exp_op, time=theta, label=qis_name) + qiskit_circ.append(gate, index_reversed) elif gate_name == "multicontrol": unitary = backend.numpy(backend.convert_to_tensor(parameters["unitary"])) ctrl_str = "".join(map(str, parameters["ctrl"]))[::-1] @@ -325,7 +329,8 @@ def qir2qiskit( ) qiskit_circ.unitary(qop, index[::-1], label=qis_name) elif gate_name == "measure": - qiskit_circ.measure(index[0], index[0]) + qiskit_circ.measure(index[0], measure_cbit) + measure_cbit += 1 elif gate_name == "reset": qiskit_circ.reset(index[0]) elif gate_name == "barrier": @@ -338,7 +343,7 @@ def qir2qiskit( qop = qi.Operator(gatem) try: qiskit_circ.unitary(qop, index[::-1], label=qis_name) - except ExtensionError: + except (CircuitError, ValueError) as _: logger.warning( "omit non unitary gate in tensorcircuit when transforming to qiskit: %s" % gate_name @@ -354,7 +359,7 @@ def _translate_qiskit_params( gate_info: CircuitInstruction, binding_params: Any ) -> List[float]: parameters = [] - for p in gate_info[0].params: + for p in gate_info.operation.params: if isinstance(p, ParameterVectorElement): parameters.append(binding_params[p.index]) elif isinstance(p, Parameter): @@ -363,30 +368,37 @@ def _translate_qiskit_params( if len(p.parameters) == 0: parameters.append(float(p)) continue - if len(p.parameters) != 1: - raise ValueError( - f"Can't translate parameter expression with more than 1 parameters: {p}" - ) - p_real = list(p.parameters)[0] - if not isinstance(p_real, ParameterVectorElement): - raise TypeError( - "Parameters in parameter expression should be ParameterVectorElement" - ) + # note "sym" != "sim" expr = p.sympify().simplify() - # only allow simple expressions like 1.0 * theta - if not expr.is_Mul: - raise ValueError(f"Unsupported parameter expression: {p}") - arg1, arg2 = expr.args - if arg1.is_number and arg2.is_symbol: - coeff = arg1 - elif arg1.is_symbol and arg2.is_number: - coeff = arg2 + if isinstance(expr, symengine.Expr): # qiskit uses symengine if available + expr = expr._sympy_() # sympy.Expr + + if expr.is_algebraic_expr(): # numpy ufuncs are not used + lambdify_module_name = "numpy" else: - raise ValueError(f"Unsupported parameter expression: {p}") - # taking real part here because using complex type will result in a type error - # for tf backend when the binding parameter is real - parameters.append(float(coeff) * binding_params[p_real.index]) + if backend.name == "pytorch": + lambdify_module_name = "math" + else: + lambdify_module_name = backend.name + + for free_symbol in expr.free_symbols: + # replace names: theta[0] -> theta_0 + # ParameterVector creates symbols with brackets like theta[0] + # but sympy.lambdify does not allow brackets in symbol names + free_symbol.name = free_symbol.name.replace("[", "_").replace("]", "") + + parameter_list = list(p.parameters) + sympy_symbols = [param._symbol_expr for param in parameter_list] + # replace names again: theta[0] -> theta_0 + sympy_symbols = [ + sympy.Symbol(str(symbol).replace("[", "_").replace("]", "")) + for symbol in sympy_symbols + ] + lam_f = sympy.lambdify(sympy_symbols, expr, modules=lambdify_module_name) + parameters.append( + lam_f(*[binding_params[param.index] for param in parameter_list]) + ) else: # numbers, arrays, etc. parameters.append(p) @@ -399,7 +411,7 @@ def ctrl_str2ctrl_state(ctrl_str: str, nctrl: int) -> List[int]: def qiskit2tc( - qcdata: List[CircuitInstruction], + qc: QuantumCircuit, n: int, inputs: Optional[List[float]] = None, is_dm: bool = False, @@ -408,19 +420,18 @@ def qiskit2tc( binding_params: Optional[Union[Sequence[float], Dict[Any, float]]] = None, ) -> Any: r""" - Generate a tensorcircuit circuit using the quantum circuit data in qiskit. + Generate a tensorcircuit circuit from the qiskit circuit. :Example: >>> qisc = QuantumCircuit(2) >>> qisc.h(0) >>> qisc.x(1) - >>> qc = tc.translation.qiskit2tc(qisc.data, 2) + >>> qc = tc.translation.qiskit2tc(qisc, 2) >>> qc.to_qir()[0]['gatef'] - h - :param qcdata: Quantum circuit data from qiskit. - :type qcdata: List[CircuitInstruction] + :param qc: A quantum circuit in qiskit. + :type qc: QuantumCircuit :param n: # of qubits :type n: int :param inputs: Input state of the circuit. Default is None. @@ -431,7 +442,7 @@ def qiskit2tc( :type circuit_params: Optional[Dict[str, Any]] :param binding_params: (variational) parameters for the circuit. Could be either a sequence or dictionary depending on the type of parameters in the Qiskit circuit. - For ``ParameterVectorElement`` use sequence. For ``Parameter`` use dictionary + For ``ParameterVectorElement`` use sequence. For ``Parameter`` use dictionary. :type binding_params: Optional[Union[Sequence[float], Dict[Any, float]]] :return: A quantum circuit in tensorcircuit :rtype: Any @@ -447,17 +458,17 @@ def qiskit2tc( if "nqubits" not in circuit_params: circuit_params["nqubits"] = n if ( - len(qcdata) > 0 - and qcdata[0][0].name == "initialize" + len(qc.data) > 0 + and qc.data[0][0].name == "initialize" and "inputs" not in circuit_params ): - circuit_params["inputs"] = perm_matrix(n) @ np.array(qcdata[0][0].params) + circuit_params["inputs"] = perm_matrix(n) @ np.array(qc.data[0][0].params) if inputs is not None: circuit_params["inputs"] = inputs tc_circuit: Any = Circ(**circuit_params) - for gate_info in qcdata: - idx = [qb.index for qb in gate_info[1]] + for gate_info in qc.data: + idx = [qc.find_bit(qb).index for qb in gate_info.qubits] gate_name = gate_info[0].name parameters = _translate_qiskit_params(gate_info, binding_params) if gate_name in [ @@ -486,6 +497,13 @@ def qiskit2tc( getattr(tc_circuit, gate_name)(*idx, theta=parameters) elif gate_name in ["crx_o0", "cry_o0", "crz_o0"]: getattr(tc_circuit, "o" + gate_name[1:-3])(*idx, theta=parameters) + elif gate_name in ["r"]: + getattr(tc_circuit, "u")( + *idx, + theta=parameters[0], + phi=parameters[1] - np.pi / 2, + lbd=-parameters[1] + np.pi / 2, + ) elif gate_name in ["u3", "u"]: getattr(tc_circuit, "u")( *idx, theta=parameters[0], phi=parameters[1], lbd=parameters[2] @@ -512,7 +530,8 @@ def qiskit2tc( tc_circuit.multicontrol( *idx, ctrl=ctrl_state, unitary=gates._x_matrix, name="x" ) - elif gate_name[0] == "c" and gate_name[:7] != "circuit": + elif gate_name[0] == "c" and gate_name[:7] != "circuit" and gate_name != "cu": + # qiskit cu bug, see https://github.com/tencent-quantum-lab/tensorcircuit/issues/199 for i in range(1, len(gate_name)): if (gate_name[-i] == "o") & (gate_name[-i - 1] == "_"): break diff --git a/tensorcircuit/vis.py b/tensorcircuit/vis.py index 092216b8..19834d95 100644 --- a/tensorcircuit/vis.py +++ b/tensorcircuit/vis.py @@ -1,6 +1,7 @@ """ Visualization on circuits """ + import os import subprocess from uuid import uuid4 diff --git a/tensorcircuit/waveforms.py b/tensorcircuit/waveforms.py new file mode 100644 index 00000000..7f6484a7 --- /dev/null +++ b/tensorcircuit/waveforms.py @@ -0,0 +1,97 @@ +from typing import List, Union +from dataclasses import dataclass + +ParamType = Union[float, str] + +__all__ = [ + "Gaussian", + "GaussianSquare", + "Drag", + "Constant", + "Sine", + "Cosine", + "CosineDrag", + "Flattop", +] + +@dataclass +class Gaussian: + amp: ParamType + duration: int + sigma: ParamType + def qasm_name(self) -> str: + return "gaussian" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma] + +@dataclass +class GaussianSquare: + amp: ParamType + duration: int + sigma: ParamType + width: ParamType + def qasm_name(self) -> str: + return "gaussian_square" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma, self.width] + +@dataclass +class Drag: + amp: ParamType + duration: int + sigma: ParamType + beta: ParamType + def qasm_name(self) -> str: + return "drag" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.sigma, self.beta] + +@dataclass +class Constant: + amp: ParamType + duration: int + def qasm_name(self) -> str: + return "constant" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration] + +@dataclass +class Sine: + amp: ParamType + frequency: ParamType + duration: int + def qasm_name(self) -> str: + return "sine" + def to_args(self) -> List[ParamType]: + return [self.amp, self.frequency, self.duration] + +@dataclass +class Cosine: + amp: ParamType + frequency: ParamType + duration: int + def qasm_name(self) -> str: + return "cosine" + def to_args(self) -> List[ParamType]: + return [self.amp, self.frequency, self.duration] + +@dataclass +class CosineDrag: + amp: ParamType + duration: int + phase: ParamType + alpha: ParamType + def qasm_name(self) -> str: + return "cosine_drag" + def to_args(self) -> List[ParamType]: + return [self.amp, self.duration, self.phase, self.alpha] + +@dataclass +class Flattop: + amp: ParamType + width: ParamType + duration: int + def qasm_name(self) -> str: + return "flattop" + def to_args(self) -> List[ParamType]: + return [self.amp, self.width, self.duration] diff --git a/tests/01_test_gate.py b/tests/01_test_gate.py new file mode 100644 index 00000000..76566aff --- /dev/null +++ b/tests/01_test_gate.py @@ -0,0 +1,53 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_gate_circuit(t): + qc = Circuit(2) + qc.h(0) + qc.cnot(0, 1) + + print(qc.to_tqasm()) + + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + # print(rf) + return rf + +qc = gen_gate_circuit(1.0) +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/02_test_param_pulse.py b/tests/02_test_param_pulse.py new file mode 100644 index 00000000..5eabe93a --- /dev/null +++ b/tests/02_test_param_pulse.py @@ -0,0 +1,68 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_parametric_waveform_circuit(t): + qc = Circuit(2) + + param0 = Param("a") + + # builder = qc.calibrate("basic_pulse", [param0]) + # builder.new_frame("drive_frame", param0) + # builder.play("drive_frame", waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + # builder.build() + # qc.add_calibration('basic_pulse', ['q[0]']) + +# 需根据以下定义的方式,修改代码 + builder = qc.calibrate("basic_pulse", [param0]) + frame = builder.new_frame("drive_frame", param0) + builder.play(frame, waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + + qc.add_calibration(builder, [0]) + + print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + # print(rf) + return rf + +qc = gen_parametric_waveform_circuit(1.0) +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/03_test_gate_pulse_mix.py b/tests/03_test_gate_pulse_mix.py new file mode 100644 index 00000000..00ce1f94 --- /dev/null +++ b/tests/03_test_gate_pulse_mix.py @@ -0,0 +1,61 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_gate_pulse_mix_circuit(t): + qc = Circuit(2) + + param0 = Param("a") + + builder = qc.calibrate("basic_pulse", [param0]) + frame = builder.new_frame("drive_frame", param0) + builder.play(frame, waveforms.CosineDrag(t, 0.2, 0.0, 0.0)) + + builder.build() + + qc.add_calibration(builder, [0]) + + qc.i(0) + qc.x(0) + + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + return rf + +qc = gen_gate_pulse_mix_circuit(1.0) +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/04_test_custom_chip.py b/tests/04_test_custom_chip.py new file mode 100644 index 00000000..aba58e2a --- /dev/null +++ b/tests/04_test_custom_chip.py @@ -0,0 +1,69 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +from tensorcircuit.cloud.tencent import Topology +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + +def gen_custom_chip_circuit(t): + qc = Circuit(3) + + # qc.h(0) + qc.cnot(0, 2) + # qc.cnot(1, 3) + # qc.cnot(0, 3) + + # print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) +# 以下是两种映射方式 + tp = Topology(d) + # tp.map_qubits([6,3,4,1]) + tp.map_qubits([6,3,4,1], [3,2,1,0]) + + # tp.map_qubit(6, 0) + # tp.map_qubit(3, 1) + # tp.map_qubit(4, 2) + # tp.map_qubit(1, 3) + + # tp.pair_qubit(0, 1) + # tp.pair_qubit(0, 2) + # tp.pair_qubit(1, 3) + pragma = tp.pragma() + print(qc.to_tqasm(pragma=pragma)) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + topology = tp, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + rf = t.results() + print(rf) + +qc = gen_custom_chip_circuit(1.0) +result = run_circuit(qc) \ No newline at end of file diff --git a/tests/05_test_multi_measure.py b/tests/05_test_multi_measure.py new file mode 100644 index 00000000..0370f89b --- /dev/null +++ b/tests/05_test_multi_measure.py @@ -0,0 +1,62 @@ +import sys +import os +import matplotlib.pyplot as plt + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices, list_properties +import re + +# from dotenv import load_dotenv +# load_dotenv() + +shots_const = 1000 + +print("✅ TEST FILE LOADED") +set_token(os.getenv("TOKEN")) +set_provider("tencent") +ds = list_devices() +print(ds) + + +def gen_multi_measure_circuit(t): + qc = Circuit(6) + + qc.h(0) + qc.cnot(0, 1) + + # 参数门在 to_tqasm 中的转换丢失了参数 + # qc.rxx(0, 5, theta=1.04632) + +# 需添加测量指令 + qc.measz(0, 1) + qc.cz(0, 1) + qc.measz(0, 1) + + + print(qc.to_tqasm()) + return qc + + +def run_circuit(qc): + device_name = "tianji_s2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=shots_const, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + # print(qc.to_tqasm()) + # n = qc._nqubits + # rf = t.results() # 需返回 multi_results + rf = t.m_results() # 需返回 multi_results + return rf + +qc = gen_multi_measure_circuit(1.0) +result = run_circuit(qc) +print(result) \ No newline at end of file diff --git a/tests/test_backends.py b/tests/test_backends.py index f63de48d..3c73c1ab 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -300,6 +300,17 @@ def test_backend_methods_2(backend): np.maximum(arr, 0), atol=1e-4, ) + np.testing.assert_allclose( + tc.backend.det(tc.backend.convert_to_tensor(np.eye(3) * 2)), 8, atol=1e-5 + ) + + +# @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb"), lf("torchb")]) +# def test_backend_array(backend): +# a = tc.backend.array([[0, 1], [1, 0]]) +# assert tc.interfaces.which_backend(a).name == tc.backend.name +# a = tc.backend.array([[0, 1], [1, 0]], dtype=tc.rdtypestr) +# assert tc.dtype(a) == "float32" @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb"), lf("torchb")]) diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 14c7784f..81f20762 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -1,8 +1,9 @@ # pylint: disable=invalid-name -import sys import os +import sys from functools import partial + import numpy as np import opt_einsum as oem import pytest @@ -422,6 +423,10 @@ def test_expectation_ps(backend): c.H(0) r = c.expectation_ps(z=[1], x=[0]) np.testing.assert_allclose(tc.backend.numpy(r), 1, atol=1e-5) + r1 = c.expectation_ps(ps=[1, 3]) + np.testing.assert_allclose(tc.backend.numpy(r1), 1, atol=1e-5) + r1 = c.expectation_ps(z=[1, 2], ps=[1, 3]) + np.testing.assert_allclose(tc.backend.numpy(r1), 1, atol=1e-5) def test_probability(): @@ -971,6 +976,7 @@ def test_qir2cirq(backend): def test_qir2qiskit(backend): try: import qiskit.quantum_info as qi + from tensorcircuit.translation import perm_matrix except ImportError: pytest.skip("qiskit is not installed") @@ -1070,9 +1076,11 @@ def test_qir2qiskit(backend): def test_qiskit2tc(): try: - from qiskit import QuantumCircuit import qiskit.quantum_info as qi + from qiskit import QuantumCircuit + from qiskit.circuit.library import HamiltonianGate from qiskit.circuit.library.standard_gates import MCXGate, SwapGate + from tensorcircuit.translation import perm_matrix except ImportError: pytest.skip("qiskit is not installed") @@ -1083,7 +1091,8 @@ def test_qiskit2tc(): zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) exp_op = qi.Operator(zz) for i in range(n): - qisc.hamiltonian(exp_op, time=np.random.uniform(), qubits=[i, (i + 1) % n]) + gate = HamiltonianGate(exp_op, time=np.random.uniform()) + qisc.append(gate, [i, (i + 1) % n]) qisc.fredkin(1, 2, 3) qisc.cswap(1, 2, 3) qisc.swap(0, 1) @@ -1101,6 +1110,9 @@ def test_qiskit2tc(): qisc.x(3) qisc.y(3) qisc.z(3) + qisc.cu( + 5.868768495722669, 2.24809352294186, 3.59102783505607, 2.0223650288392, 1, 3 + ) qisc.cnot(0, 1) qisc.cy(0, 1) qisc.cz(0, 1, ctrl_state=0) @@ -1118,6 +1130,7 @@ def test_qiskit2tc(): qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0) + qisc.r(np.random.uniform(), np.random.uniform(), 1) qisc.unitary(exp_op, [1, 3]) mcx_g = MCXGate(3, ctrl_state="010") qisc.append(mcx_g, [0, 1, 2, 3]) @@ -1138,29 +1151,37 @@ def test_qiskit2tc(): np.testing.assert_allclose(qis_unitary2, qis_unitary, atol=1e-5) -@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")]) def test_qiskit2tc_parameterized(backend): try: - from qiskit.circuit import QuantumCircuit, Parameter - from qiskit.quantum_info import Operator + from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit from qiskit.circuit.library import TwoLocal + from qiskit.quantum_info import Operator from qiskit_nature.second_q.circuit.library import UCCSD - from qiskit_nature.second_q.mappers import ParityMapper, QubitConverter + from qiskit_nature.second_q.mappers import ParityMapper except ImportError: pytest.skip("qiskit or qiskit-nature is not installed") from tensorcircuit.translation import perm_matrix mapper = ParityMapper() - converter = QubitConverter(mapper=mapper, two_qubit_reduction=True) - ansatz1 = UCCSD(2, [1, 1], converter) + ansatz1 = UCCSD(2, [1, 1], mapper) ansatz2 = TwoLocal(2, rotation_blocks="ry", entanglement_blocks="cz") ansatz3 = QuantumCircuit(1) ansatz3_param = Parameter("θ") ansatz3.rx(ansatz3_param, 0) - ansatz_list = [ansatz1, ansatz2, ansatz3] + ansatz4 = QuantumCircuit(1) + ansatz4_param = ParameterVector("φ", 3) + ansatz4.rx(2.0 * ansatz4_param[0] + 5.0, 0) + ansatz4.ry(ansatz4_param[0] * ansatz4_param[1] + ansatz4_param[2], 0) + ansatz4.rz( + np.exp(np.sin(ansatz4_param[0])) + + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]), + 0, + ) + ansatz_list = [ansatz1, ansatz2, ansatz3, ansatz4] for ansatz in ansatz_list: n = ansatz.num_qubits - if ansatz in [ansatz1, ansatz2]: + if ansatz in [ansatz1, ansatz2, ansatz4]: params = np.random.rand(ansatz.num_parameters) else: params = {ansatz3_param: 0.618} @@ -1170,25 +1191,25 @@ def test_qiskit2tc_parameterized(backend): # test jit @tc.backend.jit - def get_unitary(_params): + def get_unitary(params): return tc.Circuit.from_qiskit( - ansatz, inputs=np.eye(2**n), binding_params=_params + ansatz, inputs=np.eye(2**n), binding_params=params ).state() tc_unitary = get_unitary(params) tc_unitary = np.reshape(tc_unitary, [2**n, 2**n]) - p_mat = perm_matrix(n) + p_mat = tc.array_to_tensor(perm_matrix(n)) np.testing.assert_allclose( p_mat @ tc_unitary @ p_mat, qiskit_unitary, atol=1e-5 ) # test grad - def cost_fn(_params): - return tc.backend.real(tc.backend.sum(get_unitary(_params))) + def cost_fn(params): + return tc.backend.real(tc.backend.sum(get_unitary(params))) - if ansatz in [ansatz1, ansatz2]: + if ansatz in [ansatz1, ansatz2, ansatz4]: grad = tc.backend.grad(cost_fn)(tc.backend.convert_to_tensor(params)) - assert np.sum(np.isnan(grad)) == 0 + assert tc.backend.sum(tc.num_to_tensor(np.isnan(grad))) == 0 else: # tf only supports tf tensor as input grad = tc.backend.grad(cost_fn)( @@ -1200,8 +1221,8 @@ def cost_fn(_params): @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_qiskit_vs_tc_intialization(backend): try: - from qiskit import QuantumCircuit import qiskit.quantum_info as qi + from qiskit import QuantumCircuit except ImportError: pytest.skip("qiskit is not installed") @@ -1303,6 +1324,25 @@ def test_circuit_inverse(backend): np.testing.assert_allclose(c.state(), inputs, atol=1e-5) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_circuit_inverse_2(backend): + inputs = np.random.uniform(size=[8]) + inputs /= np.linalg.norm(inputs) + c = tc.Circuit(3, inputs=inputs) + c.iswap(0, 1) + c.iswap(1, 0, theta=0.6) + c.rxx(1, 2, theta=-0.2) + c.cu(0, 1, lbd=2.0, theta=-0.7) + c.r(2, alpha=0.3) + c.sd(2) + c.cx(1, 2) + c.unitary(0, unitary=tc.gates._x_matrix) + c1 = c.inverse() + c.append(c1) + print(c.draw()) + np.testing.assert_allclose(c.state(), inputs, atol=1e-5) + + @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) def test_jittable_amplitude(backend): # @tc.backend.jit @@ -1536,3 +1576,80 @@ def simple_ansatz(param): vs, gs = v_ansatz(K.ones([2, 3], dtype="float32")) assert K.shape_tuple(gs) == (2, 3) np.testing.assert_allclose(K.numpy(vs), -1.0 * K.ones([2]), atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")]) +def test_fancy_circuit_indexing(backend): + c = tc.Circuit(4) + c.cx([0, 1], [-1, -2]) + c.h(range(c._nqubits)) + c.rz([0], theta=0.2) + c.rx([1, 2], theta=[0.3, 0.5]) + c.rzz([2, 3], [0, 1], theta=tc.backend.ones([2])) + c.rxx([2, 0, 1], [0, 1, 2], theta=tc.backend.ones([1])) + assert c.gate_count("h") == 4 + assert c.gate_count("rzz") == 2 + assert c.gate_count("rxx") == 3 + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")]) +def test_general_kraus(backend): + c = tc.Circuit(2) + c.h([0, 1]) + p = 0.5 + status = [0.3, 0.8] + rs = [] + for i in range(2): + rs.append( + c.general_kraus( + [ + np.sqrt(p) * np.array([[1.0, 0], [0, 0]]), + np.sqrt(p) * np.array([[0, 0], [0, 1.0]]), + np.sqrt(1 - p) * np.eye(2), + ], + i, + status=status[i], + ) + ) + np.testing.assert_allclose(rs[0], 1) + np.testing.assert_allclose(rs[1], 2) + np.testing.assert_allclose(c.expectation_ps(z=[0]), -1, atol=1e-5) + np.testing.assert_allclose(c.expectation_ps(z=[1]), 0, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")]) +def test_general_kraus_with_prob(backend): + c = tc.Circuit(2) + c.h([0, 1]) + p = 0.5 + status = [0.3, 0.8] + rs = [] + for i in range(2): + rs.append( + c.general_kraus( + [ + np.sqrt(p) * np.array([[1.0, 0], [0, 0]]), + np.sqrt(p) * np.array([[0, 0], [0, 1.0]]), + np.sqrt(1 - p) * np.eye(2), + ], + i, + status=status[i], + with_prob=True, + ) + ) + np.testing.assert_allclose(rs[0][0], 1) + np.testing.assert_allclose(rs[1][0], 2) + np.testing.assert_allclose(c.expectation_ps(z=[0]), -1, atol=1e-5) + np.testing.assert_allclose(c.expectation_ps(z=[1]), 0, atol=1e-5) + np.testing.assert_allclose(rs[0][1], [0.25, 0.25, 0.5], atol=1e-5) + np.testing.assert_allclose(rs[1][1], [0.25, 0.25, 0.5], atol=1e-5) + np.testing.assert_allclose(tc.backend.norm(c.state()), 1, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")]) +def test_circuit_copy(backend): + c = tc.Circuit(2) + c.h(0) + c1 = c.copy() + c.rz(0, theta=0.1) + assert c1.gate_count() == 1 diff --git a/tests/test_cloud.py b/tests/test_cloud.py index c3f3e7ee..fb24d318 100644 --- a/tests/test_cloud.py +++ b/tests/test_cloud.py @@ -161,3 +161,59 @@ def test_batch_exp_ps(): [1, -1], atol=1e-1, ) + np.testing.assert_allclose( + wrapper.batch_expectation_ps(c, pss, device="local::default", with_rem=False), + [1, -1], + atol=1e-1, + ) + + +def test_batch_submit_template(): + run = tc.cloud.wrapper.batch_submit_template( + device="simulator:tc", batch_limit=2, prior=10 + ) + cs = [] + for i in range(4): + c = tc.Circuit(4) + c.h(i) + cs.append(c) + + rs = run(cs[:3], prior=1) + assert len(rs) == 3 + rs = run(cs[:4]) + assert len(rs) == 4 + + +def test_allz_batch(): + n = 5 + + def makec(inputs, params): + c = tc.Circuit(n) + for i in range(n): + c.rx(i, theta=inputs[i]) + for i in range(n): + c.rz(i, theta=params[0, i]) + for i in range(n - 1): + c.cx(i, i + 1) + for i in range(n): + c.rx(i, theta=params[1, i]) + return c + + pss = [] + for i in range(n): + ps = [0 for _ in range(n)] + ps[i] = 3 + pss.append(ps) + + def exp_val(c, device=None): + rs = tc.cloud.wrapper.batch_expectation_ps(c, pss, device) + return tc.backend.stack(rs) + + def qmlf(inputs, params, device=None): + c = makec(inputs, params) + return exp_val(c, device) + + inputs = tc.array_to_tensor(np.array([0, 1, 0, 1, 0])) + params = np.ones([2, n]) + print(qmlf(inputs, params, device="9gmon")) + print(qmlf(inputs, params)) diff --git a/tests/test_compiler.py b/tests/test_compiler.py index 6559b476..5b297289 100644 --- a/tests/test_compiler.py +++ b/tests/test_compiler.py @@ -1,6 +1,7 @@ import sys import os import pytest +import numpy as np # from pytest_lazyfixture import lazy_fixture as lf @@ -73,7 +74,7 @@ def test_qsikit_compiler(): def test_composed_compiler(): - from tensorcircuit.compiler import default_compiler + from tensorcircuit.compiler import DefaultCompiler c = tc.Circuit(3) c.rx(0) @@ -82,18 +83,65 @@ def test_composed_compiler(): c.rxx(0, 2, theta=0.2) c.measure_instruction(2) c.measure_instruction(0) + default_compiler = DefaultCompiler() c1, info = default_compiler(c) print(c1.draw()) - assert c1.gate_count_by_condition(lambda qir: qir["name"] == "cnot") == 4 + assert c1.gate_count_by_condition(lambda qir: qir["name"] == "cnot") == 3 assert info["positional_logical_mapping"][0] == 2 - default_compiler.add_options( + default_compiler = DefaultCompiler( { "basis_gates": ["h", "rz", "cz"], "optimization_level": 2, "coupling_map": [[0, 1], [1, 2]], } ) + c1, info = default_compiler(c) assert c1.gate_count_by_condition(lambda qir: qir["name"] == "cnot") == 0 print(info) + + +def test_replace_r(): + c = tc.Circuit(3) + c.rz(0, theta=0.1) + c.cx(0, 2) + c.ry(1) + c.rxx(1, 0, theta=0.2) + c.rx(0, theta=3.9) + c.ry(1, theta=-0.2) + c.rzz(1, 0, theta=-0.3) + c.ryy(1, 0, theta=-0.6) + c.rx(2) + + print(c.draw()) + c1 = tc.compiler.simple_compiler.replace_r(c) + print(c1.draw()) + np.testing.assert_allclose(c.matrix(), c1.matrix(), atol=1e-5) + + +def test_default_compiler(): + c = tc.Circuit(3) + c.cx(0, 1) + c.rx(0, theta=1e-5) + c.x(1) + c.y(1) + c.z(1) + c.h(1) + c.cz(2, 0) + c.h(1) + c.cz(2, 0) + c.s(2) + c.sd(2) + c.s(2) + c.s(2) + c.y(2) + c.ry(2, theta=0.1) + c.t(2) + c.td(2) + c.ry(2, theta=-0.1) + c.rz(1, theta=0.3) + + c1, _ = tc.compiler.simple_compiler.simple_compile(c) + print(c1.draw()) + assert c1.gate_count() == 3 diff --git a/tests/test_ensemble.py b/tests/test_ensemble.py index 5aec52cc..92869fd8 100644 --- a/tests/test_ensemble.py +++ b/tests/test_ensemble.py @@ -2,15 +2,19 @@ import sys import tensorflow as tf import numpy as np +import pytest thisfile = os.path.abspath(__file__) modulepath = os.path.dirname(os.path.dirname(thisfile)) sys.path.insert(0, modulepath) -from tensorcircuit.templates.ensemble import bagging +from tensorcircuit.applications.ai.ensemble import bagging +@pytest.mark.xfail( + int(tf.__version__.split(".")[1]) >= 16, reason="legacy optimizer fails tf>=2.16" +) def test_ensemble_bagging(): data_amount = 100 # Amount of data to be used linear_dimension = 4 # linear demension of the data @@ -52,7 +56,7 @@ def model(): obj_bagging.append(model(), False) obj_bagging.compile( loss=tf.keras.losses.BinaryCrossentropy(), - optimizer=tf.keras.optimizers.Adam(lr), + optimizer=tf.keras.optimizers.legacy.Adam(lr), metrics=[tf.keras.metrics.AUC(), "acc"], ) obj_bagging.train( diff --git a/tests/test_fgs.py b/tests/test_fgs.py new file mode 100644 index 00000000..dd307b3c --- /dev/null +++ b/tests/test_fgs.py @@ -0,0 +1,267 @@ +import numpy as np +import pytest +from pytest_lazyfixture import lazy_fixture as lf +import tensorflow as tf + +try: + import openfermion as _ +except ModuleNotFoundError: + pytestmark = pytest.mark.skip("skip fgs test due to missing openfermion module") + +import tensorcircuit as tc + +F = tc.fgs.FGSSimulator +FT = tc.fgs.FGSTestSimulator + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_cmatrix(backend, highp): + import openfermion + + def asymmetric_hopping(J, gamma, i, j, L): + m0 = tc.fgs.onehot_matrix(i, j, 2 * L) - tc.fgs.onehot_matrix( + j + L, i + L, 2 * L + ) + m = (J + gamma) * m0 + (J - gamma) * tc.backend.adjoint(m0) + return m / 2 + + def asymmetric_hopping_jw(J, gamma, i, j, L): + op = (J + gamma) * openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + np.conj( + J - gamma + ) * openfermion.FermionOperator(f"{str(j)}^ {str(i)}") + sop = openfermion.transforms.jordan_wigner(op) + m = openfermion.get_sparse_operator(sop, n_qubits=L).todense() + return m + + c = tc.fgs.FGSSimulator(4, [0]) + c1 = tc.fgs.FGSTestSimulator(4, [0]) + c.evol_hp(0, 1, 1.2) + c1.evol_hp(0, 1, 1.2) + c.evol_icp(2, 0.5) + c1.evol_icp(2, 0.5) + c.evol_cp(0, -0.8) + c1.evol_cp(0, -0.8) + c.evol_sp(1, 0, 0.5) + c1.evol_sp(1, 0, 0.5) + c.evol_ghamiltonian(asymmetric_hopping(1, 0.5, 0, 2, 4)) + c1.evol_ghamiltonian(np.array(asymmetric_hopping_jw(1, 0.5, 0, 2, 4))) + c.evol_sp(1, 2, 1.5) + c1.evol_sp(1, 2, 1.5) + c.evol_ihamiltonian(c.chemical_potential(1.0, 1, 4)) + c1.evol_ihamiltonian(c1.chemical_potential_jw(1.0, 1, 4)) + np.testing.assert_allclose( + c1.get_cmatrix_majorana(), c.get_cmatrix_majorana(), atol=1e-5 + ) + np.testing.assert_allclose(c1.get_cmatrix(), c.get_cmatrix(), atol=1e-5) + np.testing.assert_allclose(c1.entropy([0, 2]), c.entropy([0, 2]), atol=1e-5) + np.testing.assert_allclose( + c1.renyi_entropy(2, [1]), c.renyi_entropy(2, [1]), atol=1e-5 + ) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_otoc(backend, highp): + c = tc.FGSSimulator(4, [0, 1]) + c1 = tc.fgs.FGSTestSimulator(4, [0, 1]) + h = c.hopping(0.6, 1, 2, 4) + h += c.hopping(-0.8, 3, 2, 4) + h += c.chemical_potential(0.3, 2, 4) + h1 = c1.hopping_jw(0.6, 1, 2, 4) + h1 += c1.hopping_jw(-0.8, 3, 2, 4) + h1 += c1.chemical_potential_jw(0.3, 2, 4) + c.evol_hamiltonian(h) + m = c.get_cmatrix(now_i=True, now_j=False) + m0 = c1.get_ot_cmatrix(h1) + np.testing.assert_allclose(m, m0, atol=1e-5) + m = c.get_cmatrix(now_i=False, now_j=True) + m0 = c1.get_ot_cmatrix(h1, now_i=False) + np.testing.assert_allclose(m, m0, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_fgs_ad(backend, highp): + import optax + + N = 18 + + def f(chi): + c = tc.fgs.FGSSimulator(N, [0]) + for i in range(N - 1): + c.evol_hp(i, i + 1, chi[i]) + cm = c.get_cmatrix() + return -tc.backend.real(1 - cm[N, N]) + + chi_vg = tc.backend.jit(tc.backend.value_and_grad(f)) + + if tc.backend.name == "tensorflow": + opt = tc.backend.optimizer(tf.keras.optimizers.Adam(1e-2)) + else: + opt = tc.backend.optimizer(optax.adam(1e-2)) + + param = tc.backend.ones([N - 1], dtype="float64") + for _ in range(300): + vs, gs = chi_vg(param) + param = opt.update(gs, param) + + np.testing.assert_allclose(vs, -0.9986, atol=1e-2) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_hamiltonian_generation(backend): + hc = F.chemical_potential(0.8, 0, 3) + h1 = FT.get_hmatrix(hc, 3) + 0.4 * tc.backend.eye(2**3) + # constant shift + h2 = FT.chemical_potential_jw(0.8, 0, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + hc = F.hopping(0.8j, 0, 1, 3) + h1 = FT.get_hmatrix(hc, 3) + h2 = FT.hopping_jw(0.8j, 0, 1, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + hc = F.sc_pairing(0.8, 1, 0, 3) + h1 = FT.get_hmatrix(hc, 3) + h2 = FT.sc_pairing_jw(0.8, 1, 0, 3) + np.testing.assert_allclose(h1, h2, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_ground_state(backend, highp): + N = 3 + hc = ( + F.hopping(1.0, 0, 1, N) + + F.hopping(1.0, 1, 2, N) + + F.chemical_potential(0.4, 0, N) + - F.chemical_potential(0.4, 1, N) + + F.sc_pairing(0.8, 0, 1, N) + ) + + c = F(N, hc=hc) + c1 = FT(N, hc=hc) + + np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-6) + np.testing.assert_allclose(c1.entropy([0]), c.entropy([0]), atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_post_select(backend, highp): + for ind in [0, 1, 2]: + for keep in [0, 1]: + c = F(3, filled=[0, 2]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + c.evol_cp(1, -0.8) + c.evol_sp(0, 2, 0.3) + c.post_select(ind, keep) + c1 = FT(3, filled=[0, 2]) + c1.evol_hp(0, 1, 0.2) + c1.evol_cp(0, 0.5) + c1.evol_hp(1, 2, 0.3j) + c1.evol_cp(1, -0.8) + c1.evol_sp(0, 2, 0.3) + c1.post_select(ind, keep) + np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_jittable_measure(backend): + @tc.backend.jit + def get_cmatrix(status): + r = [] + c = F(3, filled=[0]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + r.append(c.cond_measure(1, status[0])) + c.evol_cp(1, -0.8) + r.append(c.cond_measure(2, status[1])) + r.append(c.cond_measure(1, status[3])) + c.evol_sp(0, 2, 0.3) + c.evol_hp(2, 1, 0.2) + c.evol_hp(0, 1, 0.8) + return c.get_cmatrix(), tc.backend.stack(r) + + def get_cmatrix_baseline(status): + r = [] + c = FT(3, filled=[0]) + c.evol_hp(0, 1, 0.2) + c.evol_cp(0, 0.5) + c.evol_hp(1, 2, 0.3j) + r.append(c.cond_measure(1, status[0])) + c.evol_cp(1, -0.8) + r.append(c.cond_measure(2, status[1])) + r.append(c.cond_measure(1, status[3])) + c.evol_sp(0, 2, 0.3) + c.evol_hp(2, 1, 0.2) + c.evol_hp(0, 1, 0.8) + return c.get_cmatrix(), np.array(r) + + status = np.array([0.2, 0.83, 0.61, 0.07]) + m, his = get_cmatrix(tc.backend.convert_to_tensor(status)) + m1, his1 = get_cmatrix_baseline(status) + np.testing.assert_allclose(m, m1, atol=1e-5) + np.testing.assert_allclose(his, his1, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_exp_2body(backend): + c = F(3, filled=[1]) + np.testing.assert_allclose(c.expectation_2body(4, 1), 1.0, atol=1e-5) + np.testing.assert_allclose(c.expectation_2body(5, 2), 0.0, atol=1e-5) + np.testing.assert_allclose(c.expectation_2body(1, 4), 0.0, atol=1e-5) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_exp_4body(backend): + c = F(4, filled=[0, 2]) + c.evol_hp(0, 1, 0.3) + c.evol_hp(2, 3, 0.3) + c.evol_sp(0, 3, 0.5) + c.evol_sp(0, 2, 0.9) + c.evol_cp(0, -0.4) + + c1 = FT(4, filled=[0, 2]) + c1.evol_hp(0, 1, 0.3) + c1.evol_hp(2, 3, 0.3) + c1.evol_sp(0, 3, 0.5) + c1.evol_sp(0, 2, 0.9) + c1.evol_cp(0, -0.4) + + np.testing.assert_allclose( + c.expectation_4body(0, 4, 1, 5), c.expectation_4body(0, 4, 1, 5), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 1, 4, 5), c.expectation_4body(0, 1, 4, 5), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 4, 2, 6), c.expectation_4body(0, 4, 2, 6), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 2, 3, 1), c.expectation_4body(0, 2, 3, 1), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(0, 1, 4, 6), c.expectation_4body(0, 1, 4, 6), atol=1e-5 + ) + np.testing.assert_allclose( + c.expectation_4body(1, 0, 6, 7), c.expectation_4body(1, 0, 6, 7), atol=1e-5 + ) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_overlap(backend): + def compute_overlap(FGScls): + c = FGScls(3, filled=[0, 2]) + c.evol_hp(0, 1, 1.2) + c.evol_hp(1, 2, 0.3) + c.evol_cp(0, 0.5) + c.evol_sp(0, 2, 0.3) + c1 = FGScls(3, filled=[0, 2]) + c1.evol_hp(0, 1, 0.2) + c1.evol_hp(1, 2, 0.6) + c1.evol_sp(1, 0, -1.1) + return tc.backend.abs(c.overlap(c1)) + + np.testing.assert_allclose( + compute_overlap(tc.FGSSimulator), compute_overlap(tc.fgs.FGSTestSimulator), 1e-5 + ) diff --git a/tests/test_keras.py b/tests/test_keras.py index 187a316e..3564f828 100644 --- a/tests/test_keras.py +++ b/tests/test_keras.py @@ -129,6 +129,9 @@ def qf(inputs, param): def test_keras_layer_inputs_dict(tfb): + # https://github.com/tensorflow/tensorflow/issues/65306 + # keras3 for tf2.16+ fails to accept complex valued input for keras layers + # which is vital for quantum applications n = 3 p = 0.1 K = tc.backend diff --git a/tests/test_miscs.py b/tests/test_miscs.py index 5a40d94e..b7a201cb 100644 --- a/tests/test_miscs.py +++ b/tests/test_miscs.py @@ -16,6 +16,7 @@ from tensorcircuit import experimental from tensorcircuit.quantum import PauliString2COO, PauliStringSum2COO from tensorcircuit.applications.vqes import construct_matrix_v2 +from tensorcircuit.applications.physics.baseline import TFIM1Denergy, Heisenberg1Denergy i, x, y, z = [t.tensor for t in tc.gates.pauli_gates] @@ -218,3 +219,38 @@ def fsum1(param1, param2): np.testing.assert_allclose(g1, g3, atol=1e-5) np.testing.assert_allclose(g2, g4, atol=1e-5) + + +def test_evol(jaxb): + def h_square(t, b): + return (tc.backend.sign(t - 1.0) + 1) / 2 * b * tc.gates.x().tensor + + c = tc.Circuit(3) + c.x(0) + c.cx(0, 1) + c.h(2) + c = experimental.evol_local( + c, [1], h_square, 2.0, tc.backend.convert_to_tensor(0.2) + ) + c.rx(1, theta=np.pi - 0.4) + np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5) + + ixi = tc.quantum.PauliStringSum2COO([[0, 1, 0]]) + + def h_square_sparse(t, b): + return (tc.backend.sign(t - 1.0) + 1) / 2 * b * ixi + + c = tc.Circuit(3) + c.x(0) + c.cx(0, 1) + c.h(2) + c = experimental.evol_global( + c, h_square_sparse, 2.0, tc.backend.convert_to_tensor(0.2) + ) + c.rx(1, theta=np.pi - 0.4) + np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5) + + +def test_energy_baseline(): + print(TFIM1Denergy(10)) + print(Heisenberg1Denergy(10)) diff --git a/tests/test_parametric_waveform.py b/tests/test_parametric_waveform.py new file mode 100644 index 00000000..66948262 --- /dev/null +++ b/tests/test_parametric_waveform.py @@ -0,0 +1,59 @@ +import sys +import os + +# Add the directory containing your module to Python's search path +module_path = ".." +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, gates, waveforms +from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token, list_devices +import re + +print("✅ TEST FILE LOADED") +set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") +set_provider("tencent") +ds = list_devices() +print(ds) + +def test_parametric_waveform(): + qc = Circuit(2) + + param0 = Param("a") + param1 = Param("b") + + builder = qc.calibrate("my_gate", [param0, param1]) + builder.new_frame("f0", param0) + builder.play("f0", waveforms.CosineDrag(10, 0.2, "0.5*PI", 0.01)) + builder.new_frame("f1", param1) + builder.play("f1", waveforms.CosineDrag(20, 0.01, "0", 0)) + builder.build() + + tqasm_code = qc.to_tqasm() + tqasm_code = tqasm_code + '\nmygate q[0], q[1]' + print(tqasm_code) + + assert "TQASM 0.2;" in tqasm_code + assert "defcal my_gate a, b" in tqasm_code + assert "frame f0 = newframe(a);" in tqasm_code + assert "play(f0, cosine_drag(10, 0.2, 0.5*PI, 0.01));" in tqasm_code + assert "frame f1 = newframe(b);" in tqasm_code + assert "play(f1, cosine_drag(20, 0.01, 0, 0));" in tqasm_code + assert re.search(r"defcal my_gate [^\)]* \s*\{", tqasm_code) + + + #tc.cloud.apis.set_token("xu1LTrkf0nP6sI8oh.bDPdk35RlOQZYy9hQPU6jK2J4d5AdINAOszCNPxTNGZ3-opBPhWcLcruYuSrvX8is1D9tKgw-O4Zg.Qf7fLp83AtSPP19jD6Na4piICkygomdfyxIjzhO6Zu-s5hgBu2709ZW=") + #tc.cloud.apis.set_provider("tencent") + device_name = "tianji_m2" + d = get_device(device_name) + t = submit_task( + circuit=qc, + shots=8192, + device=d, + enable_qos_gate_decomposition=False, + enable_qos_qubit_mapping=False, + ) + rf = t.results() + print(rf) + + +test_parametric_waveform() diff --git a/tests/test_qaoa.py b/tests/test_qaoa.py index fae3c69a..a1b762f9 100644 --- a/tests/test_qaoa.py +++ b/tests/test_qaoa.py @@ -7,11 +7,14 @@ sys.path.insert(0, modulepath) import numpy as np +import pytest from tensorcircuit.applications.dqas import set_op_pool from tensorcircuit.applications.graphdata import get_graph from tensorcircuit.applications.layers import Hlayer, rxlayer, zzlayer from tensorcircuit.applications.vags import evaluate_vag +from tensorcircuit.templates.ansatz import QAOA_ansatz_for_Ising +from tensorcircuit.circuit import Circuit def test_vag(tfb): @@ -25,3 +28,59 @@ def test_vag(tfb): ) print(expene, eneg, p) np.testing.assert_allclose(ene.numpy(), -7.01, rtol=1e-2) + + +cases = [ + ("X", True), + ("X", False), + ("XY", True), + ("XY", False), + ("ZZ", True), + ("ZZ", False), +] + + +@pytest.fixture +def example_inputs(): + params = [0.1, 0.2, 0.3, 0.4] + nlayers = 2 + pauli_terms = [[0, 1, 0], [1, 0, 1]] + weights = [0.5, -0.5] + return params, nlayers, pauli_terms, weights + + +@pytest.mark.parametrize("mixer, full_coupling", cases) +def test_QAOA_ansatz_for_Ising(example_inputs, full_coupling, mixer): + params, nlayers, pauli_terms, weights = example_inputs + circuit = QAOA_ansatz_for_Ising( + params, nlayers, pauli_terms, weights, full_coupling, mixer + ) + n = len(pauli_terms[0]) + assert isinstance(circuit, Circuit) + assert circuit._nqubits == n + + if mixer == "X": + assert circuit.gate_count() == n + nlayers * (len(pauli_terms) + n) + elif mixer == "XY": + if full_coupling is False: + assert circuit.gate_count() == n + nlayers * (len(pauli_terms) + 2 * n) + else: + assert circuit.gate_count() == n + nlayers * ( + len(pauli_terms) + sum(range(n + 1)) + ) + else: + if full_coupling is False: + assert circuit.gate_count() == n + nlayers * (len(pauli_terms) + n) + else: + assert circuit.gate_count() == n + nlayers * ( + len(pauli_terms) + sum(range(n + 1)) / 2 + ) + + +@pytest.mark.parametrize("mixer, full_coupling", [("AB", True), ("XY", 1), ("TC", 5)]) +def test_QAOA_ansatz_errors(example_inputs, full_coupling, mixer): + params, nlayers, pauli_terms, weights = example_inputs + with pytest.raises(ValueError): + QAOA_ansatz_for_Ising( + params, nlayers, pauli_terms, weights, full_coupling, mixer + ) diff --git a/tests/test_qem.py b/tests/test_qem.py new file mode 100644 index 00000000..6ef01cec --- /dev/null +++ b/tests/test_qem.py @@ -0,0 +1,152 @@ +from functools import partial +import pytest +from pytest_lazyfixture import lazy_fixture as lf +import numpy as np +import networkx as nx + +import tensorcircuit as tc +from tensorcircuit.noisemodel import NoiseConf +from tensorcircuit.results import qem +from tensorcircuit.results.qem import ( + zne_option, + apply_zne, + dd_option, + apply_dd, + apply_rc, +) +from tensorcircuit.results.qem import benchmark_circuits + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_benchmark_circuits(backend): + # QAOA + graph = [(2, 0), (0, 3), (1, 2)] + weight = [1] * len(graph) + params = np.array([[1, 1]]) + + _ = benchmark_circuits.QAOA_circuit(graph, weight, params) + + # mirror circuit + # return circuit and ideal counts {"01000":1} + _, _ = benchmark_circuits.mirror_circuit( + depth=5, two_qubit_gate_prob=1, connectivity_graph=nx.complete_graph(3), seed=20 + ) + + # GHZ circuit + _ = benchmark_circuits.generate_ghz_circuit(10) + + # Werner-state with linear complexity + # {'1000': 0.25, '0100': 0.25, '0010': 0.25, '0001': 0.25} + _ = benchmark_circuits.generate_w_circuit(5) + + # RB cirucit + _ = benchmark_circuits.generate_rb_circuits(2, 7)[0] + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_zne(backend): + c = tc.Circuit(2) + for _ in range(3): + c.rx(range(2), theta=0.4) + + error1 = tc.channels.generaldepolarizingchannel(0.01, 1) + noise_conf = NoiseConf() + noise_conf.add_noise("rx", error1) + + def execute(circuit): + value = circuit.expectation_ps(z=[0], noise_conf=noise_conf, nmc=10000) + return value + + random_state = np.random.RandomState(0) + noise_scaling_function = partial( + zne_option.scaling.fold_gates_at_random, + # fidelities = {"single": 1.0}, + random_state=random_state, + ) + factory = zne_option.inference.PolyFactory(scale_factors=[1, 3, 5], order=1) + # factory = zne_option.inference.ExpFactory(scale_factors=[1,1.5,2],asymptote=0.) + # factory = zne_option.inference.RichardsonFactory(scale_factors=[1,1.5,2]) + # factory = zne_option.inference.AdaExpFactory(steps=5, asymptote=0.) + + result = apply_zne( + circuit=c, + executor=execute, + factory=factory, + scale_noise=noise_scaling_function, + num_to_average=1, + ) + + ideal_value = c.expectation_ps(z=[0]) + mit_value = result + + np.testing.assert_allclose(ideal_value, mit_value, atol=4e-2) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_dd(backend): + c = tc.Circuit(2) + for _ in range(3): + c.rx(range(2), theta=0.4) + + def execute(circuit): + value = circuit.expectation_ps(z=[0]) + return value + + def execute2(circuit): + key = tc.backend.get_random_state(42) + count = circuit.sample( + batch=1000, allow_state=True, format_="count_dict_bin", random_generator=key + ) + return count + + _ = apply_dd( + circuit=c, + executor=execute, + rule=["X", "X"], + rule_args={"spacing": -1}, + full_output=True, + ignore_idle_qubit=True, + fulldd=False, + ) + + _ = apply_dd( + circuit=c, + executor=execute2, + rule=dd_option.rules.xyxy, + rule_args={"spacing": -1}, + full_output=True, + ignore_idle_qubit=True, + fulldd=True, + iscount=True, + ) + + # wash circuit based on use_qubits and washout iden gates + _ = qem.prune_ddcircuit(c, qlist=list(range(c.circuit_param["nqubits"]))) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_rc(backend): + c = tc.Circuit(2) + for _ in range(3): + c.rx(range(2), theta=0.4) + c.cnot(0, 1) + + def execute(circuit): + value = circuit.expectation_ps(z=[0]) + return value + + def execute2(circuit): + key = tc.backend.get_random_state(42) + count = circuit.sample( + batch=1000, allow_state=True, format_="count_dict_bin", random_generator=key + ) + return count + + _ = apply_rc(circuit=c, executor=execute, num_to_average=6, simplify=False) + + _ = apply_rc( + circuit=c, executor=execute2, num_to_average=6, simplify=True, iscount=True + ) + + # generate a circuit with rc + _ = qem.rc_circuit(c) diff --git a/tests/test_quantum.py b/tests/test_quantum.py index 609111ad..63ff755e 100644 --- a/tests/test_quantum.py +++ b/tests/test_quantum.py @@ -1,13 +1,13 @@ # pylint: disable=invalid-name -from functools import partial import os import sys +from functools import partial import numpy as np import pytest -from pytest_lazyfixture import lazy_fixture as lf import tensornetwork as tn +from pytest_lazyfixture import lazy_fixture as lf thisfile = os.path.abspath(__file__) modulepath = os.path.dirname(os.path.dirname(thisfile)) @@ -312,7 +312,8 @@ def test_extract_from_measure(backend): np.testing.assert_allclose(r, 1, atol=1e-5) -def test_heisenberg_ham(tfb): +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_heisenberg_ham(backend): g = tc.templates.graphs.Line1D(6) h = tc.quantum.heisenberg_hamiltonian(g, sparse=False) e, _ = tc.backend.eigh(h) @@ -364,6 +365,38 @@ def test_expectation_quantum(backend): np.testing.assert_allclose(exp1, exp2, atol=1e-5) +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_ee(backend): + c = tc.Circuit(3) + c.h(0) + c.cx(0, 1) + c.cx(1, 2) + s = c.state() + np.testing.assert_allclose( + tc.quantum.entanglement_entropy(s, [0, 1]), np.log(2.0), atol=1e-5 + ) + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_negativity(backend, highp): + c = tc.DMCircuit(2) + c.h(0) + c.cnot(0, 1) + c.depolarizing(0, px=0.1, py=0.1, pz=0.1) + dm = c.state() + np.testing.assert_allclose( + tc.quantum.log_negativity(dm, [0], base="2"), 0.485427, atol=1e-5 + ) + np.testing.assert_allclose( + tc.quantum.partial_transpose(tc.quantum.partial_transpose(dm, [0]), [0]), + dm, + atol=1e-6, + ) + np.testing.assert_allclose( + tc.quantum.entanglement_negativity(dm, [1]), -0.33176, atol=1e-5 + ) + + @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) def test_tn2qop(backend): nwires = 6 @@ -466,3 +499,28 @@ def test_ps2xyz(): xyz.update({"y": []}) assert tc.quantum.ps2xyz([0, 1, 3]) == xyz assert tc.quantum.ps2xyz([0, 1, 3, 0]) == xyz + + +@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")]) +def test_reduced_wavefunction(backend): + c = tc.Circuit(3) + c.h(0) + c.cnot(0, 1) + r = c.cond_measure(0) + s = c.state() + s1 = tc.quantum.reduced_wavefunction(s, [0, 2], [r, 0]) + if tc.backend.cast(r, tc.rdtypestr) < 0.5: + np.testing.assert_allclose(s1, np.array([1, 0]), atol=1e-5) + else: + np.testing.assert_allclose(s1, np.array([0, 1]), atol=1e-5) + + c = tc.Circuit(3) + c.h(0) + c.cnot(0, 1) + s = c.state() + s1 = tc.quantum.reduced_wavefunction(s, [2], [0]) + + c1 = tc.Circuit(2) + c1.h(0) + c1.cnot(0, 1) + np.testing.assert_allclose(s1, c1.state(), atol=1e-5) diff --git a/tests/test_shadows.py b/tests/test_shadows.py new file mode 100644 index 00000000..9d6406b6 --- /dev/null +++ b/tests/test_shadows.py @@ -0,0 +1,160 @@ +import pytest +from pytest_lazyfixture import lazy_fixture as lf +import numpy as np +import tensorcircuit as tc +from tensorcircuit.shadows import ( + shadow_bound, + shadow_snapshots, + global_shadow_state, + entropy_shadow, + renyi_entropy_2, + expectation_ps_shadow, + global_shadow_state1, +) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_jit(backend): + nq, repeat = 8, 5 + ps = [1, 0, 0, 0, 2, 0, 0, 0] + sub = (1, 3, 6, 7) + error = 0.1 + ns, k = shadow_bound(ps, error) + ns //= repeat + + thetas = 2 * np.random.rand(2, nq) - 1 + + c = tc.Circuit(nq) + for i in range(nq): + c.H(i) + for i in range(2): + for j in range(nq): + c.cnot(j, (j + 1) % nq) + for j in range(nq): + c.rz(j, theta=thetas[i, j] * np.pi) + + psi = c.state() + pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(ns, nq))) + status = tc.backend.convert_to_tensor(np.random.rand(ns, repeat)) + + def classical_shadow(psi, pauli_strings, status): + lss_states = shadow_snapshots(psi, pauli_strings, status) + expc = expectation_ps_shadow(lss_states, ps=ps, k=k) + ent = entropy_shadow(lss_states, sub=sub, alpha=2) + return expc, ent + + csjit = tc.backend.jit(classical_shadow) + + exact_expc = c.expectation_ps(ps=ps) + exact_rdm = tc.quantum.reduced_density_matrix(psi, cut=[0, 2, 4, 5]) + exact_ent = tc.quantum.renyi_entropy(exact_rdm, k=2) + expc, ent = csjit(psi, pauli_strings, status) + expc = np.median(expc) + + np.testing.assert_allclose(expc, exact_expc, atol=error) + np.testing.assert_allclose(ent, exact_ent, atol=5 * error) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_state(backend): + nq, ns = 2, 10000 + + c = tc.Circuit(nq) + c.H(0) + c.cnot(0, 1) + + psi = c.state() + bell_state = psi[:, None] @ psi[None, :] + + pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(ns, nq))) + status = tc.backend.convert_to_tensor(np.random.rand(ns, 5)) + lss_states = shadow_snapshots(c.state(), pauli_strings, status) + sdw_state = global_shadow_state(lss_states) + sdw_state1 = global_shadow_state1(lss_states) + + np.testing.assert_allclose(sdw_state, bell_state, atol=0.1) + np.testing.assert_allclose(sdw_state1, bell_state, atol=0.1) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +def test_ent(backend): + nq, ns, repeat = 6, 1000, 500 + + thetas = 2 * np.random.rand(2, nq) - 1 + + c = tc.Circuit(nq) + for i in range(nq): + c.H(i) + for i in range(2): + for j in range(nq): + c.cnot(j, (j + 1) % nq) + for j in range(nq): + c.rz(j, theta=thetas[i, j] * np.pi) + + sub = [1, 4] + psi = c.state() + + pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(ns, nq))) + status = tc.backend.convert_to_tensor(np.random.rand(ns, repeat)) + snapshots = shadow_snapshots(psi, pauli_strings, status, measurement_only=True) + + exact_rdm = tc.quantum.reduced_density_matrix( + psi, cut=[i for i in range(nq) if i not in sub] + ) + exact_ent = tc.quantum.renyi_entropy(exact_rdm, k=2) + ent = entropy_shadow(snapshots, pauli_strings, sub, alpha=2) + ent2 = renyi_entropy_2(snapshots, sub) + + np.testing.assert_allclose(ent, exact_ent, atol=0.1) + np.testing.assert_allclose(ent2, exact_ent, atol=0.1) + + +# @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")]) +# def test_expc(backend): +# import pennylane as qml +# +# nq, ns, repeat = 6, 2000, 1000 +# +# thetas = 2 * np.random.rand(2, nq) - 1 +# +# c = tc.Circuit(nq) +# for i in range(nq): +# c.H(i) +# for i in range(2): +# for j in range(nq): +# c.cnot(j, (j + 1) % nq) +# for j in range(nq): +# c.rz(j, theta=thetas[i, j] * np.pi) +# +# ps = [1, 0, 0, 0, 0, 3] +# sub = [1, 4] +# psi = c.state() +# +# pauli_strings = tc.backend.convert_to_tensor(np.random.randint(1, 4, size=(ns, nq))) +# status = tc.backend.convert_to_tensor(np.random.rand(ns, repeat)) +# snapshots = shadow_snapshots(psi, pauli_strings, status, measurement_only=True) +# +# exact_expc = c.expectation_ps(ps=ps) +# exact_rdm = tc.quantum.reduced_density_matrix( +# psi, cut=[i for i in range(nq) if i not in sub] +# ) +# exact_ent = tc.quantum.renyi_entropy(exact_rdm, k=2) +# print(exact_expc, exact_ent) +# +# expc = np.median(expection_ps_shadow(snapshots, pauli_strings, ps=ps, k=9)) +# ent = entropy_shadow(snapshots, pauli_strings, sub, alpha=2) +# ent2 = renyi_entropy_2(snapshots, sub) +# print(expc, ent, ent2) +# +# pl_snapshots = np.asarray(snapshots).reshape(ns * repeat, nq) +# pl_ps = np.tile(np.asarray(pauli_strings - 1)[:, None, :], (1, repeat, 1)).reshape( +# ns * repeat, nq +# ) +# shadow = qml.ClassicalShadow(pl_snapshots, pl_ps) +# H = qml.PauliX(0) @ qml.PauliZ(5) +# pl_expc = shadow.expval(H, k=9) +# pl_ent = shadow.entropy(sub, alpha=2) +# print(pl_expc, pl_ent) +# +# assert np.isclose(expc, pl_expc) +# assert np.isclose(ent, pl_ent) diff --git a/tests/test_templates.py b/tests/test_templates.py index c22b6a73..79e2b176 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -1,7 +1,8 @@ # pylint: disable=invalid-name -import sys import os +import sys + import numpy as np import pytest from pytest_lazyfixture import lazy_fixture as lf @@ -25,7 +26,7 @@ def test_any_measurement(): np.testing.assert_allclose(r2, 0.0, atol=1e-5) -@pytest.mark.parametrize("backend", [lf("jaxb"), lf("tfb"), lf("jaxb")]) +@pytest.mark.parametrize("backend", [lf("jaxb"), lf("tfb")]) def test_parameterized_local_measurement(backend): c = tc.Circuit(3) c.X(0) @@ -160,10 +161,6 @@ def test_operator_measurement(backend): ) dense = tc.array_to_tensor(np.kron(tc.gates._x_matrix, np.eye(2))) sparse = tc.quantum.PauliString2COO([1, 0]) - if tc.backend.name == "jax": - sparse = tc.backend.coo_sparse_matrix( - sparse.indices, sparse.values, sparse.shape - ) for h in [dense, sparse, mpo]: @@ -178,3 +175,34 @@ def f(theta): np.testing.assert_allclose(v, 0.84147, atol=1e-4) np.testing.assert_allclose(g, 0.54032, atol=1e-4) + + +@pytest.fixture +def symmetric_matrix(): + matrix = np.array([[-5.0, -2.0], [-2.0, 6.0]]) + nsym_matrix = np.array( + [[1.0, 2.0, 3.0], [2.0, 4.0, 5.0], [3.0, 5.0, 6.0], [8.0, 7.0, 6.0]] + ) + return matrix, nsym_matrix + + +def test_QUBO_to_Ising(symmetric_matrix): + matrix1, matrix2 = symmetric_matrix + pauli_terms, weights, offset = tc.templates.conversions.QUBO_to_Ising(matrix1) + n = matrix1.shape[0] + expected_num_terms = n + n * (n - 1) // 2 + assert len(pauli_terms) == expected_num_terms + assert len(weights) == expected_num_terms + assert isinstance(pauli_terms, list) + assert isinstance(weights, np.ndarray) + assert isinstance(offset, float) + assert pauli_terms == [ + [1, 0], + [0, 1], + [1, 1], + ] + assert all(weights == np.array([3.5, -2.0, -1.0])) + assert offset == -0.5 + + with pytest.raises(ValueError): + tc.templates.conversions.QUBO_to_Ising(matrix2) diff --git a/tests/test_torchnn.py b/tests/test_torchnn.py index 1d2807bb..88549248 100644 --- a/tests/test_torchnn.py +++ b/tests/test_torchnn.py @@ -14,7 +14,7 @@ try: import torch except ImportError: - pytest.skip("torch is not installed") + pytest.skip("torch is not installed", allow_module_level=True) @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")]) @@ -74,3 +74,26 @@ def f(state, noise, weights): lsum.backward() for p in layer.parameters(): print(p.grad) + + +@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")]) +def test_torchnn_hardware(backend): + n = 2 + + def qf(inputs, param): + inputs = tc.backend.convert_to_tensor(tc.get_backend("pytorch").numpy(inputs)) + param = tc.backend.convert_to_tensor(tc.get_backend("pytorch").numpy(param)) + + c = tc.Circuit(n) + c.rx(0, theta=inputs[0]) + c.rx(1, theta=inputs[1]) + c.h(1) + c.rzz(0, 1, theta=param[0]) + r = tc.backend.stack([c.expectation_ps(z=[i]) for i in range(n)]) + + r = tc.get_backend("pytorch").convert_to_tensor(tc.backend.numpy(r)) + return torch.real(r) + + ql = tc.torchnn.HardwareNet(qf, [1]) + qnet = torch.nn.Sequential(ql, torch.nn.Linear(2, 1)) + print(qnet(torch.ones([5, 2]))) diff --git a/tests/test_waveform_types_to_tqasm.py b/tests/test_waveform_types_to_tqasm.py new file mode 100644 index 00000000..f2587bfe --- /dev/null +++ b/tests/test_waveform_types_to_tqasm.py @@ -0,0 +1,48 @@ +import sys +import os + +# Add the directory containing your module to Python's search path +module_path = "/Users/mac/tensorcircuit" +sys.path.insert(0, module_path) + +from tensorcircuit import Circuit, Param, waveforms + +def test_waveform_types_to_tqasm_(): + test_cases = [ + (waveforms.CosineDrag, [10, 0.2, "PI/2", 0.01], "cosine_drag"), + (waveforms.Gaussian, [0.5, 20, 5], "gaussian"), + (waveforms.GaussianSquare, [0.5, 20, 5, 10], "gaussian_square"), + (waveforms.Drag, [0.4, 30, 10, 0.2], "drag"), + (waveforms.Flattop, [1.0, 5, 20], "flattop"), + (waveforms.Constant, [0.7, 15], "constant"), + (waveforms.Sine, [0.3, "2*PI", 10], "sine"), + (waveforms.Cosine, [0.6, "PI", 8], "cosine"), + ] + + failed = False + + for waveform_class, args, expected_name in test_cases: + qc = Circuit(1) + p = Param("q0") + + builder = qc.calibrate("test_gate", [p]) + builder.new_frame("f0", p) + builder.play("f0", waveform_class(*args)) + builder.build() + + qasm = qc.to_tqasm() + print(f"--- {expected_name} ---\n{qasm}\n") + + if f"play(f0, {expected_name}(" not in qasm: + print(f"❌ FAILED: waveform {waveform_class.__name__} expected '{expected_name}', but not found in QASM output.") + failed = True + else: + print(f"✅ PASSED: waveform {expected_name}") + + if failed: + raise AssertionError("Some waveform QASM outputs were incorrect.") + else: + print("All waveform QASM outputs passed.") + +if __name__ == "__main__": + test_waveform_types_to_tqasm_() \ No newline at end of file