From 6fd23207bc2dc97e02656839e14f1ae291815ac9 Mon Sep 17 00:00:00 2001 From: Kalan Date: Mon, 5 Jun 2023 19:24:59 -0700 Subject: [PATCH 1/3] feat(python): support TranslationOptions --- .../qcs_sdk/grpc/models/translation.pyi | 45 +++++++++++++++++++ crates/python/qcs_sdk/qpu/translation.pyi | 3 ++ crates/python/src/grpc/mod.rs | 8 ++++ crates/python/src/grpc/models/mod.rs | 8 ++++ crates/python/src/grpc/models/translation.rs | 11 ++++- 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 crates/python/qcs_sdk/grpc/models/translation.pyi diff --git a/crates/python/qcs_sdk/grpc/models/translation.pyi b/crates/python/qcs_sdk/grpc/models/translation.pyi new file mode 100644 index 000000000..78bb203b6 --- /dev/null +++ b/crates/python/qcs_sdk/grpc/models/translation.pyi @@ -0,0 +1,45 @@ +from typing import Optional, final + +class TranslationOptions: + translation_backend: Optional[TranslationBackend] = None + + ... + +@final +class TranslationBackend: + """ + Object specifying which translation backend to use to translate a particular program, + and for that given backend, what options to apply. + + Variants: + ``v1``: Corresponds to the V1 translation backend. + ``v2``: Corresponds to the V2 translation backend. + + Methods (each per variant): + - ``is_*``: if the underlying values are that type. + - ``as_*``: if the underlying values are that type, then those values, otherwise ``None``. + - ``to_*``: the underlying values as that type, raises ``ValueError`` if they are not. + - ``from_*``: wrap underlying values as this enum type. + + """ + + def is_v1(self) -> bool: ... + def is_v2(self) -> bool: ... + def as_v1(self) -> Optional[BackendV1Options]: ... + def as_v2(self) -> Optional[BackendV2Options]: ... + def to_v1(self) -> BackendV1Options: ... + def to_v2(self) -> BackendV2Options: ... + @staticmethod + def from_v1(inner: BackendV1Options) -> "TranslationBackend": ... + @staticmethod + def from_v2(inner: BackendV2Options) -> "TranslationBackend": ... + +class BackendV1Options: + """ + Options for the V1 translation backend. + """ + +class BackendV2Options: + """ + Options for the V2 translation backend. + """ \ No newline at end of file diff --git a/crates/python/qcs_sdk/qpu/translation.pyi b/crates/python/qcs_sdk/qpu/translation.pyi index ea8fd13da..11666738e 100644 --- a/crates/python/qcs_sdk/qpu/translation.pyi +++ b/crates/python/qcs_sdk/qpu/translation.pyi @@ -1,6 +1,7 @@ from typing import Dict, Optional, final from qcs_sdk.client import QCSClient +from qcs_sdk.grpc.models.translation import TranslationOptions class GetQuiltCalibrationsError(RuntimeError): """An error occured while fetching Quil-T calibrations.""" @@ -88,6 +89,7 @@ def translate( num_shots: int, quantum_processor_id: str, client: Optional[QCSClient] = None, + translation_options: Optional[TranslationOptions] = None, ) -> TranslationResult: """ Translates a native Quil program into an executable program. @@ -109,6 +111,7 @@ async def translate_async( num_shots: int, quantum_processor_id: str, client: Optional[QCSClient] = None, + translation_options: Optional[TranslationOptions] = None, ) -> TranslationResult: """ Translates a native Quil program into an executable program. diff --git a/crates/python/src/grpc/mod.rs b/crates/python/src/grpc/mod.rs index c446ac883..28364fb7d 100644 --- a/crates/python/src/grpc/mod.rs +++ b/crates/python/src/grpc/mod.rs @@ -1 +1,9 @@ +use rigetti_pyo3::create_init_submodule; + pub mod models; + +create_init_submodule! { + submodules: [ + "models": models::init_submodule + ], +} \ No newline at end of file diff --git a/crates/python/src/grpc/models/mod.rs b/crates/python/src/grpc/models/mod.rs index 8eb70c293..7d4136c54 100644 --- a/crates/python/src/grpc/models/mod.rs +++ b/crates/python/src/grpc/models/mod.rs @@ -1,2 +1,10 @@ +use rigetti_pyo3::create_init_submodule; + pub mod controller; pub mod translation; + +create_init_submodule! { + submodules: [ + "translation": translation::init_submodule + ], +} diff --git a/crates/python/src/grpc/models/translation.rs b/crates/python/src/grpc/models/translation.rs index 1c999272c..846618df4 100644 --- a/crates/python/src/grpc/models/translation.rs +++ b/crates/python/src/grpc/models/translation.rs @@ -1,7 +1,7 @@ use qcs_api_client_grpc::services::translation::{ translation_options::TranslationBackend, BackendV1Options, BackendV2Options, TranslationOptions, }; -use rigetti_pyo3::{py_wrap_data_struct, py_wrap_type, py_wrap_union_enum}; +use rigetti_pyo3::{py_wrap_data_struct, py_wrap_type, py_wrap_union_enum, create_init_submodule}; py_wrap_type! { #[derive(Default)] @@ -26,3 +26,12 @@ py_wrap_data_struct! { translation_backend: Option => Option } } + +create_init_submodule! { + classes: [ + PyTranslationBackend, + PyTranslationOptions, + PyBackendV1Options, + PyBackendV2Options + ], +} \ No newline at end of file From 327f9848a17e59418b728a0d22a9590a873ce862 Mon Sep 17 00:00:00 2001 From: Kalan Date: Mon, 5 Jun 2023 19:52:58 -0700 Subject: [PATCH 2/3] add submodule reference --- crates/lib/src/qpu/translation.rs | 47 +++++++++++++++++++++++++++---- crates/python/src/lib.rs | 1 + 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/crates/lib/src/qpu/translation.rs b/crates/lib/src/qpu/translation.rs index 6e30de029..7183c5455 100644 --- a/crates/lib/src/qpu/translation.rs +++ b/crates/lib/src/qpu/translation.rs @@ -6,8 +6,9 @@ use std::{collections::HashMap, time::Duration}; use qcs_api_client_grpc::{ models::controller::EncryptedControllerJob, services::translation::{ - translate_quil_to_encrypted_controller_job_request::NumShots, - TranslateQuilToEncryptedControllerJobRequest, TranslationOptions, + self, translate_quil_to_encrypted_controller_job_request::NumShots, + translation_options::TranslationBackend, TranslateQuilToEncryptedControllerJobRequest, + TranslationOptions as RdmTranslationOptions, }, }; use qcs_api_client_openapi::{ @@ -33,13 +34,16 @@ pub struct EncryptedTranslationResult { } /// Translate a program, returning an encrypted and translated program. -pub async fn translate( +pub async fn translate( quantum_processor_id: &str, quil_program: &str, num_shots: u32, client: &Qcs, - translation_options: Option, -) -> Result { + translation_options: TO, +) -> Result +where + TO: Into>, +{ #[cfg(feature = "tracing")] tracing::debug!( %num_shots, @@ -47,11 +51,13 @@ pub async fn translate( quantum_processor_id, ); + let options = translation_options.into(); + let request = TranslateQuilToEncryptedControllerJobRequest { quantum_processor_id: quantum_processor_id.to_owned(), num_shots: Some(NumShots::NumShotsValue(num_shots)), quil_program: quil_program.to_owned(), - options: translation_options, + options, }; let response = client @@ -104,3 +110,32 @@ pub async fn get_quilt_calibrations( }) .await? } + +/// Options available for Quil program translation. +/// +/// This wraps [`RdmTranslationOptions`] in order to improve the user experience, +/// because the structs auto-generated by `prost` can be clumsy to use directly. +#[derive(Debug, Default)] +pub struct TranslationOptions { + inner: RdmTranslationOptions, +} + +impl TranslationOptions { + /// Use the first-generation translation backend available on QCS since 2018. + pub fn use_backend_v1(&mut self) { + self.inner.translation_backend = + Some(TranslationBackend::V1(translation::BackendV1Options {})) + } + + /// Use the second-generation translation backend available on QCS since 2023 + pub fn use_backend_v2(&mut self) { + self.inner.translation_backend = + Some(TranslationBackend::V2(translation::BackendV2Options {})) + } +} + +impl From for RdmTranslationOptions { + fn from(options: TranslationOptions) -> Self { + options.inner + } +} diff --git a/crates/python/src/lib.rs b/crates/python/src/lib.rs index e1f970879..a338583fb 100644 --- a/crates/python/src/lib.rs +++ b/crates/python/src/lib.rs @@ -36,6 +36,7 @@ create_init_submodule! { submodules: [ "client": client::init_submodule, "compiler": compiler::init_submodule, + "grpc": grpc::init_submodule, "qpu": qpu::init_submodule, "qvm": qvm::init_submodule ], From 6ce00781431e0d31cddcbde6c7d054945ec77c7c Mon Sep 17 00:00:00 2001 From: Jake Selig Date: Tue, 6 Jun 2023 12:16:43 +0900 Subject: [PATCH 3/3] chore: add constructors for grpc types --- crates/python/src/grpc/models/translation.rs | 33 ++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/python/src/grpc/models/translation.rs b/crates/python/src/grpc/models/translation.rs index 846618df4..8e198a671 100644 --- a/crates/python/src/grpc/models/translation.rs +++ b/crates/python/src/grpc/models/translation.rs @@ -1,18 +1,37 @@ use qcs_api_client_grpc::services::translation::{ translation_options::TranslationBackend, BackendV1Options, BackendV2Options, TranslationOptions, }; -use rigetti_pyo3::{py_wrap_data_struct, py_wrap_type, py_wrap_union_enum, create_init_submodule}; +use rigetti_pyo3::{ + create_init_submodule, py_wrap_data_struct, py_wrap_type, py_wrap_union_enum, + pyo3::{pymethods, PyResult}, +}; py_wrap_type! { #[derive(Default)] PyBackendV1Options(BackendV1Options) as "BackendV1Options"; } +#[pymethods] +impl PyBackendV1Options { + #[new] + fn __new__() -> PyResult { + Ok(Self::default()) + } +} + py_wrap_type! { #[derive(Default)] PyBackendV2Options(BackendV2Options) as "BackendV2Options"; } +#[pymethods] +impl PyBackendV2Options { + #[new] + fn __new__() -> PyResult { + Ok(Self::default()) + } +} + py_wrap_union_enum! { PyTranslationBackend(TranslationBackend) as "TranslationBackend" { v1: V1 => PyBackendV1Options, @@ -27,6 +46,16 @@ py_wrap_data_struct! { } } +#[pymethods] +impl PyTranslationOptions { + #[new] + fn __new__(translation_backend: Option) -> PyResult { + Ok(Self(TranslationOptions { + translation_backend: translation_backend.map(|b| b.0), + })) + } +} + create_init_submodule! { classes: [ PyTranslationBackend, @@ -34,4 +63,4 @@ create_init_submodule! { PyBackendV1Options, PyBackendV2Options ], -} \ No newline at end of file +}