diff --git a/Cargo.lock b/Cargo.lock index 277c1e20..c3d2fa9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -442,6 +442,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generational-arena" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" +dependencies = [ + "cfg-if", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -464,6 +473,12 @@ dependencies = [ "syn 2.0.22", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "half" version = "1.8.2" @@ -1073,7 +1088,7 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quil-py" -version = "0.4.0-rc.0" +version = "0.4.0" dependencies = [ "ndarray", "numpy", @@ -1086,12 +1101,13 @@ dependencies = [ [[package]] name = "quil-rs" -version = "0.20.0-rc.0" +version = "0.20.0" dependencies = [ "approx", "criterion", "dot-writer", "egg", + "generational-arena", "indexmap", "insta", "itertools 0.11.0", @@ -1228,6 +1244,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "relative-path" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" + [[package]] name = "rigetti-pyo3" version = "0.1.0" @@ -1243,9 +1265,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de1bb486a691878cd320c2f0d319ba91eeaa2e894066d8b5f8f117c000e9d962" +checksum = "2b96577ca10cb3eade7b337eb46520108a67ca2818a24d0b63f41fd62bc9651c" dependencies = [ "futures", "futures-timer", @@ -1255,15 +1277,18 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290ca1a1c8ca7edb7c3283bd44dc35dd54fdec6253a3912e201ba1072018fca8" +checksum = "225e674cf31712b8bb15fdbca3ec0c1b9d825c5a24407ff2b7e005fb6a29ba03" dependencies = [ "cfg-if", + "glob", "proc-macro2 1.0.63", "quote 1.0.28", + "regex", + "relative-path", "rustc_version", - "syn 1.0.109", + "syn 2.0.22", "unicode-ident", ] diff --git a/quil-rs/Cargo.toml b/quil-rs/Cargo.toml index 4e998ca4..415efced 100644 --- a/quil-rs/Cargo.toml +++ b/quil-rs/Cargo.toml @@ -13,6 +13,7 @@ categories = ["parser-implementations", "science", "compilers", "emulators"] approx = { version = "0.5.1", features = ["num-complex"] } dot-writer = { version = "0.1.2", optional = true } egg = { version = "0.9.4", features = ["deterministic"] } +generational-arena = "0.2.9" indexmap = "1.6.1" itertools = "0.11.0" lexical = "6.1.1" @@ -33,7 +34,7 @@ insta = "1.7.1" petgraph = "0.6.2" proptest = "1.0.0" proptest-derive = "0.3.0" -rstest = "0.17.0" +rstest = "0.18.1" # These are described in the crate README.md [features] diff --git a/quil-rs/src/expression/mod.rs b/quil-rs/src/expression/mod.rs index d5626dfe..f10444dd 100644 --- a/quil-rs/src/expression/mod.rs +++ b/quil-rs/src/expression/mod.rs @@ -35,7 +35,7 @@ use std::{ #[cfg(test)] use proptest_derive::Arbitrary; -mod simplification; +//mod simplification; mod simplification_2; /// The different possible types of errors that could occur during expression evaluation. @@ -60,7 +60,7 @@ pub enum Expression { Variable(String), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct FunctionCallExpression { pub function: ExpressionFunction, pub expression: Box, @@ -75,7 +75,7 @@ impl FunctionCallExpression { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct InfixExpression { pub left: Box, pub operator: InfixOperator, @@ -92,7 +92,7 @@ impl InfixExpression { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct PrefixExpression { pub operator: PrefixOperator, pub expression: Box, @@ -135,15 +135,15 @@ impl Hash for Expression { "Infix".hash(state); operator.hash(state); match operator { - InfixOperator::Plus | InfixOperator::Star => { - // commutative, so put left & right in decreasing order by hash value - let (a, b) = ( - min_by_key(&left, &right, hash_to_u64), - max_by_key(&left, &right, hash_to_u64), - ); - a.hash(state); - b.hash(state); - } + //InfixOperator::Plus | InfixOperator::Star => { + // // commutative, so put left & right in decreasing order by hash value + // let (a, b) = ( + // min_by_key(&left, &right, hash_to_u64), + // max_by_key(&left, &right, hash_to_u64), + // ); + // a.hash(state); + // b.hash(state); + //} _ => { left.hash(state); right.hash(state); @@ -181,7 +181,17 @@ impl Hash for Expression { impl PartialEq for Expression { // Partial equality by hash value fn eq(&self, other: &Self) -> bool { - hash_to_u64(self) == hash_to_u64(other) + // hash_to_u64(self) == hash_to_u64(other) + match (self, other) { + (Self::Address(left), Self::Address(right)) => left == right, + (Self::Infix(left), Self::Infix(right)) => left == right, + (Self::Number(left), Self::Number(right)) => left == right, + (Self::Prefix(left), Self::Prefix(right)) => left == right, + (Self::FunctionCall(left), Self::FunctionCall(right)) => left == right, + (Self::Variable(left), Self::Variable(right)) => left == right, + (Self::PiConstant, Self::PiConstant) => true, + _ => false, + } } } @@ -274,9 +284,8 @@ impl Expression { *self = Expression::Number(Complex64::from(PI)); } _ => { - if let Ok(simpler) = simplification::run(self) { - *self = simpler; - } + let temp = std::mem::replace(self, Expression::PiConstant); + *self = simplification_2::run(temp); } } } diff --git a/quil-rs/src/expression/simplification_2.rs b/quil-rs/src/expression/simplification_2.rs index fa1ff83d..c0b182e0 100644 --- a/quil-rs/src/expression/simplification_2.rs +++ b/quil-rs/src/expression/simplification_2.rs @@ -1,35 +1,81 @@ +use generational_arena::{Arena, Index}; + /// Complex machinery for simplifying [`Expression`]s. use crate::expression::{ imag, real, Expression, ExpressionFunction, FunctionCallExpression, InfixExpression, InfixOperator, PrefixExpression, PrefixOperator, }; -use std::cmp::min_by_key; +use std::{cmp::min_by_key, collections::HashMap}; + +#[derive(Default)] +struct ExpressionCache { + cache: HashMap, + arena: Arena, +} + +enum SimplifiedExpression { + Expression(Expression), + Simplified(Index), +} + +impl ExpressionCache { + fn cache(&mut self, original: Expression, simplified: Expression) -> Index { + let index = self.arena.insert(simplified.clone()); + self.cache.insert(original, index); + self.cache.insert(simplified, index); + index + } + + fn get_index(&self, original: &Expression) -> Option { + self.cache.get(original).copied() + } + + fn index(&self, index: Index) -> &Expression { + &self.arena[index] + } + + fn get(&self, index: Index) -> &Expression { + self.index(index) + } + + fn remove(&mut self, index: Index) -> Expression { + self.arena.remove(index).unwrap() + } +} /// Simplify an [`Expression`]. -pub(super) fn run(expression: &Expression) -> Expression { - simplify(expression) +pub(super) fn run(expression: Expression) -> Expression { + let mut cache = ExpressionCache::default(); + let simplified = simplify(&mut cache, expression); + cache.remove(simplified) } /// Recursively simplify an [`Expression`], breaking into cases to make things more manageable. -fn simplify(e: &Expression) -> Expression { - match e { - Expression::Address(_) - | Expression::Number(_) - | Expression::PiConstant - | Expression::Variable(_) => e.clone(), - Expression::FunctionCall(FunctionCallExpression { - function, - expression, - }) => simplify_function_call(function, expression), - Expression::Infix(InfixExpression { - left, - operator, - right, - }) => simplify_infix(left, operator, right), - Expression::Prefix(PrefixExpression { - operator, - expression, - }) => simplify_prefix(operator, expression), +fn simplify(cache: &mut ExpressionCache, e: Expression) -> Index { + if let Some(index) = cache.get_index(&e) { + index + } else { + let simplified = match e.clone() { + Expression::Address(_) + | Expression::Number(_) + | Expression::PiConstant + | Expression::Variable(_) => e.clone(), + Expression::FunctionCall(FunctionCallExpression { + function, + expression, + }) => simplify_function_call(cache, function, *expression), + Expression::Infix(InfixExpression { + left, + operator, + right, + }) => simplify_infix(cache, *left, operator, *right), + Expression::Prefix(PrefixExpression { + operator, + expression, + }) => simplify_prefix(cache, operator, *expression), + }; + + cache.cache(e, simplified) } } @@ -38,10 +84,17 @@ const ZERO: num_complex::Complex64 = real!(0.0); const ONE: num_complex::Complex64 = real!(1.0); const I: num_complex::Complex64 = imag!(1.0); -fn simplify_function_call(func: &ExpressionFunction, expr: &Expression) -> Expression { +fn simplify_function_call( + cache: &mut ExpressionCache, + func: ExpressionFunction, + expr: Expression, +) -> Expression { // Evaluate numbers and π // Pass through otherwise - match (func, simplify(expr)) { + let index = simplify(cache, expr); + let expr = cache.get(index); + + match (func, expr) { (ExpressionFunction::Cis, Expression::Number(x)) => { // num_complex::Complex64::cis only accpets f64 :-( Expression::Number(x.cos() + I * x.sin()) @@ -56,19 +109,19 @@ fn simplify_function_call(func: &ExpressionFunction, expr: &Expression) -> Expre (ExpressionFunction::SquareRoot, Expression::Number(x)) => Expression::Number(x.sqrt()), (ExpressionFunction::SquareRoot, Expression::PiConstant) => Expression::Number(PI.sqrt()), (function, expression) => Expression::FunctionCall(FunctionCallExpression { - function: *function, - expression: expression.into(), + function, + expression: expression.clone().into(), }), } } #[inline] -fn is_zero(x: &num_complex::Complex64) -> bool { +fn is_zero(x: num_complex::Complex64) -> bool { x.norm() < 1e-10 } #[inline] -fn is_one(x: &num_complex::Complex64) -> bool { +fn is_one(x: num_complex::Complex64) -> bool { (x - 1.0).norm() < 1e-10 } @@ -126,9 +179,18 @@ macro_rules! div { }; } -fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Expression { +fn simplify_infix( + cache: &mut ExpressionCache, + l: Expression, + op: InfixOperator, + r: Expression, +) -> Expression { + let left = simplify(cache, l); + let right = simplify(cache, r); + let left = cache.get(left).clone(); + let right = cache.get(right).clone(); // There are … many cases here - match (&simplify(l), op, &simplify(r)) { + match (left, op, right) { //---------------------------------------------------------------- // First: only diving one deep, pattern matching on the operation // (Constant folding and cancellations, mostly) @@ -137,8 +199,8 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express // Addition and Subtraction // Adding with zero - (Expression::Number(x), InfixOperator::Plus, right) if is_zero(x) => right.clone(), - (left, InfixOperator::Plus, Expression::Number(x)) if is_zero(x) => left.clone(), + (Expression::Number(x), InfixOperator::Plus, right) if is_zero(x) => right, + (left, InfixOperator::Plus, Expression::Number(x)) if is_zero(x) => left, // Adding numbers or π (Expression::Number(x), InfixOperator::Plus, Expression::Number(y)) => { Expression::Number(x + y) @@ -155,7 +217,7 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express // Subtracting with zero (Expression::Number(x), InfixOperator::Minus, right) if is_zero(x) => { - simplify_prefix(&PrefixOperator::Minus, right) + simplify_prefix(cache, PrefixOperator::Minus, right) } (left, InfixOperator::Minus, Expression::Number(y)) if is_zero(y) => left.clone(), // Subtracting self @@ -232,17 +294,17 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express InfixOperator::Plus, Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), - ) => simplify_infix(left, &InfixOperator::Minus, expression), + ) => simplify_infix(cache, left, InfixOperator::Minus, *expression), ( Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), InfixOperator::Plus, right, - ) => simplify_infix(right, &InfixOperator::Minus, expression), + ) => simplify_infix(cache, right, InfixOperator::Minus, *expression), // Subtraction with negation ( @@ -250,22 +312,26 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express InfixOperator::Minus, Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), - ) => simplify_infix(left, &InfixOperator::Plus, expression), + ) => simplify_infix(cache, left, InfixOperator::Plus, *expression), ( // -expression - right => smaller of (-expression) - right & -(expression + right) - left @ &Expression::Prefix(PrefixExpression { + Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), InfixOperator::Minus, right, ) => { - let original = sub!(left.clone(), right.clone()); + let original = sub!(Expression::Prefix(PrefixExpression { + operator: PrefixOperator::Minus, + expression: expression.clone(), + }), right.clone()); let new = simplify_prefix( - &PrefixOperator::Minus, - &add!(expression.clone(), right.clone()), + cache, + PrefixOperator::Minus, + add!(expression.clone(), right), ); min_by_key(original, new, size) } @@ -274,38 +340,44 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - expression: ref left, + expression: left, }), InfixOperator::Star, Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - expression: ref right, + expression: right, }), - ) => simplify_infix(left, &InfixOperator::Star, right), + ) => simplify_infix(cache, *left, InfixOperator::Star, *right), ( left, InfixOperator::Star, - right @ &Expression::Prefix(PrefixExpression { + Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), ) => { - let original = mul!(left.clone(), right.clone()); - let neg_left = simplify_prefix(&PrefixOperator::Minus, left); - let new = mul!(neg_left, expression.clone()); + let original = mul!(left.clone(), Expression::Prefix(PrefixExpression { + operator: PrefixOperator::Minus, + expression: expression.clone(), + })); + let neg_left = simplify_prefix(cache, PrefixOperator::Minus, left); + let new = mul!(neg_left, *expression); min_by_key(original, new, size) } ( - left @ &Expression::Prefix(PrefixExpression { + Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), InfixOperator::Star, right, ) => { - let original = mul!(left.clone(), right.clone()); - let neg_right = simplify_prefix(&PrefixOperator::Minus, right); - let new = mul!(expression.clone(), neg_right); + let original = mul!(Expression::Prefix(PrefixExpression { + operator: PrefixOperator::Minus, + expression: expression.clone(), + }), right.clone()); + let neg_right = simplify_prefix(cache, PrefixOperator::Minus, right); + let new = mul!(*expression, neg_right); min_by_key(original, new, size) } @@ -313,32 +385,35 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - expression: ref left, + expression: left, }), InfixOperator::Slash, Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - expression: ref right, + expression: right, }), - ) => simplify_infix(left, &InfixOperator::Slash, right), + ) => simplify_infix(cache, *left, InfixOperator::Slash, *right), ( left, InfixOperator::Slash, Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), - ) if *left == **expression => Expression::Number(-ONE), + ) if left == *expression => Expression::Number(-ONE), ( left, InfixOperator::Slash, - right @ &Expression::Prefix(PrefixExpression { + Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), ) => { - let original = div!(left.clone(), right.clone()); - let neg_left = simplify_prefix(&PrefixOperator::Minus, left); + let original = div!(left.clone(), Expression::Prefix(PrefixExpression { + operator: PrefixOperator::Minus, + expression: expression.clone(), + })); + let neg_left = simplify_prefix(cache, PrefixOperator::Minus, left); let new = div!(neg_left, expression.clone()); min_by_key(original, new, size) } @@ -349,17 +424,20 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express }), InfixOperator::Slash, right, - ) if **expression == *right => Expression::Number(-ONE), + ) if **expression == right => Expression::Number(-ONE), ( - left @ &Expression::Prefix(PrefixExpression { + Expression::Prefix(PrefixExpression { operator: PrefixOperator::Minus, - ref expression, + expression, }), InfixOperator::Slash, right, ) => { - let original = div!(left.clone(), right.clone()); - let neg_right = simplify_prefix(&PrefixOperator::Minus, right); + let original = div!(Expression::Prefix(PrefixExpression { + operator: PrefixOperator::Minus, + expression: expression.clone(), + }), right.clone()); + let neg_right = simplify_prefix(cache, PrefixOperator::Minus, right); let new = div!(expression.clone(), neg_right); min_by_key(original, new, size) } @@ -371,19 +449,19 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express // (a1 * x) + (a2 * x) = (a1 + a2) * x ( Expression::Infix(InfixExpression { - left: ref left_a, + left: left_a, operator: InfixOperator::Star, - right: ref left_x, + right: left_x, }), InfixOperator::Plus, Expression::Infix(InfixExpression { - left: ref right_a, + left: right_a, operator: InfixOperator::Star, - right: ref right_x, + right: right_x, }), ) if left_x == right_x => { mul!( - simplify_infix(left_a, &InfixOperator::Plus, right_a), + simplify_infix(cache, *left_a, InfixOperator::Plus, *right_a), left_x.clone() ) } @@ -391,20 +469,20 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express // (x + b1) + (x + b2) = x + (b1 + b2) ( Expression::Infix(InfixExpression { - left: ref left_x, + left: left_x, operator: InfixOperator::Plus, - right: ref left_b, + right: left_b, }), InfixOperator::Plus, Expression::Infix(InfixExpression { - left: ref right_x, + left: right_x, operator: InfixOperator::Plus, - right: ref right_b, + right: right_b, }), ) if left_x == right_x => { add!( - mul!(Expression::Number(ONE + ONE), left_x.clone()), - simplify_infix(left_b, &InfixOperator::Plus, right_b) + mul!(Expression::Number(ONE + ONE), *left_x), + simplify_infix(cache, *left_b, InfixOperator::Plus, *right_b) ) } @@ -416,15 +494,19 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( a, InfixOperator::Plus, - right @ Expression::Infix(InfixExpression { - left: ref b, + Expression::Infix(InfixExpression { + left: b, operator: InfixOperator::Plus, - right: ref c, + right: c, }), ) => { - let original = add!(a.clone(), right.clone()); - let new_ab = simplify_infix(a, &InfixOperator::Plus, b); - let new = simplify_infix(&new_ab, &InfixOperator::Plus, c); + let original = add!(a.clone(), Expression::Infix(InfixExpression { + left: b.clone(), + operator: InfixOperator::Plus, + right: c.clone(), + })); + let new_ab = simplify_infix(cache, a, InfixOperator::Plus, *b); + let new = simplify_infix(cache, new_ab, InfixOperator::Plus, *c); min_by_key(original, new, size) } @@ -432,15 +514,19 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( a, InfixOperator::Star, - right @ Expression::Infix(InfixExpression { - left: ref b, + Expression::Infix(InfixExpression { + left: b, operator: InfixOperator::Star, - right: ref c, + right: c, }), ) => { - let original = mul!(a.clone(), right.clone()); - let new_ab = simplify_infix(a, &InfixOperator::Star, b); - let new = simplify_infix(&new_ab, &InfixOperator::Star, c); + let original = mul!(a.clone(), Expression::Infix(InfixExpression { + left: b.clone(), + operator: InfixOperator::Star, + right: c.clone(), + })); + let new_ab = simplify_infix(cache, a, InfixOperator::Star, *b); + let new = simplify_infix(cache, new_ab, InfixOperator::Star, *c); min_by_key(original, new, size) } @@ -448,15 +534,19 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( a, InfixOperator::Minus, - right @ Expression::Infix(InfixExpression { - left: ref b, + Expression::Infix(InfixExpression { + left: b, operator: InfixOperator::Minus, - right: ref c, + right: c, }), ) => { - let original = sub!(a.clone(), right.clone()); - let new_left = simplify_infix(a, &InfixOperator::Plus, c); - let new = simplify_infix(&new_left, &InfixOperator::Minus, b); + let original = sub!(a.clone(), Expression::Infix(InfixExpression { + left: b.clone(), + operator: InfixOperator::Minus, + right: c.clone(), + })); + let new_left = simplify_infix(cache, a, InfixOperator::Plus, *c); + let new = simplify_infix(cache, new_left, InfixOperator::Minus, *b); min_by_key(original, new, size) } @@ -464,15 +554,19 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( a, InfixOperator::Slash, - right @ Expression::Infix(InfixExpression { - left: ref b, + Expression::Infix(InfixExpression { + left: b, operator: InfixOperator::Slash, - right: ref c, + right: c, }), ) => { - let original = div!(a.clone(), right.clone()); - let new_left = simplify_infix(a, &InfixOperator::Star, c); - let new = simplify_infix(&new_left, &InfixOperator::Slash, b); + let original = div!(a.clone(), Expression::Infix(InfixExpression { + left: b.clone(), + operator: InfixOperator::Slash, + right: c.clone(), + })); + let new_left = simplify_infix(cache, a, InfixOperator::Star, *c); + let new = simplify_infix(cache, new_left, InfixOperator::Slash, *b); min_by_key(original, new, size) } @@ -480,33 +574,41 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( a, InfixOperator::Star, - right @ Expression::Infix(InfixExpression { - left: ref b, + Expression::Infix(InfixExpression { + left: b, operator: InfixOperator::Plus, - right: ref c, + right: c, }), ) => { - let original = mul!(a.clone(), right.clone()); - let ab = simplify_infix(a, &InfixOperator::Star, b); - let ac = simplify_infix(a, &InfixOperator::Star, c); - let new = simplify_infix(&ab, &InfixOperator::Plus, &ac); + let original = mul!(a.clone(), Expression::Infix(InfixExpression { + left: b.clone(), + operator: InfixOperator::Plus, + right: c.clone(), + })); + let ab = simplify_infix(cache, a.clone(), InfixOperator::Star, *b); + let ac = simplify_infix(cache, a, InfixOperator::Star, *c); + let new = simplify_infix(cache, ab, InfixOperator::Plus, ac); min_by_key(original, new, size) } // Left distribution ( - left @ Expression::Infix(InfixExpression { - left: ref a, + Expression::Infix(InfixExpression { + left: a, operator: InfixOperator::Plus, - right: ref b, + right: b, }), InfixOperator::Star, c, ) => { - let original = mul!(left.clone(), c.clone()); - let ac = simplify_infix(a, &InfixOperator::Star, c); - let bc = simplify_infix(b, &InfixOperator::Star, c); - let new = simplify_infix(&ac, &InfixOperator::Plus, &bc); + let original = mul!(Expression::Infix(InfixExpression { + left: a.clone(), + operator: InfixOperator::Plus, + right: b.clone(), + }), c.clone()); + let ac = simplify_infix(cache, *a, InfixOperator::Star, c.clone()); + let bc = simplify_infix(cache, *b, InfixOperator::Star, c); + let new = simplify_infix(cache, ac, InfixOperator::Plus, bc); min_by_key(original, new, size) } @@ -517,27 +619,32 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express // Mul inside Div on left, multiplicand = denominator ( Expression::Infix(InfixExpression { - left: ref multiplier, + left: multiplier, operator: InfixOperator::Star, - right: ref multiplicand, + right: multiplicand, }), InfixOperator::Slash, denominator, - ) if **multiplicand == *denominator => *multiplier.clone(), + ) if *multiplicand == denominator => *multiplier, // Mul inside Div on left ( - numerator @ &Expression::Infix(InfixExpression { - left: ref multiplier, + Expression::Infix(InfixExpression { + left: multiplier, operator: InfixOperator::Star, - right: ref multiplicand, + right: multiplicand, }), InfixOperator::Slash, denominator, ) => { - let original = div!(numerator.clone(), denominator.clone()); - let new_multiplicand = simplify_infix(multiplicand, &InfixOperator::Slash, denominator); - let new = simplify_infix(&multiplier, &InfixOperator::Star, &new_multiplicand); + let original = div!(Expression::Infix(InfixExpression { + left: multiplier.clone(), + operator: InfixOperator::Star, + right: multiplicand.clone(), + }), denominator.clone()); + let new_multiplicand = + simplify_infix(cache, *multiplicand, InfixOperator::Slash, denominator); + let new = simplify_infix(cache, *multiplier, InfixOperator::Star, new_multiplicand); min_by_key(original, new, size) } @@ -545,60 +652,71 @@ fn simplify_infix(l: &Expression, op: &InfixOperator, r: &Expression) -> Express ( numerator, InfixOperator::Slash, - denominator @ &Expression::Infix(InfixExpression { - left: ref multiplier, + Expression::Infix(InfixExpression { + left: multiplier, operator: InfixOperator::Star, - right: ref multiplicand, + right: multiplicand, }), ) => { - let original = div!(numerator.clone(), denominator.clone()); - let new_multiplier = simplify_infix(numerator, &InfixOperator::Slash, multiplier); - let new = simplify_infix(&new_multiplier, &InfixOperator::Star, multiplicand); + let original = div!(numerator.clone(), Expression::Infix(InfixExpression { + left: multiplier.clone(), + operator: InfixOperator::Star, + right: multiplicand.clone(), + })); + let new_multiplier = simplify_infix(cache, numerator, InfixOperator::Slash, *multiplier); + let new = simplify_infix(cache, new_multiplier, InfixOperator::Star, *multiplicand); min_by_key(original, new, size) } // Div inside Mul on left, denominator = multiplicand ( Expression::Infix(InfixExpression { - left: ref numerator, + left: numerator, operator: InfixOperator::Slash, - right: ref denominator, + right: denominator, }), InfixOperator::Star, multiplicand, - ) if **denominator == *multiplicand => *numerator.clone(), + ) if *denominator == multiplicand => *numerator.clone(), // Div inside Mul on right, denominator = multiplicand ( multiplicand, InfixOperator::Star, Expression::Infix(InfixExpression { - left: ref numerator, + left: numerator, operator: InfixOperator::Slash, - right: ref denominator, + right: denominator, }), - ) if **denominator == *multiplicand => *numerator.clone(), + ) if *denominator == multiplicand => *numerator.clone(), // Catch-all (left, operator, right) => Expression::Infix(InfixExpression { left: left.clone().into(), - operator: *operator, + operator, right: right.clone().into(), }), } } -fn simplify_prefix(op: &PrefixOperator, expr: &Expression) -> Expression { +fn simplify_prefix( + cache: &mut ExpressionCache, + op: PrefixOperator, + expr: Expression, +) -> Expression { // Remove + // Push - into numbers & π // Pass through otherwise - match (op, simplify(expr)) { - (PrefixOperator::Plus, expression) => expression, - (PrefixOperator::Minus, Expression::Number(x)) => Expression::Number(-x), + let index = simplify(cache, expr); + let expr = cache.get(index); + + match (op, expr) { + (PrefixOperator::Plus, expression) => expression.clone(), + (PrefixOperator::Minus, Expression::Number(x)) => Expression::Number(-*x), (PrefixOperator::Minus, Expression::PiConstant) => Expression::Number(-PI), (operator, expression) => Expression::Prefix(PrefixExpression { - operator: *operator, - expression: expression.into(), + operator, + expression: expression.clone().into(), }), } } @@ -620,7 +738,7 @@ mod tests { "Parsing expected expression `{}` failed!", $expected ); - let output = simplify(&parsed_input.unwrap()); + let output = run(parsed_input.unwrap()); assert_eq!( parsed_expected.unwrap(), output, diff --git a/quil-rs/tests/calibration_test.rs b/quil-rs/tests/calibration_test.rs new file mode 100644 index 00000000..001ed48f --- /dev/null +++ b/quil-rs/tests/calibration_test.rs @@ -0,0 +1,19 @@ +use std::fs::read_to_string; +use std::path::PathBuf; +use std::str::FromStr; + +use insta::assert_snapshot; +use rstest::rstest; + +use quil_rs::program::Program; + +/// A test to ensure that a Program doesn't incorrectly filter out calibrations +/// when it is parsed. +#[rstest] +fn test_calibration_filtering(#[files("tests/programs/calibration_*.quil")] path: PathBuf) { + let program_text = + read_to_string(&path).unwrap_or_else(|_| panic!("Should be able to load file: {:?}", path)); + let program = Program::from_str(&program_text).expect("Should be able to parse test program."); + + assert_snapshot!(path.file_name().unwrap().to_str(), program.to_string()); +} diff --git a/quil-rs/tests/programs/calibration_cz.quil b/quil-rs/tests/programs/calibration_cz.quil new file mode 100644 index 00000000..5bbb9dd6 --- /dev/null +++ b/quil-rs/tests/programs/calibration_cz.quil @@ -0,0 +1,28 @@ +DEFCAL CZ 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-07 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-07 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + +DEFCAL CZ 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-07 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-07 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + diff --git a/quil-rs/tests/programs/calibration_cz_phase.quil b/quil-rs/tests/programs/calibration_cz_phase.quil new file mode 100644 index 00000000..ec092ab1 --- /dev/null +++ b/quil-rs/tests/programs/calibration_cz_phase.quil @@ -0,0 +1,62 @@ +DEFCAL CZ 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-07 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-07 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + +DEFCAL CZ 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-07 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-07 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + +DEFCAL CPHASE(%theta) 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1.2 + 0.5*%theta + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1*(-1.2 + 0.5*%theta) + DELAY 110 "rf" 3.2e-07 + SHIFT-PHASE 110 "rf" 2.2 + DELAY 111 "rf" 3.2e-07 + SHIFT-PHASE 111 "rf" 1.2 + FENCE + SHIFT-PHASE 110 111 "xy" 1.1 + SHIFT-PHASE 110 117 "xy" 1.1 + SHIFT-PHASE 110 111 "xy" -0.6 + SHIFT-PHASE 111 112 "xy" -0.6 + SHIFT-PHASE 111 126 "xy" -0.6 + +DEFCAL CPHASE(%theta) 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1.2 + 0.5*%theta + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1*(-1.2 + 0.5*%theta) + DELAY 110 "rf" 3.2e-07 + SHIFT-PHASE 110 "rf" 2.2 + DELAY 111 "rf" 3.2e-07 + SHIFT-PHASE 111 "rf" 1.2 + FENCE + SHIFT-PHASE 110 111 "xy" 1.1 + SHIFT-PHASE 110 117 "xy" 1.1 + SHIFT-PHASE 110 111 "xy" -0.6 + SHIFT-PHASE 111 112 "xy" -0.6 + SHIFT-PHASE 111 126 "xy" -0.6 + diff --git a/quil-rs/tests/programs/calibration_measure.quil b/quil-rs/tests/programs/calibration_measure.quil new file mode 100644 index 00000000..180674fb --- /dev/null +++ b/quil-rs/tests/programs/calibration_measure.quil @@ -0,0 +1,39 @@ +DEFCAL MEASURE 0 addr: + FENCE 0 + DECLARE q0_unclassified REAL[2] + PULSE 0 "rf_f12" gaussian(duration: 6e-08, fwhm: 1.6e-08, t0: 3e-08, scale: 0.5, phase: 0.0, detuning: 0.0) + NONBLOCKING PULSE 0 "ro_tx" flat(duration: 1.6e-06, iq: 1.0, scale: 0.1, phase: 0.0, detuning: 0.0) + NONBLOCKING CAPTURE 0 "ro_rx" boxcar_kernel(duration: 1.6e-06, scale: 1.0, phase: 0.0, detuning: 0.0) q0_unclassified[0] + PRAGMA FILTER-NODE q0_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q0_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q0_unclassified "q0_unclassified[0]" + PRAGMA FILTER-NODE q0_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q0_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q0 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q0_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q0 "addr" + FENCE 0 + +DEFCAL MEASURE 10 addr: + FENCE 10 + DECLARE q10_unclassified REAL[2] + PULSE 10 "rf_f12" gaussian(duration: 7e-08, fwhm: 1.7e-08, t0: 3e-08, scale: 0.5, phase: 0.0, detuning: 0.0) + NONBLOCKING PULSE 10 "ro_tx" flat(duration: 1.6e-06, iq: 1.0, scale: 0.1, phase: 0.0, detuning: 0.0) + NONBLOCKING CAPTURE 10 "ro_rx" boxcar_kernel(duration: 1.6e-06, scale: 1.0, phase: 0.0, detuning: 0.0) q10_unclassified[0] + PRAGMA FILTER-NODE q10_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q10_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q10_unclassified "q10_unclassified[0]" + PRAGMA FILTER-NODE q10_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q10_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q10 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q10_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q10 "addr" + FENCE 10 + +DEFCAL MEASURE 100 addr: + FENCE 100 + DECLARE q100_unclassified REAL[2] + PULSE 100 "rf_f12" gaussian(duration: 8e-08, fwhm: 1.8e-08, t0: 3e-08, scale: 0.5, phase: 0.0, detuning: 0.0) + NONBLOCKING PULSE 100 "ro_tx" flat(duration: 1.6e-06, iq: 1.0, scale: 0.1, phase: 0.0, detuning: 0.0) + NONBLOCKING CAPTURE 100 "ro_rx" boxcar_kernel(duration: 1.6e-06, scale: 1.0, phase: 0.0, detuning: 0.0) q100_unclassified[0] + PRAGMA FILTER-NODE q100_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q100_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q100_unclassified "q100_unclassified[0]" + PRAGMA FILTER-NODE q100_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q10_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q100 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q100_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q100 "addr" + FENCE 100 + diff --git a/quil-rs/tests/programs/calibration_rx.quil b/quil-rs/tests/programs/calibration_rx.quil new file mode 100644 index 00000000..ae97611e --- /dev/null +++ b/quil-rs/tests/programs/calibration_rx.quil @@ -0,0 +1,40 @@ +DEFCAL RX(pi/2) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 1e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.1, scale: 0.1, phase: 0.0, detuning: 0.0) + FENCE 0 + +DEFCAL RX(-pi/2) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 1e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.2, scale: 0.2, phase: 0.0, detuning: 0.0) + FENCE 0 + +DEFCAL RX(pi) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 1e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.3, scale: 0.3, phase: 0.0, detuning: 0.0) + FENCE 0 + +DEFCAL RX(-pi) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 1e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.4, scale: 0.4, phase: 0.0, detuning: 0.0) + FENCE 0 + +DEFCAL RX(pi/2) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(duration: 2e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.1, scale: 0.1, phase: 0.0, detuning: 0.0) + FENCE 3 + +DEFCAL RX(-pi/2) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(duration: 2e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.2, scale: 0.2, phase: 0.0, detuning: 0.0) + FENCE 3 + +DEFCAL RX(pi) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(duration: 2e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.3, scale: 0.3, phase: 0.0, detuning: 0.0) + FENCE 3 + +DEFCAL RX(-pi) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(duration: 2e-08, fwhm: 1e-08, t0: 1e-08, anh: -100000000.0, alpha: -0.4, scale: 0.4, phase: 0.0, detuning: 0.0) + FENCE 3 + diff --git a/quil-rs/tests/programs/calibration_xy.quil b/quil-rs/tests/programs/calibration_xy.quil new file mode 100644 index 00000000..8d3ee320 --- /dev/null +++ b/quil-rs/tests/programs/calibration_xy.quil @@ -0,0 +1,52 @@ +DEFCAL XY(%theta) 110 111: + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -0.4 + SHIFT-PHASE 110 111 "xy" 1.8 + -0.5*%theta + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -1*(1.8 + -0.5*%theta) + DELAY 110 "rf" 1.2e-07 + SHIFT-PHASE 110 "rf" 0.8 + DELAY 111 "rf" 1.2e-07 + SHIFT-PHASE 111 "rf" 0.4 + SHIFT-PHASE 111 "rf" 0.5*%theta + SHIFT-PHASE 110 "rf" -0.5*%theta + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + SHIFT-PHASE 110 117 "xy" 0.4 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 111 112 "xy" -0.25*%theta + SHIFT-PHASE 111 126 "xy" -0.25*%theta + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 110 117 "xy" -0.25*%theta + +DEFCAL XY(%theta) 111 110: + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -0.4 + SHIFT-PHASE 110 111 "xy" 1.8 + -0.5*%theta + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -1*(1.8 + -0.5*%theta) + DELAY 110 "rf" 1.2e-07 + SHIFT-PHASE 110 "rf" 0.8 + DELAY 111 "rf" 1.2e-07 + SHIFT-PHASE 111 "rf" 0.4 + SHIFT-PHASE 111 "rf" 0.5*%theta + SHIFT-PHASE 110 "rf" -0.5*%theta + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + SHIFT-PHASE 110 117 "xy" 0.4 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 111 112 "xy" -0.25*%theta + SHIFT-PHASE 111 126 "xy" -0.25*%theta + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 110 117 "xy" -0.25*%theta + diff --git a/quil-rs/tests/snapshots/calibration_test__calibration_cz.quil.snap b/quil-rs/tests/snapshots/calibration_test__calibration_cz.quil.snap new file mode 100644 index 00000000..9d9dbab6 --- /dev/null +++ b/quil-rs/tests/snapshots/calibration_test__calibration_cz.quil.snap @@ -0,0 +1,31 @@ +--- +source: quil-rs/tests/calibration_test.rs +expression: program.to_string() +--- +DEFCAL CZ 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-7 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-7 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 +DEFCAL CZ 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-7 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-7 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + diff --git a/quil-rs/tests/snapshots/calibration_test__calibration_cz_phase.quil.snap b/quil-rs/tests/snapshots/calibration_test__calibration_cz_phase.quil.snap new file mode 100644 index 00000000..18b7d532 --- /dev/null +++ b/quil-rs/tests/snapshots/calibration_test__calibration_cz_phase.quil.snap @@ -0,0 +1,63 @@ +--- +source: quil-rs/tests/calibration_test.rs +expression: program.to_string() +--- +DEFCAL CZ 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-7 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-7 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 +DEFCAL CZ 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cz" q110_q111_cz/CZ + DELAY 110 "rf" 1.6e-7 + SHIFT-PHASE 110 "rf" 0.6 + DELAY 111 "rf" 1.6e-7 + SHIFT-PHASE 111 "rf" 0.4 + FENCE + SHIFT-PHASE 110 111 "xy" 0.3 + SHIFT-PHASE 110 117 "xy" 0.3 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 +DEFCAL CPHASE(%theta) 110 111: + FENCE + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1.2+(0.5*%theta) + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1*(-1.2+(0.5*%theta)) + DELAY 110 "rf" 3.2e-7 + SHIFT-PHASE 110 "rf" 2.2 + DELAY 111 "rf" 3.2e-7 + SHIFT-PHASE 111 "rf" 1.2 + FENCE + SHIFT-PHASE 110 111 "xy" 1.1 + SHIFT-PHASE 110 117 "xy" 1.1 + SHIFT-PHASE 110 111 "xy" -0.6 + SHIFT-PHASE 111 112 "xy" -0.6 + SHIFT-PHASE 111 126 "xy" -0.6 +DEFCAL CPHASE(%theta) 111 110: + FENCE + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1.2+(0.5*%theta) + NONBLOCKING PULSE 110 111 "cphase" q110_q111_cphase/sqrtCPHASE + SHIFT-PHASE 110 111 "cphase" -1*(-1.2+(0.5*%theta)) + DELAY 110 "rf" 3.2e-7 + SHIFT-PHASE 110 "rf" 2.2 + DELAY 111 "rf" 3.2e-7 + SHIFT-PHASE 111 "rf" 1.2 + FENCE + SHIFT-PHASE 110 111 "xy" 1.1 + SHIFT-PHASE 110 117 "xy" 1.1 + SHIFT-PHASE 110 111 "xy" -0.6 + SHIFT-PHASE 111 112 "xy" -0.6 + SHIFT-PHASE 111 126 "xy" -0.6 + diff --git a/quil-rs/tests/snapshots/calibration_test__calibration_measure.quil.snap b/quil-rs/tests/snapshots/calibration_test__calibration_measure.quil.snap new file mode 100644 index 00000000..e27a6cb7 --- /dev/null +++ b/quil-rs/tests/snapshots/calibration_test__calibration_measure.quil.snap @@ -0,0 +1,44 @@ +--- +source: quil-rs/tests/calibration_test.rs +expression: program.to_string() +--- +DEFCAL MEASURE 0 addr: + FENCE 0 + DECLARE q0_unclassified REAL[2] + PULSE 0 "rf_f12" gaussian(detuning: 0, duration: 6e-8, fwhm: 1.6e-8, phase: 0, scale: 0.5, t0: 3e-8) + NONBLOCKING PULSE 0 "ro_tx" flat(detuning: 0, duration: 1.6e-6, iq: 1, phase: 0, scale: 0.1) + NONBLOCKING CAPTURE 0 "ro_rx" boxcar_kernel(detuning: 0, duration: 1.6e-6, phase: 0, scale: 1) q0_unclassified[0] + PRAGMA FILTER-NODE q0_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q0_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q0_unclassified "q0_unclassified[0]" + PRAGMA FILTER-NODE q0_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q0_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q0 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q0_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q0 "addr" + FENCE 0 + +DEFCAL MEASURE 10 addr: + FENCE 10 + DECLARE q10_unclassified REAL[2] + PULSE 10 "rf_f12" gaussian(detuning: 0, duration: 7e-8, fwhm: 1.7e-8, phase: 0, scale: 0.5, t0: 3e-8) + NONBLOCKING PULSE 10 "ro_tx" flat(detuning: 0, duration: 1.6e-6, iq: 1, phase: 0, scale: 0.1) + NONBLOCKING CAPTURE 10 "ro_rx" boxcar_kernel(detuning: 0, duration: 1.6e-6, phase: 0, scale: 1) q10_unclassified[0] + PRAGMA FILTER-NODE q10_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q10_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q10_unclassified "q10_unclassified[0]" + PRAGMA FILTER-NODE q10_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q10_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q10 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q10_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q10 "addr" + FENCE 10 + +DEFCAL MEASURE 100 addr: + FENCE 100 + DECLARE q100_unclassified REAL[2] + PULSE 100 "rf_f12" gaussian(detuning: 0, duration: 8e-8, fwhm: 1.8e-8, phase: 0, scale: 0.5, t0: 3e-8) + NONBLOCKING PULSE 100 "ro_tx" flat(detuning: 0, duration: 1.6e-6, iq: 1, phase: 0, scale: 0.1) + NONBLOCKING CAPTURE 100 "ro_rx" boxcar_kernel(detuning: 0, duration: 1.6e-6, phase: 0, scale: 1) q100_unclassified[0] + PRAGMA FILTER-NODE q100_unclassified "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q100_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q100_unclassified "q100_unclassified[0]" + PRAGMA FILTER-NODE q100_classified "{'module':'standard.filters.classifiers','filter_type':'SingleQLinear','source':'q10_ro_rx/filter','publish':false,'params':{'a':[1.0,0.0],'threshold':0.01},'_type':'FilterNode'}" + PRAGMA FILTER-NODE q100 "{'module':'standard.filters.io','filter_type':'DataBuffer','source':'q100_classified','publish':true,'params':{},'_type':'FilterNode'}" + PRAGMA LOAD-MEMORY q100 "addr" + FENCE 100 + + diff --git a/quil-rs/tests/snapshots/calibration_test__calibration_rx.quil.snap b/quil-rs/tests/snapshots/calibration_test__calibration_rx.quil.snap new file mode 100644 index 00000000..b2f4904a --- /dev/null +++ b/quil-rs/tests/snapshots/calibration_test__calibration_rx.quil.snap @@ -0,0 +1,37 @@ +--- +source: quil-rs/tests/calibration_test.rs +expression: program.to_string() +--- +DEFCAL RX(pi/2) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(alpha: -0.1, anh: -100000000, detuning: 0, duration: 1e-8, fwhm: 1e-8, phase: 0, scale: 0.1, t0: 1e-8) + FENCE 0 +DEFCAL RX(-pi/2) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(alpha: -0.2, anh: -100000000, detuning: 0, duration: 1e-8, fwhm: 1e-8, phase: 0, scale: 0.2, t0: 1e-8) + FENCE 0 +DEFCAL RX(pi) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(alpha: -0.3, anh: -100000000, detuning: 0, duration: 1e-8, fwhm: 1e-8, phase: 0, scale: 0.3, t0: 1e-8) + FENCE 0 +DEFCAL RX(-pi) 0: + FENCE 0 + NONBLOCKING PULSE 0 "rf" drag_gaussian(alpha: -0.4, anh: -100000000, detuning: 0, duration: 1e-8, fwhm: 1e-8, phase: 0, scale: 0.4, t0: 1e-8) + FENCE 0 +DEFCAL RX(pi/2) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(alpha: -0.1, anh: -100000000, detuning: 0, duration: 2e-8, fwhm: 1e-8, phase: 0, scale: 0.1, t0: 1e-8) + FENCE 3 +DEFCAL RX(-pi/2) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(alpha: -0.2, anh: -100000000, detuning: 0, duration: 2e-8, fwhm: 1e-8, phase: 0, scale: 0.2, t0: 1e-8) + FENCE 3 +DEFCAL RX(pi) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(alpha: -0.3, anh: -100000000, detuning: 0, duration: 2e-8, fwhm: 1e-8, phase: 0, scale: 0.3, t0: 1e-8) + FENCE 3 +DEFCAL RX(-pi) 3: + FENCE 3 + NONBLOCKING PULSE 3 "rf" drag_gaussian(alpha: -0.4, anh: -100000000, detuning: 0, duration: 2e-8, fwhm: 1e-8, phase: 0, scale: 0.4, t0: 1e-8) + FENCE 3 + diff --git a/quil-rs/tests/snapshots/calibration_test__calibration_xy.quil.snap b/quil-rs/tests/snapshots/calibration_test__calibration_xy.quil.snap new file mode 100644 index 00000000..ec05a295 --- /dev/null +++ b/quil-rs/tests/snapshots/calibration_test__calibration_xy.quil.snap @@ -0,0 +1,55 @@ +--- +source: quil-rs/tests/calibration_test.rs +expression: program.to_string() +--- +DEFCAL XY(%theta) 110 111: + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -0.4 + SHIFT-PHASE 110 111 "xy" 1.8+(-0.5*%theta) + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -1*(1.8+(-0.5*%theta)) + DELAY 110 "rf" 1.2e-7 + SHIFT-PHASE 110 "rf" 0.8 + DELAY 111 "rf" 1.2e-7 + SHIFT-PHASE 111 "rf" 0.4 + SHIFT-PHASE 111 "rf" 0.5*%theta + SHIFT-PHASE 110 "rf" -0.5*%theta + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + SHIFT-PHASE 110 117 "xy" 0.4 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 111 112 "xy" -0.25*%theta + SHIFT-PHASE 111 126 "xy" -0.25*%theta + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 110 117 "xy" -0.25*%theta +DEFCAL XY(%theta) 111 110: + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -0.4 + SHIFT-PHASE 110 111 "xy" 1.8+(-0.5*%theta) + NONBLOCKING PULSE 110 111 "xy" q110_q111_xy/sqrtiSWAP + SHIFT-PHASE 110 111 "xy" -1*(1.8+(-0.5*%theta)) + DELAY 110 "rf" 1.2e-7 + SHIFT-PHASE 110 "rf" 0.8 + DELAY 111 "rf" 1.2e-7 + SHIFT-PHASE 111 "rf" 0.4 + SHIFT-PHASE 111 "rf" 0.5*%theta + SHIFT-PHASE 110 "rf" -0.5*%theta + FENCE + SHIFT-PHASE 110 111 "xy" 0.4 + SHIFT-PHASE 110 117 "xy" 0.4 + SHIFT-PHASE 110 111 "xy" -0.2 + SHIFT-PHASE 111 112 "xy" -0.2 + SHIFT-PHASE 111 126 "xy" -0.2 + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 111 112 "xy" -0.25*%theta + SHIFT-PHASE 111 126 "xy" -0.25*%theta + SHIFT-PHASE 110 111 "xy" -0.25*%theta + SHIFT-PHASE 110 117 "xy" -0.25*%theta +