From 8202a464dd69ba2c2fae47a204b7962f1de3d541 Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 16:15:45 -0600 Subject: [PATCH 1/6] feat!: use qcs-sdk-python implementation of conjugate_pauli_by_clifford and generate_randomized_benchmarking_sequence --- poetry.lock | 28 ++++---- pyproject.toml | 2 +- pyquil/api/_compiler_client.py | 118 +++++---------------------------- 3 files changed, 32 insertions(+), 116 deletions(-) diff --git a/poetry.lock b/poetry.lock index aebfbfe59..db19f4973 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1965,24 +1965,24 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "qcs-sdk-python" -version = "0.5.0rc17" +version = "0.5.0rc20" description = "Python interface for the QCS Rust SDK" category = "main" optional = false python-versions = "*" files = [ - {file = "qcs_sdk_python-0.5.0rc17-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:d54e6513a738be58fe3ce9147b8915f458e40f87e6704a4807f315600481fd15"}, - {file = "qcs_sdk_python-0.5.0rc17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ae0508a55e69065eb9c34a7e9571a18bcdbd3b9ec1aaf0dec6a7c1a82c81485"}, - {file = "qcs_sdk_python-0.5.0rc17-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47c87e214a8b9b34bbad8c9d33b9ea6cb58b357480ba6b7710f9ccfb97a43868"}, - {file = "qcs_sdk_python-0.5.0rc17-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a9e9b1f35621016b6bf67040e600a0a42fa26d24dbfa612fed3941e04f86258b"}, - {file = "qcs_sdk_python-0.5.0rc17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505aedb1967af81c7e224cab50aea175fdf7fe825821fda78398fde570c0521d"}, - {file = "qcs_sdk_python-0.5.0rc17-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1373d4fac6bda1259227d8947d36e32b5c39f06e8f2f8ad411d00af9774b36d"}, - {file = "qcs_sdk_python-0.5.0rc17-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:67a5b67a8e7f546fccf7eda027ce4c1b3a193d36de094c36aec0cb33644b3295"}, - {file = "qcs_sdk_python-0.5.0rc17-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc7abf6b06acc7dc34b5da5bba90874d47daf59603a471533c48ba81d82674e7"}, - {file = "qcs_sdk_python-0.5.0rc17-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0eb33e1519b5d8b72768cc60c19ab21b022521d6d932cb581e5f6742b60e3f7"}, - {file = "qcs_sdk_python-0.5.0rc17-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:19d3322bcb994dfbe16d5dcf92b77f82419ec2470ce95e1335d157a10a137109"}, - {file = "qcs_sdk_python-0.5.0rc17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6bfc26ceff1f8d847943df9247f87a0511e46f7b640ad52dc76d3922ef5877a"}, - {file = "qcs_sdk_python-0.5.0rc17-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1100a3ca85757cd59519de0343f530fed056d653dad3cbd7d94ca3426266cf36"}, + {file = "qcs_sdk_python-0.5.0rc20-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:7a71e27316c887bed8a736b1d223408cf5baff6967ce3db9238613aac112147d"}, + {file = "qcs_sdk_python-0.5.0rc20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aedd416159ec57b013429621805b41e02e875f6f51095f7e88a77650c002384a"}, + {file = "qcs_sdk_python-0.5.0rc20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3a2e3032deb95aca024535c24f933cb6ad6a9501ad59d95b1af01fd47479ce8"}, + {file = "qcs_sdk_python-0.5.0rc20-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:4cf6b20c3b1e984449db891ecb2d56b4149c3be9b873feeb3aa14f7bd494d629"}, + {file = "qcs_sdk_python-0.5.0rc20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e5e061a14cf2975273b93c246b8e56187e9cd291dcdef6d27db56b7dfd3bae"}, + {file = "qcs_sdk_python-0.5.0rc20-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a33b63e49ef1cddfd56f4f89ecad232931516d7630c383143ddf2f2a31096be"}, + {file = "qcs_sdk_python-0.5.0rc20-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:3da8ec54b8c10a62c4e656533c64d0b7596fa58e4b79afd05ee0dbd86a9390cc"}, + {file = "qcs_sdk_python-0.5.0rc20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5319c60213762edf44881407af00f467e99106f6bb678ea4890f0d1a652ef1df"}, + {file = "qcs_sdk_python-0.5.0rc20-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4edd1da6bb48af5baf98a1b7c4f592c9506498338ce76e3389e3ccc43186982"}, + {file = "qcs_sdk_python-0.5.0rc20-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b6fcc8b0d1afda5028c82c01c4b5169633a10f16f2064c2a4679de7bb8fc6b9d"}, + {file = "qcs_sdk_python-0.5.0rc20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d709d28c35d5b66a87d4955a0d67bfbd1689ef7d3e9a6546b55a411f4da72c4a"}, + {file = "qcs_sdk_python-0.5.0rc20-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:433735603803e26a335cef4614392daf18f830c2be7a2db2b488ec00126364b2"}, ] [[package]] @@ -2586,4 +2586,4 @@ latex = ["ipython"] [metadata] lock-version = "2.0" python-versions = "^3.8,<3.12" -content-hash = "893cd6cad7c5121beb3c1795e5be41568f5a811ba3123fe3af1ebc932f7c634d" +content-hash = "25a1413777c3e8b35f376849844267d86766c9885ed82a054b5df03db3befcf7" diff --git a/pyproject.toml b/pyproject.toml index cfb13c9c4..6715bb831 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ rpcq = "^3.10.0" pydantic = "^1.10.7" networkx = "^2.5" importlib-metadata = { version = ">=3.7.3,<5", python = "<3.8" } -qcs-sdk-python = "0.5.0rc.17" +qcs-sdk-python = "0.5.0rc.20" retry = "^0.9.2" types-python-dateutil = "^2.8.19" types-retry = "^0.9.9" diff --git a/pyquil/api/_compiler_client.py b/pyquil/api/_compiler_client.py index 68fa2e08c..b05c38a33 100644 --- a/pyquil/api/_compiler_client.py +++ b/pyquil/api/_compiler_client.py @@ -13,14 +13,23 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################################################## -from contextlib import contextmanager from dataclasses import dataclass import json -from typing import Iterator, List, Optional +from typing import List, Optional from qcs_sdk import QCSClient -from qcs_sdk.compiler.quilc import get_version_info, compile_program, CompilerOpts, TargetDevice -import rpcq +from qcs_sdk.compiler.quilc import ( + get_version_info, + compile_program, + CompilerOpts, + TargetDevice, + conjugate_pauli_by_clifford, + generate_randomized_benchmarking_sequence, + ConjugateByCliffordRequest, + ConjugatePauliByCliffordResponse, + RandomizedBenchmarkingRequest, + GenerateRandomizedBenchmarkingSequenceResponse, +) from rpcq.messages import TargetDevice as TargetQuantumProcessor @@ -87,67 +96,6 @@ class CompileToNativeQuilResponse: """Metadata for the returned Native Quil.""" -@dataclass -class ConjugatePauliByCliffordRequest: - """ - Request to conjugate a Pauli element by a Clifford element. - """ - - pauli_indices: List[int] - """Qubit indices onto which the factors of the Pauli term are applied.""" - - pauli_symbols: List[str] - """Ordered factors of the Pauli term.""" - - clifford: str - """Clifford element.""" - - -@dataclass -class ConjugatePauliByCliffordResponse: - """ - Conjugate Pauli by Clifford response. - """ - - phase_factor: int - """Encoded global phase factor on the emitted Pauli.""" - - pauli: str - """Description of the encoded Pauli.""" - - -@dataclass -class GenerateRandomizedBenchmarkingSequenceRequest: - """ - Request to generate a randomized benchmarking sequence. - """ - - depth: int - """Depth of the benchmarking sequence.""" - - num_qubits: int - """Number of qubits involved in the benchmarking sequence.""" - - gateset: List[str] - """List of Quil programs, each describing a Clifford.""" - - seed: Optional[int] - """PRNG seed. Set this to guarantee repeatable results.""" - - interleaver: Optional[str] - """Fixed Clifford, specified as a Quil string, to interleave through an RB sequence.""" - - -@dataclass -class GenerateRandomizedBenchmarkingSequenceResponse: - """ - Randomly generated benchmarking sequence response. - """ - - sequence: List[List[int]] - """List of Cliffords, each expressed as a list of generator indices.""" - - class CompilerClient: """ Client for making requests to a Quil compiler. @@ -197,48 +145,16 @@ def compile_to_native_quil(self, request: CompileToNativeQuilRequest) -> Compile ) return CompileToNativeQuilResponse(native_program=native_program, metadata=None) - def conjugate_pauli_by_clifford(self, request: ConjugatePauliByCliffordRequest) -> ConjugatePauliByCliffordResponse: + def conjugate_pauli_by_clifford(self, request: ConjugateByCliffordRequest) -> ConjugatePauliByCliffordResponse: """ Conjugate a Pauli element by a Clifford element. """ - rpcq_request = rpcq.messages.ConjugateByCliffordRequest( - pauli=rpcq.messages.PauliTerm(indices=request.pauli_indices, symbols=request.pauli_symbols), - clifford=request.clifford, - ) - with self._rpcq_client() as rpcq_client: # type: rpcq.Client - response: rpcq.messages.ConjugateByCliffordResponse = rpcq_client.call( - "conjugate_pauli_by_clifford", - rpcq_request, - ) - return ConjugatePauliByCliffordResponse(phase_factor=response.phase, pauli=response.pauli) + return conjugate_pauli_by_clifford(request=request, client=self._client_configuration) def generate_randomized_benchmarking_sequence( - self, request: GenerateRandomizedBenchmarkingSequenceRequest + self, request: RandomizedBenchmarkingRequest ) -> GenerateRandomizedBenchmarkingSequenceResponse: """ Generate a randomized benchmarking sequence. """ - rpcq_request = rpcq.messages.RandomizedBenchmarkingRequest( - depth=request.depth, - qubits=request.num_qubits, - gateset=request.gateset, - seed=request.seed, - interleaver=request.interleaver, - ) - with self._rpcq_client() as rpcq_client: # type: rpcq.Client - response: rpcq.messages.RandomizedBenchmarkingResponse = rpcq_client.call( - "generate_rb_sequence", - rpcq_request, - ) - return GenerateRandomizedBenchmarkingSequenceResponse(sequence=response.sequence) - - @contextmanager - def _rpcq_client(self) -> Iterator[rpcq.Client]: - client = rpcq.Client( - endpoint=self.base_url, - timeout=self.timeout, - ) - try: - yield client - finally: - client.close() # type: ignore + return generate_randomized_benchmarking_sequence(request=request, client=self._client_configuration) From 52ea5bd1ebca1a0e1b6dada2cd90a2cfc47ebf39 Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 16:53:10 -0600 Subject: [PATCH 2/6] fix: benchmark references --- pyquil/api/_benchmark.py | 15 +++++++++------ pyquil/api/_compiler_client.py | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pyquil/api/_benchmark.py b/pyquil/api/_benchmark.py index 129b2d4ec..7853d1054 100644 --- a/pyquil/api/_benchmark.py +++ b/pyquil/api/_benchmark.py @@ -19,8 +19,9 @@ from pyquil.api._abstract_compiler import AbstractBenchmarker from pyquil.api._compiler_client import ( - GenerateRandomizedBenchmarkingSequenceRequest, - ConjugatePauliByCliffordRequest, + RandomizedBenchmarkingRequest, + ConjugateByCliffordRequest, + PauliTerm as QuilcPauliTerm, CompilerClient, ) @@ -65,9 +66,11 @@ def apply_clifford_to_pauli(self, clifford: Program, pauli_in: PauliTerm) -> Pau indices_and_terms = list(zip(*list(pauli_in.operations_as_set()))) - request = ConjugatePauliByCliffordRequest( - pauli_indices=list(indices_and_terms[0]), - pauli_symbols=list(indices_and_terms[1]), + request = ConjugateByCliffordRequest( + pauli=QuilcPauliTerm( + indices=list(indices_and_terms[0]), + symbols=list(indices_and_terms[1]), + ), clifford=clifford.out(calibrations=False), ) response = self._compiler_client.conjugate_pauli_by_clifford(request) @@ -133,7 +136,7 @@ def generate_rb_sequence( depth = int(depth) # needs to be jsonable, no np.int64 please! - request = GenerateRandomizedBenchmarkingSequenceRequest( + request = RandomizedBenchmarkingRequest( depth=depth, num_qubits=qubits, gateset=gateset_for_api, diff --git a/pyquil/api/_compiler_client.py b/pyquil/api/_compiler_client.py index b05c38a33..b3861e6df 100644 --- a/pyquil/api/_compiler_client.py +++ b/pyquil/api/_compiler_client.py @@ -25,6 +25,7 @@ TargetDevice, conjugate_pauli_by_clifford, generate_randomized_benchmarking_sequence, + PauliTerm as PauliTerm, ConjugateByCliffordRequest, ConjugatePauliByCliffordResponse, RandomizedBenchmarkingRequest, From a264467fe24ca2fe8f1c8bddf3672a8f52271b22 Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 17:01:32 -0600 Subject: [PATCH 3/6] fix: type and import changeS --- pyquil/api/_benchmark.py | 6 +++--- pyquil/api/_compiler_client.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyquil/api/_benchmark.py b/pyquil/api/_benchmark.py index 7853d1054..3f19fa921 100644 --- a/pyquil/api/_benchmark.py +++ b/pyquil/api/_benchmark.py @@ -16,12 +16,12 @@ from typing import List, Optional, Sequence, cast from qcs_sdk import QCSClient +from qcs_sdk.compiler.quilc import PauliTerm as QuilcPauliTerm from pyquil.api._abstract_compiler import AbstractBenchmarker from pyquil.api._compiler_client import ( RandomizedBenchmarkingRequest, ConjugateByCliffordRequest, - PauliTerm as QuilcPauliTerm, CompilerClient, ) @@ -75,7 +75,7 @@ def apply_clifford_to_pauli(self, clifford: Program, pauli_in: PauliTerm) -> Pau ) response = self._compiler_client.conjugate_pauli_by_clifford(request) - phase_factor, paulis = response.phase_factor, response.pauli + phase_factor, paulis = response.phase, response.pauli pauli_out = PauliTerm("I", 0, 1.0j**phase_factor) clifford_qubits = clifford.get_qubits() @@ -138,7 +138,7 @@ def generate_rb_sequence( request = RandomizedBenchmarkingRequest( depth=depth, - num_qubits=qubits, + qubits=qubits, gateset=gateset_for_api, seed=seed, interleaver=interleaver_out, diff --git a/pyquil/api/_compiler_client.py b/pyquil/api/_compiler_client.py index b3861e6df..b05c38a33 100644 --- a/pyquil/api/_compiler_client.py +++ b/pyquil/api/_compiler_client.py @@ -25,7 +25,6 @@ TargetDevice, conjugate_pauli_by_clifford, generate_randomized_benchmarking_sequence, - PauliTerm as PauliTerm, ConjugateByCliffordRequest, ConjugatePauliByCliffordResponse, RandomizedBenchmarkingRequest, From a6d9c1f212430b105c729e66964fce9399d14ad1 Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 17:13:26 -0600 Subject: [PATCH 4/6] chore: fix imports for real for real, for real --- pyquil/api/_benchmark.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyquil/api/_benchmark.py b/pyquil/api/_benchmark.py index 3f19fa921..b51bb7bc9 100644 --- a/pyquil/api/_benchmark.py +++ b/pyquil/api/_benchmark.py @@ -16,15 +16,15 @@ from typing import List, Optional, Sequence, cast from qcs_sdk import QCSClient -from qcs_sdk.compiler.quilc import PauliTerm as QuilcPauliTerm - -from pyquil.api._abstract_compiler import AbstractBenchmarker -from pyquil.api._compiler_client import ( +from qcs_sdk.compiler.quilc import ( + PauliTerm as QuilcPauliTerm, RandomizedBenchmarkingRequest, ConjugateByCliffordRequest, - CompilerClient, ) +from pyquil.api._abstract_compiler import AbstractBenchmarker +from pyquil.api._compiler_client import CompilerClient + from pyquil.paulis import PauliTerm, is_identity from pyquil.quil import address_qubits, Program from pyquil.quilbase import Gate From 6d5975b9e3f5739c1a5d0fc72e9190345b3a7992 Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 17:34:18 -0600 Subject: [PATCH 5/6] chore: remove unnecessary tests --- test/unit/test_compiler_client.py | 63 ------------------------------- 1 file changed, 63 deletions(-) diff --git a/test/unit/test_compiler_client.py b/test/unit/test_compiler_client.py index d8d0f666f..8efc8f9b5 100644 --- a/test/unit/test_compiler_client.py +++ b/test/unit/test_compiler_client.py @@ -22,7 +22,6 @@ from mock import AsyncMock from qcs_sdk import QCSClient -import rpcq from _pytest.monkeypatch import MonkeyPatch import pytest from pytest import raises @@ -32,11 +31,6 @@ CompilerClient, CompileToNativeQuilRequest, CompileToNativeQuilResponse, - ConjugatePauliByCliffordRequest, - ConjugatePauliByCliffordResponse, - GenerateRandomizedBenchmarkingSequenceRequest, - GenerateRandomizedBenchmarkingSequenceResponse, - NativeQuilMetadataResponse, ) from pyquil.external.rpcq import CompilerISA, compiler_isa_to_target_quantum_processor @@ -102,60 +96,3 @@ def test_compile_to_native_quil__returns_native_quil( native_program="DECLARE ro BIT[1]\n", metadata=None, ) - - -def test_conjugate_pauli_by_clifford__returns_conjugation_result(mocker: MockerFixture): - client_configuration = QCSClient.load() - compiler_client = CompilerClient(client_configuration=client_configuration) - rpcq_client = patch_rpcq_client( - mocker=mocker, return_value=rpcq.messages.ConjugateByCliffordResponse(phase=42, pauli="pauli") - ) - - request = ConjugatePauliByCliffordRequest( - pauli_indices=[0, 1, 2], - pauli_symbols=["x", "y", "z"], - clifford="cliff", - ) - assert compiler_client.conjugate_pauli_by_clifford(request) == ConjugatePauliByCliffordResponse( - phase_factor=42, - pauli="pauli", - ) - rpcq_client.call.assert_called_once_with( - "conjugate_pauli_by_clifford", - rpcq.messages.ConjugateByCliffordRequest( - pauli=rpcq.messages.PauliTerm(indices=[0, 1, 2], symbols=["x", "y", "z"]), - clifford="cliff", - ), - ) - - -def test_generate_randomized_benchmarking_sequence__returns_benchmarking_sequence( - mocker: MockerFixture, -): - client_configuration = QCSClient.load() - compiler_client = CompilerClient(client_configuration=client_configuration) - - rpcq_client = patch_rpcq_client( - mocker=mocker, return_value=rpcq.messages.RandomizedBenchmarkingResponse(sequence=[[3, 1, 4], [1, 6, 1]]) - ) - - request = GenerateRandomizedBenchmarkingSequenceRequest( - depth=42, - num_qubits=3, - gateset=["some", "gate", "set"], - seed=314, - interleaver="some-interleaver", - ) - assert compiler_client.generate_randomized_benchmarking_sequence( - request - ) == GenerateRandomizedBenchmarkingSequenceResponse(sequence=[[3, 1, 4], [1, 6, 1]]) - rpcq_client.call.assert_called_once_with( - "generate_rb_sequence", - rpcq.messages.RandomizedBenchmarkingRequest( - depth=42, - qubits=3, - gateset=["some", "gate", "set"], - seed=314, - interleaver="some-interleaver", - ), - ) From 57d02896f1ffe9a4672678c2994f539cb88a998f Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Wed, 5 Apr 2023 17:47:59 -0600 Subject: [PATCH 6/6] chore: remove another unused test --- test/unit/test_compiler_client.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/unit/test_compiler_client.py b/test/unit/test_compiler_client.py index 8efc8f9b5..bbb3d37ac 100644 --- a/test/unit/test_compiler_client.py +++ b/test/unit/test_compiler_client.py @@ -57,16 +57,6 @@ def test_init__validates_compiler_url(monkeypatch: MonkeyPatch): CompilerClient(client_configuration=client_configuration) -def test_sets_timeout_on_requests(mocker: MockerFixture): - client_configuration = QCSClient.load() - compiler_client = CompilerClient(client_configuration=client_configuration, request_timeout=0.1) - - patch_rpcq_client(mocker=mocker, return_value={}) - - with compiler_client._rpcq_client() as client: - assert client.timeout == compiler_client.timeout - - @pytest.mark.skip # cannot mock `qcs_sdk` here def test_get_version__returns_version(mocker: MockerFixture): client_configuration = QCSClient.load()