From 956967bc297f03923c81239a3a394d44cd2bb618 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 08:52:53 -0500 Subject: [PATCH 01/75] New: Expression#substitute_variables --- src/expression.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/expression.rs b/src/expression.rs index 28771c4b..65b78f66 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -312,6 +312,65 @@ impl Expression { Number(number) => Ok(*number), } } + + /// Substitute an expression in the place of each matching variable. + /// Consumes the expression and returns a new one. + /// + /// # Example + /// + /// ```rust + /// use quil_rs::expression::Expression; + /// use std::str::FromStr; + /// use std::collections::HashMap; + /// use num_complex::Complex64; + /// + /// let expression = Expression::from_str("%x + %y").unwrap(); + /// + /// let mut variables = HashMap::with_capacity(1); + /// variables.insert(String::from("x"), Expression::Number(Complex64::from(1.0))); + /// + /// let evaluated = expression.substitute_variables(&variables); + /// + /// assert_eq!(evaluated, Expression::from_str("1.0 + %y").unwrap()) + /// ``` + pub fn substitute_variables(self, variable_values: &HashMap) -> Self { + use Expression::*; + + match self { + FunctionCall { + function, + expression, + } => FunctionCall { + function, + expression: expression.substitute_variables(&variable_values).into(), + }, + Infix { + left, + operator, + right, + } => { + let left = left.substitute_variables(&variable_values).into(); + let right = right.substitute_variables(&variable_values).into(); + Infix { + left, + operator, + right, + } + } + Prefix { + operator, + expression, + } => Prefix { + operator, + expression: expression.substitute_variables(&variable_values).into(), + }, + Variable(identifier) => match variable_values.get(identifier.as_str()) { + Some(value) => value.clone(), + None => Variable(identifier), + }, + other => other, + } + } } impl<'a> FromStr for Expression { From 20cdefb09c37c6f3b173283ab797e03fa85725a3 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 08:54:41 -0500 Subject: [PATCH 02/75] New: ProgramError --- src/program/error.rs | 14 ++++++++++++++ src/program/mod.rs | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/program/error.rs diff --git a/src/program/error.rs b/src/program/error.rs new file mode 100644 index 00000000..dc1ef3be --- /dev/null +++ b/src/program/error.rs @@ -0,0 +1,14 @@ +use thiserror::Error; + +use crate::instruction::Instruction; + +#[derive(Debug, Error)] +pub enum ProgramError { + #[error("invalid calibration `{0}`: {message}")] + InvalidCalibration { instruction: Instruction, message: String }, + + #[error("instruction {0} expands into itself")] + RecursiveCalibration(Instruction) +} + +pub type ProgramResult = Result; \ No newline at end of file diff --git a/src/program/mod.rs b/src/program/mod.rs index 8703e542..04a13812 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -28,6 +28,7 @@ pub use self::frame::FrameSet; pub use self::memory::MemoryRegion; mod calibration; +mod error; mod frame; pub mod graph; mod memory; From 96c1228d8643f05ad1338655a8ae42611eb28018 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 08:58:00 -0500 Subject: [PATCH 03/75] Update: parse DEFCAL MEASURE --- src/parser/command.rs | 51 +++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/parser/command.rs b/src/parser/command.rs index 1fc06927..ef94b59f 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -100,25 +100,48 @@ pub fn parse_capture(input: ParserInput, blocking: bool) -> ParserResult(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { - let (input, modifiers) = many0(parse_gate_modifier)(input)?; - let (input, name) = token!(Identifier(v))(input)?; - let (input, parameters) = opt(delimited( - token!(LParenthesis), - separated_list0(token!(Comma), parse_expression), - token!(RParenthesis), - ))(input)?; - let parameters = parameters.unwrap_or_default(); - let (input, qubits) = many0(parse_qubit)(input)?; + use crate::parser::lexer::Command::Measure; + let (input, defcal_measure) = opt(token!(Command(Measure)))(input)?; + match defcal_measure { + Some(_) => parse_defcal_measure(input), + None => { + let (input, modifiers) = many0(parse_gate_modifier)(input)?; + let (input, name) = token!(Identifier(v))(input)?; + let (input, parameters) = opt(delimited( + token!(LParenthesis), + separated_list0(token!(Comma), parse_expression), + token!(RParenthesis), + ))(input)?; + let parameters = parameters.unwrap_or_default(); + let (input, qubits) = many0(parse_qubit)(input)?; + let (input, _) = token!(Colon)(input)?; + let (input, instructions) = instruction::parse_block(input)?; + Ok(( + input, + Instruction::CalibrationDefinition(Calibration { + instructions, + modifiers, + name, + parameters, + qubits, + }), + )) + } + } +} + +/// Parse the contents of a `DEFCAL MEASURE` instruction, following the `MEASURE` token. +pub fn parse_defcal_measure<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { + let (input, qubit) = opt(parse_qubit)(input)?; + let (input, destination) = token!(Identifier(v))(input)?; let (input, _) = token!(Colon)(input)?; let (input, instructions) = instruction::parse_block(input)?; Ok(( input, - Instruction::CalibrationDefinition(Calibration { + Instruction::MeasureCalibrationDefinition(MeasureCalibrationDefinition { instructions, - modifiers, - name, - parameters, - qubits, + parameter: destination, + qubit, }), )) } From be3e7e5c738a0f9560c95d74a71fef699fe4c2db Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:15:12 -0500 Subject: [PATCH 04/75] New: Instruction#apply_to_expressions --- src/instruction.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/src/instruction.rs b/src/instruction.rs index 57f135b5..4002e3e8 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -828,3 +828,113 @@ pub struct Waveform { pub parameters: Vec, pub sample_rate: f64, } + +impl Instruction { + /// Apply the provided closure to this instruction, mutating any `Expression`s within. + /// Does not affect instructions without `Expression`s within. + /// Does not traverse or mutate instructions nested within blocks (such as + /// within `DEFCAL`). + /// + /// # Example + /// + /// ```rust + /// use std::mem::replace; + /// use std::str::FromStr; + /// use quil_rs::{expression::Expression, Program}; + /// + /// + /// let program = Program::from_str("SHIFT-PHASE 0 \"rf\" 1*%theta").unwrap(); + /// let mut instructions = program.to_instructions(true); + /// instructions.iter_mut().for_each(|inst| inst.apply_to_expressions(|expr| { + /// let previous = replace(expr, Expression::PiConstant); + /// *expr = previous.simplify(); + /// })); + /// + /// ``` + pub fn apply_to_expressions(&mut self, mut closure: F) + where + F: FnMut(&mut Expression), + { + match self { + Instruction::CalibrationDefinition(Calibration { parameters, .. }) + | Instruction::Gate(Gate { parameters, .. }) => { + parameters.iter_mut().for_each(closure); + } + Instruction::Capture(Capture { waveform, .. }) + | Instruction::Pulse(Pulse { waveform, .. }) => { + waveform.parameters.values_mut().for_each(closure); + } + Instruction::Delay(Delay { duration, .. }) + | Instruction::RawCapture(RawCapture { duration, .. }) => { + closure(duration); + } + Instruction::FrameDefinition(FrameDefinition { attributes, .. }) => { + for value in attributes.values_mut() { + if let AttributeValue::Expression(expression) = value { + closure(expression); + } + } + } + Instruction::SetFrequency(SetFrequency { + frequency: expression, + .. + }) + | Instruction::SetPhase(SetPhase { + phase: expression, .. + }) + | Instruction::SetScale(SetScale { + scale: expression, .. + }) + | Instruction::ShiftFrequency(ShiftFrequency { + frequency: expression, + .. + }) + | Instruction::ShiftPhase(ShiftPhase { + phase: expression, .. + }) => { + closure(expression); + } + Instruction::WaveformDefinition(WaveformDefinition { definition, .. }) => { + definition.matrix.iter_mut().for_each(closure); + } + Instruction::GateDefinition(GateDefinition { matrix, .. }) => { + for row in matrix { + for cell in row { + closure(cell); + } + } + } + _ => {} + } + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use crate::{expression::Expression, Program}; + + #[test] + fn apply_to_expressions() { + let mut program = Program::from_str( + "DECLARE ro BIT +SET-PHASE 0 \"rf\" pi/2 +RX(2) 0", + ) + .unwrap(); + let closure = |expr: &mut Expression| *expr = Expression::Variable(String::from("a")); + for instruction in program.instructions.iter_mut() { + instruction.apply_to_expressions(closure); + } + + let expected_program = Program::from_str( + "DECLARE ro BIT +SET-PHASE 0 \"rf\" %a +RX(%a) 0", + ) + .unwrap(); + + assert_eq!(expected_program, program); + } +} From abf369252b0b87352a41c822589783bcb5c10dab Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:27:30 -0500 Subject: [PATCH 05/75] Fix: parse DEFCAL MEASURE --- src/parser/command.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/parser/command.rs b/src/parser/command.rs index ef94b59f..52f7e24c 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -23,8 +23,9 @@ use nom::{ use crate::instruction::{ Arithmetic, ArithmeticOperand, ArithmeticOperator, Calibration, Capture, CircuitDefinition, Declaration, Delay, Exchange, Fence, FrameDefinition, Instruction, Jump, JumpUnless, JumpWhen, - Label, Load, Measurement, Move, Pragma, Pulse, RawCapture, Reset, SetFrequency, SetPhase, - SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, WaveformDefinition, + Label, Load, MeasureCalibrationDefinition, Measurement, Move, Pragma, Pulse, RawCapture, Reset, + SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, + WaveformDefinition, }; use crate::parser::common::parse_variable_qubit; use crate::parser::instruction::parse_block; From d2a7204aa51a40ab4fc1591c30bda199324ec948 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:30:16 -0500 Subject: [PATCH 06/75] Update: add DEFCAL MEASURE expansion --- src/program/calibration.rs | 147 ++++++++++++++++++++++++++++++++++--- src/program/mod.rs | 27 +++++-- 2 files changed, 155 insertions(+), 19 deletions(-) diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 9068df76..6280e628 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -17,13 +17,19 @@ use std::collections::HashMap; use crate::{ expression::Expression, - instruction::{Calibration, Gate, GateModifier, Instruction, Qubit}, + instruction::{ + Calibration, Gate, GateModifier, Instruction, MeasureCalibrationDefinition, Measurement, + Qubit, + }, }; +use super::error::{ProgramError, ProgramResult}; + /// A collection of Quil calibrations (`DEFCAL` instructions) with utility methods. #[derive(Clone, Debug, Default, PartialEq)] pub struct CalibrationSet { calibrations: Vec, + measure_calibrations: Vec, } struct MatchedCalibration<'a> { @@ -49,14 +55,21 @@ impl<'a> MatchedCalibration<'a> { impl CalibrationSet { pub fn new() -> Self { - CalibrationSet { - calibrations: vec![], - } + Self::default() } /// Given an instruction, return the instructions to which it is expanded if there is a match. - pub fn expand(&self, instruction: &Instruction) -> Option> { - match instruction { + /// Recursively calibrate instructions, returning an error if a calibration directly or indirectly + /// expands into itself. + pub fn expand( + &self, + instruction: &Instruction, + previous_calibrations: &[Instruction], + ) -> ProgramResult>> { + if previous_calibrations.contains(instruction) { + return Err(ProgramError::RecursiveCalibration(instruction.clone())); + } + let expanded_once_instructions = match instruction { Instruction::Gate(Gate { name, modifiers, @@ -75,6 +88,22 @@ impl CalibrationSet { } } + // Variables used within the calibration's definition should be replaced with the actual expressions used by the gate. + // That is, `DEFCAL RX(%theta): ...` should have `%theta` replaced by `pi` throughout if it's used to expand `RX(pi)`. + let variable_expansions: HashMap = calibration + .parameters + .iter() + .zip(parameters.iter()) + .filter_map(|(calibration_expression, gate_expression)| { + if let Expression::Variable(variable_name) = calibration_expression + { + Some((variable_name.clone(), gate_expression.clone())) + } else { + None + } + }) + .collect(); + let mut instructions = calibration.instructions.clone(); for instruction in instructions.iter_mut() { @@ -91,6 +120,11 @@ impl CalibrationSet { } } } + + instruction.apply_to_expressions(|expr| { + let previous = std::mem::replace(expr, Expression::PiConstant); + *expr = previous.substitute_variables(&variable_expansions); + }) } Some(instructions) @@ -98,8 +132,78 @@ impl CalibrationSet { None => None, } } + Instruction::Measurement(Measurement { qubit, target }) => { + let mut matching_calibrations_with_precedence: Vec<( + u32, + &MeasureCalibrationDefinition, + )> = self + .measure_calibrations + .iter() + .filter_map(|cal| match &cal.qubit { + Some(cal_qubit) if qubit == cal_qubit => Some((1, cal)), + None => Some((0, cal)), + _ => None, + }) + .collect(); + + // The matching calibration is the last-specified one that matched the target qubit (if any), + // or otherwise the last-specified one that specified no qubit. + matching_calibrations_with_precedence.sort_by_key(|(precedence, _)| *precedence); + let matching_calibration = matching_calibrations_with_precedence.last(); + match matching_calibration { + Some((_, calibration)) => { + let mut instructions = calibration.instructions.clone(); + for instruction in instructions.iter_mut() { + match instruction { + // This special-casing is an unfortunate hack to support the current use pattern + // of measurement calibrations. + Instruction::Pragma(pragma) => { + if pragma.name == "LOAD-MEMORY" + && pragma.data.as_ref() == Some(&calibration.parameter) + { + if let Some(target) = target { + pragma.data = Some(target.to_string()) + } + } + } + Instruction::Capture(capture) => { + if let Some(target) = target { + capture.memory_reference = target.clone() + } + } + _ => {} + } + } + Some(instructions) + } + None => None, + } + } _ => None, - } + }; + + // Add this instruction to the breadcrumb trail before recursion + let mut downstream_previous_calibrations = vec![instruction.clone()]; + downstream_previous_calibrations.extend_from_slice(&previous_calibrations); + + Ok(match expanded_once_instructions { + Some(instructions) => { + let mut recursively_expanded_instructions = vec![]; + + for instruction in instructions { + let expanded_instructions = + self.expand(&instruction, &downstream_previous_calibrations)?; + match expanded_instructions { + Some(instructions) => { + recursively_expanded_instructions.extend(instructions) + } + None => recursively_expanded_instructions.push(instruction), + }; + } + Some(recursively_expanded_instructions) + } + None => None, + }) } /// Return the final calibration which matches the gate per the QuilT specification: @@ -201,11 +305,22 @@ impl CalibrationSet { self.calibrations.is_empty() } - /// Add another calibration to the set. + /// Add another gate calibration to the set. + #[deprecated] pub fn push(&mut self, calibration: Calibration) { + self.push_calibration(calibration) + } + + /// Add another gate calibration (`DEFCAL`) to the set. + pub fn push_calibration(&mut self, calibration: Calibration) { self.calibrations.push(calibration) } + /// Add another measurement calibration (`DEFCAL MEASURE`) to the set. + pub fn push_measurement_calibration(&mut self, calibration: MeasureCalibrationDefinition) { + self.measure_calibrations.push(calibration) + } + /// Return the Quil instructions which describe the contained calibrations. pub fn to_instructions(&self) -> Vec { self.calibrations @@ -256,12 +371,22 @@ mod tests { ), expected: "PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", }, + TestCase { + input: concat!( + "DEFCAL X 0:\n", + " Y 0\n", + "DEFCAL Y 0:\n", + " PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", + "X 0\n" + ), + expected: "PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", + }, ]; for case in &cases { - let mut program = Program::from_str(case.input).unwrap(); - program.expand_calibrations(); - assert_eq!(program.to_string(false).as_str(), case.expected); + let program = Program::from_str(case.input).unwrap(); + let calibrated_program = program.expand_calibrations().unwrap(); + assert_eq!(calibrated_program.to_string(false).as_str(), case.expected); } } diff --git a/src/program/mod.rs b/src/program/mod.rs index 04a13812..05d12a1c 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -62,7 +62,7 @@ impl Program { pub fn add_instruction(&mut self, instruction: Instruction) { match instruction { Instruction::CalibrationDefinition(calibration) => { - self.calibrations.push(calibration); + self.calibrations.push_calibration(calibration); } Instruction::FrameDefinition(FrameDefinition { identifier, @@ -78,6 +78,9 @@ impl Program { self.memory_regions .insert(name, MemoryRegion { size, sharing }); } + Instruction::MeasureCalibrationDefinition(calibration) => { + self.calibrations.push_measurement_calibration(calibration); + } Instruction::WaveformDefinition(WaveformDefinition { name, definition }) => { self.waveforms.insert(name, definition); } @@ -86,23 +89,31 @@ impl Program { } /// Expand any instructions in the program which have a matching calibration, leaving the others - /// unchanged. - pub fn expand_calibrations(&mut self) { - let mut result: Vec = vec![]; + /// unchanged. Recurses though each instruction whil ensuring there is no cycle in the expansion + /// graph (i.e. no calibration expands directly or indirectly into itself) + pub fn expand_calibrations(&self) -> error::ProgramResult { + let mut expanded_instructions: Vec = vec![]; // TODO: Do this more efficiently, possibly with Vec::splice for instruction in &self.instructions { - match self.calibrations.expand(instruction) { + match self.calibrations.expand(instruction, &[])? { Some(expanded) => { - result.extend(expanded.into_iter()); + expanded_instructions.extend(expanded.into_iter()); } None => { - result.push(instruction.clone()); + expanded_instructions.push(instruction.clone()); } } } - self.instructions = result; + let mut new_program = self.clone(); + new_program.instructions = vec![]; + + for instruction in expanded_instructions { + new_program.add_instruction(instruction); + } + + Ok(new_program) } /// Return the frames which are either "used" or "blocked" by the given instruction. From d18e5fdc88cbd182c6b8a6bda9c11082f285fd2a Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:31:06 -0500 Subject: [PATCH 07/75] Fix: tolerate program composition instructions in ScheduledProgram#build --- src/program/graph.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/program/graph.rs b/src/program/graph.rs index ca385813..826ca303 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -537,17 +537,11 @@ impl ScheduledProgram { | Instruction::MeasureCalibrationDefinition(MeasureCalibrationDefinition { .. }) - | Instruction::WaveformDefinition(_) => Err(ScheduleError { - instruction: instruction.clone(), - variant: ScheduleErrorVariant::UnschedulableInstruction, - }), - + | Instruction::WaveformDefinition(_) => Ok(()), Instruction::Pragma(_) => { - // TODO: Handle pragmas. Here, we just silently discard them, but certain - // pragmas must be supported. + working_instructions.push(instruction); Ok(()) } - // _ => Err(()), // Unimplemented Instruction::Label(Label(value)) => { terminate_working_block!( None as Option, From fed814b4828f7fb29965450f43bae55b6f1cb023 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:31:36 -0500 Subject: [PATCH 08/75] Fix: consider PRAGMA a classical compute instruction --- src/instruction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/instruction.rs b/src/instruction.rs index 4002e3e8..b66367e0 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -466,7 +466,6 @@ impl From<&Instruction> for InstructionRole { | Instruction::Label(_) | Instruction::MeasureCalibrationDefinition(_) | Instruction::Measurement(_) - | Instruction::Pragma(_) | Instruction::WaveformDefinition(_) => InstructionRole::ProgramComposition, Instruction::Reset(_) | Instruction::Capture(_) @@ -484,6 +483,7 @@ impl From<&Instruction> for InstructionRole { | Instruction::Move(_) | Instruction::Exchange(_) | Instruction::Load(_) + | Instruction::Pragma(_) | Instruction::Store(_) => InstructionRole::ClassicalCompute, Instruction::Halt | Instruction::Jump(_) From 0bdd8472c25cf43835e7a41e55b17bcd87aabe1a Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:32:00 -0500 Subject: [PATCH 09/75] Chore: add thiserror --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 20aedead..6d4423af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ nom = "6.1.0" num-complex = "0.4.0" petgraph = "0.5.1" serde = { version = "1.0.125", features = ["derive"] } +thiserror = "1.0.30" [dev-dependencies] insta = "1.7.1" From 44fce8c9b02d4c0cb6eb94f5799ce2eb107e3dc8 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:34:30 -0500 Subject: [PATCH 10/75] Chore: fmt --- src/program/error.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/program/error.rs b/src/program/error.rs index dc1ef3be..00686fb4 100644 --- a/src/program/error.rs +++ b/src/program/error.rs @@ -5,10 +5,13 @@ use crate::instruction::Instruction; #[derive(Debug, Error)] pub enum ProgramError { #[error("invalid calibration `{0}`: {message}")] - InvalidCalibration { instruction: Instruction, message: String }, + InvalidCalibration { + instruction: Instruction, + message: String, + }, #[error("instruction {0} expands into itself")] - RecursiveCalibration(Instruction) + RecursiveCalibration(Instruction), } -pub type ProgramResult = Result; \ No newline at end of file +pub type ProgramResult = Result; From 165c4a76473db2767cb0a470527c8d057ebbb14e Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:35:47 -0500 Subject: [PATCH 11/75] Chore: lint --- src/expression.rs | 8 ++++---- src/program/calibration.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/expression.rs b/src/expression.rs index 65b78f66..8cf11fb7 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -342,15 +342,15 @@ impl Expression { expression, } => FunctionCall { function, - expression: expression.substitute_variables(&variable_values).into(), + expression: expression.substitute_variables(variable_values).into(), }, Infix { left, operator, right, } => { - let left = left.substitute_variables(&variable_values).into(); - let right = right.substitute_variables(&variable_values).into(); + let left = left.substitute_variables(variable_values).into(); + let right = right.substitute_variables(variable_values).into(); Infix { left, operator, @@ -362,7 +362,7 @@ impl Expression { expression, } => Prefix { operator, - expression: expression.substitute_variables(&variable_values).into(), + expression: expression.substitute_variables(variable_values).into(), }, Variable(identifier) => match variable_values.get(identifier.as_str()) { Some(value) => value.clone(), diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 6280e628..ee95df67 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -184,7 +184,7 @@ impl CalibrationSet { // Add this instruction to the breadcrumb trail before recursion let mut downstream_previous_calibrations = vec![instruction.clone()]; - downstream_previous_calibrations.extend_from_slice(&previous_calibrations); + downstream_previous_calibrations.extend_from_slice(previous_calibrations); Ok(match expanded_once_instructions { Some(instructions) => { From fbc7afd81bdd6771671d32c3c283c17a25e29b7c Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:12:27 -0500 Subject: [PATCH 12/75] Chore: improve docs --- src/program/calibration.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/program/calibration.rs b/src/program/calibration.rs index ee95df67..d9ea0cdc 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -306,7 +306,8 @@ impl CalibrationSet { } /// Add another gate calibration to the set. - #[deprecated] + /// Deprecated in favor of [`push_calibration`] + #[deprecated = "use ScheduledProgram#push_calibration instead"] pub fn push(&mut self, calibration: Calibration) { self.push_calibration(calibration) } From d0e44489781c0f3c2b134cd0dca98c1d951de07f Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:15:31 -0500 Subject: [PATCH 13/75] Decompose parse_defcal function --- src/parser/command.rs | 53 +++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/parser/command.rs b/src/parser/command.rs index 52f7e24c..b9fbc82b 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -99,38 +99,43 @@ pub fn parse_capture(input: ParserInput, blocking: bool) -> ParserResult(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { use crate::parser::lexer::Command::Measure; let (input, defcal_measure) = opt(token!(Command(Measure)))(input)?; match defcal_measure { Some(_) => parse_defcal_measure(input), - None => { - let (input, modifiers) = many0(parse_gate_modifier)(input)?; - let (input, name) = token!(Identifier(v))(input)?; - let (input, parameters) = opt(delimited( - token!(LParenthesis), - separated_list0(token!(Comma), parse_expression), - token!(RParenthesis), - ))(input)?; - let parameters = parameters.unwrap_or_default(); - let (input, qubits) = many0(parse_qubit)(input)?; - let (input, _) = token!(Colon)(input)?; - let (input, instructions) = instruction::parse_block(input)?; - Ok(( - input, - Instruction::CalibrationDefinition(Calibration { - instructions, - modifiers, - name, - parameters, - qubits, - }), - )) - } + None => parse_defcal_gate(input), } } +/// Parse the contents of a `DEFCAL` instruction (but not `DEFCAL MEASURE`), +/// following the `DEFCAL` token. +pub fn parse_defcal_gate<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { + let (input, modifiers) = many0(parse_gate_modifier)(input)?; + let (input, name) = token!(Identifier(v))(input)?; + let (input, parameters) = opt(delimited( + token!(LParenthesis), + separated_list0(token!(Comma), parse_expression), + token!(RParenthesis), + ))(input)?; + let parameters = parameters.unwrap_or_default(); + let (input, qubits) = many0(parse_qubit)(input)?; + let (input, _) = token!(Colon)(input)?; + let (input, instructions) = instruction::parse_block(input)?; + Ok(( + input, + Instruction::CalibrationDefinition(Calibration { + instructions, + modifiers, + name, + parameters, + qubits, + }), + )) +} + /// Parse the contents of a `DEFCAL MEASURE` instruction, following the `MEASURE` token. pub fn parse_defcal_measure<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { let (input, qubit) = opt(parse_qubit)(input)?; From e090669b504b99a0a78150e54515117acda5e2d5 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:17:15 -0500 Subject: [PATCH 14/75] Improve type annotation for apply_to_expression --- src/instruction.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index b66367e0..4a6fa15a 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -851,10 +851,7 @@ impl Instruction { /// })); /// /// ``` - pub fn apply_to_expressions(&mut self, mut closure: F) - where - F: FnMut(&mut Expression), - { + pub fn apply_to_expressions(&mut self, mut closure: impl FnMut(&mut Expression)) { match self { Instruction::CalibrationDefinition(Calibration { parameters, .. }) | Instruction::Gate(Gate { parameters, .. }) => { From 7a7eeb62b43050fbe85cf1cc10bbd9e425a6889c Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:49:52 -0500 Subject: [PATCH 15/75] Chore: improve inline docs --- src/instruction.rs | 4 +++- src/program/mod.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index 4a6fa15a..af6da2a5 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -843,13 +843,15 @@ impl Instruction { /// use quil_rs::{expression::Expression, Program}; /// /// - /// let program = Program::from_str("SHIFT-PHASE 0 \"rf\" 1*%theta").unwrap(); + /// let program = Program::from_str("SHIFT-PHASE 0 \"rf\" 2*2").unwrap(); /// let mut instructions = program.to_instructions(true); /// instructions.iter_mut().for_each(|inst| inst.apply_to_expressions(|expr| { /// let previous = replace(expr, Expression::PiConstant); /// *expr = previous.simplify(); /// })); /// + /// assert_eq!(instructions[0].to_string(), String::from("SHIFT-PHASE 0 \"rf\" 4")) + /// /// ``` pub fn apply_to_expressions(&mut self, mut closure: impl FnMut(&mut Expression)) { match self { diff --git a/src/program/mod.rs b/src/program/mod.rs index 05d12a1c..1f4ae514 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -89,7 +89,7 @@ impl Program { } /// Expand any instructions in the program which have a matching calibration, leaving the others - /// unchanged. Recurses though each instruction whil ensuring there is no cycle in the expansion + /// unchanged. Recurses though each instruction while ensuring there is no cycle in the expansion /// graph (i.e. no calibration expands directly or indirectly into itself) pub fn expand_calibrations(&self) -> error::ProgramResult { let mut expanded_instructions: Vec = vec![]; From 3c7ff0041624a2f6994d1e7da256255d6768b738 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:08:06 -0500 Subject: [PATCH 16/75] Fix: PRAGMA display --- src/instruction.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index af6da2a5..d4d3f17c 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -742,11 +742,16 @@ impl fmt::Display for Instruction { name, arguments, data, - }) => match data { - // FIXME: Handle empty argument lists - Some(data) => write!(f, "PRAGMA {} {} {}", name, arguments.join(" "), data), - None => write!(f, "PRAGMA {} {}", name, arguments.join(" ")), - }, + }) => { + write!(f, "PRAGMA {}", name)?; + if !arguments.is_empty() { + write!(f, " {}", arguments.join(" "))?; + } + if let Some(data) = data { + write!(f, "{}", data)?; + } + Ok(()) + } Instruction::RawCapture(RawCapture { blocking, frame, From bdc4c13e0f3b8366825dd82e9e36fcd6f412b787 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:10:04 -0500 Subject: [PATCH 17/75] Fix: DEFCAL MEASURE parsing --- src/parser/command.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/parser/command.rs b/src/parser/command.rs index b9fbc82b..0af18489 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -25,7 +25,7 @@ use crate::instruction::{ Declaration, Delay, Exchange, Fence, FrameDefinition, Instruction, Jump, JumpUnless, JumpWhen, Label, Load, MeasureCalibrationDefinition, Measurement, Move, Pragma, Pulse, RawCapture, Reset, SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, - WaveformDefinition, + WaveformDefinition, Qubit, }; use crate::parser::common::parse_variable_qubit; use crate::parser::instruction::parse_block; @@ -138,7 +138,8 @@ pub fn parse_defcal_gate<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruc /// Parse the contents of a `DEFCAL MEASURE` instruction, following the `MEASURE` token. pub fn parse_defcal_measure<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { - let (input, qubit) = opt(parse_qubit)(input)?; + let (input, qubit_index) = opt(token!(Integer(v)))(input)?; + let qubit = qubit_index.map(|q| Qubit::Fixed(q)); let (input, destination) = token!(Identifier(v))(input)?; let (input, _) = token!(Colon)(input)?; let (input, instructions) = instruction::parse_block(input)?; From 14ce2d1878963d2f5fb9a3162777e88e511af4b2 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:11:19 -0500 Subject: [PATCH 18/75] Improve DEFCAL MEASURE expansion readability --- src/program/calibration.rs | 53 +++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/program/calibration.rs b/src/program/calibration.rs index d9ea0cdc..91ef82e6 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -54,10 +54,6 @@ impl<'a> MatchedCalibration<'a> { } impl CalibrationSet { - pub fn new() -> Self { - Self::default() - } - /// Given an instruction, return the instructions to which it is expanded if there is a match. /// Recursively calibrate instructions, returning an error if a calibration directly or indirectly /// expands into itself. @@ -133,30 +129,27 @@ impl CalibrationSet { } } Instruction::Measurement(Measurement { qubit, target }) => { - let mut matching_calibrations_with_precedence: Vec<( - u32, - &MeasureCalibrationDefinition, - )> = self - .measure_calibrations - .iter() - .filter_map(|cal| match &cal.qubit { - Some(cal_qubit) if qubit == cal_qubit => Some((1, cal)), - None => Some((0, cal)), - _ => None, - }) - .collect(); - // The matching calibration is the last-specified one that matched the target qubit (if any), // or otherwise the last-specified one that specified no qubit. - matching_calibrations_with_precedence.sort_by_key(|(precedence, _)| *precedence); - let matching_calibration = matching_calibrations_with_precedence.last(); + let mut matching_calibration = None; + let mut found_matching_calibration_without_qubit = false; + for cal in self.measure_calibrations.iter().rev() { + if let Some(cal_qubit) = &cal.qubit { + if cal_qubit == qubit { + matching_calibration = Some(cal); + break + } + } else if !found_matching_calibration_without_qubit { + matching_calibration = Some(cal); + found_matching_calibration_without_qubit = true; + } + } + match matching_calibration { - Some((_, calibration)) => { + Some(calibration) => { let mut instructions = calibration.instructions.clone(); for instruction in instructions.iter_mut() { match instruction { - // This special-casing is an unfortunate hack to support the current use pattern - // of measurement calibrations. Instruction::Pragma(pragma) => { if pragma.name == "LOAD-MEMORY" && pragma.data.as_ref() == Some(&calibration.parameter) @@ -338,7 +331,7 @@ mod tests { use crate::program::Program; #[test] - fn test_expansion() { + fn expansion() { struct TestCase<'a> { input: &'a str, expected: &'a str, @@ -382,6 +375,20 @@ mod tests { ), expected: "PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", }, + TestCase { + input: concat!( + "DEFCAL MEASURE 0 addr:\n", + " PRAGMA INCORRECT_ORDERING\n", + "DEFCAL MEASURE 0 addr:\n", + " PRAGMA CORRECT\n", + "DEFCAL MEASURE 1 addr:\n", + " PRAGMA INCORRECT_QUBIT\n", + "DEFCAL MEASURE addr:\n", + " PRAGMA INCORRECT_PRECEDENCE\n", + "MEASURE 0 ro\n" + ), + expected: "PRAGMA CORRECT\n", + }, ]; for case in &cases { From 9e99f008528d9c334af41d438021865ffb9225e0 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:12:30 -0500 Subject: [PATCH 19/75] Fix: construct CalibrationSet::default() --- src/program/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 1f4ae514..855847bd 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -50,7 +50,7 @@ pub struct Program { impl Program { pub fn new() -> Self { Program { - calibrations: CalibrationSet::new(), + calibrations: CalibrationSet::default(), frames: FrameSet::new(), memory_regions: HashMap::new(), waveforms: HashMap::new(), From 653d0b2374e23e6ca8ad2b626a08b2e7c0c5b2b2 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:13:03 -0500 Subject: [PATCH 20/75] Chore: fmt --- src/parser/command.rs | 8 ++++---- src/program/calibration.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/parser/command.rs b/src/parser/command.rs index 0af18489..46477770 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -23,9 +23,9 @@ use nom::{ use crate::instruction::{ Arithmetic, ArithmeticOperand, ArithmeticOperator, Calibration, Capture, CircuitDefinition, Declaration, Delay, Exchange, Fence, FrameDefinition, Instruction, Jump, JumpUnless, JumpWhen, - Label, Load, MeasureCalibrationDefinition, Measurement, Move, Pragma, Pulse, RawCapture, Reset, - SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, - WaveformDefinition, Qubit, + Label, Load, MeasureCalibrationDefinition, Measurement, Move, Pragma, Pulse, Qubit, RawCapture, + Reset, SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, Store, Waveform, + WaveformDefinition, }; use crate::parser::common::parse_variable_qubit; use crate::parser::instruction::parse_block; @@ -139,7 +139,7 @@ pub fn parse_defcal_gate<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruc /// Parse the contents of a `DEFCAL MEASURE` instruction, following the `MEASURE` token. pub fn parse_defcal_measure<'a>(input: ParserInput<'a>) -> ParserResult<'a, Instruction> { let (input, qubit_index) = opt(token!(Integer(v)))(input)?; - let qubit = qubit_index.map(|q| Qubit::Fixed(q)); + let qubit = qubit_index.map(Qubit::Fixed); let (input, destination) = token!(Identifier(v))(input)?; let (input, _) = token!(Colon)(input)?; let (input, instructions) = instruction::parse_block(input)?; diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 91ef82e6..0ba00009 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -137,7 +137,7 @@ impl CalibrationSet { if let Some(cal_qubit) = &cal.qubit { if cal_qubit == qubit { matching_calibration = Some(cal); - break + break; } } else if !found_matching_calibration_without_qubit { matching_calibration = Some(cal); From 8de828754df65bce79be49c968c2a4ecdf16099d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 8 Mar 2022 13:47:45 +0000 Subject: [PATCH 21/75] Release v0.8.4 [skip ci] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ea32883e..c16dec91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version ="0.8.3" +version ="0.8.4" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" From 472ac22e9624f0fa2463674f39a4d5bfbe687899 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 11:19:06 -0700 Subject: [PATCH 22/75] chore: include latest Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8fe6abce..18f4cd5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,7 +324,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.1" +version = "0.8.2" dependencies = [ "indexmap", "insta", From 3eda5338644b8fd3d1433da64e4915850ebc77f5 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 12:07:10 -0700 Subject: [PATCH 23/75] feat: update program to use btreemap for deterministic ordering --- src/program/mod.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 6f3435bc..73b9499b 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -use std::collections::HashMap; +use std::collections::BTreeMap; use std::str::FromStr; use crate::instruction::{ @@ -42,8 +42,8 @@ mod memory; pub struct Program { pub calibrations: CalibrationSet, pub frames: FrameSet, - pub memory_regions: HashMap, - pub waveforms: HashMap, + pub memory_regions: BTreeMap, + pub waveforms: BTreeMap, pub instructions: Vec, } @@ -52,8 +52,8 @@ impl Program { Program { calibrations: CalibrationSet::default(), frames: FrameSet::new(), - memory_regions: HashMap::new(), - waveforms: HashMap::new(), + memory_regions: BTreeMap::new(), + waveforms: BTreeMap::new(), instructions: vec![], } } @@ -252,7 +252,7 @@ impl FromStr for Program { #[cfg(test)] mod tests { - use std::str::FromStr; + use std::{collections::BTreeMap, iter::FromIterator, str::FromStr}; use super::Program; @@ -351,4 +351,16 @@ I 0 " ); } + + #[test] + fn program_deterministic_ordering() { + const MEMORIES: &[&str; 3] = &["DECLARE ro BIT;", "DECLARE anc BIT;", "DECLARE ec BIT;"]; + let input = &MEMORIES.concat(); + let program1 = Program::from_str(input).unwrap().to_string(true); + let program2 = Program::from_str(input).unwrap().to_string(true); + + // verify that each memory declaration in the program is in the same index as the same + // program after being re-parsed and serialized. + assert!(program1.lines().eq(program2.lines())); + } } From 1fbda96c663a8ebedbffe790390179fd07ed609a Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 14:55:57 -0700 Subject: [PATCH 24/75] fix: remove unused imports --- src/program/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 73b9499b..19d7a772 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -252,7 +252,7 @@ impl FromStr for Program { #[cfg(test)] mod tests { - use std::{collections::BTreeMap, iter::FromIterator, str::FromStr}; + use std::str::FromStr; use super::Program; From 75a47ca3c4762ea43ac78671cebaf90828439de3 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 14:56:59 -0700 Subject: [PATCH 25/75] chore: add update check to cargo.lock in CI, include in assets list --- .github/workflows/release.yml | 6 +++ package.json | 84 +++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 457b3d4c..a9b98001 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,12 @@ jobs: profile: minimal override: true + - name: Update Cargo.lock + uses: actions-rs/cargo@v1 + with: + command: update + args: -w + - name: Install semantic-release-rust uses: actions-rs/cargo@v1 with: diff --git a/package.json b/package.json index 593ba248..7cef4cc6 100644 --- a/package.json +++ b/package.json @@ -10,32 +10,68 @@ "semantic-release": "^17.1.1" }, "release": { - "branches": ["main", {"name": "rc", "prerelease": true}], + "branches": [ + "main", + { + "name": "rc", + "prerelease": true + } + ], "plugins": [ - ["@semantic-release/commit-analyzer",{ - "preset": "eslint", - "releaseRules": [ - {"tag": "Breaking", "release": "minor"}, - {"tag": "Update", "release": "patch"}, - {"tag": "Fix", "release": "patch"}, - {"tag": "New", "release": "patch"}, - {"tag": "Upgrade", "release": "patch"} - ] - }], - ["@semantic-release/release-notes-generator", { - "preset": "eslint" - }], - ["@semantic-release/exec",{ - "verifyConditionsCmd": "semantic-release-rust verify-conditions", - "prepareCmd": "semantic-release-rust prepare ${nextRelease.version}", - "publishCmd": "semantic-release-rust publish" - }], + [ + "@semantic-release/commit-analyzer", + { + "preset": "eslint", + "releaseRules": [ + { + "tag": "Breaking", + "release": "minor" + }, + { + "tag": "Update", + "release": "patch" + }, + { + "tag": "Fix", + "release": "patch" + }, + { + "tag": "New", + "release": "patch" + }, + { + "tag": "Upgrade", + "release": "patch" + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "eslint" + } + ], + [ + "@semantic-release/exec", + { + "verifyConditionsCmd": "semantic-release-rust verify-conditions", + "prepareCmd": "semantic-release-rust prepare ${nextRelease.version}", + "publishCmd": "semantic-release-rust publish" + } + ], "@semantic-release/github", - ["@semantic-release/git", { - "assets": ["Cargo.toml"], - "message": "Release v${nextRelease.version} [skip ci]" - }] + [ + "@semantic-release/git", + { + "assets": [ + "Cargo.lock", + "Cargo.toml" + ], + "message": "Release v${nextRelease.version} [skip ci]" + } + ] ], "repositoryUrl": "ssh://git@github.com/rigetti/quil-rust.git" } -} +} \ No newline at end of file From 9a2beffdb06376a4e8c55d112656744c6f5e781b Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 15:08:26 -0700 Subject: [PATCH 26/75] chore: use single string input, revert from slice to check indicies --- src/program/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 19d7a772..3420ad6e 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -354,8 +354,11 @@ I 0 #[test] fn program_deterministic_ordering() { - const MEMORIES: &[&str; 3] = &["DECLARE ro BIT;", "DECLARE anc BIT;", "DECLARE ec BIT;"]; - let input = &MEMORIES.concat(); + let input = " +DECLARE ro BIT +DECLARE anc BIT +DECLARE ec BIT +"; let program1 = Program::from_str(input).unwrap().to_string(true); let program2 = Program::from_str(input).unwrap().to_string(true); From 91140a5d6cb00a3481c447a6787e129d188e3582 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Mon, 7 Mar 2022 15:13:22 -0700 Subject: [PATCH 27/75] fix: move cargo update inline with semantic-release prepare cmd --- .github/workflows/release.yml | 6 ------ package.json | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9b98001..457b3d4c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,12 +28,6 @@ jobs: profile: minimal override: true - - name: Update Cargo.lock - uses: actions-rs/cargo@v1 - with: - command: update - args: -w - - name: Install semantic-release-rust uses: actions-rs/cargo@v1 with: diff --git a/package.json b/package.json index 7cef4cc6..30fd3bc5 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@semantic-release/exec", { "verifyConditionsCmd": "semantic-release-rust verify-conditions", - "prepareCmd": "semantic-release-rust prepare ${nextRelease.version}", + "prepareCmd": "semantic-release-rust prepare ${nextRelease.version} && cargo update -w", "publishCmd": "semantic-release-rust publish" } ], From 5e15122569415cc64dba4f44f75f69c79ebd190d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Tue, 8 Mar 2022 11:32:20 -0700 Subject: [PATCH 28/75] Update: update Cargo.lock version (#52) --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 18f4cd5a..f5cd45cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,7 +324,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.2" +version = "0.8.4" dependencies = [ "indexmap", "insta", From 11dfd03e17c68f93d45766311d56637bfbc5bb39 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 8 Mar 2022 18:35:25 +0000 Subject: [PATCH 29/75] Release v0.8.5 [skip ci] --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5cd45cf..7921bf45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,7 +324,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.4" +version = "0.8.5" dependencies = [ "indexmap", "insta", diff --git a/Cargo.toml b/Cargo.toml index c16dec91..1ef18a57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version ="0.8.4" +version ="0.8.5" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" From 6165a1bbd27d0feb90c370312da4972b11b22f5d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 9 Mar 2022 20:39:11 -0700 Subject: [PATCH 30/75] Update: add automated benchmarks for parsing quilc test programs (#53) * feat: add automated benchmarks for parsing quilc test programs * chore: add exceptions for deny.toml * chore: remove unused env vars from bench workflow * chore: include filter_map simplification Co-authored-by: Dylan Anthony <43723790+dbanty@users.noreply.github.com> * chore: address pr feedback * fix: revert pathbuf to be platform independent --- .github/workflows/bench.yml | 66 ++++++ .gitmodules | 3 + Cargo.lock | 450 +++++++++++++++++++++++++++++++++++- Cargo.toml | 7 +- benches/parser.rs | 54 +++++ benches/quilc | 1 + deny.toml | 18 +- 7 files changed, 585 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/bench.yml create mode 100644 .gitmodules create mode 100644 benches/parser.rs create mode 160000 benches/quilc diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 00000000..b0203754 --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,66 @@ +# Based on https://github.com/actions-rs/meta/blob/master/recipes/msrv.md + +on: [ pull_request ] + +name: Benchmark + +jobs: + benchmark: + name: Run benchmarks + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + steps: + - name: Checkout sources + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + + - name: Set env vars + run: | + THIS_SHA=$(echo $GITHUB_SHA | cut -c 1-7) + MAIN_SHA=$(echo $(git rev-parse main) | cut -c 1-7) + + echo "THIS_BENCH=${THIS_SHA}.bench" >> $GITHUB_ENV + echo "MAIN_BENCH=${MAIN_SHA}.bench" >> $GITHUB_ENV + + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + + - uses: Swatinem/rust-cache@v1 + + - name: Install critcmp + run: cargo install critcmp + + - name: Run cargo check + uses: actions-rs/cargo@v1 + with: + command: check + + # - name: Download benchmark artifacts + # uses: actions/download-artifact@v3 + # with: + # name: benchmarks + + - name: Run cargo benchmark + uses: actions-rs/cargo@v1 + with: + command: bench + args: --bench parser -- --save-baseline $THIS_SHA + + - name: Archive benchmark results + uses: actions/upload-artifact@v3 + with: + name: benchmarks + path: target/criterion + + # - name: Compare benchmark to main + # run: | + # echo "comparing this benchmark to $MAIN_BENCH (main)" + # critcmp $MAIN_BENCH $THIS_BENCH \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e423fff0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "benches/quilc"] + path = benches/quilc + url = git@github.com:quil-lang/quilc.git diff --git a/Cargo.lock b/Cargo.lock index 7921bf45..64ca90bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -47,18 +58,56 @@ dependencies = [ "wyz", ] +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + [[package]] name = "console" version = "0.15.0" @@ -72,6 +121,114 @@ dependencies = [ "winapi", ] +[[package]] +name = "criterion" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -116,12 +273,27 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "indexmap" version = "1.8.0" @@ -155,12 +327,36 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -202,12 +398,30 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "nom" version = "6.2.1" @@ -239,12 +453,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "petgraph" version = "0.5.1" @@ -255,6 +485,34 @@ dependencies = [ "indexmap", ] +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -326,6 +584,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" name = "quil-rs" version = "0.8.5" dependencies = [ + "criterion", "indexmap", "insta", "lexical", @@ -400,6 +659,31 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rayon" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.11" @@ -409,6 +693,21 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.25" @@ -424,6 +723,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rusty-fork" version = "0.3.0" @@ -442,6 +750,27 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" + [[package]] name = "serde" version = "1.0.136" @@ -451,6 +780,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.136" @@ -468,7 +807,7 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -549,6 +888,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -576,12 +940,87 @@ dependencies = [ "libc", ] +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.36", + "quote 1.0.15", + "syn 1.0.86", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote 1.0.15", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2 1.0.36", + "quote 1.0.15", + "syn 1.0.86", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -598,6 +1037,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 1ef18a57..bb1c4bd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version ="0.8.5" +version = "0.8.5" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" @@ -21,3 +21,8 @@ thiserror = "1.0.30" insta = "1.7.1" proptest = "1.0.0" proptest-derive = "0.3.0" +criterion = { version = "0.3.5", features = ["html_reports"] } + +[[bench]] +name = "parser" +harness = false diff --git a/benches/parser.rs b/benches/parser.rs new file mode 100644 index 00000000..0b11b767 --- /dev/null +++ b/benches/parser.rs @@ -0,0 +1,54 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use std::{fs, path::PathBuf, str::FromStr}; + +fn benchmark_quil_corpus(c: &mut Criterion) { + from_corpus().iter().for_each(|cfg| { + c.bench_function(&cfg.name, |b| { + b.iter(|| { + let _ = quil_rs::Program::from_str(&cfg.program); + }) + }); + }) +} + +struct QuilBenchConfig { + name: String, + program: String, +} + +fn from_corpus() -> Vec { + const PATH_SRC: &str = "benches/quilc/tests/good-test-files"; + + // collect valid quil programs + let mut programs = vec![]; + let mut corpus_dir = PathBuf::new(); + PATH_SRC.split('/').for_each(|p| corpus_dir.push(p)); + let dir = fs::read_dir(corpus_dir).expect("failed to locate quil corpus directory"); + + dir.filter_map(Result::ok) + .filter(|entry| { + entry + .metadata() + .expect("failed to read file metadata") + .is_file() + }) + .for_each(|entry| { + let program = + fs::read_to_string(entry.path()).expect("failed to read quil program file"); + let name = entry + .file_name() + .to_str() + .expect("bad filename") + .to_string(); + + // attempt to parse the quil once, ignoring unparsable input (only benchmark parsable code) + if quil_rs::Program::from_str(&program).is_ok() { + programs.push(QuilBenchConfig { name, program }); + } + }); + + programs +} + +criterion_group!(benches, benchmark_quil_corpus); +criterion_main!(benches); diff --git a/benches/quilc b/benches/quilc new file mode 160000 index 00000000..a2925c5d --- /dev/null +++ b/benches/quilc @@ -0,0 +1 @@ +Subproject commit a2925c5dd1764534ef8ea4e66b051cc43cecea30 diff --git a/deny.toml b/deny.toml index ce5d4c28..eda54c00 100644 --- a/deny.toml +++ b/deny.toml @@ -25,7 +25,7 @@ notice = "deny" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ - #"RUSTSEC-0000-0000", + "RUSTSEC-2021-0127", # `serde_cbor` is unmaintained ] # This section is considered when running `cargo deny check licenses` @@ -33,18 +33,11 @@ ignore = [ # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [licenses] unlicensed = "deny" -allow = [ - "Apache-2.0", - "BSD-2-Clause", - "BSD-3-Clause", - "MIT", -] +allow = ["Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "MIT"] # List of explictly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -deny = [ - #"Nokia", -] +deny = [] # Lint level for licenses considered copyleft copyleft = "deny" # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses @@ -78,8 +71,9 @@ multiple-versions = "deny" wildcards = "deny" highlight = "all" skip-tree = [ - { name = "syn", version = "*", depth = 5 }, # Used in both serde_derive and proptest-derive - { name = "quick-error", version = "*" }, # proptest relies on two versions of this + { name = "syn", version = "*", depth = 5 }, # Used in both serde_derive and proptest-derive + { name = "quick-error", version = "*" }, # proptest relies on two versions of this + { name = "itoa", version = "*" }, # various dependencies rely on two versions of this ] # This section is considered when running `cargo deny check sources`. From fdbb0888a7fd7256fea3c813a32dd64f05759a96 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 10 Mar 2022 03:43:11 +0000 Subject: [PATCH 31/75] Release v0.8.6 [skip ci] --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64ca90bb..462cf389 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -582,7 +582,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.5" +version = "0.8.6" dependencies = [ "criterion", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index bb1c4bd8..bb3b9468 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version = "0.8.5" +version ="0.8.6" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" From 9522237a3d30a67e4194166b708f0bdb8181d31e Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Thu, 10 Mar 2022 11:19:13 -0700 Subject: [PATCH 32/75] test use of criterion default baselines with archive (#56) * test use of criterion default baselines with archive * include check for submodules, init if not (for local runs) * add multi-os benchmark strategy, and bench against same os base results --- .github/workflows/bench.yml | 47 ++++++++++++------------------------- benches/parser.rs | 19 ++++++++++++--- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index b0203754..da788eb5 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -1,31 +1,22 @@ -# Based on https://github.com/actions-rs/meta/blob/master/recipes/msrv.md - -on: [ pull_request ] +on: [ push, pull_request ] name: Benchmark jobs: benchmark: name: Run benchmarks - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] rust: - stable + steps: - name: Checkout sources uses: actions/checkout@v2 with: submodules: recursive - fetch-depth: 0 - - - name: Set env vars - run: | - THIS_SHA=$(echo $GITHUB_SHA | cut -c 1-7) - MAIN_SHA=$(echo $(git rev-parse main) | cut -c 1-7) - - echo "THIS_BENCH=${THIS_SHA}.bench" >> $GITHUB_ENV - echo "MAIN_BENCH=${MAIN_SHA}.bench" >> $GITHUB_ENV - name: Install toolchain uses: actions-rs/toolchain@v1 @@ -34,33 +25,25 @@ jobs: override: true - uses: Swatinem/rust-cache@v1 - - - name: Install critcmp - run: cargo install critcmp - - - name: Run cargo check - uses: actions-rs/cargo@v1 + + - name: Download benchmark artifacts + uses: dawidd6/action-download-artifact@v2 with: - command: check - - # - name: Download benchmark artifacts - # uses: actions/download-artifact@v3 - # with: - # name: benchmarks + workflow: bench.yml + name: benchmarks-${{ matrix.os }} + path: target/criterion + continue-on-error: true - name: Run cargo benchmark uses: actions-rs/cargo@v1 with: command: bench - args: --bench parser -- --save-baseline $THIS_SHA + args: --bench parser -- --warm-up-time=2 --measurement-time=3 --sample-size=500 --color=always - name: Archive benchmark results + if: ${{ github.ref == 'refs/heads/main'}} uses: actions/upload-artifact@v3 with: - name: benchmarks + name: benchmarks-${{ matrix.os }} path: target/criterion - - # - name: Compare benchmark to main - # run: | - # echo "comparing this benchmark to $MAIN_BENCH (main)" - # critcmp $MAIN_BENCH $THIS_BENCH \ No newline at end of file + \ No newline at end of file diff --git a/benches/parser.rs b/benches/parser.rs index 0b11b767..34d558fd 100644 --- a/benches/parser.rs +++ b/benches/parser.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use std::{fs, path::PathBuf, str::FromStr}; +use std::{fs, path::Path, process::Command, str::FromStr}; fn benchmark_quil_corpus(c: &mut Criterion) { from_corpus().iter().for_each(|cfg| { @@ -21,8 +21,11 @@ fn from_corpus() -> Vec { // collect valid quil programs let mut programs = vec![]; - let mut corpus_dir = PathBuf::new(); - PATH_SRC.split('/').for_each(|p| corpus_dir.push(p)); + let corpus_dir = Path::new(PATH_SRC); + if !corpus_dir.exists() { + init_submodules() + } + let dir = fs::read_dir(corpus_dir).expect("failed to locate quil corpus directory"); dir.filter_map(Result::ok) @@ -50,5 +53,15 @@ fn from_corpus() -> Vec { programs } +// in the event someone wants to run the benchmarks locally, this will download the corpus of quil used +fn init_submodules() { + Command::new("git") + .args(["submodule", "update", "--init", "--recursive"]) + .spawn() + .expect("failed to spawn git process") + .wait_with_output() + .expect("failed to init submodules, verify `git` is installed"); +} + criterion_group!(benches, benchmark_quil_corpus); criterion_main!(benches); From e143dc1229121e1674da90ff8ba4dc3fba0dc5d2 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Fri, 11 Mar 2022 16:47:15 +0000 Subject: [PATCH 33/75] Fix: change quilc submodule to use HTTPS --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e423fff0..4769fdae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "benches/quilc"] path = benches/quilc - url = git@github.com:quil-lang/quilc.git + url = https://github.com/quil-lang/quilc.git From 701bc619eddbc7a245641a51ebc14668f0e10b8b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 11 Mar 2022 16:54:38 +0000 Subject: [PATCH 34/75] Release v0.8.7 [skip ci] --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 462cf389..a09b0ef2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -582,7 +582,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.6" +version = "0.8.7" dependencies = [ "criterion", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index bb3b9468..b30b1468 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version ="0.8.6" +version ="0.8.7" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" From c7293e0b4b61c82d3a8b67fa151771623ec43030 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:56:39 -0700 Subject: [PATCH 35/75] Move graphviz-dot format writer to own module --- Cargo.lock | 21 +++++ src/program/dot.rs | 195 +++++++++++++++++++++++++++++++++++++++++++ src/program/graph.rs | 186 +---------------------------------------- src/program/mod.rs | 1 + 4 files changed, 218 insertions(+), 185 deletions(-) create mode 100644 src/program/dot.rs diff --git a/Cargo.lock b/Cargo.lock index a09b0ef2..6a3e9549 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -594,6 +594,7 @@ dependencies = [ "proptest", "proptest-derive", "serde", + "thiserror", ] [[package]] @@ -897,6 +898,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2 1.0.36", + "quote 1.0.15", + "syn 1.0.86", +] + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/src/program/dot.rs b/src/program/dot.rs new file mode 100644 index 00000000..90e1b56f --- /dev/null +++ b/src/program/dot.rs @@ -0,0 +1,195 @@ +// Utilities for working with Graphviz dot format files + +use crate::program::graph::{ + BlockTerminator, ExecutionDependency, MemoryAccessType, ScheduledGraphNode, +}; + +use super::graph::{InstructionBlock, ScheduledProgram}; + +impl InstructionBlock { + /// Write a DOT-formatted string to the provided writer for use with GraphViz. + /// This output can be used within a `subgraph` or at the top level of a `digraph`. + /// + /// Parameters: + /// + /// * line_prefix: The prefix for each new line in the output. This can be used to indent this + /// output for readability in a larger definition. + /// * element_prefix: The prefix for each graph element (node and edge). This can be used to + /// namespace this block when used with other blocks which may have conflicting labels. + pub fn write_dot_format( + &self, + f: &mut std::fmt::Formatter, + line_prefix: &str, + element_prefix: &str, + ) -> std::fmt::Result { + self.graph.nodes().try_for_each(|node| { + match &node { + ScheduledGraphNode::BlockEnd => { + writeln!( + f, + "{}\"{}end\" [ label=end, shape=circle ]", + line_prefix, element_prefix + ) + } + ScheduledGraphNode::BlockStart => { + writeln!( + f, + "{}\"{}start\" [ label=start, shape=circle ]", + line_prefix, element_prefix + ) + } + ScheduledGraphNode::InstructionIndex(index) => { + write!( + f, + "{}\"{}{}\" [label=\"", + line_prefix, element_prefix, index + )?; + write_escaped(f, &format!("{}", self.instructions.get(*index).unwrap()))?; + writeln!(f, "\"]") + } + }?; + self.graph.edges(node).try_for_each(|(src, dest, edge)| { + match &src { + ScheduledGraphNode::BlockEnd => { + write!(f, "{}\"{}end\"", line_prefix, element_prefix) + } + ScheduledGraphNode::BlockStart => { + write!(f, "{}\"{}start\"", line_prefix, element_prefix) + } + ScheduledGraphNode::InstructionIndex(index) => { + write!(f, "{}\"{}{}\"", line_prefix, element_prefix, index) + } + }?; + write!(f, " -> ")?; + match &dest { + ScheduledGraphNode::BlockEnd => write!(f, "\"{}end\"", element_prefix), + ScheduledGraphNode::BlockStart => { + write!(f, "\"{}start\"", element_prefix) + } + ScheduledGraphNode::InstructionIndex(index) => { + write!(f, "\"{}{}\"", element_prefix, index) + } + }?; + let mut labels = edge + .iter() + .map(|dependency| match dependency { + ExecutionDependency::AwaitMemoryAccess(access_type) => match access_type { + MemoryAccessType::Read => "await read", + MemoryAccessType::Write => "await write", + MemoryAccessType::Capture => "await capture", + }, + ExecutionDependency::ReferenceFrame => "frame", + ExecutionDependency::StableOrdering => "ordering", + }) + .collect::>(); + + // We sort them so that graph output is deterministic; iterating over the set + // without sorting would cause flaky tests. + labels.sort_unstable(); + let label = labels.join("\n"); + writeln!(f, " [ label=\"{}\" ]", label) + }) + })?; + Ok(()) + } +} + +impl ScheduledProgram { + /// Write a DOT format string to the provided writer for use with Graphviz. + /// + /// This outputs a `digraph` object with a `subgraph` for each block to inform the layout engine. + /// Each `subgraph` ID is prefixed with `cluster_` which instructs some supporting layout engines + /// to enclose the subgraph with a border. This improves readability of the graph. + /// + /// Lines on the graph indicate scheduling dependencies within blocks and control flow among blocks. + /// Each node representing an instruction is labeled with the contents of that instruction. + pub fn write_dot_format(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + writeln!(f, "digraph {{")?; + + let mut iter = self.blocks.iter().peekable(); + + writeln!(f, "\tentry [label=\"Entry Point\"]")?; + + if let Some((first_label, _)) = iter.peek() { + writeln!(f, "\tentry -> \"{}_start\"", first_label)?; + } + + while let Some((label, block)) = iter.next() { + writeln!(f, "\tsubgraph \"cluster_{}\" {{", label)?; + writeln!(f, "\t\tlabel=\"{}\"", label)?; + writeln!(f, "\t\tnode [ style=\"filled\" ]")?; + + let line_prefix = "\t\t"; + // let element_prefix = format!("b{}_", index); + let element_prefix = format!("{}_", label); + + block.write_dot_format(f, line_prefix, &element_prefix)?; + writeln!(f, "\t}}")?; + + let next_block_label = iter.peek().map(|(next_label, _)| (*next_label).clone()); + match &block.terminator { + BlockTerminator::Conditional { + condition, + target, + jump_if_condition_true, + } => { + let equality_operators = if *jump_if_condition_true { + ("==", "!=") + } else { + ("!=", "==") + }; + writeln!( + f, + "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", + label, target, condition, equality_operators.0, + )?; + if let Some(next_label) = next_block_label { + writeln!( + f, + "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", + label, next_label, condition, equality_operators.1 + )?; + }; + } + BlockTerminator::Unconditional { target } => { + writeln!( + f, + "\"{}_end\" -> \"{}_start\" [label=\"always\"]", + label, target + )?; + } + BlockTerminator::Continue => { + if let Some(next_label) = next_block_label { + writeln!( + f, + "\"{}_end\" -> \"{}_start\" [label=\"always\"]", + label, next_label + )?; + }; + } + BlockTerminator::Halt => {} + } + } + writeln!(f, "}}") + } +} + +/// Escape strings for use as DOT format quoted ID's +fn write_escaped(f: &mut std::fmt::Formatter, s: &str) -> std::fmt::Result { + for c in s.chars() { + write_char(f, c)?; + } + Ok(()) +} + +/// Escape a single character for use within a DOT format quoted ID. +fn write_char(f: &mut std::fmt::Formatter, c: char) -> std::fmt::Result { + use std::fmt::Write; + match c { + '"' | '\\' => f.write_char('\\')?, + // \l is for left justified linebreak + '\n' => return f.write_str("\\l"), + _ => {} + } + f.write_char(c) +} diff --git a/src/program/graph.rs b/src/program/graph.rs index 127b97fd..f055b878 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -197,7 +197,7 @@ pub type DependencyGraph = GraphMap, - graph: DependencyGraph, + pub(super) graph: DependencyGraph, pub terminator: BlockTerminator, } @@ -322,92 +322,6 @@ impl InstructionBlock { &self.graph } - /// Write a DOT-formatted string to the provided writer for use with GraphViz. - /// This output can be used within a `subgraph` or at the top level of a `digraph`. - /// - /// Parameters: - /// - /// * line_prefix: The prefix for each new line in the output. This can be used to indent this - /// output for readability in a larger definition. - /// * element_prefix: The prefix for each graph element (node and edge). This can be used to - /// namespace this block when used with other blocks which may have conflicting labels. - pub fn write_dot_format( - &self, - f: &mut fmt::Formatter, - line_prefix: &str, - element_prefix: &str, - ) -> fmt::Result { - self.graph.nodes().try_for_each(|node| { - match &node { - ScheduledGraphNode::BlockEnd => { - writeln!( - f, - "{}\"{}end\" [ label=end, shape=circle ]", - line_prefix, element_prefix - ) - } - ScheduledGraphNode::BlockStart => { - writeln!( - f, - "{}\"{}start\" [ label=start, shape=circle ]", - line_prefix, element_prefix - ) - } - ScheduledGraphNode::InstructionIndex(index) => { - write!( - f, - "{}\"{}{}\" [label=\"", - line_prefix, element_prefix, index - )?; - write_escaped(f, &format!("{}", self.instructions.get(*index).unwrap()))?; - writeln!(f, "\"]") - } - }?; - self.graph.edges(node).try_for_each(|(src, dest, edge)| { - match &src { - ScheduledGraphNode::BlockEnd => { - write!(f, "{}\"{}end\"", line_prefix, element_prefix) - } - ScheduledGraphNode::BlockStart => { - write!(f, "{}\"{}start\"", line_prefix, element_prefix) - } - ScheduledGraphNode::InstructionIndex(index) => { - write!(f, "{}\"{}{}\"", line_prefix, element_prefix, index) - } - }?; - write!(f, " -> ")?; - match &dest { - ScheduledGraphNode::BlockEnd => write!(f, "\"{}end\"", element_prefix), - ScheduledGraphNode::BlockStart => { - write!(f, "\"{}start\"", element_prefix) - } - ScheduledGraphNode::InstructionIndex(index) => { - write!(f, "\"{}{}\"", element_prefix, index) - } - }?; - let mut labels = edge - .iter() - .map(|dependency| match dependency { - ExecutionDependency::AwaitMemoryAccess(access_type) => match access_type { - MemoryAccessType::Read => "await read", - MemoryAccessType::Write => "await write", - MemoryAccessType::Capture => "await capture", - }, - ExecutionDependency::ReferenceFrame => "frame", - ExecutionDependency::StableOrdering => "ordering", - }) - .collect::>(); - - // We sort them so that graph output is deterministic; iterating over the set - // without sorting would cause flaky tests. - labels.sort_unstable(); - let label = labels.join("\n"); - writeln!(f, " [ label=\"{}\" ]", label) - }) - })?; - Ok(()) - } - /// Return a particular-indexed instruction (if present). pub fn get_instruction(&self, node_id: usize) -> Option<&Instruction> { self.instructions.get(node_id) @@ -442,26 +356,6 @@ pub enum BlockTerminator { Halt, } -/// Escape strings for use as DOT format quoted ID's -fn write_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result { - for c in s.chars() { - write_char(f, c)?; - } - Ok(()) -} - -/// Escape a single character for use within a DOT format quoted ID. -fn write_char(f: &mut fmt::Formatter, c: char) -> fmt::Result { - use std::fmt::Write; - match c { - '"' | '\\' => f.write_char('\\')?, - // \l is for left justified linebreak - '\n' => return f.write_str("\\l"), - _ => {} - } - f.write_char(c) -} - #[derive(Clone, Debug)] pub struct ScheduledProgram { /// All blocks within the ScheduledProgram, keyed on string label. @@ -637,84 +531,6 @@ impl ScheduledProgram { } label } - - /// Write a DOT format string to the provided writer for use with Graphviz. - /// - /// This outputs a `digraph` object with a `subgraph` for each block to inform the layout engine. - /// Each `subgraph` ID is prefixed with `cluster_` which instructs some supporting layout engines - /// to enclose the subgraph with a border. This improves readability of the graph. - /// - /// Lines on the graph indicate scheduling dependencies within blocks and control flow among blocks. - /// Each node representing an instruction is labeled with the contents of that instruction. - pub fn write_dot_format(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "digraph {{")?; - - let mut iter = self.blocks.iter().peekable(); - - writeln!(f, "\tentry [label=\"Entry Point\"]")?; - - if let Some((first_label, _)) = iter.peek() { - writeln!(f, "\tentry -> \"{}_start\"", first_label)?; - } - - while let Some((label, block)) = iter.next() { - writeln!(f, "\tsubgraph \"cluster_{}\" {{", label)?; - writeln!(f, "\t\tlabel=\"{}\"", label)?; - writeln!(f, "\t\tnode [ style=\"filled\" ]")?; - - let line_prefix = "\t\t"; - // let element_prefix = format!("b{}_", index); - let element_prefix = format!("{}_", label); - - block.write_dot_format(f, line_prefix, &element_prefix)?; - writeln!(f, "\t}}")?; - - let next_block_label = iter.peek().map(|(next_label, _)| (*next_label).clone()); - match &block.terminator { - BlockTerminator::Conditional { - condition, - target, - jump_if_condition_true, - } => { - let equality_operators = if *jump_if_condition_true { - ("==", "!=") - } else { - ("!=", "==") - }; - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", - label, target, condition, equality_operators.0, - )?; - if let Some(next_label) = next_block_label { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", - label, next_label, condition, equality_operators.1 - )?; - }; - } - BlockTerminator::Unconditional { target } => { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"always\"]", - label, target - )?; - } - BlockTerminator::Continue => { - if let Some(next_label) = next_block_label { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"always\"]", - label, next_label - )?; - }; - } - BlockTerminator::Halt => {} - } - } - writeln!(f, "}}") - } } #[cfg(test)] diff --git a/src/program/mod.rs b/src/program/mod.rs index 3420ad6e..40964479 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -29,6 +29,7 @@ pub use self::memory::MemoryRegion; mod calibration; mod error; +pub mod dot; mod frame; pub mod graph; mod memory; From f0f925b016b0f06313b05e3bd8a59d7b439e9a66 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 18:11:22 -0700 Subject: [PATCH 36/75] Install dot_writer --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + 2 files changed, 8 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6a3e9549..352f41b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,6 +223,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "dot-writer" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1defb949b123415131ecae40ab5dca70e9f39eedda3de2cebb03a8a98fdf5894" + [[package]] name = "either" version = "1.6.1" @@ -585,6 +591,7 @@ name = "quil-rs" version = "0.8.7" dependencies = [ "criterion", + "dot-writer", "indexmap", "insta", "lexical", diff --git a/Cargo.toml b/Cargo.toml index b30b1468..e174f47e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ keywords = ["Quil", "Quantum", "Rigetti"] categories = ["parser-implementations", "science", "compilers", "emulators"] [dependencies] +dot-writer = "0.1.2" indexmap = "1.6.1" lexical = "5.2.0" nom = "6.1.0" From a053a418a238359563f1748f031755ddb1a25f0f Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 18:14:02 -0700 Subject: [PATCH 37/75] Breaking: revise graphviz dot generation API --- src/program/dot.rs | 285 +++++++++--------- src/program/graph.rs | 17 +- ...sts__graph__active_reset_single_frame.snap | 77 +++-- ...__graph__tests__graph__chained_pulses.snap | 45 ++- ...sts__graph__different_frames_blocking.snap | 37 ++- ...__graph__different_frames_nonblocking.snap | 41 ++- ...ogram__graph__tests__graph__fence_all.snap | 29 +- ...ph__fence_all_with_nonblocking_pulses.snap | 53 ++-- ...s__program__graph__tests__graph__jump.snap | 75 +++-- ...ram__graph__tests__graph__labels_only.snap | 55 ++-- ...raph__multiple_classical_instructions.snap | 47 ++- ...graph__tests__graph__parametric_pulse.snap | 37 ++- ...rametric_pulses_using_capture_results.snap | 83 +++-- ...ph__tests__graph__pulse_after_capture.snap | 35 ++- ...__graph__tests__graph__simple_capture.snap | 31 +- ...h__tests__graph__simple_memory_access.snap | 43 ++- ...raph__tests__graph__single_dependency.snap | 33 +- ...aph__tests__graph__single_instruction.snap | 29 +- 18 files changed, 516 insertions(+), 536 deletions(-) diff --git a/src/program/dot.rs b/src/program/dot.rs index 90e1b56f..12de752d 100644 --- a/src/program/dot.rs +++ b/src/program/dot.rs @@ -1,75 +1,59 @@ -// Utilities for working with Graphviz dot format files +//! Utilities for working with Graphviz dot format files + +/** + * Copyright 2021 Rigetti Computing + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +use dot_writer::{Attributes, DotWriter, Shape, Style}; use crate::program::graph::{ - BlockTerminator, ExecutionDependency, MemoryAccessType, ScheduledGraphNode, + BlockTerminator, ExecutionDependency, InstructionBlock, MemoryAccessType, ScheduledGraphNode, + ScheduledProgram, }; -use super::graph::{InstructionBlock, ScheduledProgram}; - impl InstructionBlock { - /// Write a DOT-formatted string to the provided writer for use with GraphViz. - /// This output can be used within a `subgraph` or at the top level of a `digraph`. - /// - /// Parameters: - /// - /// * line_prefix: The prefix for each new line in the output. This can be used to indent this - /// output for readability in a larger definition. - /// * element_prefix: The prefix for each graph element (node and edge). This can be used to - /// namespace this block when used with other blocks which may have conflicting labels. - pub fn write_dot_format( - &self, - f: &mut std::fmt::Formatter, - line_prefix: &str, - element_prefix: &str, - ) -> std::fmt::Result { - self.graph.nodes().try_for_each(|node| { + /// Given a [dot_writer::Scope] representing a subgraph/cluster, write the timing graph for this block into it. + /// Uses the `node_prefix` argument for namespacing so that node IDs remain unique within the overall graph. + fn write_dot_format(&self, cluster: &mut dot_writer::Scope, node_prefix: &str) { + self.graph.nodes().for_each(|node| { + let node_id = get_node_id(&node, node_prefix); match &node { ScheduledGraphNode::BlockEnd => { - writeln!( - f, - "{}\"{}end\" [ label=end, shape=circle ]", - line_prefix, element_prefix - ) + // cluster.node_named(format!("{}end")) + cluster + .node_named(node_id) + .set_shape(Shape::Circle) + .set_label("end"); } ScheduledGraphNode::BlockStart => { - writeln!( - f, - "{}\"{}start\" [ label=start, shape=circle ]", - line_prefix, element_prefix - ) + cluster + .node_named(node_id) + .set_shape(Shape::Circle) + .set_label("start"); } ScheduledGraphNode::InstructionIndex(index) => { - write!( - f, - "{}\"{}{}\" [label=\"", - line_prefix, element_prefix, index - )?; - write_escaped(f, &format!("{}", self.instructions.get(*index).unwrap()))?; - writeln!(f, "\"]") + cluster + .node_named(node_id) + .set_label(&escape_label(&format!( + "{}", + self.instructions.get(*index).unwrap() + ))); } - }?; - self.graph.edges(node).try_for_each(|(src, dest, edge)| { - match &src { - ScheduledGraphNode::BlockEnd => { - write!(f, "{}\"{}end\"", line_prefix, element_prefix) - } - ScheduledGraphNode::BlockStart => { - write!(f, "{}\"{}start\"", line_prefix, element_prefix) - } - ScheduledGraphNode::InstructionIndex(index) => { - write!(f, "{}\"{}{}\"", line_prefix, element_prefix, index) - } - }?; - write!(f, " -> ")?; - match &dest { - ScheduledGraphNode::BlockEnd => write!(f, "\"{}end\"", element_prefix), - ScheduledGraphNode::BlockStart => { - write!(f, "\"{}start\"", element_prefix) - } - ScheduledGraphNode::InstructionIndex(index) => { - write!(f, "\"{}{}\"", element_prefix, index) - } - }?; + }; + self.graph.edges(node).for_each(|(src, dest, edge)| { + let source = get_node_id(&src, node_prefix); + let target = get_node_id(&dest, node_prefix); let mut labels = edge .iter() .map(|dependency| match dependency { @@ -87,15 +71,17 @@ impl InstructionBlock { // without sorting would cause flaky tests. labels.sort_unstable(); let label = labels.join("\n"); - writeln!(f, " [ label=\"{}\" ]", label) + cluster + .edge(source, target) + .attributes() + .set_label(label.as_str()); }) - })?; - Ok(()) + }); } } impl ScheduledProgram { - /// Write a DOT format string to the provided writer for use with Graphviz. + /// Return a DOT format string (as bytes) for use with Graphviz. /// /// This outputs a `digraph` object with a `subgraph` for each block to inform the layout engine. /// Each `subgraph` ID is prefixed with `cluster_` which instructs some supporting layout engines @@ -103,93 +89,114 @@ impl ScheduledProgram { /// /// Lines on the graph indicate scheduling dependencies within blocks and control flow among blocks. /// Each node representing an instruction is labeled with the contents of that instruction. - pub fn write_dot_format(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - writeln!(f, "digraph {{")?; - - let mut iter = self.blocks.iter().peekable(); - - writeln!(f, "\tentry [label=\"Entry Point\"]")?; - - if let Some((first_label, _)) = iter.peek() { - writeln!(f, "\tentry -> \"{}_start\"", first_label)?; - } + pub fn get_dot_format(&self) -> Vec { + let mut output_bytes = Vec::new(); - while let Some((label, block)) = iter.next() { - writeln!(f, "\tsubgraph \"cluster_{}\" {{", label)?; - writeln!(f, "\t\tlabel=\"{}\"", label)?; - writeln!(f, "\t\tnode [ style=\"filled\" ]")?; + { + let mut writer = DotWriter::from(&mut output_bytes); + writer.set_pretty_print(true); + let mut digraph = writer.digraph(); - let line_prefix = "\t\t"; - // let element_prefix = format!("b{}_", index); - let element_prefix = format!("{}_", label); + let mut iter = self.blocks.iter().peekable(); + if let Some((first_label, _)) = iter.peek() { + digraph.edge( + "entry", + get_node_id(&ScheduledGraphNode::BlockStart, first_label), + ); + } + digraph.node_named("entry").set_label("Entry Point"); - block.write_dot_format(f, line_prefix, &element_prefix)?; - writeln!(f, "\t}}")?; + while let Some((label, block)) = iter.next() { + let node_prefix = label; + { + let mut cluster = digraph.cluster(); + cluster.set_label(label); + cluster.node_attributes().set_style(Style::Filled); - let next_block_label = iter.peek().map(|(next_label, _)| (*next_label).clone()); - match &block.terminator { - BlockTerminator::Conditional { - condition, - target, - jump_if_condition_true, - } => { - let equality_operators = if *jump_if_condition_true { - ("==", "!=") - } else { - ("!=", "==") - }; - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", - label, target, condition, equality_operators.0, - )?; - if let Some(next_label) = next_block_label { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"if {} {} 0\"]", - label, next_label, condition, equality_operators.1 - )?; - }; - } - BlockTerminator::Unconditional { target } => { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"always\"]", - label, target - )?; + block.write_dot_format(&mut cluster, node_prefix); } - BlockTerminator::Continue => { - if let Some(next_label) = next_block_label { - writeln!( - f, - "\"{}_end\" -> \"{}_start\" [label=\"always\"]", - label, next_label - )?; - }; + + let next_block_label = iter.peek().map(|(next_label, _)| (*next_label).clone()); + let terminator_source_label = + get_node_id(&ScheduledGraphNode::BlockEnd, node_prefix); + match &block.terminator { + BlockTerminator::Conditional { + condition, + target, + jump_if_condition_true, + } => { + let equality_operators = if *jump_if_condition_true { + ("==", "!=") + } else { + ("!=", "==") + }; + digraph + .edge( + &terminator_source_label, + get_node_id(&ScheduledGraphNode::BlockStart, target), + ) + .attributes() + .set_label( + format!("if {} {} 0", condition, equality_operators.0).as_str(), + ); + if let Some(next_label) = next_block_label { + digraph + .edge( + &terminator_source_label, + get_node_id(&ScheduledGraphNode::BlockStart, &next_label), + ) + .attributes() + .set_label( + format!("if {} {} 0", condition, equality_operators.1).as_str(), + ); + }; + } + BlockTerminator::Unconditional { target } => { + digraph + .edge( + &terminator_source_label, + get_node_id(&ScheduledGraphNode::BlockStart, target), + ) + .attributes() + .set_label("always"); + } + BlockTerminator::Continue => { + if let Some(next_label) = next_block_label { + digraph + .edge( + &terminator_source_label, + get_node_id(&ScheduledGraphNode::BlockStart, &next_label), + ) + .attributes() + .set_label("always"); + }; + } + BlockTerminator::Halt => {} } - BlockTerminator::Halt => {} } } - writeln!(f, "}}") + + output_bytes } } -/// Escape strings for use as DOT format quoted ID's -fn write_escaped(f: &mut std::fmt::Formatter, s: &str) -> std::fmt::Result { - for c in s.chars() { - write_char(f, c)?; - } - Ok(()) +/// Escape a string for safe use as a Graphviz node ID or label +fn escape_label(original: &str) -> String { + original.replace("\"", "\\\"") } -/// Escape a single character for use within a DOT format quoted ID. -fn write_char(f: &mut std::fmt::Formatter, c: char) -> std::fmt::Result { - use std::fmt::Write; - match c { - '"' | '\\' => f.write_char('\\')?, - // \l is for left justified linebreak - '\n' => return f.write_str("\\l"), - _ => {} +/// Return a string to be used as the node ID within the graph text. +/// `prefix` parameter allows namespacing for uniqueness. +fn get_node_id(node: &ScheduledGraphNode, prefix: &str) -> String { + match node { + ScheduledGraphNode::BlockEnd => { + format!("\"{}_end\"", prefix) + } + ScheduledGraphNode::BlockStart => { + format!("\"{}_start\"", prefix) + } + ScheduledGraphNode::InstructionIndex(index) => { + format!("\"{}_{}\"", prefix, index) + } } - f.write_char(c) } diff --git a/src/program/graph.rs b/src/program/graph.rs index f055b878..106cf278 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -16,7 +16,6 @@ * limitations under the License. **/ use std::collections::{HashMap, HashSet}; -use std::fmt; use indexmap::IndexMap; use petgraph::graphmap::GraphMap; @@ -554,7 +553,6 @@ mod tests { ($name: ident, $input:expr) => { #[test] fn $name() { - use std::fmt; const FRAME_DEFINITIONS: &'static str = " DEFFRAME 0 \"rf\": INITIAL-FREQUENCY: 1e6 @@ -581,19 +579,10 @@ DEFFRAME 0 \"ro_tx\": ); } - struct ProgramDebugWrapper<'a> { - pub program: &'a ScheduledProgram, - } + let dot_format_bytes = scheduled_program.get_dot_format(); + let dot_format = String::from_utf8_lossy(&dot_format_bytes); - impl<'a> fmt::Debug for ProgramDebugWrapper<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.program.write_dot_format(f) - } - } - - insta::assert_debug_snapshot!(ProgramDebugWrapper { - program: &scheduled_program - }); + insta::assert_snapshot!(dot_format); } }; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap index e7024f78..29e89281 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap @@ -1,44 +1,43 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "measure_start" - subgraph "cluster_measure" { - label="measure" - node [ style="filled" ] - "measure_start" [ label=start, shape=circle ] - "measure_start" -> "measure_0" [ label="frame" ] - "measure_start" -> "measure_1" [ label="frame" ] - "measure_start" -> "measure_end" [ label="ordering" ] - "measure_0" [label="NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"] - "measure_0" -> "measure_end" [ label="frame" ] - "measure_1" [label="NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"] - "measure_1" -> "measure_end" [ label="await capture -frame" ] - "measure_end" [ label=end, shape=circle ] - } -"measure_end" -> "end_start" [label="if ro[0] == 0"] -"measure_end" -> "feedback_start" [label="if ro[0] != 0"] - subgraph "cluster_feedback" { - label="feedback" - node [ style="filled" ] - "feedback_start" [ label=start, shape=circle ] - "feedback_start" -> "feedback_0" [ label="frame" ] - "feedback_start" -> "feedback_end" [ label="ordering" ] - "feedback_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "feedback_0" -> "feedback_end" [ label="frame" ] - "feedback_end" [ label=end, shape=circle ] - } -"feedback_end" -> "measure_start" [label="always"] - subgraph "cluster_end" { - label="end" - node [ style="filled" ] - "end_start" [ label=start, shape=circle ] - "end_start" -> "end_end" [ label="ordering" ] - "end_end" [ label=end, shape=circle ] - } + entry -> "measure_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="measure"; + node [style="filled"]; + "measure_start" [shape=circle, label="start"]; + "measure_start" -> "measure_0" [label="frame"]; + "measure_start" -> "measure_1" [label="frame"]; + "measure_start" -> "measure_end" [label="ordering"]; + "measure_0" [label="NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; + "measure_0" -> "measure_end" [label="frame"]; + "measure_1" [label="NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; + "measure_1" -> "measure_end" [label="await capture +frame"]; + "measure_end" [shape=circle, label="end"]; + } + "measure_end" -> "end_start" [label="if ro[0] == 0"]; + "measure_end" -> "feedback_start" [label="if ro[0] != 0"]; + subgraph cluster_1 { + label="feedback"; + node [style="filled"]; + "feedback_start" [shape=circle, label="start"]; + "feedback_start" -> "feedback_0" [label="frame"]; + "feedback_start" -> "feedback_end" [label="ordering"]; + "feedback_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "feedback_0" -> "feedback_end" [label="frame"]; + "feedback_end" [shape=circle, label="end"]; + } + "feedback_end" -> "measure_start" [label="always"]; + subgraph cluster_2 { + label="end"; + node [style="filled"]; + "end_start" [shape=circle, label="start"]; + "end_start" -> "end_end" [label="ordering"]; + "end_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap index 9a19a717..b05376e8 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap @@ -1,28 +1,27 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_1" [ label="frame" ] - "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_1" -> "block_0_2" [ label="frame" ] - "block_0_2" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_2" -> "block_0_3" [ label="frame" ] - "block_0_3" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_3" -> "block_0_4" [ label="frame" ] - "block_0_4" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_4" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" -> "block_0_2" [label="frame"]; + "block_0_2" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_2" -> "block_0_3" [label="frame"]; + "block_0_3" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" -> "block_0_4" [label="frame"]; + "block_0_4" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_4" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap index d2da033d..4dd2c40f 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap @@ -1,24 +1,23 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_1" [ label="frame" ] - "block_0_1" [label="PULSE 1 \"rf\" test(duration: 1000000)"] - "block_0_1" -> "block_0_2" [ label="frame" ] - "block_0_2" [label="PULSE 2 \"rf\" test(duration: 1000000)"] - "block_0_2" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_1" [label="PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" -> "block_0_2" [label="frame"]; + "block_0_2" [label="PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap index f1087593..5cb0c7f4 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap @@ -1,26 +1,25 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_1" [ label="frame" ] - "block_0_start" -> "block_0_2" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_end" [ label="frame" ] - "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"] - "block_0_1" -> "block_0_end" [ label="frame" ] - "block_0_2" [label="NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"] - "block_0_2" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_1" [label="frame"]; + "block_0_start" -> "block_0_2" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_end" [label="frame"]; + "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" -> "block_0_end" [label="frame"]; + "block_0_2" [label="NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap index e9f5b3e1..9208a831 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap @@ -1,20 +1,19 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="FENCE"] - "block_0_0" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="FENCE"]; + "block_0_0" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap index 083ccb19..04c76529 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap @@ -1,32 +1,31 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_1" [ label="frame" ] - "block_0_start" -> "block_0_2" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_2" [ label="frame" ] - "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"] - "block_0_1" -> "block_0_2" [ label="frame" ] - "block_0_2" [label="FENCE"] - "block_0_2" -> "block_0_3" [ label="frame" ] - "block_0_2" -> "block_0_4" [ label="frame" ] - "block_0_2" -> "block_0_end" [ label="frame" ] - "block_0_3" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_3" -> "block_0_end" [ label="frame" ] - "block_0_4" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"] - "block_0_4" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_1" [label="frame"]; + "block_0_start" -> "block_0_2" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_2" [label="frame"]; + "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" -> "block_0_2" [label="frame"]; + "block_0_2" [label="FENCE"]; + "block_0_2" -> "block_0_3" [label="frame"]; + "block_0_2" -> "block_0_4" [label="frame"]; + "block_0_2" -> "block_0_end" [label="frame"]; + "block_0_3" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" -> "block_0_end" [label="frame"]; + "block_0_4" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_4" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap index 890b9ea1..f235ad77 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap @@ -1,43 +1,42 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "first-block_start" - subgraph "cluster_first-block" { - label="first-block" - node [ style="filled" ] - "first-block_start" [ label=start, shape=circle ] - "first-block_start" -> "first-block_0" [ label="frame" ] - "first-block_start" -> "first-block_end" [ label="ordering" ] - "first-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "first-block_0" -> "first-block_end" [ label="frame" ] - "first-block_end" [ label=end, shape=circle ] - } -"first-block_end" -> "third-block_start" [label="if ro[0] != 0"] -"first-block_end" -> "second-block_start" [label="if ro[0] == 0"] - subgraph "cluster_second-block" { - label="second-block" - node [ style="filled" ] - "second-block_start" [ label=start, shape=circle ] - "second-block_start" -> "second-block_0" [ label="frame" ] - "second-block_start" -> "second-block_end" [ label="ordering" ] - "second-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "second-block_0" -> "second-block_end" [ label="frame" ] - "second-block_end" [ label=end, shape=circle ] - } -"second-block_end" -> "third-block_start" [label="always"] - subgraph "cluster_third-block" { - label="third-block" - node [ style="filled" ] - "third-block_start" [ label=start, shape=circle ] - "third-block_start" -> "third-block_0" [ label="frame" ] - "third-block_start" -> "third-block_end" [ label="ordering" ] - "third-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "third-block_0" -> "third-block_end" [ label="frame" ] - "third-block_end" [ label=end, shape=circle ] - } + entry -> "first-block_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="first-block"; + node [style="filled"]; + "first-block_start" [shape=circle, label="start"]; + "first-block_start" -> "first-block_0" [label="frame"]; + "first-block_start" -> "first-block_end" [label="ordering"]; + "first-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "first-block_0" -> "first-block_end" [label="frame"]; + "first-block_end" [shape=circle, label="end"]; + } + "first-block_end" -> "third-block_start" [label="if ro[0] != 0"]; + "first-block_end" -> "second-block_start" [label="if ro[0] == 0"]; + subgraph cluster_1 { + label="second-block"; + node [style="filled"]; + "second-block_start" [shape=circle, label="start"]; + "second-block_start" -> "second-block_0" [label="frame"]; + "second-block_start" -> "second-block_end" [label="ordering"]; + "second-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "second-block_0" -> "second-block_end" [label="frame"]; + "second-block_end" [shape=circle, label="end"]; + } + "second-block_end" -> "third-block_start" [label="always"]; + subgraph cluster_2 { + label="third-block"; + node [style="filled"]; + "third-block_start" [shape=circle, label="start"]; + "third-block_start" -> "third-block_0" [label="frame"]; + "third-block_start" -> "third-block_end" [label="ordering"]; + "third-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "third-block_0" -> "third-block_end" [label="frame"]; + "third-block_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap index 6da250e1..36897314 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap @@ -1,33 +1,32 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "a_start" - subgraph "cluster_a" { - label="a" - node [ style="filled" ] - "a_start" [ label=start, shape=circle ] - "a_start" -> "a_end" [ label="ordering" ] - "a_end" [ label=end, shape=circle ] - } -"a_end" -> "b_start" [label="always"] - subgraph "cluster_b" { - label="b" - node [ style="filled" ] - "b_start" [ label=start, shape=circle ] - "b_start" -> "b_end" [ label="ordering" ] - "b_end" [ label=end, shape=circle ] - } -"b_end" -> "c_start" [label="always"] - subgraph "cluster_c" { - label="c" - node [ style="filled" ] - "c_start" [ label=start, shape=circle ] - "c_start" -> "c_end" [ label="ordering" ] - "c_end" [ label=end, shape=circle ] - } + entry -> "a_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="a"; + node [style="filled"]; + "a_start" [shape=circle, label="start"]; + "a_start" -> "a_end" [label="ordering"]; + "a_end" [shape=circle, label="end"]; + } + "a_end" -> "b_start" [label="always"]; + subgraph cluster_1 { + label="b"; + node [style="filled"]; + "b_start" [shape=circle, label="start"]; + "b_start" -> "b_end" [label="ordering"]; + "b_end" [shape=circle, label="end"]; + } + "b_end" -> "c_start" [label="always"]; + subgraph cluster_2 { + label="c"; + node [style="filled"]; + "c_start" [shape=circle, label="start"]; + "c_start" -> "c_end" [label="ordering"]; + "c_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap index fd3e5a95..8ef3d28a 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap @@ -1,30 +1,29 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="ordering" ] - "block_0_0" [label="MOVE ro[0] 1"] - "block_0_0" -> "block_0_1" [ label="await write -ordering" ] - "block_0_1" [label="MOVE ro[1] 0"] - "block_0_1" -> "block_0_2" [ label="await write -ordering" ] - "block_0_2" [label="ADD ro[0] 5"] - "block_0_2" -> "block_0_3" [ label="await write -ordering" ] - "block_0_3" [label="SUB ro[1] ro[0]"] - "block_0_3" -> "block_0_end" [ label="await read + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="ordering"]; + "block_0_0" [label="MOVE ro[0] 1"]; + "block_0_0" -> "block_0_1" [label="await write +ordering"]; + "block_0_1" [label="MOVE ro[1] 0"]; + "block_0_1" -> "block_0_2" [label="await write +ordering"]; + "block_0_2" [label="ADD ro[0] 5"]; + "block_0_2" -> "block_0_3" [label="await write +ordering"]; + "block_0_3" [label="SUB ro[1] ro[0]"]; + "block_0_3" -> "block_0_end" [label="await read await write -ordering" ] - "block_0_end" [ label=end, shape=circle ] - } +ordering"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap index 109f559a..63a26d0d 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap @@ -1,25 +1,24 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="PULSE 0 \"rf\" test(a: param[0])"] - "block_0_0" -> "block_0_1" [ label="frame" ] - "block_0_0" -> "block_0_end" [ label="await read" ] - "block_0_1" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"] - "block_0_1" -> "block_0_end" [ label="await capture + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="PULSE 0 \"rf\" test(a: param[0])"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_0" -> "block_0_end" [label="await read"]; + "block_0_1" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_1" -> "block_0_end" [label="await capture await read -frame" ] - "block_0_end" [ label=end, shape=circle ] - } +frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap index 5af50007..c666b701 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap @@ -1,48 +1,47 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"] - "block_0_0" -> "block_0_1" [ label="await capture -frame" ] - "block_0_0" -> "block_0_2" [ label="await capture -frame" ] - "block_0_0" -> "block_0_3" [ label="await capture -frame" ] - "block_0_0" -> "block_0_end" [ label="await read" ] - "block_0_1" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"] - "block_0_1" -> "block_0_3" [ label="await read -frame" ] - "block_0_1" -> "block_0_end" [ label="await read" ] - "block_0_2" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"] - "block_0_2" -> "block_0_3" [ label="await read -frame" ] - "block_0_2" -> "block_0_end" [ label="await read" ] - "block_0_3" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"] - "block_0_3" -> "block_0_4" [ label="await capture -frame" ] - "block_0_3" -> "block_0_5" [ label="await capture -frame" ] - "block_0_3" -> "block_0_end" [ label="await capture + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_0" -> "block_0_1" [label="await capture +frame"]; + "block_0_0" -> "block_0_2" [label="await capture +frame"]; + "block_0_0" -> "block_0_3" [label="await capture +frame"]; + "block_0_0" -> "block_0_end" [label="await read"]; + "block_0_1" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_1" -> "block_0_3" [label="await read +frame"]; + "block_0_1" -> "block_0_end" [label="await read"]; + "block_0_2" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_2" -> "block_0_3" [label="await read +frame"]; + "block_0_2" -> "block_0_end" [label="await read"]; + "block_0_3" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_3" -> "block_0_4" [label="await capture +frame"]; + "block_0_3" -> "block_0_5" [label="await capture +frame"]; + "block_0_3" -> "block_0_end" [label="await capture await read -frame" ] - "block_0_4" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"] - "block_0_4" -> "block_0_end" [ label="await read -frame" ] - "block_0_5" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"] - "block_0_5" -> "block_0_end" [ label="await read -frame" ] - "block_0_end" [ label=end, shape=circle ] - } +frame"]; + "block_0_4" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_4" -> "block_0_end" [label="await read +frame"]; + "block_0_5" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_5" -> "block_0_end" [label="await read +frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap index c551098e..7e4546d9 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap @@ -1,23 +1,22 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"] - "block_0_0" -> "block_0_1" [ label="frame" ] - "block_0_0" -> "block_0_end" [ label="await capture" ] - "block_0_1" [label="PULSE 0 \"rf\" test()"] - "block_0_1" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_0" -> "block_0_end" [label="await capture"]; + "block_0_1" [label="PULSE 0 \"rf\" test()"]; + "block_0_1" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap index b25ecc53..3619cfef 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap @@ -1,21 +1,20 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"] - "block_0_0" -> "block_0_end" [ label="await capture -frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" -> "block_0_end" [label="await capture +frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap index 0b073dd8..bcb82b38 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap @@ -1,28 +1,27 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="ordering" ] - "block_0_0" [label="MOVE a[0] 1"] - "block_0_0" -> "block_0_1" [ label="ordering" ] - "block_0_0" -> "block_0_2" [ label="await write" ] - "block_0_1" [label="MOVE b[0] 2"] - "block_0_1" -> "block_0_2" [ label="await write -ordering" ] - "block_0_1" -> "block_0_end" [ label="await write" ] - "block_0_2" [label="ADD a[0] b[0]"] - "block_0_2" -> "block_0_end" [ label="await read + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="ordering"]; + "block_0_0" [label="MOVE a[0] 1"]; + "block_0_0" -> "block_0_1" [label="ordering"]; + "block_0_0" -> "block_0_2" [label="await write"]; + "block_0_1" [label="MOVE b[0] 2"]; + "block_0_1" -> "block_0_2" [label="await write +ordering"]; + "block_0_1" -> "block_0_end" [label="await write"]; + "block_0_2" [label="ADD a[0] b[0]"]; + "block_0_2" -> "block_0_end" [label="await read await write -ordering" ] - "block_0_end" [ label=end, shape=circle ] - } +ordering"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap index 183a3fd2..6ed94db4 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap @@ -1,22 +1,21 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_1" [ label="frame" ] - "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_1" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap index f6cc65a4..69c4acc9 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap @@ -1,20 +1,19 @@ --- -source: quil/src/program/graph.rs -expression: "ProgramDebugWrapper{program: &scheduled_program,}" - +source: src/program/graph.rs +expression: dot_format --- digraph { - entry [label="Entry Point"] - entry -> "block_0_start" - subgraph "cluster_block_0" { - label="block_0" - node [ style="filled" ] - "block_0_start" [ label=start, shape=circle ] - "block_0_start" -> "block_0_0" [ label="frame" ] - "block_0_start" -> "block_0_end" [ label="ordering" ] - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"] - "block_0_0" -> "block_0_end" [ label="frame" ] - "block_0_end" [ label=end, shape=circle ] - } + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } } From 3e9aaed7070603a9317c35b51d718f3fc90bdd8c Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 19:26:29 -0700 Subject: [PATCH 38/75] Update: represent instructions as rectangles in program graphviz dot format --- src/program/dot.rs | 1 + src/program/mod.rs | 2 +- ...sts__graph__active_reset_single_frame.snap | 6 ++--- ...__graph__tests__graph__chained_pulses.snap | 10 ++++---- ...sts__graph__different_frames_blocking.snap | 6 ++--- ...__graph__different_frames_nonblocking.snap | 6 ++--- ...ogram__graph__tests__graph__fence_all.snap | 2 +- ...ph__fence_all_with_nonblocking_pulses.snap | 10 ++++---- ...s__program__graph__tests__graph__jump.snap | 6 ++--- ...raph__multiple_classical_instructions.snap | 8 +++---- ...graph__tests__graph__parametric_pulse.snap | 4 ++-- ...rametric_pulses_using_capture_results.snap | 24 ++++++++----------- ...ph__tests__graph__pulse_after_capture.snap | 4 ++-- ...__graph__tests__graph__simple_capture.snap | 2 +- ...h__tests__graph__simple_memory_access.snap | 7 +++--- ...raph__tests__graph__single_dependency.snap | 4 ++-- ...aph__tests__graph__single_instruction.snap | 2 +- 17 files changed, 50 insertions(+), 54 deletions(-) diff --git a/src/program/dot.rs b/src/program/dot.rs index 12de752d..5bbcbf83 100644 --- a/src/program/dot.rs +++ b/src/program/dot.rs @@ -45,6 +45,7 @@ impl InstructionBlock { ScheduledGraphNode::InstructionIndex(index) => { cluster .node_named(node_id) + .set_shape(Shape::Rectangle) .set_label(&escape_label(&format!( "{}", self.instructions.get(*index).unwrap() diff --git a/src/program/mod.rs b/src/program/mod.rs index 40964479..422fcc29 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -28,8 +28,8 @@ pub use self::frame::FrameSet; pub use self::memory::MemoryRegion; mod calibration; -mod error; pub mod dot; +mod error; mod frame; pub mod graph; mod memory; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap index 29e89281..814a647f 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap @@ -12,9 +12,9 @@ digraph { "measure_start" -> "measure_0" [label="frame"]; "measure_start" -> "measure_1" [label="frame"]; "measure_start" -> "measure_end" [label="ordering"]; - "measure_0" [label="NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; + "measure_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; "measure_0" -> "measure_end" [label="frame"]; - "measure_1" [label="NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; + "measure_1" [shape=rectangle, label="NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; "measure_1" -> "measure_end" [label="await capture frame"]; "measure_end" [shape=circle, label="end"]; @@ -27,7 +27,7 @@ frame"]; "feedback_start" [shape=circle, label="start"]; "feedback_start" -> "feedback_0" [label="frame"]; "feedback_start" -> "feedback_end" [label="ordering"]; - "feedback_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "feedback_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "feedback_0" -> "feedback_end" [label="frame"]; "feedback_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap index b05376e8..fcc25619 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap @@ -11,15 +11,15 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_3" [label="frame"]; - "block_0_3" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_3" -> "block_0_4" [label="frame"]; - "block_0_4" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap index 4dd2c40f..893c8a53 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap @@ -11,11 +11,11 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [label="PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [label="PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="PULSE 2 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap index 5cb0c7f4..2c806785 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap @@ -13,11 +13,11 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_end" [label="frame"]; - "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_end" [label="frame"]; - "block_0_2" [label="NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap index 9208a831..9081754f 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="FENCE"]; + "block_0_0" [shape=rectangle, label="FENCE"]; "block_0_0" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap index 04c76529..f0eca454 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap @@ -13,17 +13,17 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_2" [label="frame"]; - "block_0_1" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [label="FENCE"]; + "block_0_2" [shape=rectangle, label="FENCE"]; "block_0_2" -> "block_0_3" [label="frame"]; "block_0_2" -> "block_0_4" [label="frame"]; "block_0_2" -> "block_0_end" [label="frame"]; - "block_0_3" [label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_3" -> "block_0_end" [label="frame"]; - "block_0_4" [label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap index f235ad77..ffe40fb1 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap @@ -11,7 +11,7 @@ digraph { "first-block_start" [shape=circle, label="start"]; "first-block_start" -> "first-block_0" [label="frame"]; "first-block_start" -> "first-block_end" [label="ordering"]; - "first-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "first-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "first-block_0" -> "first-block_end" [label="frame"]; "first-block_end" [shape=circle, label="end"]; } @@ -23,7 +23,7 @@ digraph { "second-block_start" [shape=circle, label="start"]; "second-block_start" -> "second-block_0" [label="frame"]; "second-block_start" -> "second-block_end" [label="ordering"]; - "second-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "second-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "second-block_0" -> "second-block_end" [label="frame"]; "second-block_end" [shape=circle, label="end"]; } @@ -34,7 +34,7 @@ digraph { "third-block_start" [shape=circle, label="start"]; "third-block_start" -> "third-block_0" [label="frame"]; "third-block_start" -> "third-block_end" [label="ordering"]; - "third-block_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "third-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "third-block_0" -> "third-block_end" [label="frame"]; "third-block_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap index 8ef3d28a..a7085578 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap @@ -10,16 +10,16 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="ordering"]; - "block_0_0" [label="MOVE ro[0] 1"]; + "block_0_0" [shape=rectangle, label="MOVE ro[0] 1"]; "block_0_0" -> "block_0_1" [label="await write ordering"]; - "block_0_1" [label="MOVE ro[1] 0"]; + "block_0_1" [shape=rectangle, label="MOVE ro[1] 0"]; "block_0_1" -> "block_0_2" [label="await write ordering"]; - "block_0_2" [label="ADD ro[0] 5"]; + "block_0_2" [shape=rectangle, label="ADD ro[0] 5"]; "block_0_2" -> "block_0_3" [label="await write ordering"]; - "block_0_3" [label="SUB ro[1] ro[0]"]; + "block_0_3" [shape=rectangle, label="SUB ro[1] ro[0]"]; "block_0_3" -> "block_0_end" [label="await read await write ordering"]; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap index 63a26d0d..c3e00449 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap @@ -11,10 +11,10 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="PULSE 0 \"rf\" test(a: param[0])"]; + "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(a: param[0])"]; "block_0_0" -> "block_0_1" [label="frame"]; "block_0_0" -> "block_0_end" [label="await read"]; - "block_0_1" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_1" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_1" -> "block_0_end" [label="await capture await read frame"]; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap index c666b701..3452af76 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap @@ -11,34 +11,30 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_0" -> "block_0_1" [label="await capture frame"]; - "block_0_0" -> "block_0_2" [label="await capture -frame"]; - "block_0_0" -> "block_0_3" [label="await capture -frame"]; + "block_0_0" -> "block_0_2" [label="frame"]; + "block_0_0" -> "block_0_3" [label="frame"]; "block_0_0" -> "block_0_end" [label="await read"]; - "block_0_1" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; "block_0_1" -> "block_0_3" [label="await read frame"]; "block_0_1" -> "block_0_end" [label="await read"]; - "block_0_2" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_2" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; "block_0_2" -> "block_0_3" [label="await read frame"]; "block_0_2" -> "block_0_end" [label="await read"]; - "block_0_3" [label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_3" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_3" -> "block_0_4" [label="await capture frame"]; - "block_0_3" -> "block_0_5" [label="await capture -frame"]; - "block_0_3" -> "block_0_end" [label="await capture -await read + "block_0_3" -> "block_0_5" [label="frame"]; + "block_0_3" -> "block_0_end" [label="await read frame"]; - "block_0_4" [label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_4" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; "block_0_4" -> "block_0_end" [label="await read frame"]; - "block_0_5" [label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_5" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; "block_0_5" -> "block_0_end" [label="await read frame"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap index 7e4546d9..79d1b4d3 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap @@ -11,10 +11,10 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; "block_0_0" -> "block_0_1" [label="frame"]; "block_0_0" -> "block_0_end" [label="await capture"]; - "block_0_1" [label="PULSE 0 \"rf\" test()"]; + "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test()"]; "block_0_1" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap index 3619cfef..d8aef9df 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; "block_0_0" -> "block_0_end" [label="await capture frame"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap index bcb82b38..8ce1d753 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap @@ -10,14 +10,13 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="ordering"]; - "block_0_0" [label="MOVE a[0] 1"]; + "block_0_0" [shape=rectangle, label="MOVE a[0] 1"]; "block_0_0" -> "block_0_1" [label="ordering"]; "block_0_0" -> "block_0_2" [label="await write"]; - "block_0_1" [label="MOVE b[0] 2"]; + "block_0_1" [shape=rectangle, label="MOVE b[0] 2"]; "block_0_1" -> "block_0_2" [label="await write ordering"]; - "block_0_1" -> "block_0_end" [label="await write"]; - "block_0_2" [label="ADD a[0] b[0]"]; + "block_0_2" [shape=rectangle, label="ADD a[0] b[0]"]; "block_0_2" -> "block_0_end" [label="await read await write ordering"]; diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap index 6ed94db4..6f80d1b3 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap @@ -11,9 +11,9 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap index 69c4acc9..619abf59 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } From d71d455ddffc096e58238b0dd1e1320370e8835f Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 19:28:20 -0700 Subject: [PATCH 39/75] Fix: error in memory access dependencies --- src/program/graph.rs | 38 +++++++++---------- ...raph__multiple_classical_instructions.snap | 3 +- ...rametric_pulses_using_capture_results.snap | 2 - 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/program/graph.rs b/src/program/graph.rs index 106cf278..335090d3 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -137,16 +137,14 @@ impl MemoryAccessQueue { }); } + self.pending_capture = None; + self.pending_write = None; + match access { - // Mark the given node as reading from this memory region. If there was a write pending, - // return it to be used as a dependency. Read => { self.pending_reads.push(node_id); - result } - // Mark the given node as writing to this memory region. If there were any reads or another - // write or capture pending, return those as a dependency list. - Capture | Write => { + Capture => { for upstream_node_id in self.pending_reads.iter() { result.push(MemoryAccessDependency { node_id: *upstream_node_id, @@ -154,21 +152,24 @@ impl MemoryAccessQueue { }); } - match access { - Capture => { - self.pending_capture = Some(node_id); - self.pending_write = None; - } - Write => { - self.pending_capture = None; - self.pending_write = Some(node_id); - } - _ => panic!("expected Capture or Write memory dependency"), + self.pending_reads = vec![]; + self.pending_capture = Some(node_id); + } + + Write => { + for upstream_node_id in self.pending_reads.iter() { + result.push(MemoryAccessDependency { + node_id: *upstream_node_id, + access_type: Read, + }); } - result + self.pending_reads = vec![]; + self.pending_write = Some(node_id); } } + + result } } @@ -260,9 +261,6 @@ impl InstructionBlock { }), }?; - // FIXME: This will handle reads, writes, and captures in arbitrary order, which is a bug. - // Must be handled as reads -> (writes / captures). Instructions read all values prior to any - // writes they make to those values. let accesses = instruction.get_memory_accesses(); for (regions, access_type) in [ (accesses.reads, MemoryAccessType::Read), diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap index a7085578..39c1763a 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap @@ -20,8 +20,7 @@ ordering"]; "block_0_2" -> "block_0_3" [label="await write ordering"]; "block_0_3" [shape=rectangle, label="SUB ro[1] ro[0]"]; - "block_0_3" -> "block_0_end" [label="await read -await write + "block_0_3" -> "block_0_end" [label="await write ordering"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap index 3452af76..8cc42672 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap @@ -20,11 +20,9 @@ frame"]; "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; "block_0_1" -> "block_0_3" [label="await read frame"]; - "block_0_1" -> "block_0_end" [label="await read"]; "block_0_2" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; "block_0_2" -> "block_0_3" [label="await read frame"]; - "block_0_2" -> "block_0_end" [label="await read"]; "block_0_3" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_3" -> "block_0_4" [label="await capture frame"]; From ee2538991bc2d21ec0eedf6166105e1816d53536 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 4 Apr 2022 20:35:42 -0700 Subject: [PATCH 40/75] Chore: linter fix --- src/program/dot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/program/dot.rs b/src/program/dot.rs index 5bbcbf83..dec2867e 100644 --- a/src/program/dot.rs +++ b/src/program/dot.rs @@ -183,7 +183,7 @@ impl ScheduledProgram { /// Escape a string for safe use as a Graphviz node ID or label fn escape_label(original: &str) -> String { - original.replace("\"", "\\\"") + original.replace('\"', "\\\"") } /// Return a string to be used as the node ID within the graph text. From a68466dd24be5c4b7c0f39feeaddfeec9925d986 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 27 Apr 2022 13:36:13 -0700 Subject: [PATCH 41/75] Merge branch 'main' into feat/improve-dot-graphs --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/expression.rs | 90 ++++++++++++++++++++++++++++++++++++++++------ src/instruction.rs | 38 +++++++++++++++++++- 4 files changed, 119 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce4fbe04..75e6373c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,7 +589,7 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quil-rs" -version = "0.8.7" +version = "0.9.0" dependencies = [ "criterion", "dot-writer", diff --git a/Cargo.toml b/Cargo.toml index e174f47e..62667a7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "quil-rs" description = "Rust tooling for Quil (Quantum Instruction Language)" -version ="0.8.7" +version ="0.9.0" edition = "2018" license = "Apache-2.0" repository = "https://github.com/rigetti/quil-rust" diff --git a/src/expression.rs b/src/expression.rs index 8cf11fb7..b2a70e67 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -25,9 +25,15 @@ use proptest_derive::Arbitrary; use crate::parser::{lex, parse_expression}; use crate::{imag, instruction::MemoryReference, real}; +/// The different possible types of errors that could occur during expression evaluation. #[derive(Clone, Debug, PartialEq, Eq)] pub enum EvaluationError { + /// There wasn't enough information to completely evaluate an expression. Incomplete, + /// An operation expected a real number but received a complex one. + NumberNotReal, + /// An operation expected a number but received a different type of expression. + NotANumber, } #[derive(Clone, Debug)] @@ -52,7 +58,7 @@ pub enum Expression { } /// Hash value helper: turn a hashable thing into a u64. -fn _hash_to_u64(t: &T) -> u64 { +fn hash_to_u64(t: &T) -> u64 { let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() @@ -89,8 +95,8 @@ impl Hash for Expression { 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), + min_by_key(left, right, hash_to_u64), + max_by_key(left, right, hash_to_u64), ); a.hash(state); b.hash(state); @@ -135,7 +141,7 @@ 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) } } @@ -172,6 +178,12 @@ fn calculate_function( } } +/// Is this a small floating point number? +#[inline(always)] +fn is_small(x: f64) -> bool { + x.abs() < 1e-16 +} + impl Expression { /// Consume the expression, simplifying it as much as possible. /// @@ -371,6 +383,17 @@ impl Expression { other => other, } } + + /// If this is a number with imaginary part "equal to" zero (of _small_ absolute value), return + /// that number. Otherwise, error with an evaluation error of a descriptive type. + pub fn to_real(self) -> Result { + match self { + Expression::PiConstant => Ok(PI), + Expression::Number(x) if is_small(x.im) => Ok(x.re), + Expression::Number(_) => Err(EvaluationError::NumberNotReal), + _ => Err(EvaluationError::NotANumber), + } + } } impl<'a> FromStr for Expression { @@ -724,14 +747,61 @@ mod tests { } #[test] - fn eq_implies_hash_eq(x in arb_expr(), y in arb_expr()) { - let mut s = DefaultHasher::new(); - x.hash(&mut s); - let h_x = s.finish(); - y.hash(&mut s); - let h_y = s.finish(); + fn eq_iff_hash_eq(x in arb_expr(), y in arb_expr()) { + let h_x = { + let mut s = DefaultHasher::new(); + x.hash(&mut s); + s.finish() + }; + let h_y = { + let mut s = DefaultHasher::new(); + y.hash(&mut s); + s.finish() + }; prop_assert_eq!(x == y, h_x == h_y); } + #[test] + fn reals_are_real(x in any::()) { + prop_assert_eq!(Expression::Number(real!(x)).to_real(), Ok(x)) + } + + #[test] + fn some_nums_are_real(re in any::(), im in any::()) { + let result = Expression::Number(Complex64{re, im}).to_real(); + if is_small(im) { + prop_assert_eq!(result, Ok(re)) + } else { + prop_assert_eq!(result, Err(EvaluationError::NumberNotReal)) + } + } + + #[test] + fn no_other_exps_are_real(expr in arb_expr().prop_filter("Not numbers", |e| match e { + Expression::Number(_) | Expression::PiConstant => false, + _ => true, + } + )) { + prop_assert_eq!(expr.to_real(), Err(EvaluationError::NotANumber)) + } + + } + + #[test] + fn specific_to_real_tests() { + for (input, expected) in vec![ + (Expression::PiConstant, Ok(PI)), + (Expression::Number(Complex64 { re: 1.0, im: 0.0 }), Ok(1.0)), + ( + Expression::Number(Complex64 { re: 1.0, im: 1.0 }), + Err(EvaluationError::NumberNotReal), + ), + ( + Expression::Variable("Not a number".into()), + Err(EvaluationError::NotANumber), + ), + ] { + assert_eq!(input.to_real(), expected) + } } } diff --git a/src/instruction.rs b/src/instruction.rs index fb6eed88..55334992 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -748,7 +748,7 @@ impl fmt::Display for Instruction { write!(f, " {}", arguments.join(" "))?; } if let Some(data) = data { - write!(f, "{}", data)?; + write!(f, " \"{}\"", data)?; } Ok(()) } @@ -810,6 +810,42 @@ impl fmt::Display for Instruction { } } +#[cfg(test)] +mod test_instruction_display { + use super::{Instruction, Pragma}; + + #[test] + fn pragma() { + assert_eq!( + Instruction::Pragma(Pragma { + name: String::from("INITIAL_REWIRING"), + arguments: vec![], + data: Some(String::from("PARTIAL")), + }) + .to_string(), + "PRAGMA INITIAL_REWIRING \"PARTIAL\"" + ); + assert_eq!( + Instruction::Pragma(Pragma { + name: String::from("LOAD-MEMORY"), + arguments: vec![String::from("q0")], + data: Some(String::from("addr")), + }) + .to_string(), + "PRAGMA LOAD-MEMORY q0 \"addr\"" + ); + assert_eq!( + Instruction::Pragma(Pragma { + name: String::from("PRESERVE_BLOCK"), + arguments: vec![], + data: None, + }) + .to_string(), + "PRAGMA PRESERVE_BLOCK" + ); + } +} + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum Qubit { Fixed(u64), From 49669fdc6ea65cb00611b037981de9d05cbeae73 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 2 May 2022 19:57:27 -0700 Subject: [PATCH 42/75] Chore: improve apply_to_expressions docstring --- src/instruction.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/instruction.rs b/src/instruction.rs index 55334992..bba90509 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -885,6 +885,9 @@ impl Instruction { /// let program = Program::from_str("SHIFT-PHASE 0 \"rf\" 2*2").unwrap(); /// let mut instructions = program.to_instructions(true); /// instructions.iter_mut().for_each(|inst| inst.apply_to_expressions(|expr| { + /// // Here, `Expression::PiConstant` is used simply as a placeholder value + /// // allowing the closure to take ownership of the subject expression. + /// // Its value is ignored. /// let previous = replace(expr, Expression::PiConstant); /// *expr = previous.simplify(); /// })); From 988304d5d15ecac009a1ebc88b79a7a51079b0e1 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 2 May 2022 20:39:35 -0700 Subject: [PATCH 43/75] Chore: add top-level crate docs with links --- src/lib.rs | 52 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e8e0af24..a60ee34f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,40 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Welcome to the Rust implementation of the +//! [Quil quantum programming language](https://github.com/quil-lang/quil). +//! +//! Within this crate you'll find: +//! +//! * Builder utilities for Quil [programs], [instructions], and [expressions] +//! * A [parser] and [serializer] for converting Quil to and from text strings +//! * A [constructor for timing graphs], for understanding and debugging Quil-T +//! pulse control programs +//! +//! This crate is still early in its development and does not fully support all +//! Quil features, nor claim a stable API. Prior to `v1.0`, minor-version changes +//! are considered breaking changes. Please pin your versions when needed, and +//! closely follow the +//! [changelog](https://github.com/rigetti/quil-rust/releases) when upgrading. +//! +//! [constructor for timing graphs]: crate::program::graph::ScheduledProgram#method.get_dot_format +//! [expressions]: crate::expression::Expression +//! [instructions]: crate::instruction::Instruction +//! [parser]: crate::program::Program#method.from_str +//! [programs]: crate::program::Program +//! [serializer]: crate::program::Program#method.to_string + pub mod expression; pub mod instruction; mod macros; From 879e6546b4e33b74f96f2a59634ff37fcfa3ca26 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 2 May 2022 20:40:15 -0700 Subject: [PATCH 44/75] Chore: fix copyright notice header formatting --- src/macros.rs | 28 +++++++++++++--------------- src/parser/macros.rs | 28 +++++++++++++--------------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index fa6340da..b0c05e59 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,18 +1,16 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// Construct a complex number with the provided real component. #[macro_export] diff --git a/src/parser/macros.rs b/src/parser/macros.rs index 5d750d39..da6638b0 100644 --- a/src/parser/macros.rs +++ b/src/parser/macros.rs @@ -1,18 +1,16 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[macro_export] macro_rules! expected_token { From ae1013558af9b1fa96c661bfa8f5e808ea60ebe7 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Mon, 2 May 2022 20:40:38 -0700 Subject: [PATCH 45/75] Chore: fix inline docstrings --- src/program/calibration.rs | 2 +- src/program/dot.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 0ba00009..7907482a 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -299,7 +299,7 @@ impl CalibrationSet { } /// Add another gate calibration to the set. - /// Deprecated in favor of [`push_calibration`] + /// Deprecated in favor of [`Self::push_calibration`] #[deprecated = "use ScheduledProgram#push_calibration instead"] pub fn push(&mut self, calibration: Calibration) { self.push_calibration(calibration) diff --git a/src/program/dot.rs b/src/program/dot.rs index dec2867e..dcf5a275 100644 --- a/src/program/dot.rs +++ b/src/program/dot.rs @@ -30,7 +30,6 @@ impl InstructionBlock { let node_id = get_node_id(&node, node_prefix); match &node { ScheduledGraphNode::BlockEnd => { - // cluster.node_named(format!("{}end")) cluster .node_named(node_id) .set_shape(Shape::Circle) From e32999eb31c3be38922ea5c890163b3461c9cf01 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 3 May 2022 12:13:38 -0700 Subject: [PATCH 46/75] Prefix instruction text with [index] in dotfile output --- src/program/dot.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/program/dot.rs b/src/program/dot.rs index dcf5a275..c5f51149 100644 --- a/src/program/dot.rs +++ b/src/program/dot.rs @@ -46,7 +46,8 @@ impl InstructionBlock { .node_named(node_id) .set_shape(Shape::Rectangle) .set_label(&escape_label(&format!( - "{}", + "[{}] {}", + index, self.instructions.get(*index).unwrap() ))); } From da9b72f9742603708c59e83739ecda6411fe048a Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 16:12:32 -0700 Subject: [PATCH 47/75] Move graphviz dot utility behind a feature flag --- Cargo.toml | 5 ++++- src/program/{dot.rs => graphviz_dot.rs} | 0 src/program/mod.rs | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) rename src/program/{dot.rs => graphviz_dot.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index da64d073..cfd7cf27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ keywords = ["Quil", "Quantum", "Rigetti"] categories = ["parser-implementations", "science", "compilers", "emulators"] [dependencies] -dot-writer = "0.1.2" +dot-writer = { version = "0.1.2", optional = true } indexmap = "1.6.1" lexical = "5.2.0" nom = "6.1.0" @@ -24,6 +24,9 @@ proptest = "1.0.0" proptest-derive = "0.3.0" criterion = { version = "0.3.5", features = ["html_reports"] } +[features] +graphviz-dot = ["dot-writer"] + [[bench]] name = "parser" harness = false diff --git a/src/program/dot.rs b/src/program/graphviz_dot.rs similarity index 100% rename from src/program/dot.rs rename to src/program/graphviz_dot.rs diff --git a/src/program/mod.rs b/src/program/mod.rs index 422fcc29..5dbbb852 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -28,12 +28,14 @@ pub use self::frame::FrameSet; pub use self::memory::MemoryRegion; mod calibration; -pub mod dot; mod error; mod frame; pub mod graph; mod memory; +#[cfg(feature = "graphviz-dot")] +pub mod graphviz_dot; + /// A Quil Program instance describes a quantum program with metadata used in execution. /// /// This contains not only instructions which are executed in turn on the quantum processor, but From 402d95a4e36658f49b4b5c8c35a5e5cd74a3510c Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 16:15:14 -0700 Subject: [PATCH 48/75] Chore: fix docstring --- src/program/graphviz_dot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index c5f51149..7dea2509 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -23,7 +23,7 @@ use crate::program::graph::{ }; impl InstructionBlock { - /// Given a [dot_writer::Scope] representing a subgraph/cluster, write the timing graph for this block into it. + /// Given a [`dot_writer::Scope`] representing a subgraph/cluster, write the timing graph for this block into it. /// Uses the `node_prefix` argument for namespacing so that node IDs remain unique within the overall graph. fn write_dot_format(&self, cluster: &mut dot_writer::Scope, node_prefix: &str) { self.graph.nodes().for_each(|node| { From d4bb33e6b33d5de0e227bb340028869cf9ad8143 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 16:32:06 -0700 Subject: [PATCH 49/75] Chore: Test with --all-features in CI --- .github/workflows/msrv.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index d9435365..c8e744bf 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -48,6 +48,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test + args: --all-features fmt: name: Rustfmt From 638c57dd659004b1e456fdaae08fb981dc725d79 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 16:32:44 -0700 Subject: [PATCH 50/75] Fix: move graphviz-dot tests out to conditional module --- src/program/graph.rs | 199 ----------------- src/program/graphviz_dot.rs | 200 ++++++++++++++++++ ...ts__graph__active_reset_single_frame.snap} | 0 ...iz_dot__tests__graph__chained_pulses.snap} | 2 +- ...ts__graph__different_frames_blocking.snap} | 2 +- ..._graph__different_frames_nonblocking.snap} | 2 +- ...raphviz_dot__tests__graph__fence_all.snap} | 2 +- ...h__fence_all_with_nonblocking_pulses.snap} | 2 +- ...am__graphviz_dot__tests__graph__jump.snap} | 2 +- ...phviz_dot__tests__graph__labels_only.snap} | 2 +- ...aph__multiple_classical_instructions.snap} | 2 +- ..._dot__tests__graph__parametric_pulse.snap} | 2 +- ...rametric_pulse_using_capture_results.snap} | 2 +- ...ametric_pulses_using_capture_results.snap} | 2 +- ...t__tests__graph__pulse_after_capture.snap} | 2 +- ...iz_dot__tests__graph__simple_capture.snap} | 2 +- ...__tests__graph__simple_memory_access.snap} | 2 +- ...dot__tests__graph__single_dependency.snap} | 2 +- ...ot__tests__graph__single_instruction.snap} | 2 +- 19 files changed, 216 insertions(+), 215 deletions(-) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__active_reset_single_frame.snap => quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap} (100%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__chained_pulses.snap => quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap} (96%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__different_frames_blocking.snap => quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap => quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap} (96%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__fence_all.snap => quil_rs__program__graphviz_dot__tests__graph__fence_all.snap} (93%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap => quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap} (97%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__jump.snap => quil_rs__program__graphviz_dot__tests__graph__jump.snap} (97%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__labels_only.snap => quil_rs__program__graphviz_dot__tests__graph__labels_only.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap => quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__parametric_pulse.snap => quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__parametric_pulse_using_capture_results.snap => quil_rs__program__graphviz_dot__tests__graph__parametric_pulse_using_capture_results.snap} (94%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap => quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap} (97%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__pulse_after_capture.snap => quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__simple_capture.snap => quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap} (93%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__simple_memory_access.snap => quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap} (95%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__single_dependency.snap => quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap} (94%) rename src/program/snapshots/{quil_rs__program__graph__tests__graph__single_instruction.snap => quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap} (93%) diff --git a/src/program/graph.rs b/src/program/graph.rs index 335090d3..b1e7d242 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -529,202 +529,3 @@ impl ScheduledProgram { label } } - -#[cfg(test)] -mod tests { - mod graph { - use std::str::FromStr; - - use crate::program::Program; - - use super::super::ScheduledProgram; - - /// Build a test case which compiles the input program, builds the dot-format string from the program, - /// and then compares that to a "correct" snapshot of that dot format. This makes diffs easy to compare and - /// understand; if a test is failing, you can copy the snapshot contents out to your preferred Graphviz - /// viewer to help understand why. - /// - /// NOTE: because this relies on direct string comparison, it will be brittle against changes in the way - /// that the `write_dot_format` methods work. If _all_ or _most_ of these tests are failing, examine the - /// diffs closely to determine if it's only a matter of reformatting. - macro_rules! build_dot_format_snapshot_test_case { - ($name: ident, $input:expr) => { - #[test] - fn $name() { - const FRAME_DEFINITIONS: &'static str = " -DEFFRAME 0 \"rf\": - INITIAL-FREQUENCY: 1e6 -DEFFRAME 1 \"rf\": - INITIAL-FREQUENCY: 1e6 -DEFFRAME 2 \"rf\": - INITIAL-FREQUENCY: 1e6 -DEFFRAME 0 \"ro_rx\": - INITIAL-FREQUENCY: 1e6 -DEFFRAME 0 \"ro_tx\": - INITIAL-FREQUENCY: 1e6 -"; - - let program = - Program::from_str(&format!("{}\n{}", FRAME_DEFINITIONS, $input)).unwrap(); - let scheduled_program = ScheduledProgram::from_program(&program).unwrap(); - - for block in scheduled_program.blocks.values() { - let graph = block.get_dependency_graph(); - assert!( - !petgraph::algo::is_cyclic_directed(graph), - "cycle in graph: {:?}", - graph - ); - } - - let dot_format_bytes = scheduled_program.get_dot_format(); - let dot_format = String::from_utf8_lossy(&dot_format_bytes); - - insta::assert_snapshot!(dot_format); - } - }; - } - - build_dot_format_snapshot_test_case!( - single_instruction, - "PULSE 0 \"rf\" test(duration: 1e6)" - ); - - build_dot_format_snapshot_test_case!( - single_dependency, - " -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 0 \"rf\" test(duration: 1e6) -" - ); - - build_dot_format_snapshot_test_case!( - chained_pulses, - " -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 0 \"rf\" test(duration: 1e6) -" - ); - - build_dot_format_snapshot_test_case!( - different_frames_blocking, - " -PULSE 0 \"rf\" test(duration: 1e6) -PULSE 1 \"rf\" test(duration: 1e6) -PULSE 2 \"rf\" test(duration: 1e6) -" - ); - - build_dot_format_snapshot_test_case!( - different_frames_nonblocking, - " -NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) -NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) -NONBLOCKING PULSE 2 \"rf\" test(duration: 1e6) -" - ); - - build_dot_format_snapshot_test_case!( - fence_all_with_nonblocking_pulses, - " -NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) -NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) -FENCE -NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) -NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) -" - ); - build_dot_format_snapshot_test_case!(fence_all, "FENCE"); - - build_dot_format_snapshot_test_case!( - jump, - "DECLARE ro BIT -LABEL @first-block -PULSE 0 \"rf\" test(duration: 1e6) -JUMP-UNLESS @third-block ro[0] -LABEL @second-block -PULSE 0 \"rf\" test(duration: 1e6) -LABEL @third-block -PULSE 0 \"rf\" test(duration: 1e6) -" - ); - - build_dot_format_snapshot_test_case!( - active_reset_single_frame, - "DECLARE ro BIT -LABEL @measure -NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1e6) -NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1e6) ro -JUMP-WHEN @end ro[0] -LABEL @feedback -PULSE 0 \"rf\" test(duration: 1e6) -JUMP @measure -LABEL @end -" - ); - - build_dot_format_snapshot_test_case!( - labels_only, - "LABEL @a -LABEL @b -LABEL @c -" - ); - - // assert that read and write memory dependencies are expressed correctly - build_dot_format_snapshot_test_case!( - simple_memory_access, - "DECLARE a INTEGER -DECLARE b INTEGER -MOVE a 1 -MOVE b 2 -ADD a b -" - ); - - // assert that a block "waits" for a capture to complete - build_dot_format_snapshot_test_case!( - simple_capture, - "DECLARE ro BIT -CAPTURE 0 \"ro_rx\" test ro" - ); - - // assert that a block "waits" for a capture to complete even with a pulse after it - build_dot_format_snapshot_test_case!( - pulse_after_capture, - "DECLARE ro BIT -CAPTURE 0 \"ro_rx\" test ro -PULSE 0 \"rf\" test" - ); - - // assert that a block "waits" for a capture to complete - build_dot_format_snapshot_test_case!( - parametric_pulse, - "DECLARE ro BIT -DECLARE param REAL -PULSE 0 \"rf\" test(a: param[0]) -CAPTURE 0 \"ro_rx\" test(a: param[0]) ro" - ); - - // Assert that all pulses following a capture block on that capture, until the next capture - build_dot_format_snapshot_test_case!( - parametric_pulses_using_capture_results, - "DECLARE ro BIT -DECLARE param REAL -CAPTURE 0 \"ro_rx\" test(a: param[0]) ro -NONBLOCKING PULSE 0 \"rf\" test(a: ro[0]) -NONBLOCKING PULSE 1 \"rf\" test(a: ro[0]) -CAPTURE 0 \"ro_rx\" test(a: param[0]) ro -NONBLOCKING PULSE 0 \"rf\" test(a: ro[0]) -NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])" - ); - - build_dot_format_snapshot_test_case!( - multiple_classical_instructions, - "DECLARE ro INTEGER[2]\nMOVE ro[0] 1\nMOVE ro[1] 0\nADD ro[0] 5\nSUB ro[1] ro[0]" - ); - } -} diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index 7dea2509..1f14f792 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -201,3 +201,203 @@ fn get_node_id(node: &ScheduledGraphNode, prefix: &str) -> String { } } } + + +#[cfg(test)] +mod tests { + mod graph { + use std::str::FromStr; + + use crate::program::Program; + + use super::super::ScheduledProgram; + + /// Build a test case which compiles the input program, builds the dot-format string from the program, + /// and then compares that to a "correct" snapshot of that dot format. This makes diffs easy to compare and + /// understand; if a test is failing, you can copy the snapshot contents out to your preferred Graphviz + /// viewer to help understand why. + /// + /// NOTE: because this relies on direct string comparison, it will be brittle against changes in the way + /// that the `get_dot_format` method works. If _all_ or _most_ of these tests are failing, examine the + /// diffs closely to determine if it's only a matter of reformatting. + macro_rules! build_dot_format_snapshot_test_case { + ($name: ident, $input:expr) => { + #[test] + fn $name() { + const FRAME_DEFINITIONS: &'static str = " +DEFFRAME 0 \"rf\": + INITIAL-FREQUENCY: 1e6 +DEFFRAME 1 \"rf\": + INITIAL-FREQUENCY: 1e6 +DEFFRAME 2 \"rf\": + INITIAL-FREQUENCY: 1e6 +DEFFRAME 0 \"ro_rx\": + INITIAL-FREQUENCY: 1e6 +DEFFRAME 0 \"ro_tx\": + INITIAL-FREQUENCY: 1e6 +"; + + let program = + Program::from_str(&format!("{}\n{}", FRAME_DEFINITIONS, $input)).unwrap(); + let scheduled_program = ScheduledProgram::from_program(&program).unwrap(); + + for block in scheduled_program.blocks.values() { + let graph = block.get_dependency_graph(); + assert!( + !petgraph::algo::is_cyclic_directed(graph), + "cycle in graph: {:?}", + graph + ); + } + + let dot_format_bytes = scheduled_program.get_dot_format(); + let dot_format = String::from_utf8_lossy(&dot_format_bytes); + + insta::assert_snapshot!(dot_format); + } + }; + } + + build_dot_format_snapshot_test_case!( + single_instruction, + "PULSE 0 \"rf\" test(duration: 1e6)" + ); + + build_dot_format_snapshot_test_case!( + single_dependency, + " +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 0 \"rf\" test(duration: 1e6) +" + ); + + build_dot_format_snapshot_test_case!( + chained_pulses, + " +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 0 \"rf\" test(duration: 1e6) +" + ); + + build_dot_format_snapshot_test_case!( + different_frames_blocking, + " +PULSE 0 \"rf\" test(duration: 1e6) +PULSE 1 \"rf\" test(duration: 1e6) +PULSE 2 \"rf\" test(duration: 1e6) +" + ); + + build_dot_format_snapshot_test_case!( + different_frames_nonblocking, + " +NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) +NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) +NONBLOCKING PULSE 2 \"rf\" test(duration: 1e6) +" + ); + + build_dot_format_snapshot_test_case!( + fence_all_with_nonblocking_pulses, + " +NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) +NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) +FENCE +NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) +NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) +" + ); + build_dot_format_snapshot_test_case!(fence_all, "FENCE"); + + build_dot_format_snapshot_test_case!( + jump, + "DECLARE ro BIT +LABEL @first-block +PULSE 0 \"rf\" test(duration: 1e6) +JUMP-UNLESS @third-block ro[0] +LABEL @second-block +PULSE 0 \"rf\" test(duration: 1e6) +LABEL @third-block +PULSE 0 \"rf\" test(duration: 1e6) +" + ); + + build_dot_format_snapshot_test_case!( + active_reset_single_frame, + "DECLARE ro BIT +LABEL @measure +NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1e6) +NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1e6) ro +JUMP-WHEN @end ro[0] +LABEL @feedback +PULSE 0 \"rf\" test(duration: 1e6) +JUMP @measure +LABEL @end +" + ); + + build_dot_format_snapshot_test_case!( + labels_only, + "LABEL @a +LABEL @b +LABEL @c +" + ); + + // assert that read and write memory dependencies are expressed correctly + build_dot_format_snapshot_test_case!( + simple_memory_access, + "DECLARE a INTEGER +DECLARE b INTEGER +MOVE a 1 +MOVE b 2 +ADD a b +" + ); + + // assert that a block "waits" for a capture to complete + build_dot_format_snapshot_test_case!( + simple_capture, + "DECLARE ro BIT +CAPTURE 0 \"ro_rx\" test ro" + ); + + // assert that a block "waits" for a capture to complete even with a pulse after it + build_dot_format_snapshot_test_case!( + pulse_after_capture, + "DECLARE ro BIT +CAPTURE 0 \"ro_rx\" test ro +PULSE 0 \"rf\" test" + ); + + // assert that a block "waits" for a capture to complete + build_dot_format_snapshot_test_case!( + parametric_pulse, + "DECLARE ro BIT +DECLARE param REAL +PULSE 0 \"rf\" test(a: param[0]) +CAPTURE 0 \"ro_rx\" test(a: param[0]) ro" + ); + + // Assert that all pulses following a capture block on that capture, until the next capture + build_dot_format_snapshot_test_case!( + parametric_pulses_using_capture_results, + "DECLARE ro BIT +DECLARE param REAL +CAPTURE 0 \"ro_rx\" test(a: param[0]) ro +NONBLOCKING PULSE 0 \"rf\" test(a: ro[0]) +NONBLOCKING PULSE 1 \"rf\" test(a: ro[0]) +CAPTURE 0 \"ro_rx\" test(a: param[0]) ro +NONBLOCKING PULSE 0 \"rf\" test(a: ro[0]) +NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])" + ); + + build_dot_format_snapshot_test_case!( + multiple_classical_instructions, + "DECLARE ro INTEGER[2]\nMOVE ro[0] 1\nMOVE ro[1] 0\nADD ro[0] 5\nSUB ro[1] ro[0]" + ); + } +} diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap similarity index 100% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__active_reset_single_frame.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap similarity index 96% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap index fcc25619..3d837e60 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__chained_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap index 893c8a53..611ffa56 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap similarity index 96% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap index 2c806785..dfbca5a5 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__different_frames_nonblocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap similarity index 93% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap index 9081754f..e22daf83 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap similarity index 97% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap index f0eca454..403b02fd 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__fence_all_with_nonblocking_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap similarity index 97% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap index ffe40fb1..f76fdc5d 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__jump.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__labels_only.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__labels_only.snap index 36897314..b610baeb 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__labels_only.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__labels_only.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap index 39c1763a..54edce77 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__multiple_classical_instructions.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap index c3e00449..e6f401eb 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse_using_capture_results.snap similarity index 94% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse_using_capture_results.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse_using_capture_results.snap index 50e4cf7c..c2f1dd71 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulse_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse_using_capture_results.snap @@ -1,5 +1,5 @@ --- -source: quil/src/program/graph.rs +source: quil/src/program/graphviz_dot.rs expression: "ProgramDebugWrapper{program: &scheduled_program,}" --- diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap similarity index 97% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap index 8cc42672..8a4f6086 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap index 79d1b4d3..a573b31d 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__pulse_after_capture.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap similarity index 93% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap index d8aef9df..24e83b3a 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_capture.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap similarity index 95% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap index 8ce1d753..f8071dc3 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__simple_memory_access.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap similarity index 94% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap index 6f80d1b3..ee44efd6 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_dependency.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { diff --git a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap similarity index 93% rename from src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap rename to src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap index 619abf59..dd716dc6 100644 --- a/src/program/snapshots/quil_rs__program__graph__tests__graph__single_instruction.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { From 72e44da4296db96dc24cb99537ac6437fb26f7cc Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 16:33:46 -0700 Subject: [PATCH 51/75] Chore: update test snapshots to include instruction index --- ...dot__tests__graph__active_reset_single_frame.snap | 8 ++++---- ...__graphviz_dot__tests__graph__chained_pulses.snap | 10 +++++----- ...dot__tests__graph__different_frames_blocking.snap | 6 +++--- ...__tests__graph__different_frames_nonblocking.snap | 6 +++--- ...ogram__graphviz_dot__tests__graph__fence_all.snap | 2 +- ...ts__graph__fence_all_with_nonblocking_pulses.snap | 10 +++++----- ...s__program__graphviz_dot__tests__graph__jump.snap | 6 +++--- ...ests__graph__multiple_classical_instructions.snap | 8 ++++---- ...graphviz_dot__tests__graph__parametric_pulse.snap | 4 ++-- ...aph__parametric_pulses_using_capture_results.snap | 12 ++++++------ ...phviz_dot__tests__graph__pulse_after_capture.snap | 4 ++-- ...__graphviz_dot__tests__graph__simple_capture.snap | 2 +- ...hviz_dot__tests__graph__simple_memory_access.snap | 6 +++--- ...raphviz_dot__tests__graph__single_dependency.snap | 4 ++-- ...aphviz_dot__tests__graph__single_instruction.snap | 2 +- 15 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap index 814a647f..96ecb34c 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap @@ -1,5 +1,5 @@ --- -source: src/program/graph.rs +source: src/program/graphviz_dot.rs expression: dot_format --- digraph { @@ -12,9 +12,9 @@ digraph { "measure_start" -> "measure_0" [label="frame"]; "measure_start" -> "measure_1" [label="frame"]; "measure_start" -> "measure_end" [label="ordering"]; - "measure_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; + "measure_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; "measure_0" -> "measure_end" [label="frame"]; - "measure_1" [shape=rectangle, label="NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; + "measure_1" [shape=rectangle, label="[1] NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; "measure_1" -> "measure_end" [label="await capture frame"]; "measure_end" [shape=circle, label="end"]; @@ -27,7 +27,7 @@ frame"]; "feedback_start" [shape=circle, label="start"]; "feedback_start" -> "feedback_0" [label="frame"]; "feedback_start" -> "feedback_end" [label="ordering"]; - "feedback_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "feedback_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "feedback_0" -> "feedback_end" [label="frame"]; "feedback_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap index 3d837e60..db480023 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap @@ -11,15 +11,15 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_3" [label="frame"]; - "block_0_3" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="[3] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_3" -> "block_0_4" [label="frame"]; - "block_0_4" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="[4] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap index 611ffa56..5029b958 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap @@ -11,11 +11,11 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [shape=rectangle, label="PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] PULSE 2 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap index dfbca5a5..5f53bd7c 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap @@ -13,11 +13,11 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_end" [label="frame"]; - "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_end" [label="frame"]; - "block_0_2" [shape=rectangle, label="NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap index e22daf83..469d4bad 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="FENCE"]; + "block_0_0" [shape=rectangle, label="[0] FENCE"]; "block_0_0" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap index 403b02fd..c912643e 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap @@ -13,17 +13,17 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_2" [label="frame"]; - "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [shape=rectangle, label="FENCE"]; + "block_0_2" [shape=rectangle, label="[2] FENCE"]; "block_0_2" -> "block_0_3" [label="frame"]; "block_0_2" -> "block_0_4" [label="frame"]; "block_0_2" -> "block_0_end" [label="frame"]; - "block_0_3" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="[3] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_3" -> "block_0_end" [label="frame"]; - "block_0_4" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="[4] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap index f76fdc5d..9ceeebda 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap @@ -11,7 +11,7 @@ digraph { "first-block_start" [shape=circle, label="start"]; "first-block_start" -> "first-block_0" [label="frame"]; "first-block_start" -> "first-block_end" [label="ordering"]; - "first-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "first-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "first-block_0" -> "first-block_end" [label="frame"]; "first-block_end" [shape=circle, label="end"]; } @@ -23,7 +23,7 @@ digraph { "second-block_start" [shape=circle, label="start"]; "second-block_start" -> "second-block_0" [label="frame"]; "second-block_start" -> "second-block_end" [label="ordering"]; - "second-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "second-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "second-block_0" -> "second-block_end" [label="frame"]; "second-block_end" [shape=circle, label="end"]; } @@ -34,7 +34,7 @@ digraph { "third-block_start" [shape=circle, label="start"]; "third-block_start" -> "third-block_0" [label="frame"]; "third-block_start" -> "third-block_end" [label="ordering"]; - "third-block_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "third-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "third-block_0" -> "third-block_end" [label="frame"]; "third-block_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap index 54edce77..d422ef84 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__multiple_classical_instructions.snap @@ -10,16 +10,16 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="ordering"]; - "block_0_0" [shape=rectangle, label="MOVE ro[0] 1"]; + "block_0_0" [shape=rectangle, label="[0] MOVE ro[0] 1"]; "block_0_0" -> "block_0_1" [label="await write ordering"]; - "block_0_1" [shape=rectangle, label="MOVE ro[1] 0"]; + "block_0_1" [shape=rectangle, label="[1] MOVE ro[1] 0"]; "block_0_1" -> "block_0_2" [label="await write ordering"]; - "block_0_2" [shape=rectangle, label="ADD ro[0] 5"]; + "block_0_2" [shape=rectangle, label="[2] ADD ro[0] 5"]; "block_0_2" -> "block_0_3" [label="await write ordering"]; - "block_0_3" [shape=rectangle, label="SUB ro[1] ro[0]"]; + "block_0_3" [shape=rectangle, label="[3] SUB ro[1] ro[0]"]; "block_0_3" -> "block_0_end" [label="await write ordering"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap index e6f401eb..0dce3c01 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulse.snap @@ -11,10 +11,10 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(a: param[0])"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(a: param[0])"]; "block_0_0" -> "block_0_1" [label="frame"]; "block_0_0" -> "block_0_end" [label="await read"]; - "block_0_1" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_1" [shape=rectangle, label="[1] CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_1" -> "block_0_end" [label="await capture await read frame"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap index 8a4f6086..5330e3de 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap @@ -11,28 +11,28 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_0" [shape=rectangle, label="[0] CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_0" -> "block_0_1" [label="await capture frame"]; "block_0_0" -> "block_0_2" [label="frame"]; "block_0_0" -> "block_0_3" [label="frame"]; "block_0_0" -> "block_0_end" [label="await read"]; - "block_0_1" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; "block_0_1" -> "block_0_3" [label="await read frame"]; - "block_0_2" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; "block_0_2" -> "block_0_3" [label="await read frame"]; - "block_0_3" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; + "block_0_3" [shape=rectangle, label="[3] CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_3" -> "block_0_4" [label="await capture frame"]; "block_0_3" -> "block_0_5" [label="frame"]; "block_0_3" -> "block_0_end" [label="await read frame"]; - "block_0_4" [shape=rectangle, label="NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; + "block_0_4" [shape=rectangle, label="[4] NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; "block_0_4" -> "block_0_end" [label="await read frame"]; - "block_0_5" [shape=rectangle, label="NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; + "block_0_5" [shape=rectangle, label="[5] NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; "block_0_5" -> "block_0_end" [label="await read frame"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap index a573b31d..c78798ff 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__pulse_after_capture.snap @@ -11,10 +11,10 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" [shape=rectangle, label="[0] CAPTURE 0 \"ro_rx\" test() ro[0]"]; "block_0_0" -> "block_0_1" [label="frame"]; "block_0_0" -> "block_0_end" [label="await capture"]; - "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test()"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test()"]; "block_0_1" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap index 24e83b3a..aeacf601 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_capture.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="CAPTURE 0 \"ro_rx\" test() ro[0]"]; + "block_0_0" [shape=rectangle, label="[0] CAPTURE 0 \"ro_rx\" test() ro[0]"]; "block_0_0" -> "block_0_end" [label="await capture frame"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap index f8071dc3..891fbd04 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__simple_memory_access.snap @@ -10,13 +10,13 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="ordering"]; - "block_0_0" [shape=rectangle, label="MOVE a[0] 1"]; + "block_0_0" [shape=rectangle, label="[0] MOVE a[0] 1"]; "block_0_0" -> "block_0_1" [label="ordering"]; "block_0_0" -> "block_0_2" [label="await write"]; - "block_0_1" [shape=rectangle, label="MOVE b[0] 2"]; + "block_0_1" [shape=rectangle, label="[1] MOVE b[0] 2"]; "block_0_1" -> "block_0_2" [label="await write ordering"]; - "block_0_2" [shape=rectangle, label="ADD a[0] b[0]"]; + "block_0_2" [shape=rectangle, label="[2] ADD a[0] b[0]"]; "block_0_2" -> "block_0_end" [label="await read await write ordering"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap index ee44efd6..c1d24d5c 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap @@ -11,9 +11,9 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_1" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap index dd716dc6..dd5b4517 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; "block_0_0" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } From a39fb74cafc15deeb58a9334ae1fd35446636863 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:47:47 -0700 Subject: [PATCH 52/75] Chore: fmt --- src/program/graphviz_dot.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index 1f14f792..f66b878d 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -202,7 +202,6 @@ fn get_node_id(node: &ScheduledGraphNode, prefix: &str) -> String { } } - #[cfg(test)] mod tests { mod graph { From 4dffc79c12a0fcd8800b96cc748cba4b5607eb05 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:27:02 -0700 Subject: [PATCH 53/75] Add private method for parsing a single instruction from a string --- src/instruction.rs | 12 +++++++++++- src/parser/mod.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index bd273d11..6b1e42a9 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use nom::combinator::all_consuming; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; -use crate::expression::Expression; +use crate::{expression::Expression, parser::{instruction::parse_instruction, lex}}; #[cfg(test)] use proptest_derive::Arbitrary; @@ -942,6 +943,15 @@ impl Instruction { _ => {} } } + + /// Parse a single instruction from an input string. Returns an error if the input fails to parse, + /// or if there is input left over after parsing. + pub fn parse(input: &str) -> Result { + let lexed = lex(input)?; + println!("{:?}", lexed); + let (_, instruction) = all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; + Ok(instruction) + } } #[cfg(test)] diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 42a86582..cb5e8954 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -28,7 +28,7 @@ mod macros; mod common; mod error; mod expression; -mod instruction; +pub(crate) mod instruction; mod lexer; type ParserInput<'a> = &'a [Token]; From 6e898994b78ba85f4aca0748a0e7e226d2756ea0 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:27:21 -0700 Subject: [PATCH 54/75] WIP: Match frames by composable condition --- src/program/frame.rs | 89 ++++++++++++++++++++++---- src/program/mod.rs | 146 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 200 insertions(+), 35 deletions(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index 8b2ed984..d1cad882 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -35,18 +35,60 @@ impl FrameSet { self.frames.keys().collect() } - /// Return all contained FrameIdentifiers which include **exactly** these qubits (in any order) - /// and - if names are provided - match one of the names. - pub fn get_matching_keys(&self, qubits: &[Qubit], names: &[String]) -> Vec<&FrameIdentifier> { - let qubit_set: HashSet<&Qubit> = qubits.iter().collect(); - self.frames - .iter() - .filter(|(identifier, _)| { - (names.is_empty() || names.contains(&identifier.name)) - && qubit_set == identifier.qubits.iter().collect() - }) - .map(|(id, _)| id) - .collect::>() + /// Return all frames in the set which match all of these conditions. If a frame _would_ match, but is + /// not present in this [FrameSet], then it is not returned (notably, the [FrameMatchCondition::Specific] + /// match condition). + pub fn get_matching_keys(&self, condition: FrameMatchCondition) -> HashSet<&FrameIdentifier> { + let keys = self.frames.keys(); + + match condition { + FrameMatchCondition::All => keys.collect(), + FrameMatchCondition::AnyOfNames(names) => { + keys.filter(|&f| names.contains(&f.name)).collect() + } + FrameMatchCondition::AnyOfQubits(qubits) => { + let any_of_set: HashSet<_> = qubits.iter().collect(); + + keys.filter(|&f| f.qubits.iter().any(|q| any_of_set.contains(q))) + .collect() + } + FrameMatchCondition::ExactQubits(qubits) => { + let all_of_set: HashSet<_> = qubits.iter().collect(); + + keys.filter(|&f| f.qubits.iter().all(|q| all_of_set.contains(q))) + .collect() + } + FrameMatchCondition::Specific(frame) => { + if let Some(frame) = self.frames.get_key(&frame) { + vec![frame].into_iter().collect() + } else { + HashSet::new() + } + } + FrameMatchCondition::And(conditions) => { + let individual_sets: Vec> = conditions + .into_iter() + .map(|c| self.get_matching_keys(c)) + .collect(); + individual_sets + .into_iter() + .reduce(|acc, el| acc.into_iter().filter(|&v| el.contains(v)).collect()) + .unwrap_or_default() + } + FrameMatchCondition::Or(conditions) => { + let individual_sets: Vec> = conditions + .into_iter() + .map(|c| self.get_matching_keys(c)) + .collect(); + individual_sets + .into_iter() + .reduce(|acc, el| { + el.into_iter().for_each(|v| { acc.insert(v); }); + acc + }) + .unwrap_or_default() + } + } } /// Retrieve the attributes of a frame by its identifier. @@ -87,3 +129,26 @@ impl FrameSet { .collect() } } + +pub(crate) enum FrameMatchCondition { + /// Match all frames in the set + All, + + /// Match all frames which shares any one of these names + AnyOfNames(Vec), + + /// Match all frames which contain any of these qubits + AnyOfQubits(Vec), + + /// Match all frames which contain exactly these qubits + ExactQubits(Vec), + + /// Return these specific frames, if present in the set + Specific(FrameIdentifier), + + /// Return all frames which match all of these conditions + And(Vec), + + /// Return all frames which match any of these conditions + Or(Vec), +} diff --git a/src/program/mod.rs b/src/program/mod.rs index 5dbbb852..1a39cbe7 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -14,6 +14,7 @@ * limitations under the License. **/ use std::collections::BTreeMap; +use std::error::Error; use std::str::FromStr; use crate::instruction::{ @@ -24,6 +25,7 @@ use crate::instruction::{ use crate::parser::{lex, parse_instructions}; pub use self::calibration::CalibrationSet; +use self::frame::FrameMatchCondition; pub use self::frame::FrameSet; pub use self::memory::MemoryRegion; @@ -126,19 +128,28 @@ impl Program { /// /// Return `None` if the instruction does not execute in the context of a frame - such /// as classical instructions. + /// + /// See the [Quil-T spec](https://github.com/quil-lang/quil/blob/master/rfcs/analog/proposal.md) + /// for more information. pub fn get_frames_for_instruction<'a>( &'a self, instruction: &'a Instruction, include_blocked: bool, ) -> Option> { - match &instruction { + let condition = match &instruction { Instruction::Pulse(Pulse { blocking, frame, .. + }) + | Instruction::Capture(Capture { + blocking, frame, .. + }) + | Instruction::RawCapture(RawCapture { + blocking, frame, .. }) => { if *blocking && include_blocked { - Some(self.frames.get_keys()) + FrameMatchCondition::AnyOfQubits(frame.qubits) } else { - Some(vec![frame]) + FrameMatchCondition::Specific(frame.clone()) } } Instruction::Delay(Delay { @@ -146,35 +157,34 @@ impl Program { qubits, .. }) => { - let frame_ids = self.frames.get_matching_keys(qubits, frame_names); - Some(frame_ids) - } - Instruction::Fence(Fence { qubits }) => { - if qubits.is_empty() { - Some(self.frames.get_keys()) + if frame_names.is_empty() { + FrameMatchCondition::ExactQubits(qubits.clone()) } else { - Some(self.frames.get_matching_keys(qubits, &[])) + FrameMatchCondition::And(vec![ + FrameMatchCondition::ExactQubits(qubits.clone()), + FrameMatchCondition::AnyOfNames(frame_names.clone()), + ]) } } - Instruction::Capture(Capture { - blocking, frame, .. - }) - | Instruction::RawCapture(RawCapture { - blocking, frame, .. - }) => { - if *blocking && include_blocked { - Some(self.frames.get_keys()) + Instruction::Fence(Fence { qubits }) => { + if include_blocked { + FrameMatchCondition::AnyOfQubits(qubits.clone()) } else { - Some(vec![frame]) + return None; } } Instruction::SetFrequency(SetFrequency { frame, .. }) | Instruction::SetPhase(SetPhase { frame, .. }) | Instruction::SetScale(SetScale { frame, .. }) | Instruction::ShiftFrequency(ShiftFrequency { frame, .. }) - | Instruction::ShiftPhase(ShiftPhase { frame, .. }) => Some(vec![frame]), + | Instruction::ShiftPhase(ShiftPhase { frame, .. }) => { + FrameMatchCondition::Specific(frame.clone()) + } Instruction::SwapPhases(SwapPhases { frame_1, frame_2 }) => { - Some(vec![frame_1, frame_2]) + FrameMatchCondition::And(vec![ + FrameMatchCondition::Specific(frame_1.clone()), + FrameMatchCondition::Specific(frame_2.clone()), + ]) } Instruction::Gate(_) | Instruction::CircuitDefinition(_) @@ -196,8 +206,10 @@ impl Program { | Instruction::Store(_) | Instruction::Jump(_) | Instruction::JumpWhen(_) - | Instruction::JumpUnless(_) => None, - } + | Instruction::JumpUnless(_) => return None, + }; + + Some(self.frames.get_matching_keys(condition).into_iter().collect()) } pub fn to_instructions(&self, include_headers: bool) -> Vec { @@ -257,6 +269,8 @@ impl FromStr for Program { mod tests { use std::str::FromStr; + use crate::instruction::Instruction; + use super::Program; #[test] @@ -369,4 +383,90 @@ DECLARE ec BIT // program after being re-parsed and serialized. assert!(program1.lines().eq(program2.lines())); } + + #[test] + fn frame_blocking() { + let input = "DEFFRAME 0 \"a\": +\tHARDWARE-OBJECT: \"hardware\" + +DEFFRAME 0 \"b\": +\tHARDWARE-OBJECT: \"hardware\" + +DEFFRAME 1 \"c\": +\tHARDWARE-OBJECT: \"hardware\" + +DEFFRAME 0 1 \"2q\": +\tHARDWARE-OBJECT: \"hardware\" +"; + + let program = Program::from_str(input).unwrap(); + + for (instruction_string, expected_used_frames, expected_blocked_frames) in vec![ + // Blocking pulses block their qubits + ( + "PULSE 0 \"a\" custom_waveform", + vec!["0 \"a\""], + vec!["0 \"a\"", "0 \"b\"", "0 1 \"2q\""], + ), + ( + "PULSE 1 \"c\" custom_waveform", + vec!["1 \"c\""], + vec!["1 \"c\"", "0 1 \"2q\""], + ), + // Pulses on non-declared frames and unused qubits do not use or block any frames in the program + ("PULSE 2 \"a\" custom_waveform", vec![], vec![]), + // Captures work identically to Pulses + ( + "CAPTURE 0 \"a\" custom_waveform", + vec!["0 \"a\""], + vec!["0 \"a\"", "0 \"b\"", "0 1 \"2q\""], + ), + ( + "CAPTURE 1 \"c\" custom_waveform", + vec!["1 \"c\""], + vec!["1 \"c\"", "0 1 \"2q\""], + ), + ("CAPTURE 2 \"a\" custom_waveform", vec![], vec![]), + // A non-blocking pulse blocks only its precise frame, not other frames on the same qubits + ( + "NONBLOCKING PULSE 0 \"a\" custom_waveform", + vec!["0 \"a\""], + vec!["0 \"a\""], + ), + ( + "NONBLOCKING PULSE 1 \"c\" custom_waveform", + vec!["1 \"c\""], + vec!["1 \"c\""], + ), + ( + "NONBLOCKING PULSE 0 1 \"2q\" custom_waveform", + vec!["0 1 \"2q\""], + vec!["0 1 \"2q\""], + ), + ] { + let instruction = Instruction::parse(instruction_string).unwrap(); + let used_frames: Vec = program + .get_frames_for_instruction(&instruction, false) + .unwrap() + .into_iter() + .map(|f| f.to_string()) + .collect(); + assert_eq!( + used_frames, expected_used_frames, + "Instruction {} *used* frames `{:?}` but we expected `{:?}", + instruction, used_frames, expected_used_frames + ); + let blocked_frames: Vec = program + .get_frames_for_instruction(&instruction, true) + .unwrap() + .into_iter() + .map(|f| f.to_string()) + .collect(); + assert_eq!( + blocked_frames, expected_blocked_frames, + "Instruction {} *blocked* frames `{:?}` but we expected `{:?}", + instruction, blocked_frames, expected_blocked_frames + ); + } + } } From 42d0e59f78211d134c16a865b322ceeb3f0ff586 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:46:18 -0700 Subject: [PATCH 55/75] Remove extraneous println --- src/instruction.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/instruction.rs b/src/instruction.rs index 6b1e42a9..400c5bc9 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -948,7 +948,6 @@ impl Instruction { /// or if there is input left over after parsing. pub fn parse(input: &str) -> Result { let lexed = lex(input)?; - println!("{:?}", lexed); let (_, instruction) = all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; Ok(instruction) } From 3e9788058b57e298d5a337cd4c0887d0546e3df4 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:47:07 -0700 Subject: [PATCH 56/75] Fix: instruction frame blocking --- src/program/frame.rs | 29 ++++++++++-------- src/program/mod.rs | 72 +++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index d1cad882..4ef6d104 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -36,9 +36,12 @@ impl FrameSet { } /// Return all frames in the set which match all of these conditions. If a frame _would_ match, but is - /// not present in this [FrameSet], then it is not returned (notably, the [FrameMatchCondition::Specific] + /// not present in this [FrameSet], then it is not returned (notably, the [FrameMatchCondition::Specific] /// match condition). - pub fn get_matching_keys(&self, condition: FrameMatchCondition) -> HashSet<&FrameIdentifier> { + pub(crate) fn get_matching_keys<'s, 'a>( + &'s self, + condition: FrameMatchCondition<'a>, + ) -> HashSet<&'s FrameIdentifier> { let keys = self.frames.keys(); match condition { @@ -59,7 +62,7 @@ impl FrameSet { .collect() } FrameMatchCondition::Specific(frame) => { - if let Some(frame) = self.frames.get_key(&frame) { + if let Some((frame, _)) = self.frames.get_key_value(&frame) { vec![frame].into_iter().collect() } else { HashSet::new() @@ -82,8 +85,10 @@ impl FrameSet { .collect(); individual_sets .into_iter() - .reduce(|acc, el| { - el.into_iter().for_each(|v| { acc.insert(v); }); + .reduce(|mut acc, el| { + el.into_iter().for_each(|v| { + acc.insert(v); + }); acc }) .unwrap_or_default() @@ -130,25 +135,25 @@ impl FrameSet { } } -pub(crate) enum FrameMatchCondition { +pub(crate) enum FrameMatchCondition<'a> { /// Match all frames in the set All, /// Match all frames which shares any one of these names - AnyOfNames(Vec), + AnyOfNames(&'a [String]), /// Match all frames which contain any of these qubits - AnyOfQubits(Vec), + AnyOfQubits(&'a [Qubit]), /// Match all frames which contain exactly these qubits - ExactQubits(Vec), + ExactQubits(&'a [Qubit]), /// Return these specific frames, if present in the set - Specific(FrameIdentifier), + Specific(&'a FrameIdentifier), /// Return all frames which match all of these conditions - And(Vec), + And(Vec>), /// Return all frames which match any of these conditions - Or(Vec), + Or(Vec>), } diff --git a/src/program/mod.rs b/src/program/mod.rs index 1a39cbe7..069b8e18 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -14,7 +14,6 @@ * limitations under the License. **/ use std::collections::BTreeMap; -use std::error::Error; use std::str::FromStr; use crate::instruction::{ @@ -147,9 +146,9 @@ impl Program { blocking, frame, .. }) => { if *blocking && include_blocked { - FrameMatchCondition::AnyOfQubits(frame.qubits) + FrameMatchCondition::AnyOfQubits(&frame.qubits) } else { - FrameMatchCondition::Specific(frame.clone()) + FrameMatchCondition::Specific(frame) } } Instruction::Delay(Delay { @@ -158,17 +157,21 @@ impl Program { .. }) => { if frame_names.is_empty() { - FrameMatchCondition::ExactQubits(qubits.clone()) + FrameMatchCondition::ExactQubits(qubits) } else { FrameMatchCondition::And(vec![ - FrameMatchCondition::ExactQubits(qubits.clone()), - FrameMatchCondition::AnyOfNames(frame_names.clone()), + FrameMatchCondition::ExactQubits(qubits), + FrameMatchCondition::AnyOfNames(frame_names), ]) } } Instruction::Fence(Fence { qubits }) => { if include_blocked { - FrameMatchCondition::AnyOfQubits(qubits.clone()) + if qubits.is_empty() { + FrameMatchCondition::All + } else { + FrameMatchCondition::AnyOfQubits(qubits) + } } else { return None; } @@ -178,12 +181,12 @@ impl Program { | Instruction::SetScale(SetScale { frame, .. }) | Instruction::ShiftFrequency(ShiftFrequency { frame, .. }) | Instruction::ShiftPhase(ShiftPhase { frame, .. }) => { - FrameMatchCondition::Specific(frame.clone()) + FrameMatchCondition::Specific(frame) } Instruction::SwapPhases(SwapPhases { frame_1, frame_2 }) => { FrameMatchCondition::And(vec![ - FrameMatchCondition::Specific(frame_1.clone()), - FrameMatchCondition::Specific(frame_2.clone()), + FrameMatchCondition::Specific(frame_1), + FrameMatchCondition::Specific(frame_2), ]) } Instruction::Gate(_) @@ -209,7 +212,12 @@ impl Program { | Instruction::JumpUnless(_) => return None, }; - Some(self.frames.get_matching_keys(condition).into_iter().collect()) + Some( + self.frames + .get_matching_keys(condition) + .into_iter() + .collect(), + ) } pub fn to_instructions(&self, include_headers: bool) -> Vec { @@ -267,7 +275,7 @@ impl FromStr for Program { #[cfg(test)] mod tests { - use std::str::FromStr; + use std::{str::FromStr, collections::HashSet}; use crate::instruction::Instruction; @@ -417,16 +425,16 @@ DEFFRAME 0 1 \"2q\": ("PULSE 2 \"a\" custom_waveform", vec![], vec![]), // Captures work identically to Pulses ( - "CAPTURE 0 \"a\" custom_waveform", + "CAPTURE 0 \"a\" custom_waveform ro[0]", vec!["0 \"a\""], vec!["0 \"a\"", "0 \"b\"", "0 1 \"2q\""], ), ( - "CAPTURE 1 \"c\" custom_waveform", + "CAPTURE 1 \"c\" custom_waveform ro[0]", vec!["1 \"c\""], vec!["1 \"c\"", "0 1 \"2q\""], ), - ("CAPTURE 2 \"a\" custom_waveform", vec![], vec![]), + ("CAPTURE 2 \"a\" custom_waveform ro[0]", vec![], vec![]), // A non-blocking pulse blocks only its precise frame, not other frames on the same qubits ( "NONBLOCKING PULSE 0 \"a\" custom_waveform", @@ -443,25 +451,53 @@ DEFFRAME 0 1 \"2q\": vec!["0 1 \"2q\""], vec!["0 1 \"2q\""], ), + ( + "FENCE 1", + vec![], + vec!["1 \"c\"", "0 1 \"2q\""], + ), + ( + "FENCE", + vec![], + vec!["0 \"a\"", "0 \"b\"", "1 \"c\"", "0 1 \"2q\""], + ), + ( + "DELAY 0 1.0", + vec!["0 \"a\"", "0 \"b\""], + vec!["0 \"a\"", "0 \"b\""], + ), + ( + "DELAY 1 1.0", + vec!["1 \"c\""], + vec!["1 \"c\""], + ), + ( + "DELAY 1 \"c\" 1.0", + vec!["1 \"c\""], + vec!["1 \"c\""], + ), ] { let instruction = Instruction::parse(instruction_string).unwrap(); - let used_frames: Vec = program + let used_frames: HashSet = program .get_frames_for_instruction(&instruction, false) - .unwrap() + .unwrap_or_default() .into_iter() .map(|f| f.to_string()) .collect(); + let expected_used_frames: HashSet = expected_used_frames.into_iter().map(|el| el.to_owned()).collect(); assert_eq!( used_frames, expected_used_frames, "Instruction {} *used* frames `{:?}` but we expected `{:?}", instruction, used_frames, expected_used_frames ); - let blocked_frames: Vec = program + + let blocked_frames: HashSet = program .get_frames_for_instruction(&instruction, true) .unwrap() .into_iter() .map(|f| f.to_string()) .collect(); + let expected_blocked_frames: HashSet = expected_blocked_frames.into_iter().map(|el| el.to_owned()).collect(); assert_eq!( blocked_frames, expected_blocked_frames, "Instruction {} *blocked* frames `{:?}` but we expected `{:?}", From c0ca7bc5428a75125a6b817b316d4551830ae06e Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 18:48:33 -0700 Subject: [PATCH 57/75] Chore: fmt --- src/instruction.rs | 8 ++++++-- src/program/mod.rs | 30 ++++++++++++------------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index 400c5bc9..8f37546a 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -17,7 +17,10 @@ use nom::combinator::all_consuming; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; -use crate::{expression::Expression, parser::{instruction::parse_instruction, lex}}; +use crate::{ + expression::Expression, + parser::{instruction::parse_instruction, lex}, +}; #[cfg(test)] use proptest_derive::Arbitrary; @@ -948,7 +951,8 @@ impl Instruction { /// or if there is input left over after parsing. pub fn parse(input: &str) -> Result { let lexed = lex(input)?; - let (_, instruction) = all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; + let (_, instruction) = + all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; Ok(instruction) } } diff --git a/src/program/mod.rs b/src/program/mod.rs index 069b8e18..05adbe72 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -275,7 +275,7 @@ impl FromStr for Program { #[cfg(test)] mod tests { - use std::{str::FromStr, collections::HashSet}; + use std::{collections::HashSet, str::FromStr}; use crate::instruction::Instruction; @@ -451,11 +451,7 @@ DEFFRAME 0 1 \"2q\": vec!["0 1 \"2q\""], vec!["0 1 \"2q\""], ), - ( - "FENCE 1", - vec![], - vec!["1 \"c\"", "0 1 \"2q\""], - ), + ("FENCE 1", vec![], vec!["1 \"c\"", "0 1 \"2q\""]), ( "FENCE", vec![], @@ -466,16 +462,8 @@ DEFFRAME 0 1 \"2q\": vec!["0 \"a\"", "0 \"b\""], vec!["0 \"a\"", "0 \"b\""], ), - ( - "DELAY 1 1.0", - vec!["1 \"c\""], - vec!["1 \"c\""], - ), - ( - "DELAY 1 \"c\" 1.0", - vec!["1 \"c\""], - vec!["1 \"c\""], - ), + ("DELAY 1 1.0", vec!["1 \"c\""], vec!["1 \"c\""]), + ("DELAY 1 \"c\" 1.0", vec!["1 \"c\""], vec!["1 \"c\""]), ] { let instruction = Instruction::parse(instruction_string).unwrap(); let used_frames: HashSet = program @@ -484,7 +472,10 @@ DEFFRAME 0 1 \"2q\": .into_iter() .map(|f| f.to_string()) .collect(); - let expected_used_frames: HashSet = expected_used_frames.into_iter().map(|el| el.to_owned()).collect(); + let expected_used_frames: HashSet = expected_used_frames + .into_iter() + .map(|el| el.to_owned()) + .collect(); assert_eq!( used_frames, expected_used_frames, "Instruction {} *used* frames `{:?}` but we expected `{:?}", @@ -497,7 +488,10 @@ DEFFRAME 0 1 \"2q\": .into_iter() .map(|f| f.to_string()) .collect(); - let expected_blocked_frames: HashSet = expected_blocked_frames.into_iter().map(|el| el.to_owned()).collect(); + let expected_blocked_frames: HashSet = expected_blocked_frames + .into_iter() + .map(|el| el.to_owned()) + .collect(); assert_eq!( blocked_frames, expected_blocked_frames, "Instruction {} *blocked* frames `{:?}` but we expected `{:?}", From 18f2cce1521887173cb6cca3440b91c8b7b8b114 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:18:47 -0700 Subject: [PATCH 58/75] Fix visibility of Instruction::parse --- src/instruction.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/instruction.rs b/src/instruction.rs index 8f37546a..69fff0f0 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -947,9 +947,10 @@ impl Instruction { } } + #[cfg(test)] /// Parse a single instruction from an input string. Returns an error if the input fails to parse, /// or if there is input left over after parsing. - pub fn parse(input: &str) -> Result { + pub(crate) fn parse(input: &str) -> Result { let lexed = lex(input)?; let (_, instruction) = all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; From f770f5a291d68e5310083370814171508f4b03f2 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:19:45 -0700 Subject: [PATCH 59/75] Fix: frame dependency calculation in ScheduledProgram --- src/program/graph.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/program/graph.rs b/src/program/graph.rs index b1e7d242..33278803 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -234,19 +234,29 @@ impl InstructionBlock { Ok(()) } InstructionRole::RFControl => { - let frames = match program.get_frames_for_instruction(instruction, true) { + let used_frames = match program.get_frames_for_instruction(instruction, false) { + Some(frames) => frames, + None => vec![], + }; + let blocked_frames = match program.get_frames_for_instruction(instruction, true) { Some(frames) => frames, None => vec![], }; - // Mark a dependency on the last instruction which executed in the context of each target frame - for frame in frames { + // Take a dependency on any previous instructions to _block_ or _use_ a frame which this instruction _uses_. + for frame in used_frames { let previous_node_id = last_instruction_by_frame .entry(frame.clone()) .or_insert(ScheduledGraphNode::BlockStart); add_dependency!(graph, *previous_node_id => node, ExecutionDependency::ReferenceFrame); last_instruction_by_frame.insert(frame.clone(), node); } + + // We mark all "blocked" frames as such for later instructions to take a dependency on + for frame in blocked_frames { + last_instruction_by_frame.insert(frame.clone(), node); + } + Ok(()) } InstructionRole::ControlFlow => Err(ScheduleError { From 000bf2a5783b350b71584022f3e0fcff8d4aaf6a Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:20:53 -0700 Subject: [PATCH 60/75] Fix how FENCE uses frames --- src/program/mod.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 05adbe72..486eb4ab 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -166,14 +166,10 @@ impl Program { } } Instruction::Fence(Fence { qubits }) => { - if include_blocked { - if qubits.is_empty() { - FrameMatchCondition::All - } else { - FrameMatchCondition::AnyOfQubits(qubits) - } + if qubits.is_empty() { + FrameMatchCondition::All } else { - return None; + FrameMatchCondition::AnyOfQubits(qubits) } } Instruction::SetFrequency(SetFrequency { frame, .. }) From f5598684761ef31ce7feb5992bd40fc46f5170dd Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:21:15 -0700 Subject: [PATCH 61/75] Chore: fix tests for new frame-blocking behavior --- src/program/graphviz_dot.rs | 10 +++++++ src/program/mod.rs | 8 ++++-- ...sts__graph__different_frames_blocking.snap | 6 +++-- ...hviz_dot__tests__graph__fence_wrapper.snap | 27 +++++++++++++++++++ ...rametric_pulses_using_capture_results.snap | 10 +++---- 5 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_wrapper.snap diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index f66b878d..b916e099 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -234,6 +234,8 @@ DEFFRAME 0 \"ro_rx\": INITIAL-FREQUENCY: 1e6 DEFFRAME 0 \"ro_tx\": INITIAL-FREQUENCY: 1e6 +DEFFRAME 0 1 \"cz\": + INITIAL-FREQUENCY: 1e6 "; let program = @@ -309,8 +311,16 @@ NONBLOCKING PULSE 0 \"rf\" test(duration: 1e6) NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) " ); + build_dot_format_snapshot_test_case!(fence_all, "FENCE"); + build_dot_format_snapshot_test_case!(fence_wrapper, " +FENCE +NONBLOCKING PULSE 0 1 \"cz\" test(duration: 1e-6) +NONBLOCKING PULSE 1 \"rf\" test(duration: 1e-6) +FENCE 1 +"); + build_dot_format_snapshot_test_case!( jump, "DECLARE ro BIT diff --git a/src/program/mod.rs b/src/program/mod.rs index 486eb4ab..dbaec3e4 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -447,10 +447,14 @@ DEFFRAME 0 1 \"2q\": vec!["0 1 \"2q\""], vec!["0 1 \"2q\""], ), - ("FENCE 1", vec![], vec!["1 \"c\"", "0 1 \"2q\""]), + ( + "FENCE 1", + vec!["1 \"c\"", "0 1 \"2q\""], + vec!["1 \"c\"", "0 1 \"2q\""], + ), ( "FENCE", - vec![], + vec!["0 \"a\"", "0 \"b\"", "1 \"c\"", "0 1 \"2q\""], vec!["0 \"a\"", "0 \"b\"", "1 \"c\"", "0 1 \"2q\""], ), ( diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap index 5029b958..a57b2777 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap @@ -10,11 +10,13 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_1" [label="frame"]; + "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; - "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_0" -> "block_0_end" [label="frame"]; "block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1000000)"]; - "block_0_1" -> "block_0_2" [label="frame"]; + "block_0_1" -> "block_0_end" [label="frame"]; "block_0_2" [shape=rectangle, label="[2] PULSE 2 \"rf\" test(duration: 1000000)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_wrapper.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_wrapper.snap new file mode 100644 index 00000000..a67b6d58 --- /dev/null +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_wrapper.snap @@ -0,0 +1,27 @@ +--- +source: src/program/graphviz_dot.rs +expression: dot_format +--- +digraph { + entry -> "block_0_start"; + entry [label="Entry Point"]; + subgraph cluster_0 { + label="block_0"; + node [style="filled"]; + "block_0_start" [shape=circle, label="start"]; + "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_end" [label="ordering"]; + "block_0_0" [shape=rectangle, label="[0] FENCE"]; + "block_0_0" -> "block_0_1" [label="frame"]; + "block_0_0" -> "block_0_2" [label="frame"]; + "block_0_0" -> "block_0_end" [label="frame"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 0 1 \"cz\" test(duration: 0.000001)"]; + "block_0_1" -> "block_0_3" [label="frame"]; + "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 1 \"rf\" test(duration: 0.000001)"]; + "block_0_2" -> "block_0_3" [label="frame"]; + "block_0_3" [shape=rectangle, label="[3] FENCE 1"]; + "block_0_3" -> "block_0_end" [label="frame"]; + "block_0_end" [shape=circle, label="end"]; + } +} + diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap index 5330e3de..79060814 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__parametric_pulses_using_capture_results.snap @@ -10,23 +10,21 @@ digraph { node [style="filled"]; "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; + "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; "block_0_0" [shape=rectangle, label="[0] CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_0" -> "block_0_1" [label="await capture frame"]; - "block_0_0" -> "block_0_2" [label="frame"]; "block_0_0" -> "block_0_3" [label="frame"]; "block_0_0" -> "block_0_end" [label="await read"]; "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; - "block_0_1" -> "block_0_3" [label="await read -frame"]; + "block_0_1" -> "block_0_3" [label="await read"]; "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 1 \"rf\" test(a: ro[0])"]; - "block_0_2" -> "block_0_3" [label="await read -frame"]; + "block_0_2" -> "block_0_3" [label="await read"]; + "block_0_2" -> "block_0_5" [label="frame"]; "block_0_3" [shape=rectangle, label="[3] CAPTURE 0 \"ro_rx\" test(a: param[0]) ro[0]"]; "block_0_3" -> "block_0_4" [label="await capture frame"]; - "block_0_3" -> "block_0_5" [label="frame"]; "block_0_3" -> "block_0_end" [label="await read frame"]; "block_0_4" [shape=rectangle, label="[4] NONBLOCKING PULSE 0 \"rf\" test(a: ro[0])"]; From 2ba1d1b4951475aa493654cf94df93162782e345 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:24:02 -0700 Subject: [PATCH 62/75] Chore: linter fixes --- src/instruction.rs | 6 +++--- src/program/frame.rs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index 69fff0f0..f4281e3d 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -use nom::combinator::all_consuming; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; use crate::{ expression::Expression, - parser::{instruction::parse_instruction, lex}, }; #[cfg(test)] @@ -951,9 +949,11 @@ impl Instruction { /// Parse a single instruction from an input string. Returns an error if the input fails to parse, /// or if there is input left over after parsing. pub(crate) fn parse(input: &str) -> Result { + use crate::parser::{instruction::parse_instruction, lex}; + let lexed = lex(input)?; let (_, instruction) = - all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; + nom::combinator::all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; Ok(instruction) } } diff --git a/src/program/frame.rs b/src/program/frame.rs index 4ef6d104..0599b68c 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -155,5 +155,6 @@ pub(crate) enum FrameMatchCondition<'a> { And(Vec>), /// Return all frames which match any of these conditions + #[allow(dead_code)] Or(Vec>), } From 48d5751049f159ab412475d0e570e1c4c2a1e8e1 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:24:11 -0700 Subject: [PATCH 63/75] Chore: fmt --- src/instruction.rs | 6 ++---- src/program/graph.rs | 3 ++- src/program/graphviz_dot.rs | 7 +++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index f4281e3d..9a125f5a 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -16,9 +16,7 @@ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; -use crate::{ - expression::Expression, -}; +use crate::expression::Expression; #[cfg(test)] use proptest_derive::Arbitrary; @@ -950,7 +948,7 @@ impl Instruction { /// or if there is input left over after parsing. pub(crate) fn parse(input: &str) -> Result { use crate::parser::{instruction::parse_instruction, lex}; - + let lexed = lex(input)?; let (_, instruction) = nom::combinator::all_consuming(parse_instruction)(&lexed).map_err(|e| e.to_string())?; diff --git a/src/program/graph.rs b/src/program/graph.rs index 33278803..86a0ec08 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -238,7 +238,8 @@ impl InstructionBlock { Some(frames) => frames, None => vec![], }; - let blocked_frames = match program.get_frames_for_instruction(instruction, true) { + let blocked_frames = match program.get_frames_for_instruction(instruction, true) + { Some(frames) => frames, None => vec![], }; diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index b916e099..bd7f27a9 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -314,12 +314,15 @@ NONBLOCKING PULSE 1 \"rf\" test(duration: 1e6) build_dot_format_snapshot_test_case!(fence_all, "FENCE"); - build_dot_format_snapshot_test_case!(fence_wrapper, " + build_dot_format_snapshot_test_case!( + fence_wrapper, + " FENCE NONBLOCKING PULSE 0 1 \"cz\" test(duration: 1e-6) NONBLOCKING PULSE 1 \"rf\" test(duration: 1e-6) FENCE 1 -"); +" + ); build_dot_format_snapshot_test_case!( jump, From b3958b8c757f27a791b40f0a9155747d68d49bb0 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Tue, 31 May 2022 19:42:25 -0700 Subject: [PATCH 64/75] Chore: linter fixes & inline doc --- src/program/frame.rs | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index 0599b68c..51ff3b73 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -62,37 +62,29 @@ impl FrameSet { .collect() } FrameMatchCondition::Specific(frame) => { - if let Some((frame, _)) = self.frames.get_key_value(&frame) { + // This unusual pattern (fetch key & value by key, discard value) allows us to return + // a reference to `self` rather than `condition`, keeping lifetimes simpler. + if let Some((frame, _)) = self.frames.get_key_value(frame) { vec![frame].into_iter().collect() } else { HashSet::new() } } - FrameMatchCondition::And(conditions) => { - let individual_sets: Vec> = conditions - .into_iter() - .map(|c| self.get_matching_keys(c)) - .collect(); - individual_sets - .into_iter() - .reduce(|acc, el| acc.into_iter().filter(|&v| el.contains(v)).collect()) - .unwrap_or_default() - } - FrameMatchCondition::Or(conditions) => { - let individual_sets: Vec> = conditions - .into_iter() - .map(|c| self.get_matching_keys(c)) - .collect(); - individual_sets - .into_iter() - .reduce(|mut acc, el| { - el.into_iter().for_each(|v| { - acc.insert(v); - }); - acc - }) - .unwrap_or_default() - } + FrameMatchCondition::And(conditions) => conditions + .into_iter() + .map(|c| self.get_matching_keys(c)) + .reduce(|acc, el| acc.into_iter().filter(|&v| el.contains(v)).collect()) + .unwrap_or_default(), + FrameMatchCondition::Or(conditions) => conditions + .into_iter() + .map(|c| self.get_matching_keys(c)) + .reduce(|mut acc, el| { + el.into_iter().for_each(|v| { + acc.insert(v); + }); + acc + }) + .unwrap_or_default(), } } From 083824bf286dfa020b26abfa26536050a8b2c80e Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:16:36 -0700 Subject: [PATCH 65/75] Chore: fix inconsistent copyright headers --- src/expression.rs | 29 ++++++++++++++--------------- src/instruction.rs | 29 ++++++++++++++--------------- src/parser/command.rs | 29 ++++++++++++++--------------- src/parser/common.rs | 29 ++++++++++++++--------------- src/parser/error.rs | 29 ++++++++++++++--------------- src/parser/expression.rs | 29 ++++++++++++++--------------- src/parser/gate.rs | 29 ++++++++++++++--------------- src/parser/instruction.rs | 29 ++++++++++++++--------------- src/parser/lexer.rs | 29 ++++++++++++++--------------- src/parser/mod.rs | 29 ++++++++++++++--------------- src/program/calibration.rs | 29 ++++++++++++++--------------- src/program/error.rs | 14 ++++++++++++++ src/program/frame.rs | 29 ++++++++++++++--------------- src/program/graph.rs | 29 ++++++++++++++--------------- src/program/graphviz_dot.rs | 29 ++++++++++++++--------------- src/program/memory.rs | 29 ++++++++++++++--------------- src/program/mod.rs | 29 ++++++++++++++--------------- 17 files changed, 238 insertions(+), 240 deletions(-) diff --git a/src/expression.rs b/src/expression.rs index 596f1983..25bff53b 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use num_complex::Complex64; use std::collections::{hash_map::DefaultHasher, HashMap}; use std::f64::consts::PI; diff --git a/src/instruction.rs b/src/instruction.rs index bd273d11..9b374d59 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; diff --git a/src/parser/command.rs b/src/parser/command.rs index 7ce0937d..d885b2ee 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::{ combinator::opt, multi::{many0, many1, separated_list0, separated_list1}, diff --git a/src/parser/common.rs b/src/parser/common.rs index 2ddffcf6..0e76497c 100644 --- a/src/parser/common.rs +++ b/src/parser/common.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::HashMap; use nom::{ diff --git a/src/parser/error.rs b/src/parser/error.rs index 508cdb2e..22da6ea7 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::fmt; use super::lexer::{Command, Token}; diff --git a/src/parser/expression.rs b/src/parser/expression.rs index b211c20d..1a068413 100644 --- a/src/parser/expression.rs +++ b/src/parser/expression.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::combinator::opt; use crate::{ diff --git a/src/parser/gate.rs b/src/parser/gate.rs index 59350d6a..7a3499d6 100644 --- a/src/parser/gate.rs +++ b/src/parser/gate.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::{combinator::opt, multi::many0, multi::separated_list0, sequence::delimited}; use crate::{instruction::Instruction, token}; diff --git a/src/parser/instruction.rs b/src/parser/instruction.rs index e94752a0..d12dbadf 100644 --- a/src/parser/instruction.rs +++ b/src/parser/instruction.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::{ combinator::all_consuming, multi::{many0, many1}, diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 4db79e2a..6a88f6e6 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::{ branch::alt, bytes::complete::{is_a, is_not, tag, take_until, take_while, take_while1}, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 42a86582..d45268a0 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use nom::IResult; use error::Error; diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 01e26d81..24ce9413 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::HashMap; use crate::{ diff --git a/src/program/error.rs b/src/program/error.rs index 00686fb4..155c5c29 100644 --- a/src/program/error.rs +++ b/src/program/error.rs @@ -1,3 +1,17 @@ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use thiserror::Error; use crate::instruction::Instruction; diff --git a/src/program/frame.rs b/src/program/frame.rs index 8b2ed984..fa0ee052 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::{HashMap, HashSet}; use crate::instruction::{FrameAttributes, FrameDefinition, FrameIdentifier, Instruction, Qubit}; diff --git a/src/program/graph.rs b/src/program/graph.rs index b1e7d242..042f718e 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -1,20 +1,19 @@ //! Utilities for analysis of the dependency graph of a Quil Program -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::{HashMap, HashSet}; use indexmap::IndexMap; diff --git a/src/program/graphviz_dot.rs b/src/program/graphviz_dot.rs index f66b878d..97cd99aa 100644 --- a/src/program/graphviz_dot.rs +++ b/src/program/graphviz_dot.rs @@ -1,20 +1,19 @@ //! Utilities for working with Graphviz dot format files -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use dot_writer::{Attributes, DotWriter, Shape, Style}; use crate::program::graph::{ diff --git a/src/program/memory.rs b/src/program/memory.rs index f71a31bf..dd0c8200 100644 --- a/src/program/memory.rs +++ b/src/program/memory.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::HashSet; use crate::expression::Expression; diff --git a/src/program/mod.rs b/src/program/mod.rs index 998822e5..c04f8a73 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -1,18 +1,17 @@ -/** - * Copyright 2021 Rigetti Computing - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +// Copyright 2021 Rigetti Computing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use std::collections::BTreeMap; use std::str::FromStr; From d97394a40055c37ed0970e03a552db23c0f24c23 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:19:34 -0700 Subject: [PATCH 66/75] Chore: fix test --- src/expression.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expression.rs b/src/expression.rs index 25bff53b..949d9be1 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -798,7 +798,7 @@ mod tests { fn complexes_are_parseable_as_expressions(value in arb_complex64()) { let parsed = Expression::from_str(&format_complex(&value)); assert!(parsed.is_ok()); - assert_eq!(Expression::Number(value), parsed.unwrap().simplify()); + assert_eq!(Expression::Number(value), parsed.unwrap().into_simplified()); } } From 87d84de1b84e2595a36f5f77dfff26f7fa80b2a4 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:20:13 -0700 Subject: [PATCH 67/75] Chore: update snapshots after merge --- ...z_dot__tests__graph__active_reset_single_frame.snap | 6 +++--- ...am__graphviz_dot__tests__graph__chained_pulses.snap | 10 +++++----- ...z_dot__tests__graph__different_frames_blocking.snap | 6 +++--- ...ot__tests__graph__different_frames_nonblocking.snap | 6 +++--- ...ests__graph__fence_all_with_nonblocking_pulses.snap | 8 ++++---- ..._rs__program__graphviz_dot__tests__graph__jump.snap | 6 +++--- ..._graphviz_dot__tests__graph__single_dependency.snap | 4 ++-- ...graphviz_dot__tests__graph__single_instruction.snap | 2 +- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap index 96ecb34c..c000579d 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__active_reset_single_frame.snap @@ -12,9 +12,9 @@ digraph { "measure_start" -> "measure_0" [label="frame"]; "measure_start" -> "measure_1" [label="frame"]; "measure_start" -> "measure_end" [label="ordering"]; - "measure_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"]; + "measure_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000.0)"]; "measure_0" -> "measure_end" [label="frame"]; - "measure_1" [shape=rectangle, label="[1] NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"]; + "measure_1" [shape=rectangle, label="[1] NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000.0) ro[0]"]; "measure_1" -> "measure_end" [label="await capture frame"]; "measure_end" [shape=circle, label="end"]; @@ -27,7 +27,7 @@ frame"]; "feedback_start" [shape=circle, label="start"]; "feedback_start" -> "feedback_0" [label="frame"]; "feedback_start" -> "feedback_end" [label="ordering"]; - "feedback_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "feedback_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "feedback_0" -> "feedback_end" [label="frame"]; "feedback_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap index db480023..8022d73d 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__chained_pulses.snap @@ -11,15 +11,15 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [shape=rectangle, label="[2] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_2" -> "block_0_3" [label="frame"]; - "block_0_3" [shape=rectangle, label="[3] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="[3] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_3" -> "block_0_4" [label="frame"]; - "block_0_4" [shape=rectangle, label="[4] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="[4] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap index 5029b958..56de0ae4 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_blocking.snap @@ -11,11 +11,11 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1000000.0)"]; "block_0_1" -> "block_0_2" [label="frame"]; - "block_0_2" [shape=rectangle, label="[2] PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] PULSE 2 \"rf\" test(duration: 1000000.0)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap index 5f53bd7c..7f76fefd 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__different_frames_nonblocking.snap @@ -13,11 +13,11 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_end" [label="frame"]; - "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000.0)"]; "block_0_1" -> "block_0_end" [label="frame"]; - "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"]; + "block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000.0)"]; "block_0_2" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap index c912643e..9bc61a13 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__fence_all_with_nonblocking_pulses.snap @@ -13,17 +13,17 @@ digraph { "block_0_start" -> "block_0_1" [label="frame"]; "block_0_start" -> "block_0_2" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_2" [label="frame"]; - "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000.0)"]; "block_0_1" -> "block_0_2" [label="frame"]; "block_0_2" [shape=rectangle, label="[2] FENCE"]; "block_0_2" -> "block_0_3" [label="frame"]; "block_0_2" -> "block_0_4" [label="frame"]; "block_0_2" -> "block_0_end" [label="frame"]; - "block_0_3" [shape=rectangle, label="[3] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_3" [shape=rectangle, label="[3] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_3" -> "block_0_end" [label="frame"]; - "block_0_4" [shape=rectangle, label="[4] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"]; + "block_0_4" [shape=rectangle, label="[4] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000.0)"]; "block_0_4" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap index 9ceeebda..822216f0 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__jump.snap @@ -11,7 +11,7 @@ digraph { "first-block_start" [shape=circle, label="start"]; "first-block_start" -> "first-block_0" [label="frame"]; "first-block_start" -> "first-block_end" [label="ordering"]; - "first-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "first-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "first-block_0" -> "first-block_end" [label="frame"]; "first-block_end" [shape=circle, label="end"]; } @@ -23,7 +23,7 @@ digraph { "second-block_start" [shape=circle, label="start"]; "second-block_start" -> "second-block_0" [label="frame"]; "second-block_start" -> "second-block_end" [label="ordering"]; - "second-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "second-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "second-block_0" -> "second-block_end" [label="frame"]; "second-block_end" [shape=circle, label="end"]; } @@ -34,7 +34,7 @@ digraph { "third-block_start" [shape=circle, label="start"]; "third-block_start" -> "third-block_0" [label="frame"]; "third-block_start" -> "third-block_end" [label="ordering"]; - "third-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "third-block_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "third-block_0" -> "third-block_end" [label="frame"]; "third-block_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap index c1d24d5c..708c543c 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_dependency.snap @@ -11,9 +11,9 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_1" [label="frame"]; - "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_1" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } diff --git a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap index dd5b4517..4fcc3157 100644 --- a/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap +++ b/src/program/snapshots/quil_rs__program__graphviz_dot__tests__graph__single_instruction.snap @@ -11,7 +11,7 @@ digraph { "block_0_start" [shape=circle, label="start"]; "block_0_start" -> "block_0_0" [label="frame"]; "block_0_start" -> "block_0_end" [label="ordering"]; - "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"]; + "block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000.0)"]; "block_0_0" -> "block_0_end" [label="frame"]; "block_0_end" [shape=circle, label="end"]; } From a48b73ee784188ebe2d15f848f78b6913a035b97 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:28:37 -0700 Subject: [PATCH 68/75] Chore: fix tests after merge from main --- src/instruction.rs | 2 +- src/program/calibration.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index 9b374d59..c770eabf 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -885,7 +885,7 @@ impl Instruction { /// let mut instructions = program.to_instructions(true); /// instructions.iter_mut().for_each(|inst| inst.apply_to_expressions(Expression::simplify)); /// - /// assert_eq!(instructions[0].to_string(), String::from("SHIFT-PHASE 0 \"rf\" 4")) + /// assert_eq!(instructions[0].to_string(), String::from("SHIFT-PHASE 0 \"rf\" 4.0")) /// /// ``` pub fn apply_to_expressions(&mut self, mut closure: impl FnMut(&mut Expression)) { diff --git a/src/program/calibration.rs b/src/program/calibration.rs index 24ce9413..89bca9ff 100644 --- a/src/program/calibration.rs +++ b/src/program/calibration.rs @@ -374,7 +374,7 @@ mod tests { " PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", "X 0\n" ), - expected: "PULSE 0 \"xy\" gaussian(duration: 1, fwhm: 2, t0: 3)\n", + expected: "PULSE 0 \"xy\" gaussian(duration: 1.0, fwhm: 2.0, t0: 3.0)\n", }, TestCase { input: concat!( From 68a2fde877d8b3836bbeb6d1325504fa0478510b Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:32:20 -0700 Subject: [PATCH 69/75] Chore: code cleanup --- src/program/graph.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/program/graph.rs b/src/program/graph.rs index 16a7b5f2..30a13b11 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -233,15 +233,12 @@ impl InstructionBlock { Ok(()) } InstructionRole::RFControl => { - let used_frames = match program.get_frames_for_instruction(instruction, false) { - Some(frames) => frames, - None => vec![], - }; - let blocked_frames = match program.get_frames_for_instruction(instruction, true) - { - Some(frames) => frames, - None => vec![], - }; + let used_frames = program + .get_frames_for_instruction(instruction, false) + .unwrap_or_default(); + let blocked_frames = program + .get_frames_for_instruction(instruction, true) + .unwrap_or_default(); // Take a dependency on any previous instructions to _block_ or _use_ a frame which this instruction _uses_. for frame in used_frames { From 67a74aa8c818b971543644679b88318186f889a1 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:55:17 -0700 Subject: [PATCH 70/75] Fix bug in DELAY frame utilization --- src/program/frame.rs | 4 ++-- src/program/mod.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index d962308e..bec3ecfe 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -55,9 +55,9 @@ impl FrameSet { .collect() } FrameMatchCondition::ExactQubits(qubits) => { - let all_of_set: HashSet<_> = qubits.iter().collect(); + let exact_set: HashSet<_> = qubits.iter().collect(); - keys.filter(|&f| f.qubits.iter().all(|q| all_of_set.contains(q))) + keys.filter(|&f| f.qubits.iter().collect::>() == exact_set) .collect() } FrameMatchCondition::Specific(frame) => { diff --git a/src/program/mod.rs b/src/program/mod.rs index 37fe498c..254af692 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -461,8 +461,7 @@ DEFFRAME 0 1 \"2q\": vec!["0 \"a\"", "0 \"b\""], vec!["0 \"a\"", "0 \"b\""], ), - ("DELAY 1 1.0", vec!["1 \"c\""], vec!["1 \"c\""]), - ("DELAY 1 \"c\" 1.0", vec!["1 \"c\""], vec!["1 \"c\""]), + (r#"DELAY 0 1 1.0"#, vec![r#"0 1 "2q""#], vec![r#"0 1 "2q""#]), ] { let instruction = Instruction::parse(instruction_string).unwrap(); let used_frames: HashSet = program From 41249bcfc6d08e52556e263adfabb6b2620b7d9b Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:55:42 -0700 Subject: [PATCH 71/75] Chore: remove dead code --- src/program/frame.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index bec3ecfe..d2089e7e 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -74,16 +74,6 @@ impl FrameSet { .map(|c| self.get_matching_keys(c)) .reduce(|acc, el| acc.into_iter().filter(|&v| el.contains(v)).collect()) .unwrap_or_default(), - FrameMatchCondition::Or(conditions) => conditions - .into_iter() - .map(|c| self.get_matching_keys(c)) - .reduce(|mut acc, el| { - el.into_iter().for_each(|v| { - acc.insert(v); - }); - acc - }) - .unwrap_or_default(), } } @@ -144,8 +134,4 @@ pub(crate) enum FrameMatchCondition<'a> { /// Return all frames which match all of these conditions And(Vec>), - - /// Return all frames which match any of these conditions - #[allow(dead_code)] - Or(Vec>), } From 3cacfcfd7d6559b7de8a63c932441bdca16d4dca Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:55:58 -0700 Subject: [PATCH 72/75] Chore: fix docstring --- src/program/frame.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/program/frame.rs b/src/program/frame.rs index d2089e7e..53bfb8ef 100644 --- a/src/program/frame.rs +++ b/src/program/frame.rs @@ -120,7 +120,7 @@ pub(crate) enum FrameMatchCondition<'a> { /// Match all frames in the set All, - /// Match all frames which shares any one of these names + /// Match all frames which share any one of these names AnyOfNames(&'a [String]), /// Match all frames which contain any of these qubits From 2c866485e5ab27e50cf93a982e7fe6df41d0becf Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 12:56:25 -0700 Subject: [PATCH 73/75] Chore: make test cases more readable --- src/program/mod.rs | 87 +++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/src/program/mod.rs b/src/program/mod.rs index 254af692..033eadee 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -405,62 +405,79 @@ DEFFRAME 0 1 \"2q\": let program = Program::from_str(input).unwrap(); for (instruction_string, expected_used_frames, expected_blocked_frames) in vec![ - // Blocking pulses block their qubits + // Blocking pulses use only the specified frame but block frames intersecting the frame's qubits ( - "PULSE 0 \"a\" custom_waveform", - vec!["0 \"a\""], - vec!["0 \"a\"", "0 \"b\"", "0 1 \"2q\""], + r#"PULSE 0 "a" custom_waveform"#, + vec![r#"0 "a""#], + vec![r#"0 "a""#, r#"0 "b""#, r#"0 1 "2q""#], ), ( - "PULSE 1 \"c\" custom_waveform", - vec!["1 \"c\""], - vec!["1 \"c\"", "0 1 \"2q\""], + r#"PULSE 1 "c" custom_waveform"#, + vec![r#"1 "c""#], + vec![r#"1 "c""#, r#"0 1 "2q""#], ), // Pulses on non-declared frames and unused qubits do not use or block any frames in the program - ("PULSE 2 \"a\" custom_waveform", vec![], vec![]), + (r#"PULSE 2 "a" custom_waveform"#, vec![], vec![]), // Captures work identically to Pulses ( - "CAPTURE 0 \"a\" custom_waveform ro[0]", - vec!["0 \"a\""], - vec!["0 \"a\"", "0 \"b\"", "0 1 \"2q\""], + r#"CAPTURE 0 "a" custom_waveform ro[0]"#, + vec![r#"0 "a""#], + vec![r#"0 "a""#, r#"0 "b""#, r#"0 1 "2q""#], ), ( - "CAPTURE 1 \"c\" custom_waveform ro[0]", - vec!["1 \"c\""], - vec!["1 \"c\"", "0 1 \"2q\""], + r#"CAPTURE 1 "c" custom_waveform ro[0]"#, + vec![r#"1 "c""#], + vec![r#"1 "c""#, r#"0 1 "2q""#], ), - ("CAPTURE 2 \"a\" custom_waveform ro[0]", vec![], vec![]), + (r#"CAPTURE 2 "a" custom_waveform ro[0]"#, vec![], vec![]), + // Raw Captures work identically to Pulses + ( + r#"RAW-CAPTURE 0 "a" 1e-6 ro[0]"#, + vec![r#"0 "a""#], + vec![r#"0 "a""#, r#"0 "b""#, r#"0 1 "2q""#], + ), + ( + r#"RAW-CAPTURE 1 "c" 1e-6 ro[0]"#, + vec![r#"1 "c""#], + vec![r#"1 "c""#, r#"0 1 "2q""#], + ), + (r#"RAW-CAPTURE 2 "a" 1e-6 ro[0]"#, vec![], vec![]), // A non-blocking pulse blocks only its precise frame, not other frames on the same qubits ( - "NONBLOCKING PULSE 0 \"a\" custom_waveform", - vec!["0 \"a\""], - vec!["0 \"a\""], + r#"NONBLOCKING PULSE 0 "a" custom_waveform"#, + vec![r#"0 "a""#], + vec![r#"0 "a""#], ), ( - "NONBLOCKING PULSE 1 \"c\" custom_waveform", - vec!["1 \"c\""], - vec!["1 \"c\""], + r#"NONBLOCKING PULSE 1 "c" custom_waveform"#, + vec![r#"1 "c""#], + vec![r#"1 "c""#], ), ( - "NONBLOCKING PULSE 0 1 \"2q\" custom_waveform", - vec!["0 1 \"2q\""], - vec!["0 1 \"2q\""], + r#"NONBLOCKING PULSE 0 1 "2q" custom_waveform"#, + vec![r#"0 1 "2q""#], + vec![r#"0 1 "2q""#], ), + // A Fence with qubits specified uses and blocks all frames intersecting that qubit ( - "FENCE 1", - vec!["1 \"c\"", "0 1 \"2q\""], - vec!["1 \"c\"", "0 1 \"2q\""], + r#"FENCE 1"#, + vec![r#"1 "c""#, r#"0 1 "2q""#], + vec![r#"1 "c""#, r#"0 1 "2q""#], ), + // Fence-all uses and blocks all frames declared in the program ( - "FENCE", - vec!["0 \"a\"", "0 \"b\"", "1 \"c\"", "0 1 \"2q\""], - vec!["0 \"a\"", "0 \"b\"", "1 \"c\"", "0 1 \"2q\""], + r#"FENCE"#, + vec![r#"0 "a""#, r#"0 "b""#, r#"1 "c""#, r#"0 1 "2q""#], + vec![r#"0 "a""#, r#"0 "b""#, r#"1 "c""#, r#"0 1 "2q""#], ), + // Delay uses and blocks frames on exactly the given qubits and with any of the given names ( - "DELAY 0 1.0", - vec!["0 \"a\"", "0 \"b\""], - vec!["0 \"a\"", "0 \"b\""], + r#"DELAY 0 1.0"#, + vec![r#"0 "a""#, r#"0 "b""#], + vec![r#"0 "a""#, r#"0 "b""#], ), + (r#"DELAY 1 1.0"#, vec![r#"1 "c""#], vec![r#"1 "c""#]), + (r#"DELAY 1 "c" 1.0"#, vec![r#"1 "c""#], vec![r#"1 "c""#]), (r#"DELAY 0 1 1.0"#, vec![r#"0 1 "2q""#], vec![r#"0 1 "2q""#]), ] { let instruction = Instruction::parse(instruction_string).unwrap(); @@ -476,7 +493,7 @@ DEFFRAME 0 1 \"2q\": .collect(); assert_eq!( used_frames, expected_used_frames, - "Instruction {} *used* frames `{:?}` but we expected `{:?}", + "Instruction {} *used* frames `{:?}` but we expected `{:?}`", instruction, used_frames, expected_used_frames ); @@ -492,7 +509,7 @@ DEFFRAME 0 1 \"2q\": .collect(); assert_eq!( blocked_frames, expected_blocked_frames, - "Instruction {} *blocked* frames `{:?}` but we expected `{:?}", + "Instruction {} *blocked* frames `{:?}` but we expected `{:?}`", instruction, blocked_frames, expected_blocked_frames ); } From 98b903a5b58e0685d0a1a59f419948a98e41b0cd Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:17:16 -0700 Subject: [PATCH 74/75] Simplify frame dependency code --- src/program/graph.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/program/graph.rs b/src/program/graph.rs index 30a13b11..2734be68 100644 --- a/src/program/graph.rs +++ b/src/program/graph.rs @@ -240,13 +240,12 @@ impl InstructionBlock { .get_frames_for_instruction(instruction, true) .unwrap_or_default(); - // Take a dependency on any previous instructions to _block_ or _use_ a frame which this instruction _uses_. + // Take a dependency on any previous instructions to _block_ a frame which this instruction _uses_. for frame in used_frames { let previous_node_id = last_instruction_by_frame - .entry(frame.clone()) - .or_insert(ScheduledGraphNode::BlockStart); + .get(frame) + .unwrap_or(&ScheduledGraphNode::BlockStart); add_dependency!(graph, *previous_node_id => node, ExecutionDependency::ReferenceFrame); - last_instruction_by_frame.insert(frame.clone(), node); } // We mark all "blocked" frames as such for later instructions to take a dependency on From 4cabba830bd48ce7af1a2a6b5e6892bc97376197 Mon Sep 17 00:00:00 2001 From: kalzoo <22137047+kalzoo@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:20:58 -0700 Subject: [PATCH 75/75] Add Instruction.get_frame_match_condition --- src/instruction.rs | 73 ++++++++++++++++++++++++++++++++++++ src/program/mod.rs | 92 +++++----------------------------------------- 2 files changed, 82 insertions(+), 83 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index 15692f94..d2c56b8d 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -16,6 +16,7 @@ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt}; use crate::expression::Expression; +use crate::program::frame::FrameMatchCondition; #[cfg(test)] use proptest_derive::Arbitrary; @@ -942,6 +943,78 @@ impl Instruction { } } + pub(crate) fn get_frame_match_condition( + &self, + include_blocked: bool, + ) -> Option { + match self { + Instruction::Pulse(Pulse { + blocking, frame, .. + }) + | Instruction::Capture(Capture { + blocking, frame, .. + }) + | Instruction::RawCapture(RawCapture { + blocking, frame, .. + }) => Some(if *blocking && include_blocked { + FrameMatchCondition::AnyOfQubits(&frame.qubits) + } else { + FrameMatchCondition::Specific(frame) + }), + Instruction::Delay(Delay { + frame_names, + qubits, + .. + }) => Some(if frame_names.is_empty() { + FrameMatchCondition::ExactQubits(qubits) + } else { + FrameMatchCondition::And(vec![ + FrameMatchCondition::ExactQubits(qubits), + FrameMatchCondition::AnyOfNames(frame_names), + ]) + }), + Instruction::Fence(Fence { qubits }) => Some(if qubits.is_empty() { + FrameMatchCondition::All + } else { + FrameMatchCondition::AnyOfQubits(qubits) + }), + Instruction::SetFrequency(SetFrequency { frame, .. }) + | Instruction::SetPhase(SetPhase { frame, .. }) + | Instruction::SetScale(SetScale { frame, .. }) + | Instruction::ShiftFrequency(ShiftFrequency { frame, .. }) + | Instruction::ShiftPhase(ShiftPhase { frame, .. }) => { + Some(FrameMatchCondition::Specific(frame)) + } + Instruction::SwapPhases(SwapPhases { frame_1, frame_2 }) => { + Some(FrameMatchCondition::And(vec![ + FrameMatchCondition::Specific(frame_1), + FrameMatchCondition::Specific(frame_2), + ])) + } + Instruction::Gate(_) + | Instruction::CircuitDefinition(_) + | Instruction::GateDefinition(_) + | Instruction::Declaration(_) + | Instruction::Measurement(_) + | Instruction::Reset(_) + | Instruction::CalibrationDefinition(_) + | Instruction::FrameDefinition(_) + | Instruction::MeasureCalibrationDefinition(_) + | Instruction::Pragma(_) + | Instruction::WaveformDefinition(_) + | Instruction::Arithmetic(_) + | Instruction::Halt + | Instruction::Label(_) + | Instruction::Move(_) + | Instruction::Exchange(_) + | Instruction::Load(_) + | Instruction::Store(_) + | Instruction::Jump(_) + | Instruction::JumpWhen(_) + | Instruction::JumpUnless(_) => None, + } + } + #[cfg(test)] /// Parse a single instruction from an input string. Returns an error if the input fails to parse, /// or if there is input left over after parsing. diff --git a/src/program/mod.rs b/src/program/mod.rs index 033eadee..e18644cf 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -16,20 +16,17 @@ use std::collections::BTreeMap; use std::str::FromStr; use crate::instruction::{ - Capture, Declaration, Delay, Fence, FrameDefinition, FrameIdentifier, Instruction, Pulse, - RawCapture, SetFrequency, SetPhase, SetScale, ShiftFrequency, ShiftPhase, SwapPhases, Waveform, - WaveformDefinition, + Declaration, FrameDefinition, FrameIdentifier, Instruction, Waveform, WaveformDefinition, }; use crate::parser::{lex, parse_instructions}; pub use self::calibration::CalibrationSet; -use self::frame::FrameMatchCondition; pub use self::frame::FrameSet; pub use self::memory::MemoryRegion; mod calibration; mod error; -mod frame; +pub(crate) mod frame; pub mod graph; mod memory; @@ -134,85 +131,14 @@ impl Program { instruction: &'a Instruction, include_blocked: bool, ) -> Option> { - let condition = match &instruction { - Instruction::Pulse(Pulse { - blocking, frame, .. + instruction + .get_frame_match_condition(include_blocked) + .map(|condition| { + self.frames + .get_matching_keys(condition) + .into_iter() + .collect() }) - | Instruction::Capture(Capture { - blocking, frame, .. - }) - | Instruction::RawCapture(RawCapture { - blocking, frame, .. - }) => { - if *blocking && include_blocked { - FrameMatchCondition::AnyOfQubits(&frame.qubits) - } else { - FrameMatchCondition::Specific(frame) - } - } - Instruction::Delay(Delay { - frame_names, - qubits, - .. - }) => { - if frame_names.is_empty() { - FrameMatchCondition::ExactQubits(qubits) - } else { - FrameMatchCondition::And(vec![ - FrameMatchCondition::ExactQubits(qubits), - FrameMatchCondition::AnyOfNames(frame_names), - ]) - } - } - Instruction::Fence(Fence { qubits }) => { - if qubits.is_empty() { - FrameMatchCondition::All - } else { - FrameMatchCondition::AnyOfQubits(qubits) - } - } - Instruction::SetFrequency(SetFrequency { frame, .. }) - | Instruction::SetPhase(SetPhase { frame, .. }) - | Instruction::SetScale(SetScale { frame, .. }) - | Instruction::ShiftFrequency(ShiftFrequency { frame, .. }) - | Instruction::ShiftPhase(ShiftPhase { frame, .. }) => { - FrameMatchCondition::Specific(frame) - } - Instruction::SwapPhases(SwapPhases { frame_1, frame_2 }) => { - FrameMatchCondition::And(vec![ - FrameMatchCondition::Specific(frame_1), - FrameMatchCondition::Specific(frame_2), - ]) - } - Instruction::Gate(_) - | Instruction::CircuitDefinition(_) - | Instruction::GateDefinition(_) - | Instruction::Declaration(_) - | Instruction::Measurement(_) - | Instruction::Reset(_) - | Instruction::CalibrationDefinition(_) - | Instruction::FrameDefinition(_) - | Instruction::MeasureCalibrationDefinition(_) - | Instruction::Pragma(_) - | Instruction::WaveformDefinition(_) - | Instruction::Arithmetic(_) - | Instruction::Halt - | Instruction::Label(_) - | Instruction::Move(_) - | Instruction::Exchange(_) - | Instruction::Load(_) - | Instruction::Store(_) - | Instruction::Jump(_) - | Instruction::JumpWhen(_) - | Instruction::JumpUnless(_) => return None, - }; - - Some( - self.frames - .get_matching_keys(condition) - .into_iter() - .collect(), - ) } pub fn to_instructions(&self, include_headers: bool) -> Vec {