From 375357751aaabf1870ca7b8c4cc661cc18948669 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 30 Nov 2023 12:22:35 +0000 Subject: [PATCH 01/20] Reports backend_info --- docs/changelog.rst | 5 +++++ pytket/extensions/qulacs/backends/qulacs_backend.py | 4 ++-- setup.py | 2 +- tests/test_qulacs_backend.py | 5 +++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 9460c7b..f0788a5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,11 @@ Changelog ~~~~~~~~~ +Unreleased +-------------------- + +* Backends now report backend_info. + 0.32.0 (November 2023) ---------------------- diff --git a/pytket/extensions/qulacs/backends/qulacs_backend.py b/pytket/extensions/qulacs/backends/qulacs_backend.py index 12360e1..0e905e5 100644 --- a/pytket/extensions/qulacs/backends/qulacs_backend.py +++ b/pytket/extensions/qulacs/backends/qulacs_backend.py @@ -122,7 +122,7 @@ def __init__( type(self).__name__, None, __extension_version__, - Architecture([]), + None, self._GATE_SET, ) self._result_type = result_type @@ -142,7 +142,7 @@ def _result_id_type(self) -> _ResultIdTuple: @property def backend_info(self) -> Optional["BackendInfo"]: - return None + return self._backend_info @property def required_predicates(self) -> List[Predicate]: diff --git a/setup.py b/setup.py index c0e5fa9..8136579 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ license="Apache 2", packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, - install_requires=["pytket ~= 1.22", "qulacs ~= 0.6.0"], + install_requires=["pytket ~= 1.23.0rc0", "qulacs ~= 0.6.0"], classifiers=[ "Environment :: Console", "Programming Language :: Python :: 3.9", diff --git a/tests/test_qulacs_backend.py b/tests/test_qulacs_backend.py index bcf72c7..d2d37d2 100644 --- a/tests/test_qulacs_backend.py +++ b/tests/test_qulacs_backend.py @@ -335,6 +335,11 @@ def test_backend_with_circuit_permutation() -> None: assert np.allclose(sv, sv1, atol=1e-10) +def test_backend_info() -> None: + for b in backends: + assert b.backend_info is not None + + @given( n_shots=strategies.integers(min_value=1, max_value=10), # type: ignore n_bits=strategies.integers(min_value=0, max_value=10), From a5bd2e284089df6cc479e33fbeec8212863ff8ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 02:00:57 +0000 Subject: [PATCH 02/20] Bump the python-packages group with 1 update Updates the requirements on [openfermion](https://github.com/quantumlib/OpenFermion) to permit the latest version. - [Release notes](https://github.com/quantumlib/OpenFermion/releases) - [Commits](https://github.com/quantumlib/OpenFermion/compare/v1.3.0...v1.6.0) --- updated-dependencies: - dependency-name: openfermion dependency-type: direct:production dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- tests/test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-requirements.txt b/tests/test-requirements.txt index cc94ffa..ddf35c2 100644 --- a/tests/test-requirements.txt +++ b/tests/test-requirements.txt @@ -2,4 +2,4 @@ pytest pytest-timeout ~= 2.2.0 hypothesis requests_mock -openfermion~=1.3 +openfermion~=1.6 From 865eb25ad2814216b0db7486d8e324cf1637a827 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 01:26:43 +0000 Subject: [PATCH 03/20] Bump actions/deploy-pages from 2 to 3 Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 3. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index bc84a52..aa5c249 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -150,4 +150,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v3 From 4f7b38af823e15d11560680f6cb62a5b64e18179 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 01:14:13 +0000 Subject: [PATCH 04/20] Bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build_and_test.yml | 8 ++++---- .github/workflows/docs.yml | 2 +- .github/workflows/lint.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index aa5c249..94db14b 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -32,7 +32,7 @@ jobs: - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/* - name: Set up Python 3.9 if: github.event_name == 'push' || github.event_name == 'schedule' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.9' - name: Build and test (3.9) @@ -41,7 +41,7 @@ jobs: run: | ./.github/workflows/build-test nomypy - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Build and test including remote checks (3.10) mypy @@ -56,7 +56,7 @@ jobs: ./.github/workflows/build-test nomypy - name: Set up Python 3.11 if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'schedule' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Build and test (3.11) @@ -111,7 +111,7 @@ jobs: with: fetch-depth: '0' - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Download all wheels diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 34f5179..fce1a7c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Upgrade pip and install wheel diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bed8273..8af01e0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python 3.x - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Update pip From e58f056d5ab2e5cd66bc3466b97e542a0d6d4998 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 14:01:27 +0000 Subject: [PATCH 05/20] Bump actions/download-artifact from 3 to 4 (#66) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 94db14b..0308892 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -87,7 +87,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download all wheels - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: wheelhouse - name: Put them all in the dist folder @@ -115,7 +115,7 @@ jobs: with: python-version: '3.10' - name: Download all wheels - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: wheelhouse - name: Install pip, wheel From 24f3e2a561bac6412faae8239d71b174ffb83ed3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 14:01:48 +0000 Subject: [PATCH 06/20] Bump actions/upload-artifact from 3 to 4 (#67) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yml | 2 +- .github/workflows/docs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 0308892..62bed93 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -64,7 +64,7 @@ jobs: shell: bash run: | ./.github/workflows/build-test nomypy - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: github.event_name == 'release' || contains(github.ref, 'refs/heads/wheel') with: name: artefacts diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index fce1a7c..9c7fcaa 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,7 @@ jobs: cd .github/workflows/docs mkdir extensions ./build-docs -d ${GITHUB_WORKSPACE}/.github/workflows/docs/extensions - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: pytket-extension-docs path: .github/workflows/docs/extensions/ From 526fb35f9ffa262e5b94dc84b68137560b540143 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Fri, 15 Dec 2023 15:02:38 +0000 Subject: [PATCH 07/20] update actions and add PR template (#68) * update github actions * add PR template --- .github/pull_request_template.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..558b033 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,15 @@ +# Description + +Please summarise the changes. + +# Related issues + +Please mention any github issues addressed by this PR. + +# Checklist + +- [ ] I have performed a self-review of my code. +- [ ] I have commented hard-to-understand parts of my code. +- [ ] I have made corresponding changes to the public API documentation. +- [ ] I have added tests that prove my fix is effective or that my feature works. +- [ ] I have updated the changelog with any user-facing changes. From ad3e90378d8681f6a5d41dcfa5ec38029a4df259 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 11:11:50 +0100 Subject: [PATCH 08/20] Bump actions/upload-pages-artifact from 2 to 3 (#70) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 62bed93..53b2a2d 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -132,7 +132,7 @@ jobs: mkdir extensions ./build-docs -d ${GITHUB_WORKSPACE}/.github/workflows/docs/extensions/api - name: Upload docs as artefact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: path: .github/workflows/docs/extensions From d423140c87858a591610f7358d669e7617d89027 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 11:12:05 +0100 Subject: [PATCH 09/20] Bump actions/deploy-pages from 3 to 4 (#69) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 3 to 4. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 53b2a2d..a220a42 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -150,4 +150,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v3 + uses: actions/deploy-pages@v4 From e17574ad603e03e1d6f1739779bafbc5617c676b Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:47:11 +0000 Subject: [PATCH 10/20] Fix/workflow 2023 (#71) * fix artifact name related to update of actions/upload-artifact@v4 * split download in three options * update download of wheels --- .github/workflows/build_and_test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index a220a42..1e307ce 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -67,7 +67,7 @@ jobs: - uses: actions/upload-artifact@v4 if: github.event_name == 'release' || contains(github.ref, 'refs/heads/wheel') with: - name: artefacts + name: artefact-${{ matrix.os }} path: wheelhouse/ - name: Install docs dependencies if: (matrix.os == 'ubuntu-22.04') && (github.event_name == 'pull_request' || github.event_name == 'schedule' ) @@ -87,9 +87,13 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download all wheels + # downloading all three files into the wheelhouse + # all files are identical, so there will only be one file uses: actions/download-artifact@v4 with: path: wheelhouse + pattern: artefact-* + merge-multiple: true - name: Put them all in the dist folder run: | mkdir dist From 02064eb185b07a19d235739e9a9305c46fbad10a Mon Sep 17 00:00:00 2001 From: Calin Georgescu Date: Thu, 21 Dec 2023 14:12:20 +0100 Subject: [PATCH 11/20] Add support for converting multi-register circuits to Qulacs --- pytket/extensions/qulacs/qulacs_convert.py | 73 +++++++++++++++++++--- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/pytket/extensions/qulacs/qulacs_convert.py b/pytket/extensions/qulacs/qulacs_convert.py index b3187ed..126d27b 100644 --- a/pytket/extensions/qulacs/qulacs_convert.py +++ b/pytket/extensions/qulacs/qulacs_convert.py @@ -17,6 +17,60 @@ import numpy as np from qulacs import QuantumCircuit, gate from pytket.circuit import Circuit, OpType +from pytket.unit_id import Qubit + +def get_register_offset_map(circuit: Circuit) -> dict[str, int]: + """Creates a map that accounts for the offset required to access the + `pytket._tket.unit_id.Qubit`s of a `pytket._tket.unit_id.QubitRegister` + with an absolute index. + + Args: + circuit (Circuit): The circuit for which to create the map. + + Returns: + dict[str, int]: A dictionary where the keys are the names of the quantum registers + of the circuit and the values are the total number of qubits in preceeding registers. + """ + qubits_preceeding = 0 + offset_dict: dict[str, int] = {} + + for register in circuit.q_registers: + # The number of qubits to offset by is the number + # Of qubits in all register preceeding this one + offset_dict[register.name] = qubits_preceeding + + # Increase the number of qubits + # By the number of qubits this register contains + qubits_preceeding += register.size + + return offset_dict + +def get_qubit_index_map(circuit: Circuit, reverse_order: bool) -> dict[Qubit, int]: + """Creates a map that contains the absolute position of a qubit in a given circuit, + accounting for each qubit's register as well. + + Args: + circuit (Circuit): The circuit for which to create the map. + reverse_order (bool): Whether the circuits' qubit positions are reversed. + + Returns: + dict[Qubit, int]: A dictionary where the keys are the circuit's qubits + and the values are the absolute positions of qubits, accounting for the register's position. + """ + # Get the dictionary accounting for register positions + offset_map = get_register_offset_map(circuit) + index_map: dict[Qubit, int] = {} + + for register in circuit.q_registers: + for qubit_index, qubit in enumerate(register.to_list()): + # The position of the qubit is the sum of the offset (preceeding qubits) + # And the position of the qubit within its register + qubit_position = offset_map[register.name] + qubit_index + + # Invert the if the qubits are stored in reverse order + index_map[qubit] = qubit_position if not reverse_order else circuit.n_qubits - 1 - qubit_position + + return index_map _ONE_QUBIT_GATES = { OpType.X: gate.X, @@ -47,14 +101,17 @@ def tk_to_qulacs( circ.replace_implicit_wire_swaps() n_qubits = circ.n_qubits qulacs_circ = QuantumCircuit(circ.n_qubits) - index_map = { - i: (i if not reverse_index else n_qubits - 1 - i) for i in range(n_qubits) - } + + # Dictionary mapping qubits to their absolute position + # Within the quantum circuit + index_map = get_qubit_index_map(circ, reverse_index) + for com in circ: optype = com.op.type if optype in _IBM_GATES: qulacs_gate = _IBM_GATES[optype] - index = index_map[com.qubits[0].index[0]] + + index = index_map[com.qubits[0]] if optype == OpType.U1: param = com.op.params[0] @@ -70,19 +127,19 @@ def tk_to_qulacs( elif optype in _ONE_QUBIT_GATES: qulacs_gate = _ONE_QUBIT_GATES[optype] - index = index_map[com.qubits[0].index[0]] + index = index_map[com.qubits[0]] add_gate = qulacs_gate(index) elif optype in _ONE_QUBIT_ROTATIONS: qulacs_gate = _ONE_QUBIT_ROTATIONS[optype] - index = index_map[com.qubits[0].index[0]] + index = index_map[com.qubits[0]] param = com.op.params[0] * np.pi add_gate = qulacs_gate(index, -param) # parameter negated for qulacs elif optype in _TWO_QUBIT_GATES: qulacs_gate = _TWO_QUBIT_GATES[optype] - id1 = index_map[com.qubits[0].index[0]] - id2 = index_map[com.qubits[1].index[0]] + id1 = index_map[com.qubits[0]] + id2 = index_map[com.qubits[1]] add_gate = qulacs_gate(id1, id2) elif optype in _MEASURE_GATES: From bbe0df0cdf8eb8163a5e9c39863245d7c9eed859 Mon Sep 17 00:00:00 2001 From: Calin Georgescu Date: Thu, 21 Dec 2023 14:15:34 +0100 Subject: [PATCH 12/20] Reformat to contribution standard --- .../qulacs/backends/qulacs_backend.py | 2 +- pytket/extensions/qulacs/qulacs_convert.py | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pytket/extensions/qulacs/backends/qulacs_backend.py b/pytket/extensions/qulacs/backends/qulacs_backend.py index 0e905e5..f2e1fa7 100644 --- a/pytket/extensions/qulacs/backends/qulacs_backend.py +++ b/pytket/extensions/qulacs/backends/qulacs_backend.py @@ -291,7 +291,7 @@ def get_operator_expectation_value( self._check_all_circuits([state_circuit], nomeasure_warn=False) observable = Observable(state_circuit.n_qubits) - for (qps, coeff) in operator._dict.items(): + for qps, coeff in operator._dict.items(): _items = [] if qps != QubitPauliString(): for qubit, pauli in qps.map.items(): diff --git a/pytket/extensions/qulacs/qulacs_convert.py b/pytket/extensions/qulacs/qulacs_convert.py index 126d27b..c156cca 100644 --- a/pytket/extensions/qulacs/qulacs_convert.py +++ b/pytket/extensions/qulacs/qulacs_convert.py @@ -19,6 +19,7 @@ from pytket.circuit import Circuit, OpType from pytket.unit_id import Qubit + def get_register_offset_map(circuit: Circuit) -> dict[str, int]: """Creates a map that accounts for the offset required to access the `pytket._tket.unit_id.Qubit`s of a `pytket._tket.unit_id.QubitRegister` @@ -33,17 +34,18 @@ def get_register_offset_map(circuit: Circuit) -> dict[str, int]: """ qubits_preceeding = 0 offset_dict: dict[str, int] = {} - + for register in circuit.q_registers: # The number of qubits to offset by is the number # Of qubits in all register preceeding this one offset_dict[register.name] = qubits_preceeding - + # Increase the number of qubits # By the number of qubits this register contains qubits_preceeding += register.size - - return offset_dict + + return offset_dict + def get_qubit_index_map(circuit: Circuit, reverse_order: bool) -> dict[Qubit, int]: """Creates a map that contains the absolute position of a qubit in a given circuit, @@ -60,18 +62,23 @@ def get_qubit_index_map(circuit: Circuit, reverse_order: bool) -> dict[Qubit, in # Get the dictionary accounting for register positions offset_map = get_register_offset_map(circuit) index_map: dict[Qubit, int] = {} - + for register in circuit.q_registers: for qubit_index, qubit in enumerate(register.to_list()): # The position of the qubit is the sum of the offset (preceeding qubits) # And the position of the qubit within its register qubit_position = offset_map[register.name] + qubit_index - + # Invert the if the qubits are stored in reverse order - index_map[qubit] = qubit_position if not reverse_order else circuit.n_qubits - 1 - qubit_position - + index_map[qubit] = ( + qubit_position + if not reverse_order + else circuit.n_qubits - 1 - qubit_position + ) + return index_map + _ONE_QUBIT_GATES = { OpType.X: gate.X, OpType.Y: gate.Y, @@ -101,16 +108,15 @@ def tk_to_qulacs( circ.replace_implicit_wire_swaps() n_qubits = circ.n_qubits qulacs_circ = QuantumCircuit(circ.n_qubits) - + # Dictionary mapping qubits to their absolute position # Within the quantum circuit index_map = get_qubit_index_map(circ, reverse_index) - + for com in circ: optype = com.op.type if optype in _IBM_GATES: qulacs_gate = _IBM_GATES[optype] - index = index_map[com.qubits[0]] if optype == OpType.U1: From b593082b8bcc633c0dc2e32b79003f3715af4964 Mon Sep 17 00:00:00 2001 From: Calin Georgescu Date: Thu, 21 Dec 2023 14:20:14 +0100 Subject: [PATCH 13/20] Lint to contribution standard --- pytket/extensions/qulacs/backends/qulacs_backend.py | 1 - pytket/extensions/qulacs/qulacs_convert.py | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pytket/extensions/qulacs/backends/qulacs_backend.py b/pytket/extensions/qulacs/backends/qulacs_backend.py index f2e1fa7..77563fe 100644 --- a/pytket/extensions/qulacs/backends/qulacs_backend.py +++ b/pytket/extensions/qulacs/backends/qulacs_backend.py @@ -55,7 +55,6 @@ from pytket.circuit import Pauli from pytket.passes import auto_rebase_pass from pytket.pauli import QubitPauliString -from pytket.architecture import Architecture from pytket.utils.operators import QubitPauliOperator from pytket.utils.outcomearray import OutcomeArray from pytket.extensions.qulacs.qulacs_convert import ( diff --git a/pytket/extensions/qulacs/qulacs_convert.py b/pytket/extensions/qulacs/qulacs_convert.py index c156cca..8e4a8ce 100644 --- a/pytket/extensions/qulacs/qulacs_convert.py +++ b/pytket/extensions/qulacs/qulacs_convert.py @@ -29,8 +29,9 @@ def get_register_offset_map(circuit: Circuit) -> dict[str, int]: circuit (Circuit): The circuit for which to create the map. Returns: - dict[str, int]: A dictionary where the keys are the names of the quantum registers - of the circuit and the values are the total number of qubits in preceeding registers. + dict[str, int]: A dictionary where the keys are the names of the quantum + registers of the circuit and the values are + the total number of qubits in preceeding registers. """ qubits_preceeding = 0 offset_dict: dict[str, int] = {} @@ -57,7 +58,8 @@ def get_qubit_index_map(circuit: Circuit, reverse_order: bool) -> dict[Qubit, in Returns: dict[Qubit, int]: A dictionary where the keys are the circuit's qubits - and the values are the absolute positions of qubits, accounting for the register's position. + and the values are the absolute positions of qubits, + accounting for the register's position. """ # Get the dictionary accounting for register positions offset_map = get_register_offset_map(circuit) @@ -106,8 +108,7 @@ def tk_to_qulacs( circ = circuit.copy() if replace_implicit_swaps: circ.replace_implicit_wire_swaps() - n_qubits = circ.n_qubits - qulacs_circ = QuantumCircuit(circ.n_qubits) + qulacs_circ = QuantumCircuit(circ.n_qubits) # Dictionary mapping qubits to their absolute position # Within the quantum circuit From 02ee688d46af4561a6b8a9b80dda2e2c93254898 Mon Sep 17 00:00:00 2001 From: Calin Georgescu Date: Thu, 21 Dec 2023 15:03:57 +0100 Subject: [PATCH 14/20] Fix indendation --- pytket/extensions/qulacs/qulacs_convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytket/extensions/qulacs/qulacs_convert.py b/pytket/extensions/qulacs/qulacs_convert.py index 8e4a8ce..d0ea2dd 100644 --- a/pytket/extensions/qulacs/qulacs_convert.py +++ b/pytket/extensions/qulacs/qulacs_convert.py @@ -108,7 +108,7 @@ def tk_to_qulacs( circ = circuit.copy() if replace_implicit_swaps: circ.replace_implicit_wire_swaps() - qulacs_circ = QuantumCircuit(circ.n_qubits) + qulacs_circ = QuantumCircuit(circ.n_qubits) # Dictionary mapping qubits to their absolute position # Within the quantum circuit From 243f1a4af264e2a104131b8e70e6c196df6bd267 Mon Sep 17 00:00:00 2001 From: Calin Georgescu Date: Thu, 21 Dec 2023 17:44:49 +0100 Subject: [PATCH 15/20] Replace relative register indexing with flattening pass --- pytket/extensions/qulacs/qulacs_convert.py | 87 ++++------------------ 1 file changed, 14 insertions(+), 73 deletions(-) diff --git a/pytket/extensions/qulacs/qulacs_convert.py b/pytket/extensions/qulacs/qulacs_convert.py index d0ea2dd..00aaa52 100644 --- a/pytket/extensions/qulacs/qulacs_convert.py +++ b/pytket/extensions/qulacs/qulacs_convert.py @@ -17,69 +17,7 @@ import numpy as np from qulacs import QuantumCircuit, gate from pytket.circuit import Circuit, OpType -from pytket.unit_id import Qubit - - -def get_register_offset_map(circuit: Circuit) -> dict[str, int]: - """Creates a map that accounts for the offset required to access the - `pytket._tket.unit_id.Qubit`s of a `pytket._tket.unit_id.QubitRegister` - with an absolute index. - - Args: - circuit (Circuit): The circuit for which to create the map. - - Returns: - dict[str, int]: A dictionary where the keys are the names of the quantum - registers of the circuit and the values are - the total number of qubits in preceeding registers. - """ - qubits_preceeding = 0 - offset_dict: dict[str, int] = {} - - for register in circuit.q_registers: - # The number of qubits to offset by is the number - # Of qubits in all register preceeding this one - offset_dict[register.name] = qubits_preceeding - - # Increase the number of qubits - # By the number of qubits this register contains - qubits_preceeding += register.size - - return offset_dict - - -def get_qubit_index_map(circuit: Circuit, reverse_order: bool) -> dict[Qubit, int]: - """Creates a map that contains the absolute position of a qubit in a given circuit, - accounting for each qubit's register as well. - - Args: - circuit (Circuit): The circuit for which to create the map. - reverse_order (bool): Whether the circuits' qubit positions are reversed. - - Returns: - dict[Qubit, int]: A dictionary where the keys are the circuit's qubits - and the values are the absolute positions of qubits, - accounting for the register's position. - """ - # Get the dictionary accounting for register positions - offset_map = get_register_offset_map(circuit) - index_map: dict[Qubit, int] = {} - - for register in circuit.q_registers: - for qubit_index, qubit in enumerate(register.to_list()): - # The position of the qubit is the sum of the offset (preceeding qubits) - # And the position of the qubit within its register - qubit_position = offset_map[register.name] + qubit_index - - # Invert the if the qubits are stored in reverse order - index_map[qubit] = ( - qubit_position - if not reverse_order - else circuit.n_qubits - 1 - qubit_position - ) - - return index_map - +from pytket.passes import FlattenRegisters _ONE_QUBIT_GATES = { OpType.X: gate.X, @@ -106,19 +44,22 @@ def tk_to_qulacs( ) -> QuantumCircuit: """Convert a pytket circuit to a qulacs circuit object.""" circ = circuit.copy() + + if not circ.is_simple: + FlattenRegisters().apply(circ) + if replace_implicit_swaps: circ.replace_implicit_wire_swaps() + n_qubits = circ.n_qubits qulacs_circ = QuantumCircuit(circ.n_qubits) - - # Dictionary mapping qubits to their absolute position - # Within the quantum circuit - index_map = get_qubit_index_map(circ, reverse_index) - + index_map = { + i: (i if not reverse_index else n_qubits - 1 - i) for i in range(n_qubits) + } for com in circ: optype = com.op.type if optype in _IBM_GATES: qulacs_gate = _IBM_GATES[optype] - index = index_map[com.qubits[0]] + index = index_map[com.qubits[0].index[0]] if optype == OpType.U1: param = com.op.params[0] @@ -134,19 +75,19 @@ def tk_to_qulacs( elif optype in _ONE_QUBIT_GATES: qulacs_gate = _ONE_QUBIT_GATES[optype] - index = index_map[com.qubits[0]] + index = index_map[com.qubits[0].index[0]] add_gate = qulacs_gate(index) elif optype in _ONE_QUBIT_ROTATIONS: qulacs_gate = _ONE_QUBIT_ROTATIONS[optype] - index = index_map[com.qubits[0]] + index = index_map[com.qubits[0].index[0]] param = com.op.params[0] * np.pi add_gate = qulacs_gate(index, -param) # parameter negated for qulacs elif optype in _TWO_QUBIT_GATES: qulacs_gate = _TWO_QUBIT_GATES[optype] - id1 = index_map[com.qubits[0]] - id2 = index_map[com.qubits[1]] + id1 = index_map[com.qubits[0].index[0]] + id2 = index_map[com.qubits[1].index[0]] add_gate = qulacs_gate(id1, id2) elif optype in _MEASURE_GATES: From e1336c983bcdd70d62ef2afa0190b06668e548c9 Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:28:54 +0000 Subject: [PATCH 16/20] Correct URL for documentation. (#73) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8136579..5231bf4 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ author_email="tket-support@cambridgequantum.com", python_requires=">=3.9", project_urls={ - "Documentation": "https://tket.quantinuum.com/extensions/pytket-qulacs/api/index.html", + "Documentation": "https://tket.quantinuum.com/extensions/pytket-qulacs/index.html", "Source": "https://github.com/CQCL/pytket-qulacs", "Tracker": "https://github.com/CQCL/pytket-qulacs/issues", }, From 69b003db7283e8b3f9997c99555a96d36688d5ce Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 10 Jan 2024 14:52:59 +0000 Subject: [PATCH 17/20] update pytket version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5231bf4..c316ae1 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ license="Apache 2", packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, - install_requires=["pytket ~= 1.23.0rc0", "qulacs ~= 0.6.0"], + install_requires=["pytket ~= 1.23", "qulacs ~= 0.6.0"], classifiers=[ "Environment :: Console", "Programming Language :: Python :: 3.9", From 514e080478712bd1cdd087c09740880256ba5016 Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 10 Jan 2024 14:59:19 +0000 Subject: [PATCH 18/20] update changelog --- docs/changelog.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f0788a5..3b59437 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,9 +1,10 @@ Changelog ~~~~~~~~~ -Unreleased --------------------- +0.33.0 (January 2024) +--------------------- +* Updated pytket version requirement to 1.23. * Backends now report backend_info. 0.32.0 (November 2023) From 01889b6eda328097149d422fca4a40d7b4a81c8f Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 10 Jan 2024 16:08:27 +0000 Subject: [PATCH 19/20] update version --- _metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_metadata.py b/_metadata.py index 869a4c6..6559c0a 100644 --- a/_metadata.py +++ b/_metadata.py @@ -1,2 +1,2 @@ -__extension_version__ = "0.32.0" +__extension_version__ = "0.33.0" __extension_name__ = "pytket-qulacs" From 34ca5385c1853440f122eefdea21a3b031a279ce Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 10 Jan 2024 16:32:40 +0000 Subject: [PATCH 20/20] update deploy-pages@4.0.1 --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 1e307ce..18deb3d 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -154,4 +154,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v4.0.1