Skip to content

Commit

Permalink
feat!: Loading a Qcs Client is now infallible and is the primary clie…
Browse files Browse the repository at this point in the history
…nt used throughout the library. (#302)

---------

Co-authored-by: Michael Bryant <[email protected]>
  • Loading branch information
MarquessV and Shadow53 authored May 25, 2023
1 parent 3866fb4 commit 54fe5ef
Show file tree
Hide file tree
Showing 27 changed files with 212 additions and 272 deletions.
48 changes: 30 additions & 18 deletions crates/lib/src/qpu/client.rs → crates/lib/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ pub struct Qcs {

impl Qcs {
/// Create a [`Qcs`] and initialize it with the user's default [`ClientConfiguration`]
pub async fn load() -> Result<Self, LoadError> {
ClientConfiguration::load_default()
.await
.or_else(|_| {
#[cfg(feature = "tracing")]
tracing::info!(
"No QCS client configuration found. QPU data and QCS will be inaccessible and only generic QVMs will be available for execution"
);
Ok(ClientConfiguration::default())
})
.map(Self::with_config)
pub async fn load() -> Self {
let config = if let Ok(config) = ClientConfiguration::load_default().await {
config
} else {
#[cfg(feature = "tracing")]
tracing::info!(
"No QCS client configuration found. QPU data and QCS will be inaccessible and only generic QVMs will be available for execution"
);
ClientConfiguration::default()
};
Self::with_config(config)
}

/// Create a [`Qcs`] and initialize it with the given [`ClientConfiguration`]
Expand All @@ -65,17 +65,29 @@ impl Qcs {
}
}

/// Create a [`Qcs`] and initialized with the given `profile`.
///
/// # Errors
///
/// A [`LoadError`] will be returned if QCS credentials are
/// not correctly configured or the given profile is not defined.
pub async fn with_profile(profile: String) -> Result<Qcs, LoadError> {
ClientConfiguration::load_profile(profile)
.await
.map(Self::with_config)
}

/// Enable or disable the use of Gateway service for execution
#[must_use]
pub fn with_use_gateway(mut self, use_gateway: bool) -> Self {
self.use_gateway = use_gateway;
self
}

/// Return a copy of all settings parsed and resolved from configuration sources.
/// Return a reference to the underlying [`ClientConfiguration`] with all settings parsed and resolved from configuration sources.
#[must_use]
pub fn get_config(&self) -> ClientConfiguration {
self.config.clone()
pub fn get_config(&self) -> &ClientConfiguration {
&self.config
}

pub(crate) async fn get_controller_client(
Expand All @@ -85,7 +97,7 @@ impl Qcs {
{
let uri = self.get_controller_endpoint(quantum_processor_id).await?;
let channel = get_channel(uri).map_err(|err| GrpcEndpointError::GrpcError(err.into()))?;
let service = wrap_channel_with(channel, self.get_config());
let service = wrap_channel_with(channel, self.get_config().clone());
Ok(ControllerClient::new(service))
}

Expand All @@ -96,12 +108,12 @@ impl Qcs {
{
let uri = self.get_controller_endpoint_by_id(endpoint_id).await?;
let channel = get_channel(uri).map_err(|err| GrpcEndpointError::GrpcError(err.into()))?;
let service = wrap_channel_with(channel, self.get_config());
let service = wrap_channel_with(channel, self.get_config().clone());
Ok(ControllerClient::new(service))
}

pub(crate) fn get_openapi_client(&self) -> OpenApiConfiguration {
OpenApiConfiguration::with_qcs_config(self.get_config())
OpenApiConfiguration::with_qcs_config(self.get_config().clone())
}

pub(crate) fn get_translation_client(
Expand All @@ -122,7 +134,7 @@ impl Qcs {
> {
let uri = parse_uri(translation_grpc_endpoint)?;
let channel = get_channel(uri)?;
let service = wrap_channel_with(channel, self.get_config());
let service = wrap_channel_with(channel, self.get_config().clone());
Ok(TranslationClient::new(service))
}

Expand Down
24 changes: 9 additions & 15 deletions crates/lib/src/compiler/quilc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use qcs_api_client_openapi::models::InstructionSetArchitecture;
use super::isa::{self, Compiler};
use super::rpcq;

use crate::qpu::client::Qcs;
use crate::client::Qcs;

/// Number of seconds to wait before timing out.
pub const DEFAULT_COMPILER_TIMEOUT: f64 = 30.0;
Expand Down Expand Up @@ -47,8 +47,7 @@ pub fn compile_program(
#[cfg(feature = "tracing")]
tracing::debug!(compiler_options=?options, "compiling quil program with quilc",);

let config = client.get_config();
let endpoint = config.quilc_url();
let endpoint = client.get_config().quilc_url();
let params = QuilcParams::new(quil, isa).with_protoquil(options.protoquil);
let request =
rpcq::RPCRequest::new("quil_to_native_quil", &params).with_timeout(options.timeout);
Expand Down Expand Up @@ -428,7 +427,7 @@ mod tests {
let output = compile_program(
"MEASURE 0",
TargetDevice::try_from(qvm_isa()).expect("Couldn't build target device from ISA"),
&Qcs::load().await.unwrap_or_default(),
&Qcs::load().await,
CompilerOpts::default(),
)
.expect("Could not compile");
Expand All @@ -446,7 +445,7 @@ MEASURE 1 ro[1]

#[tokio::test]
async fn run_compiled_bell_state_on_qvm() {
let client = Qcs::load().await.unwrap_or_default();
let client = Qcs::load().await;
let output = compile_program(
BELL_STATE,
TargetDevice::try_from(aspen_9_isa()).expect("Couldn't build target device from ISA"),
Expand All @@ -456,12 +455,7 @@ MEASURE 1 ro[1]
.expect("Could not compile");
let mut results = crate::qvm::Execution::new(&output.program.to_string(true))
.unwrap()
.run(
10,
&[Cow::Borrowed("ro")],
&HashMap::default(),
&client.get_config(),
)
.run(10, &[Cow::Borrowed("ro")], &HashMap::default(), &client)
.await
.expect("Could not run program on QVM");
for shot in results
Expand All @@ -478,7 +472,7 @@ MEASURE 1 ro[1]

#[tokio::test]
async fn test_compile_declare_only() {
let client = Qcs::load().await.unwrap_or_default();
let client = Qcs::load().await;
let output = compile_program(
"DECLARE ro BIT[1]\n",
TargetDevice::try_from(aspen_9_isa()).expect("Couldn't build target device from ISA"),
Expand All @@ -492,15 +486,15 @@ MEASURE 1 ro[1]

#[tokio::test]
async fn get_version_info_from_quilc() {
let client = Qcs::load().await.unwrap_or_default();
let client = Qcs::load().await;
let version = get_version_info(&client).expect("Should get version info from quilc");
let semver_re = Regex::new(r"^([0-9]+)\.([0-9]+)\.([0-9]+)$").unwrap();
assert!(semver_re.is_match(&version));
}

#[tokio::test]
async fn test_conjugate_pauli_by_clifford() {
let client = Qcs::load().await.unwrap_or_default();
let client = Qcs::load().await;
let request = ConjugateByCliffordRequest {
pauli: PauliTerm {
indices: vec![0],
Expand All @@ -522,7 +516,7 @@ MEASURE 1 ro[1]

#[tokio::test]
async fn test_generate_randomized_benchmark_sequence() {
let client = Qcs::load().await.unwrap_or_default();
let client = Qcs::load().await;
let request = RandomizedBenchmarkingRequest {
depth: 2,
qubits: 1,
Expand Down
Loading

0 comments on commit 54fe5ef

Please sign in to comment.