quil_rs/instruction/
waveform.rs1use indexmap::IndexMap;
2
3use crate::{
4 expression::Expression,
5 quil::{write_join_quil, Quil, INDENT},
6};
7
8use super::write_parameter_string;
9
10#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub struct Waveform {
12 pub matrix: Vec<Expression>,
13 pub parameters: Vec<String>,
14}
15
16impl Waveform {
17 pub fn new(matrix: Vec<Expression>, parameters: Vec<String>) -> Self {
18 Self { matrix, parameters }
19 }
20}
21
22#[derive(Clone, Debug, PartialEq, Eq, Hash)]
23pub struct WaveformDefinition {
24 pub name: String,
25 pub definition: Waveform,
26}
27
28impl WaveformDefinition {
29 pub fn new(name: String, definition: Waveform) -> Self {
30 Self { name, definition }
31 }
32}
33
34impl Quil for WaveformDefinition {
35 fn write(
36 &self,
37 f: &mut impl std::fmt::Write,
38 fall_back_to_debug: bool,
39 ) -> crate::quil::ToQuilResult<()> {
40 write!(f, "DEFWAVEFORM {}", self.name)?;
41 write_parameter_string(f, &self.definition.parameters)?;
42 write!(f, ":\n{INDENT}")?;
43 write_join_quil(f, fall_back_to_debug, &self.definition.matrix, ", ", "")
44 }
45}
46
47#[cfg(test)]
48mod test_waveform_definition {
49 use super::{Waveform, WaveformDefinition};
50 use crate::expression::Expression;
51 use crate::quil::Quil;
52 use crate::real;
53
54 use insta::assert_snapshot;
55 use rstest::rstest;
56
57 #[rstest]
58 #[case(
59 "Simple WaveformDefinition",
60 WaveformDefinition {
61 name: "WF".to_string(),
62 definition: Waveform {
63 matrix: vec![
64 Expression::Number(real!(0.0)),
65 Expression::Number(real!(0.0)),
66 Expression::Number(real!(0.00027685415721916584))
67 ],
68 parameters: vec!["theta".to_string()]
69 }
70 }
71 )]
72 fn test_display(#[case] description: &str, #[case] waveform_def: WaveformDefinition) {
73 insta::with_settings!({
74 snapshot_suffix => description,
75 }, {
76 assert_snapshot!(waveform_def.to_quil_or_debug())
77 })
78 }
79}
80
81pub type WaveformParameters = IndexMap<String, Expression>;
82
83#[derive(Clone, Debug, PartialEq, Eq)]
84pub struct WaveformInvocation {
85 pub name: String,
86 pub parameters: WaveformParameters,
87}
88
89impl WaveformInvocation {
90 pub fn new(name: String, parameters: WaveformParameters) -> Self {
91 Self { name, parameters }
92 }
93}
94
95impl Quil for WaveformInvocation {
96 fn write(
97 &self,
98 f: &mut impl std::fmt::Write,
99 _fall_back_to_debug: bool,
100 ) -> crate::quil::ToQuilResult<()> {
101 let mut key_value_pairs = self
102 .parameters
103 .iter()
104 .collect::<Vec<(&String, &Expression)>>();
105
106 key_value_pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
107
108 if key_value_pairs.is_empty() {
109 write!(f, "{}", self.name,)?;
110 } else {
111 write!(
112 f,
113 "{}({})",
114 self.name,
115 key_value_pairs
116 .iter()
117 .map(|(k, v)| format!("{k}: {}", v.to_quil_or_debug()))
118 .collect::<Vec<String>>()
119 .join(", ")
120 )?;
121 }
122 Ok(())
123 }
124}
125
126#[cfg(test)]
127mod waveform_invocation_tests {
128 use super::WaveformParameters;
129
130 use crate::{instruction::WaveformInvocation, quil::Quil};
131
132 #[test]
133 fn format_no_parameters() {
134 let invocation = WaveformInvocation {
135 name: "CZ".into(),
136 parameters: WaveformParameters::new(),
137 };
138 assert_eq!(invocation.to_quil_or_debug(), "CZ".to_string());
139 }
140}