From 43a01cff478f67085e5edda793ca9bae0d783715 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 15 Jul 2021 13:32:20 +0100 Subject: [PATCH] Breaking: instruction_matrix returns a Result --- Cargo.lock | 3 ++- Cargo.toml | 2 +- src/matrix.rs | 69 +++++++++++++++++++++++++++++++++++++----------- src/vm/errors.rs | 4 +++ src/vm/mod.rs | 2 +- 5 files changed, 61 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bca9b1..969ffca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,7 +447,7 @@ dependencies = [ [[package]] name = "quil" version = "0.2.3" -source = "git+https://github.com/rigetti/quil-rust.git?tag=v0.2.3#78cff3d2c5ce1b4bccc69aa49e6fa2c138ec7622" +source = "git+https://github.com/rigetti/quil-rust.git?branch=derive-error-for-evaluation-error#08a5e2f48ff157e9a77534c881a81d01da1a2e68" dependencies = [ "indexmap", "lexical", @@ -455,6 +455,7 @@ dependencies = [ "num-complex 0.3.1", "petgraph", "serde", + "thiserror", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5dcf38c..2d9c01c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] structopt = "0.3.13" -quil = { git = "https://github.com/rigetti/quil-rust.git", tag = "v0.2.3" } +quil = { git = "https://github.com/rigetti/quil-rust.git", branch = "derive-error-for-evaluation-error" } num = "0.4.0" ndarray = "0.15.3" num-complex = "0.4.0" diff --git a/src/matrix.rs b/src/matrix.rs index 76001cf..fc182a3 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,39 +1,76 @@ use std::collections::HashMap; +use num::complex::Complex64; +use thiserror::Error; use crate::gates::{gate_matrix, QGate}; -use num::complex::Complex64; + use quil::instruction::{Instruction, Qubit}; +use quil::expression::EvaluationError; +use crate::matrix::InstructionMatrixError::{InvalidQubit, InvalidInstruction}; pub const C0: Complex64 = Complex64::new(0.0, 0.0); pub const C1: Complex64 = Complex64::new(1.0, 0.0); pub const I1: Complex64 = Complex64::new(0.0, 1.0); -pub fn instruction_matrix(instruction: Instruction) -> QGate { +#[derive(Error, Debug)] +pub enum InstructionMatrixError { + #[error("invalid parameter")] + InvalidParameter(#[from] EvaluationError), + #[error("cannot create matrix from gate with variable qubit {0}")] + InvalidQubit(String), + #[error("cannot create matrix from non-gate instruction {0}")] + InvalidInstruction(String), +} + +pub fn instruction_matrix(instruction: Instruction) -> Result { match instruction { Instruction::Gate { name, parameters, qubits, modifiers: _, - } => gate_matrix( - name, - parameters + } => { + let params: Result, EvaluationError> = parameters .iter() .map(|p| { - p.to_owned() - .evaluate_to_complex(&HashMap::new()) - .expect("bad") - .re + match p.to_owned().evaluate_to_complex(&HashMap::new()) { + Ok(c) => Ok(c.re), + Err(e) => Err(e), + } }) - .collect(), - qubits + .collect(); + let qubits: Result, _> = qubits .iter() .map(|q| match q { - Qubit::Fixed(i) => *i as usize, - Qubit::Variable(_) => todo!(), + Qubit::Fixed(i) => Ok(*i as usize), + Qubit::Variable(q) => Err(InvalidQubit(q.clone())), }) - .collect(), - ), - _ => todo!(), + .collect(); + Ok(gate_matrix(name, params?, qubits?)) + } + instruction => Err(InvalidInstruction(instruction.to_string())), } } + +#[cfg(test)] +pub mod test { + use crate::matrix::{instruction_matrix, InstructionMatrixError}; + use quil::instruction::{Instruction, Qubit}; + use crate::gates::QGate; + use quil::expression::Expression; + use quil::expression::Expression::Address; + + #[test] + pub fn blah() { + let instruction = Instruction::Gate { + name: "RX".to_string(), + parameters: vec![Expression::Variable("yo".to_string())], + qubits: vec![Qubit::Variable("a".to_string()), Qubit::Fixed(1)], + modifiers: vec![] + }; + match instruction_matrix(instruction) { + Ok(_) => {} + Err(e) => println!("{:?}", e) + } + } +} \ No newline at end of file diff --git a/src/vm/errors.rs b/src/vm/errors.rs index 210e225..f1f016d 100644 --- a/src/vm/errors.rs +++ b/src/vm/errors.rs @@ -1,4 +1,5 @@ use thiserror::Error; +use crate::matrix::InstructionMatrixError; #[derive(Error, Debug)] pub enum VMError { @@ -54,6 +55,9 @@ pub enum VMError { ssource: String, destination: String, }, + + #[error("Error when creating matrix")] + MatrixError(#[from] InstructionMatrixError), } // TODO VMError is nice but it doesn't show which instruction caused the error. Define a VMRunError diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 1e9bf85..a38819c 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -231,7 +231,7 @@ impl VM { Instruction::Gate { .. } => { // TODO errors - let matrix = instruction_matrix(instruction); + let matrix = instruction_matrix(instruction)?; self.apply(&matrix); }