Skip to content

Commit

Permalink
feat!: use qcs-sdk-python implementation of conjugate_pauli_by_cliffo…
Browse files Browse the repository at this point in the history
…rd and generate_randomized_benchmarking_sequence (#1557)

* feat!: use qcs-sdk-python implementation of conjugate_pauli_by_clifford and generate_randomized_benchmarking_sequence

* fix: benchmark references

* fix: type and import changeS

* chore: fix imports for real for real, for real

* chore: remove unnecessary tests

* chore: remove another unused test
  • Loading branch information
jselig-rigetti committed Apr 6, 2023
1 parent c5a9913 commit 05d6e15
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 200 deletions.
28 changes: 14 additions & 14 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
25 changes: 14 additions & 11 deletions pyquil/api/_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
from typing import List, Optional, Sequence, cast

from qcs_sdk import QCSClient
from qcs_sdk.compiler.quilc import (
PauliTerm as QuilcPauliTerm,
RandomizedBenchmarkingRequest,
ConjugateByCliffordRequest,
)

from pyquil.api._abstract_compiler import AbstractBenchmarker
from pyquil.api._compiler_client import (
GenerateRandomizedBenchmarkingSequenceRequest,
ConjugatePauliByCliffordRequest,
CompilerClient,
)
from pyquil.api._compiler_client import CompilerClient

from pyquil.paulis import PauliTerm, is_identity
from pyquil.quil import address_qubits, Program
Expand Down Expand Up @@ -65,14 +66,16 @@ 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)

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()
Expand Down Expand Up @@ -133,9 +136,9 @@ def generate_rb_sequence(

depth = int(depth) # needs to be jsonable, no np.int64 please!

request = GenerateRandomizedBenchmarkingSequenceRequest(
request = RandomizedBenchmarkingRequest(
depth=depth,
num_qubits=qubits,
qubits=qubits,
gateset=gateset_for_api,
seed=seed,
interleaver=interleaver_out,
Expand Down
118 changes: 17 additions & 101 deletions pyquil/api/_compiler_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
73 changes: 0 additions & 73 deletions test/unit/test_compiler_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -32,11 +31,6 @@
CompilerClient,
CompileToNativeQuilRequest,
CompileToNativeQuilResponse,
ConjugatePauliByCliffordRequest,
ConjugatePauliByCliffordResponse,
GenerateRandomizedBenchmarkingSequenceRequest,
GenerateRandomizedBenchmarkingSequenceResponse,
NativeQuilMetadataResponse,
)
from pyquil.external.rpcq import CompilerISA, compiler_isa_to_target_quantum_processor

Expand All @@ -63,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()
Expand Down Expand Up @@ -102,60 +86,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",
),
)

0 comments on commit 05d6e15

Please sign in to comment.