1use crate::gates::Gate;
16use crate::stabilizer::PauliOp;
17
18pub struct V
28{
29}
30
31impl V
32{
33 pub fn new() -> Self
35 {
36 V { }
37 }
38}
39
40impl crate::gates::Gate for V
41{
42 fn cost(&self) -> f64
43 {
44 crate::gates::U3::cost()
45 }
46
47 fn description(&self) -> &str
48 {
49 "V"
50 }
51
52 fn nr_affected_bits(&self) -> usize
53 {
54 1
55 }
56
57 fn matrix(&self) -> crate::cmatrix::CMatrix
58 {
59 let h = 0.5 * crate::cmatrix::COMPLEX_ONE;
60 let hi = 0.5 * crate::cmatrix::COMPLEX_I;
61 array![[h+hi, h-hi], [h-hi, h+hi]]
62 }
63
64 fn is_stabilizer(&self) -> bool
65 {
66 true
67 }
68
69 fn conjugate(&self, ops: &mut [PauliOp]) -> crate::error::Result<bool>
70 {
71 self.check_nr_bits(ops.len())?;
72 let (op, phase) = match ops[0]
73 {
74 PauliOp::I => (PauliOp::I, false),
75 PauliOp::Z => (PauliOp::Y, true),
76 PauliOp::X => (PauliOp::X, false),
77 PauliOp::Y => (PauliOp::Z, false)
78 };
79 ops[0] = op;
80 Ok(phase)
81 }
82}
83
84impl crate::export::OpenQasm for V
85{
86 fn open_qasm(&self, bit_names: &[String], bits: &[usize])
87 -> crate::error::Result<String>
88 {
89 Ok(format!("u3(pi/2, -pi/2, pi/2) {}", bit_names[bits[0]]))
90 }
91}
92
93impl crate::export::CQasm for V
94{
95 fn c_qasm(&self, bit_names: &[String], bits: &[usize])
96 -> crate::error::Result<String>
97 {
98 Ok(format!("x90 {}", bit_names[bits[0]]))
99 }
100}
101
102impl crate::export::Latex for V
103{
104 fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
105 -> crate::error::Result<()>
106 {
107 self.check_nr_bits(bits.len())?;
108 state.add_block_gate(bits, "V")
109 }
110}
111
112pub struct Vdg
116{
117}
118
119impl Vdg
120{
121 pub fn new() -> Self
123 {
124 Vdg { }
125 }
126}
127
128impl crate::gates::Gate for Vdg
129{
130 fn cost(&self) -> f64
131 {
132 crate::gates::U3::cost()
133 }
134
135 fn description(&self) -> &str
136 {
137 "V†"
138 }
139
140 fn nr_affected_bits(&self) -> usize
141 {
142 1
143 }
144
145 fn matrix(&self) -> crate::cmatrix::CMatrix
146 {
147 let h = 0.5 * crate::cmatrix::COMPLEX_ONE;
148 let hi = 0.5 * crate::cmatrix::COMPLEX_I;
149 array![[h-hi, h+hi], [h+hi, h-hi]]
150 }
151
152 fn is_stabilizer(&self) -> bool
153 {
154 true
155 }
156
157 fn conjugate(&self, ops: &mut [PauliOp]) -> crate::error::Result<bool>
158 {
159 self.check_nr_bits(ops.len())?;
160 let (op, phase) = match ops[0]
161 {
162 PauliOp::I => (PauliOp::I, false),
163 PauliOp::Z => (PauliOp::Y, false),
164 PauliOp::X => (PauliOp::X, false),
165 PauliOp::Y => (PauliOp::Z, true)
166 };
167 ops[0] = op;
168 Ok(phase)
169 }
170}
171
172impl crate::export::OpenQasm for Vdg
173{
174 fn open_qasm(&self, bit_names: &[String], bits: &[usize])
175 -> crate::error::Result<String>
176 {
177 Ok(format!("u3(pi/2, pi/2, -pi/2) {}", bit_names[bits[0]]))
178 }
179}
180
181impl crate::export::CQasm for Vdg
182{
183 fn c_qasm(&self, bit_names: &[String], bits: &[usize])
184 -> crate::error::Result<String>
185 {
186 Ok(format!("mx90 {}", bit_names[bits[0]]))
187 }
188}
189
190impl crate::export::Latex for Vdg
191{
192 fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
193 -> crate::error::Result<()>
194 {
195 self.check_nr_bits(bits.len())?;
196 state.add_block_gate(bits, r"V^\dagger")
197 }
198}
199
200#[cfg(test)]
201mod tests
202{
203 use super::{V, Vdg};
204 use crate::export::{Latex, LatexExportState, OpenQasm, CQasm};
205 use crate::gates::{gate_test, Gate};
206 use crate::stabilizer::PauliOp;
207
208 #[test]
209 fn test_description()
210 {
211 let gate = V::new();
212 assert_eq!(gate.description(), "V");
213 let gate = Vdg::new();
214 assert_eq!(gate.description(), "V†");
215 }
216
217 #[test]
218 fn test_cost()
219 {
220 let gate = V::new();
221 assert_eq!(gate.cost(), 201.0);
222 let gate = Vdg::new();
223 assert_eq!(gate.cost(), 201.0);
224 }
225
226 #[test]
227 fn test_matrix()
228 {
229 let h = 0.5*crate::cmatrix::COMPLEX_ONE;
230 let hi = 0.5*crate::cmatrix::COMPLEX_I;
231
232 let gate = V::new();
233 assert_complex_matrix_eq!(gate.matrix(), array![[h+hi, h-hi], [h-hi, h+hi]]);
234
235 let gate = Vdg::new();
236 assert_complex_matrix_eq!(gate.matrix(), array![[h-hi, h+hi], [h+hi, h-hi]]);
237 }
238
239 #[test]
240 fn test_apply()
241 {
242 let z = crate::cmatrix::COMPLEX_ZERO;
243 let o = crate::cmatrix::COMPLEX_ONE;
244 let i = crate::cmatrix::COMPLEX_I;
245 let x = crate::cmatrix::COMPLEX_HSQRT2;
246 let h = 0.5 * o;
247 let hi = 0.5 * i;
248
249 let mut state = array![
250 [o, z, x, x],
251 [z, o, x, -x]
252 ];
253 let result = array![
254 [h+hi, h-hi, x, x*i],
255 [h-hi, h+hi, x, -x*i]
256 ];
257 gate_test(V::new(), &mut state, &result);
258
259 let mut state = array![
260 [o, z, x, x],
261 [z, o, x, -x]
262 ];
263 let result = array![
264 [h-hi, h+hi, x, -x*i],
265 [h+hi, h-hi, x, x*i]
266 ];
267 gate_test(Vdg::new(), &mut state, &result);
268 }
269
270 #[test]
271 fn test_open_qasm()
272 {
273 let bit_names = [String::from("qb")];
274 let qasm = V::new().open_qasm(&bit_names, &[0]);
275 assert_eq!(qasm, Ok(String::from("u3(pi/2, -pi/2, pi/2) qb")));
276 let qasm = Vdg::new().open_qasm(&bit_names, &[0]);
277 assert_eq!(qasm, Ok(String::from("u3(pi/2, pi/2, -pi/2) qb")));
278 }
279
280 #[test]
281 fn test_c_qasm()
282 {
283 let bit_names = [String::from("qb")];
284 let qasm = V::new().c_qasm(&bit_names, &[0]);
285 assert_eq!(qasm, Ok(String::from("x90 qb")));
286 let qasm = Vdg::new().c_qasm(&bit_names, &[0]);
287 assert_eq!(qasm, Ok(String::from("mx90 qb")));
288 }
289
290 #[test]
291 fn test_latex()
292 {
293 let gate = V::new();
294 let mut state = LatexExportState::new(1, 0);
295 assert_eq!(gate.latex(&[0], &mut state), Ok(()));
296 assert_eq!(state.code(),
297r#"\Qcircuit @C=1em @R=.7em {
298 \lstick{\ket{0}} & \gate{V} & \qw \\
299}
300"#);
301
302 let gate = Vdg::new();
303 let mut state = LatexExportState::new(1, 0);
304 assert_eq!(gate.latex(&[0], &mut state), Ok(()));
305 assert_eq!(state.code(),
306r#"\Qcircuit @C=1em @R=.7em {
307 \lstick{\ket{0}} & \gate{V^\dagger} & \qw \\
308}
309"#);
310 }
311
312 #[test]
313 fn test_conjugate()
314 {
315 let mut op = [PauliOp::I];
316 assert_eq!(V::new().conjugate(&mut op), Ok(false));
317 assert_eq!(op, [PauliOp::I]);
318
319 let mut op = [PauliOp::Z];
320 assert_eq!(V::new().conjugate(&mut op), Ok(true));
321 assert_eq!(op, [PauliOp::Y]);
322
323 let mut op = [PauliOp::X];
324 assert_eq!(V::new().conjugate(&mut op), Ok(false));
325 assert_eq!(op, [PauliOp::X]);
326
327 let mut op = [PauliOp::Y];
328 assert_eq!(V::new().conjugate(&mut op), Ok(false));
329 assert_eq!(op, [PauliOp::Z]);
330
331 let mut op = [PauliOp::I];
332 assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
333 assert_eq!(op, [PauliOp::I]);
334
335 let mut op = [PauliOp::Z];
336 assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
337 assert_eq!(op, [PauliOp::Y]);
338
339 let mut op = [PauliOp::X];
340 assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
341 assert_eq!(op, [PauliOp::X]);
342
343 let mut op = [PauliOp::Y];
344 assert_eq!(Vdg::new().conjugate(&mut op), Ok(true));
345 assert_eq!(op, [PauliOp::Z]);
346 }
347}