Skip to content

Commit

Permalink
fix: only rewrite arithmetic when targeting Aspen processors (#1679)
Browse files Browse the repository at this point in the history
* fix: only rewrite arithmetic when targeting Aspen-M-3

* use translation Backend

* clarify comment

* update naming

* update pyproject

* update qcs-sdk-python

* fix type

* format

* rename per review
  • Loading branch information
notmgsk authored Oct 18, 2023
1 parent ca07ff6 commit a73a896
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 23 deletions.
38 changes: 19 additions & 19 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.12.7"
qcs-sdk-python = "0.12.8"
tenacity = "^8.2.2"
types-python-dateutil = "^2.8.19"
types-retry = "^0.9.9"
Expand Down
56 changes: 53 additions & 3 deletions pyquil/api/_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
# limitations under the License.
##############################################################################
from typing import Any, Dict, Optional
from warnings import warn

from qcs_sdk import QCSClient
from qcs_sdk.qpu.rewrite_arithmetic import rewrite_arithmetic
from qcs_sdk.qpu.translation import (
get_quilt_calibrations,
translate,
TranslationOptions as QPUCompilerAPIOptions,
TranslationBackend,
)
from qcs_sdk.compiler.quilc import QuilcClient
from rpcq.messages import ParameterSpec
Expand Down Expand Up @@ -106,10 +108,17 @@ def native_quil_to_executable(
If `api_options` is provided, it overrides the options set on `self`.
"""
rewrite_response = rewrite_arithmetic(nq_program.out())
program = nq_program.out()
recalculation_table = []
backend = api_options.backend if api_options is not None else None
backend = select_backend_for_quantum_processor_id(self.quantum_processor_id, backend)
if backend is TranslationBackend.V1:
rewrite_response = rewrite_arithmetic(nq_program.out())
program = rewrite_response.program
recalculation_table = list(rewrite_response.recalculation_table)

translated_program = translate(
native_quil=rewrite_response.program,
native_quil=program,
num_shots=nq_program.num_shots,
quantum_processor_id=self.quantum_processor_id,
translation_options=api_options or self.api_options,
Expand All @@ -121,7 +130,7 @@ def native_quil_to_executable(
program=translated_program.program,
memory_descriptors=_collect_memory_descriptors(nq_program),
ro_sources={parse_mref(mref): source for mref, source in ro_sources.items() or []},
recalculation_table=list(rewrite_response.recalculation_table),
recalculation_table=recalculation_table,
)

def _fetch_calibration_program(self) -> Program:
Expand Down Expand Up @@ -191,3 +200,44 @@ def __init__(

def native_quil_to_executable(self, nq_program: Program, **kwargs: Any) -> QuantumExecutable:
return nq_program


class IncompatibleBackendForQuantumProcessorIDWarning(Warning):
pass


def select_backend_for_quantum_processor_id(
quantum_processor_id: str, backend: Optional[TranslationBackend]
) -> TranslationBackend:
"""
Check that the translation backend is supported for the quantum processor.
If the translation backend is not supported by the quantum processor, a supported
translation backend is returned.
Aspen processors only support the V1 backend. Later processors support V2.
Once Aspen-M-3 is EOL, this function can be removed as `TranslationBackend.V2`
will be the only supported backend.
"""
if backend is None:
if quantum_processor_id.startswith("Aspen-"):
return TranslationBackend.V1
else:
return TranslationBackend.V2

if backend is TranslationBackend.V2 and quantum_processor_id.startswith("Aspen"):
warn(
"Backend V2 is not supported for Aspen processors. Backend has been changed to V1.",
IncompatibleBackendForQuantumProcessorIDWarning,
)
return TranslationBackend.V1

if backend is TranslationBackend.V1 and not quantum_processor_id.startswith("Aspen"):
warn(
"Backend V1 is only supported for Aspen processors. Backend has been changed to V2.",
IncompatibleBackendForQuantumProcessorIDWarning,
)
return TranslationBackend.V2

return backend
26 changes: 26 additions & 0 deletions test/unit/test_compiler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import math
from typing import Optional

import pytest
from syrupy.assertion import SnapshotAssertion

from pyquil import Program
from pyquil.api._compiler import QPUCompiler
from pyquil.gates import RX, MEASURE, RZ
from pyquil.quilatom import FormalArgument
from pyquil.quilbase import DefCalibration
from pyquil.api._compiler import select_backend_for_quantum_processor_id, IncompatibleBackendForQuantumProcessorIDWarning
from qcs_sdk.qpu.translation import TranslationBackend


def simple_program():
Expand All @@ -28,7 +32,29 @@ def test_compile_with_quilt_calibrations(compiler: QPUCompiler):
assert program.calibrations == cals
assert compilation_result == program


def test_transpile_qasm_2(compiler: QPUCompiler, snapshot: SnapshotAssertion):
qasm = 'OPENQASM 2.0;\nqreg q[3];\ncreg ro[2];\nmeasure q[0] -> ro[0];\nmeasure q[1] -> ro[1];'
program = compiler.transpile_qasm_2(qasm)
assert program.out() == snapshot


@pytest.mark.parametrize(
"quantum_processor_id,backend,expected,warns",
[
("Aspen-M-3", None, TranslationBackend.V1, False),
("Aspen-M-3", TranslationBackend.V1, TranslationBackend.V1, False),
("Aspen-M-3", TranslationBackend.V2, TranslationBackend.V1, True),
("Not-Aspen", None, TranslationBackend.V2, False),
("Not-Aspen", TranslationBackend.V1, TranslationBackend.V2, True),
("Not-Aspen", TranslationBackend.V2, TranslationBackend.V2, False),
]
)
def test_translation_backend_validation(quantum_processor_id: str, backend: Optional[TranslationBackend], expected: TranslationBackend, warns: bool):
if warns:
with pytest.warns(IncompatibleBackendForQuantumProcessorIDWarning):
actual = select_backend_for_quantum_processor_id(quantum_processor_id, backend)
else:
actual = select_backend_for_quantum_processor_id(quantum_processor_id, backend)
assert actual == expected

0 comments on commit a73a896

Please sign in to comment.