quil_rs/instruction/
waveform.rs

1use 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}