Skip to content

Commit

Permalink
feat: change panic to an error if cannot initialize libquil
Browse files Browse the repository at this point in the history
  • Loading branch information
notmgsk committed Oct 16, 2023
1 parent 9bc8edf commit f8e6643
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 25 deletions.
18 changes: 9 additions & 9 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::{
ffi::{CStr, CString},
path::{Path, PathBuf},
path::PathBuf,
str::Utf8Error,
sync::Once,
};
Expand All @@ -22,7 +22,7 @@ pub(crate) mod bindings {
static START: Once = Once::new();

#[derive(Debug, thiserror::Error)]
enum Error {
pub enum Error {
#[error("Could not find libquil core file. Set the LIBQUIL_CORE_PATH environment variable.")]
CoreFileNotFound,
}
Expand All @@ -45,13 +45,11 @@ fn find_core_file() -> Result<String, Error> {
}

/// Initializes libquil using it's core image. No-op after the first call.
pub(crate) fn init_libquil() {
pub(crate) fn init_libquil() -> Result<(), Error> {
let core_path = find_core_file()?;

START.call_once(|| {
let path = match find_core_file() {
Ok(path) => path,
Err(e) => panic!("{e}"),
};
let ptr = CString::new(path).unwrap().into_raw();
let ptr = CString::new(core_path).unwrap().into_raw();

unsafe {
// The library built by maturin does link to libquil, but
Expand All @@ -67,7 +65,9 @@ pub(crate) fn init_libquil() {
bindings::init(ptr);
let _ = CString::from_raw(ptr);
}
})
});

Ok(())
}

pub(crate) fn handle_libquil_error(errno: libquil_error_t) -> Result<(), String> {
Expand Down
24 changes: 14 additions & 10 deletions lib/src/quilc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub enum Error {
ProgramString(String),
#[error("invalid UTF-8 program: {0}")]
ProgramUtf8(#[from] std::str::Utf8Error),
#[error("failed to initialize libquil: {0}")]
FailedToInitializeLibquil(#[from] crate::Error),
}
/// A quilc chip specification
#[derive(Clone, Debug)]
Expand All @@ -54,7 +56,7 @@ impl TryFrom<CString> for Chip {
type Error = Error;

fn try_from(json: CString) -> Result<Self, Self::Error> {
crate::init_libquil();
crate::init_libquil()?;

let ptr = json.into_raw();
let mut chip: chip_specification = std::ptr::null_mut();
Expand Down Expand Up @@ -97,7 +99,7 @@ impl TryFrom<CString> for Program {
type Error = Error;

fn try_from(program: CString) -> Result<Self, Self::Error> {
init_libquil();
init_libquil()?;

let ptr = program.into_raw();
let mut parsed_program: quil_program = std::ptr::null_mut();
Expand Down Expand Up @@ -128,7 +130,7 @@ impl Drop for Program {

impl Program {
pub fn to_string(&self) -> Result<String, Error> {
init_libquil();
init_libquil()?;

unsafe {
let mut program_string_ptr: *mut std::os::raw::c_char = std::ptr::null_mut();
Expand All @@ -145,7 +147,7 @@ impl Program {

/// Compiles the [`Program`] for the given [`Chip`]
pub fn compile_program(program: &Program, chip: &Chip) -> Result<CompilationResult, Error> {
init_libquil();
init_libquil()?;
let mut compiled_program: quil_program = std::ptr::null_mut();

unsafe {
Expand Down Expand Up @@ -238,7 +240,8 @@ pub struct CompilationResult {
/// Compiles the [`Program`] for the given [`Chip`] and restricts
/// the resulting [`Program`] to satisfy "protoquil" constraints
pub fn compile_protoquil(program: &Program, chip: &Chip) -> Result<CompilationResult, Error> {
init_libquil();
init_libquil()?;

let mut compiled_program: quil_program = std::ptr::null_mut();
let metadata_ptr: quilc_compilation_metadata = std::ptr::null_mut();

Expand All @@ -265,7 +268,8 @@ pub fn compile_protoquil(program: &Program, chip: &Chip) -> Result<CompilationRe

/// Get a fully-connected 2Q [`Chip`]
pub fn get_chip() -> Result<Chip, Error> {
init_libquil();
init_libquil()?;

let mut chip: chip_specification = std::ptr::null_mut();

unsafe {
Expand All @@ -278,7 +282,7 @@ pub fn get_chip() -> Result<Chip, Error> {

/// Prints the given [`Program`] to stdout
pub fn print_program(program: &Program) -> Result<(), Error> {
init_libquil();
init_libquil()?;

unsafe {
let err = quilc_print_program.unwrap()(program.0);
Expand All @@ -299,7 +303,7 @@ pub fn conjugate_pauli_by_clifford(
pauli_terms: Vec<CString>,
clifford: &Program,
) -> Result<ConjugatePauliByCliffordResult, Error> {
init_libquil();
init_libquil()?;

unsafe {
let mut phase = 0;
Expand Down Expand Up @@ -336,7 +340,7 @@ pub fn generate_rb_sequence(
seed: Option<i32>,
interleaver: Option<&Program>,
) -> Result<Vec<Vec<i32>>, Error> {
init_libquil();
init_libquil()?;

let mut gateset = gateset.iter().map(|p| p.0).collect::<Vec<_>>();
let mut results_ptr: *mut std::ffi::c_int = std::ptr::null_mut();
Expand Down Expand Up @@ -399,7 +403,7 @@ impl Display for VersionInfo {
}

pub fn get_version_info() -> Result<VersionInfo, Error> {
init_libquil();
init_libquil()?;

unsafe {
let mut version_info: quilc_version_info = std::ptr::null_mut();
Expand Down
14 changes: 8 additions & 6 deletions lib/src/qvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub enum Error {
Wavefunction(String),
#[error("failed to perform expectation: {0}")]
Expectation(String),
#[error("failed to initialize libquil: {0}")]
FailedToInitializeLibquil(#[from] crate::Error),
}

#[derive(Debug)]
Expand All @@ -43,7 +45,7 @@ impl Display for VersionInfo {
}

pub fn get_version_info() -> Result<VersionInfo, Error> {
init_libquil();
init_libquil()?;

unsafe {
let mut version_info: qvm_version_info = std::ptr::null_mut();
Expand Down Expand Up @@ -144,7 +146,7 @@ pub fn multishot(
) -> Result<HashMap<String, Vec<Vec<u32>>>, Error> {
let mut multishot = HashMap::new();

init_libquil();
init_libquil()?;
let addresses: QvmMultishotAddresses = addresses.try_into()?;
let mut result_ptr: qvm_multishot_result = std::ptr::null_mut();

Expand Down Expand Up @@ -205,7 +207,7 @@ pub fn multishot_measure(
qubits: &[i32],
trials: i32,
) -> Result<Vec<Vec<i32>>, Error> {
init_libquil();
init_libquil()?;

// NOTE(mgsk): There might be a way for this to be a Vec<Vec<i32>>
// which would exactly match our return type. In practice, however,
Expand Down Expand Up @@ -237,7 +239,7 @@ pub fn wavefunction(
program: &quilc::Program,
n_qubits: u32,
) -> Result<Vec<num_complex::Complex64>, Error> {
init_libquil();
init_libquil()?;

let mut wavefunction = vec![0.0; 2 * 2u32.pow(n_qubits) as usize];

Expand All @@ -259,7 +261,7 @@ pub fn wavefunction(
/// of finding the quantum state in `|i>`. For example, `v[2]` is the probability
/// of finding the quantum state in `|10>`; `v[5]` the probability of `|101>`; etc.
pub fn probabilities(program: &quilc::Program, n_qubits: u32) -> Result<Vec<f64>, Error> {
init_libquil();
init_libquil()?;

let mut probabilities = vec![0.0; 2u32.pow(n_qubits) as usize];

Expand All @@ -277,7 +279,7 @@ pub fn expectation(
program: &quilc::Program,
operators: Vec<&quilc::Program>,
) -> Result<Vec<f64>, Error> {
init_libquil();
init_libquil()?;

unsafe {
let mut expectations = vec![0.0; operators.len()];
Expand Down

0 comments on commit f8e6643

Please sign in to comment.