microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
swernli/parallel

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

library/src/tests/intrinsic.rs

4064lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes, clippy::too_many_lines)]
5
6use expect_test::expect;
7use indoc::indoc;
8use qsc::{SparseSim, interpret::Value, target::Profile};
9
10use super::{test_expression, test_expression_fails, test_expression_with_lib_and_profile_and_sim};
11
12// These tests verify multi-controlled decomposition logic for gate operations. Each test
13// manually allocates 2N qubits, performs the decomposed operation from the library on the first N,
14// verifies the resulting state via dump, and then uncomputes the operation via simulator-native
15// multi-controlled operations to verify via Choi-Jamiolkowski isomorphism that the decomposition
16// was correct.
17
18#[test]
19fn test_mch_1_control() {
20 let mut sim = SparseSim::default();
21 let dump = test_expression_with_lib_and_profile_and_sim(
22 indoc! {"{
23 let qs = QIR.Runtime.AllocateQubitArray(2);
24 let aux = QIR.Runtime.AllocateQubitArray(2);
25 for i in 0..1 {
26 H(aux[i]);
27 CNOT(aux[i], qs[i]);
28 }
29 Controlled H(qs[0..0], qs[1]);
30 Std.Diagnostics.DumpMachine();
31 }"},
32 "",
33 Profile::Unrestricted,
34 &mut sim,
35 &Value::unit(),
36 );
37 expect![[r#"
38 STATE:
39 |0000⟩: 0.5000+0.0000𝑖
40 |0101⟩: 0.5000+0.0000𝑖
41 |1010⟩: 0.3536+0.0000𝑖
42 |1011⟩: 0.3536+0.0000𝑖
43 |1110⟩: 0.3536+0.0000𝑖
44 |1111⟩: −0.3536+0.0000𝑖
45 "#]]
46 .assert_eq(&dump);
47
48 sim.sim.mch(&[0], 1);
49 for i in 0..2 {
50 sim.sim.mcx(&[i + 2], i);
51 sim.sim.h(i + 2);
52 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
53 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
54 }
55}
56
57#[test]
58fn test_mch_2_control() {
59 let mut sim = SparseSim::default();
60 let dump = test_expression_with_lib_and_profile_and_sim(
61 indoc! {"{
62 let qs = QIR.Runtime.AllocateQubitArray(3);
63 let aux = QIR.Runtime.AllocateQubitArray(3);
64 for i in 0..2 {
65 H(aux[i]);
66 CNOT(aux[i], qs[i]);
67 }
68 Controlled H(qs[0..1], qs[2]);
69 Std.Diagnostics.DumpMachine();
70 }"},
71 "",
72 Profile::Unrestricted,
73 &mut sim,
74 &Value::unit(),
75 );
76 expect![[r#"
77 STATE:
78 |000000⟩: 0.3536+0.0000𝑖
79 |001001⟩: 0.3536+0.0000𝑖
80 |010010⟩: 0.3536+0.0000𝑖
81 |011011⟩: 0.3536+0.0000𝑖
82 |100100⟩: 0.3536+0.0000𝑖
83 |101101⟩: 0.3536+0.0000𝑖
84 |110110⟩: 0.2500+0.0000𝑖
85 |110111⟩: 0.2500+0.0000𝑖
86 |111110⟩: 0.2500+0.0000𝑖
87 |111111⟩: −0.2500+0.0000𝑖
88 "#]]
89 .assert_eq(&dump);
90
91 sim.sim.mch(&[0, 1], 2);
92 for i in 0..3 {
93 sim.sim.mcx(&[i + 3], i);
94 sim.sim.h(i + 3);
95 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
96 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
97 }
98}
99
100#[test]
101fn test_unrestricted_mch_3_control() {
102 let mut sim = SparseSim::default();
103 let dump = test_expression_with_lib_and_profile_and_sim(
104 indoc! {"{
105 let qs = QIR.Runtime.AllocateQubitArray(4);
106 let aux = QIR.Runtime.AllocateQubitArray(4);
107 for i in 0..3 {
108 H(aux[i]);
109 CNOT(aux[i], qs[i]);
110 }
111 Controlled H(qs[0..2], qs[3]);
112 Std.Diagnostics.DumpMachine();
113 }"},
114 "",
115 Profile::Unrestricted,
116 &mut sim,
117 &Value::unit(),
118 );
119 expect![[r#"
120 STATE:
121 |00000000⟩: 0.2500+0.0000𝑖
122 |00010001⟩: 0.2500+0.0000𝑖
123 |00100010⟩: 0.2500+0.0000𝑖
124 |00110011⟩: 0.2500+0.0000𝑖
125 |01000100⟩: 0.2500+0.0000𝑖
126 |01010101⟩: 0.2500+0.0000𝑖
127 |01100110⟩: 0.2500+0.0000𝑖
128 |01110111⟩: 0.2500+0.0000𝑖
129 |10001000⟩: 0.2500+0.0000𝑖
130 |10011001⟩: 0.2500+0.0000𝑖
131 |10101010⟩: 0.2500+0.0000𝑖
132 |10111011⟩: 0.2500+0.0000𝑖
133 |11001100⟩: 0.2500+0.0000𝑖
134 |11011101⟩: 0.2500+0.0000𝑖
135 |11101110⟩: 0.1768+0.0000𝑖
136 |11101111⟩: 0.1768+0.0000𝑖
137 |11111110⟩: 0.1768+0.0000𝑖
138 |11111111⟩: −0.1768+0.0000𝑖
139 "#]]
140 .assert_eq(&dump);
141
142 sim.sim.mch(&[0, 1, 2], 3);
143 for i in 0..4 {
144 sim.sim.mcx(&[i + 4], i);
145 sim.sim.h(i + 4);
146 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
147 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
148 }
149}
150
151#[test]
152fn test_base_mch_3_control() {
153 let mut sim = SparseSim::default();
154 let dump = test_expression_with_lib_and_profile_and_sim(
155 indoc! {"{
156 let qs = QIR.Runtime.AllocateQubitArray(4);
157 let aux = QIR.Runtime.AllocateQubitArray(4);
158 for i in 0..3 {
159 H(aux[i]);
160 CNOT(aux[i], qs[i]);
161 }
162 Controlled H(qs[0..2], qs[3]);
163 Std.Diagnostics.DumpMachine();
164 let result : Result[] = [];
165 result
166 }"},
167 "",
168 Profile::Base,
169 &mut sim,
170 &Value::Array(Vec::new().into()),
171 );
172 expect![[r#"
173 STATE:
174 |00000000⟩: 0.2500+0.0000𝑖
175 |00010001⟩: 0.2500+0.0000𝑖
176 |00100010⟩: 0.2500+0.0000𝑖
177 |00110011⟩: 0.2500+0.0000𝑖
178 |01000100⟩: 0.2500+0.0000𝑖
179 |01010101⟩: 0.2500+0.0000𝑖
180 |01100110⟩: 0.2500+0.0000𝑖
181 |01110111⟩: 0.2500+0.0000𝑖
182 |10001000⟩: 0.2500+0.0000𝑖
183 |10011001⟩: 0.2500+0.0000𝑖
184 |10101010⟩: 0.2500+0.0000𝑖
185 |10111011⟩: 0.2500+0.0000𝑖
186 |11001100⟩: 0.2500+0.0000𝑖
187 |11011101⟩: 0.2500+0.0000𝑖
188 |11101110⟩: 0.1768+0.0000𝑖
189 |11101111⟩: 0.1768+0.0000𝑖
190 |11111110⟩: 0.1768+0.0000𝑖
191 |11111111⟩: −0.1768+0.0000𝑖
192 "#]]
193 .assert_eq(&dump);
194
195 sim.sim.mch(&[0, 1, 2], 3);
196 for i in 0..4 {
197 sim.sim.mcx(&[i + 4], i);
198 sim.sim.h(i + 4);
199 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
200 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
201 }
202}
203
204#[test]
205fn test_unrestricted_mch_4_control() {
206 let mut sim = SparseSim::default();
207 let dump = test_expression_with_lib_and_profile_and_sim(
208 indoc! {"{
209 let qs = QIR.Runtime.AllocateQubitArray(5);
210 let aux = QIR.Runtime.AllocateQubitArray(5);
211 for i in 0..4 {
212 H(aux[i]);
213 CNOT(aux[i], qs[i]);
214 }
215 Controlled H(qs[0..3], qs[4]);
216 Std.Diagnostics.DumpMachine();
217 }"},
218 "",
219 Profile::Unrestricted,
220 &mut sim,
221 &Value::unit(),
222 );
223 expect![[r#"
224 STATE:
225 |0000000000⟩: 0.1768+0.0000𝑖
226 |0000100001⟩: 0.1768+0.0000𝑖
227 |0001000010⟩: 0.1768+0.0000𝑖
228 |0001100011⟩: 0.1768+0.0000𝑖
229 |0010000100⟩: 0.1768+0.0000𝑖
230 |0010100101⟩: 0.1768+0.0000𝑖
231 |0011000110⟩: 0.1768+0.0000𝑖
232 |0011100111⟩: 0.1768+0.0000𝑖
233 |0100001000⟩: 0.1768+0.0000𝑖
234 |0100101001⟩: 0.1768+0.0000𝑖
235 |0101001010⟩: 0.1768+0.0000𝑖
236 |0101101011⟩: 0.1768+0.0000𝑖
237 |0110001100⟩: 0.1768+0.0000𝑖
238 |0110101101⟩: 0.1768+0.0000𝑖
239 |0111001110⟩: 0.1768+0.0000𝑖
240 |0111101111⟩: 0.1768+0.0000𝑖
241 |1000010000⟩: 0.1768+0.0000𝑖
242 |1000110001⟩: 0.1768+0.0000𝑖
243 |1001010010⟩: 0.1768+0.0000𝑖
244 |1001110011⟩: 0.1768+0.0000𝑖
245 |1010010100⟩: 0.1768+0.0000𝑖
246 |1010110101⟩: 0.1768+0.0000𝑖
247 |1011010110⟩: 0.1768+0.0000𝑖
248 |1011110111⟩: 0.1768+0.0000𝑖
249 |1100011000⟩: 0.1768+0.0000𝑖
250 |1100111001⟩: 0.1768+0.0000𝑖
251 |1101011010⟩: 0.1768+0.0000𝑖
252 |1101111011⟩: 0.1768+0.0000𝑖
253 |1110011100⟩: 0.1768+0.0000𝑖
254 |1110111101⟩: 0.1768+0.0000𝑖
255 |1111011110⟩: 0.1250+0.0000𝑖
256 |1111011111⟩: 0.1250+0.0000𝑖
257 |1111111110⟩: 0.1250+0.0000𝑖
258 |1111111111⟩: −0.1250+0.0000𝑖
259 "#]]
260 .assert_eq(&dump);
261
262 sim.sim.mch(&[0, 1, 2, 3], 4);
263 for i in 0..5 {
264 sim.sim.mcx(&[i + 5], i);
265 sim.sim.h(i + 5);
266 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
267 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
268 }
269}
270
271#[test]
272fn test_base_mch_4_control() {
273 let mut sim = SparseSim::default();
274 let dump = test_expression_with_lib_and_profile_and_sim(
275 indoc! {"{
276 let qs = QIR.Runtime.AllocateQubitArray(5);
277 let aux = QIR.Runtime.AllocateQubitArray(5);
278 for i in 0..4 {
279 H(aux[i]);
280 CNOT(aux[i], qs[i]);
281 }
282 Controlled H(qs[0..3], qs[4]);
283 Std.Diagnostics.DumpMachine();
284 let result : Result[] = [];
285 result
286 }"},
287 "",
288 Profile::Base,
289 &mut sim,
290 &Value::Array(Vec::new().into()),
291 );
292 expect![[r#"
293 STATE:
294 |0000000000⟩: 0.1768+0.0000𝑖
295 |0000100001⟩: 0.1768+0.0000𝑖
296 |0001000010⟩: 0.1768+0.0000𝑖
297 |0001100011⟩: 0.1768+0.0000𝑖
298 |0010000100⟩: 0.1768+0.0000𝑖
299 |0010100101⟩: 0.1768+0.0000𝑖
300 |0011000110⟩: 0.1768+0.0000𝑖
301 |0011100111⟩: 0.1768+0.0000𝑖
302 |0100001000⟩: 0.1768+0.0000𝑖
303 |0100101001⟩: 0.1768+0.0000𝑖
304 |0101001010⟩: 0.1768+0.0000𝑖
305 |0101101011⟩: 0.1768+0.0000𝑖
306 |0110001100⟩: 0.1768+0.0000𝑖
307 |0110101101⟩: 0.1768+0.0000𝑖
308 |0111001110⟩: 0.1768+0.0000𝑖
309 |0111101111⟩: 0.1768+0.0000𝑖
310 |1000010000⟩: 0.1768+0.0000𝑖
311 |1000110001⟩: 0.1768+0.0000𝑖
312 |1001010010⟩: 0.1768+0.0000𝑖
313 |1001110011⟩: 0.1768+0.0000𝑖
314 |1010010100⟩: 0.1768+0.0000𝑖
315 |1010110101⟩: 0.1768+0.0000𝑖
316 |1011010110⟩: 0.1768+0.0000𝑖
317 |1011110111⟩: 0.1768+0.0000𝑖
318 |1100011000⟩: 0.1768+0.0000𝑖
319 |1100111001⟩: 0.1768+0.0000𝑖
320 |1101011010⟩: 0.1768+0.0000𝑖
321 |1101111011⟩: 0.1768+0.0000𝑖
322 |1110011100⟩: 0.1768+0.0000𝑖
323 |1110111101⟩: 0.1768+0.0000𝑖
324 |1111011110⟩: 0.1250+0.0000𝑖
325 |1111011111⟩: 0.1250+0.0000𝑖
326 |1111111110⟩: 0.1250+0.0000𝑖
327 |1111111111⟩: −0.1250+0.0000𝑖
328 "#]]
329 .assert_eq(&dump);
330
331 sim.sim.mch(&[0, 1, 2, 3], 4);
332 for i in 0..5 {
333 sim.sim.mcx(&[i + 5], i);
334 sim.sim.h(i + 5);
335 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
336 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
337 }
338}
339
340#[test]
341fn test_mcrz_1_control() {
342 let mut sim = SparseSim::default();
343 let dump = test_expression_with_lib_and_profile_and_sim(
344 indoc! {"{
345 let qs = QIR.Runtime.AllocateQubitArray(2);
346 let aux = QIR.Runtime.AllocateQubitArray(2);
347 for i in 0..1 {
348 H(aux[i]);
349 CNOT(aux[i], qs[i]);
350 }
351 Controlled Rz(qs[0..0], (Std.Math.PI() / 7.0, qs[1]));
352 Std.Diagnostics.DumpMachine();
353 }"},
354 "",
355 Profile::Unrestricted,
356 &mut sim,
357 &Value::unit(),
358 );
359 expect![[r#"
360 STATE:
361 |0000⟩: 0.5000+0.0000𝑖
362 |0101⟩: 0.5000+0.0000𝑖
363 |1010⟩: 0.4875−0.1113𝑖
364 |1111⟩: 0.4875+0.1113𝑖
365 "#]]
366 .assert_eq(&dump);
367
368 sim.sim.mcrz(&[0], std::f64::consts::PI / -7.0, 1);
369 for i in 0..2 {
370 sim.sim.mcx(&[i + 2], i);
371 sim.sim.h(i + 2);
372 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
373 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
374 }
375}
376
377#[test]
378fn test_unrestricted_mcrz_2_control() {
379 let mut sim = SparseSim::default();
380 let dump = test_expression_with_lib_and_profile_and_sim(
381 indoc! {"{
382 let qs = QIR.Runtime.AllocateQubitArray(3);
383 let aux = QIR.Runtime.AllocateQubitArray(3);
384 for i in 0..2 {
385 H(aux[i]);
386 CNOT(aux[i], qs[i]);
387 }
388 Controlled Rz(qs[0..1], (Std.Math.PI() / 7.0, qs[2]));
389 Std.Diagnostics.DumpMachine();
390 }"},
391 "",
392 Profile::Unrestricted,
393 &mut sim,
394 &Value::unit(),
395 );
396 expect![[r#"
397 STATE:
398 |000000⟩: 0.3536+0.0000𝑖
399 |001001⟩: 0.3536+0.0000𝑖
400 |010010⟩: 0.3536+0.0000𝑖
401 |011011⟩: 0.3536+0.0000𝑖
402 |100100⟩: 0.3536+0.0000𝑖
403 |101101⟩: 0.3536+0.0000𝑖
404 |110110⟩: 0.3447−0.0787𝑖
405 |111111⟩: 0.3447+0.0787𝑖
406 "#]]
407 .assert_eq(&dump);
408
409 sim.sim.mcrz(&[0, 1], std::f64::consts::PI / -7.0, 2);
410 for i in 0..3 {
411 sim.sim.mcx(&[i + 3], i);
412 sim.sim.h(i + 3);
413 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
414 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
415 }
416}
417
418#[test]
419fn test_base_mcrz_2_control() {
420 let mut sim = SparseSim::default();
421 let dump = test_expression_with_lib_and_profile_and_sim(
422 indoc! {"{
423 let qs = QIR.Runtime.AllocateQubitArray(3);
424 let aux = QIR.Runtime.AllocateQubitArray(3);
425 for i in 0..2 {
426 H(aux[i]);
427 CNOT(aux[i], qs[i]);
428 }
429 Controlled Rz(qs[0..1], (Std.Math.PI() / 7.0, qs[2]));
430 Std.Diagnostics.DumpMachine();
431 let result : Result[] = [];
432 result
433 }"},
434 "",
435 Profile::Base,
436 &mut sim,
437 &Value::Array(Vec::new().into()),
438 );
439 expect![[r#"
440 STATE:
441 |000000⟩: 0.3536+0.0000𝑖
442 |001001⟩: 0.3536+0.0000𝑖
443 |010010⟩: 0.3536+0.0000𝑖
444 |011011⟩: 0.3536+0.0000𝑖
445 |100100⟩: 0.3536+0.0000𝑖
446 |101101⟩: 0.3536+0.0000𝑖
447 |110110⟩: 0.3447−0.0787𝑖
448 |111111⟩: 0.3447+0.0787𝑖
449 "#]]
450 .assert_eq(&dump);
451
452 sim.sim.mcrz(&[0, 1], std::f64::consts::PI / -7.0, 2);
453 for i in 0..3 {
454 sim.sim.mcx(&[i + 3], i);
455 sim.sim.h(i + 3);
456 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
457 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
458 }
459}
460
461#[test]
462fn test_unrestricted_mcrz_3_control() {
463 let mut sim = SparseSim::default();
464 let dump = test_expression_with_lib_and_profile_and_sim(
465 indoc! {"{
466 let qs = QIR.Runtime.AllocateQubitArray(4);
467 let aux = QIR.Runtime.AllocateQubitArray(4);
468 for i in 0..3 {
469 H(aux[i]);
470 CNOT(aux[i], qs[i]);
471 }
472 Controlled Rz(qs[0..2], (Std.Math.PI() / 7.0, qs[3]));
473 Std.Diagnostics.DumpMachine();
474 }"},
475 "",
476 Profile::Unrestricted,
477 &mut sim,
478 &Value::unit(),
479 );
480 expect![[r#"
481 STATE:
482 |00000000⟩: 0.2500+0.0000𝑖
483 |00010001⟩: 0.2500+0.0000𝑖
484 |00100010⟩: 0.2500+0.0000𝑖
485 |00110011⟩: 0.2500+0.0000𝑖
486 |01000100⟩: 0.2500+0.0000𝑖
487 |01010101⟩: 0.2500+0.0000𝑖
488 |01100110⟩: 0.2500+0.0000𝑖
489 |01110111⟩: 0.2500+0.0000𝑖
490 |10001000⟩: 0.2500+0.0000𝑖
491 |10011001⟩: 0.2500+0.0000𝑖
492 |10101010⟩: 0.2500+0.0000𝑖
493 |10111011⟩: 0.2500+0.0000𝑖
494 |11001100⟩: 0.2500+0.0000𝑖
495 |11011101⟩: 0.2500+0.0000𝑖
496 |11101110⟩: 0.2437−0.0556𝑖
497 |11111111⟩: 0.2437+0.0556𝑖
498 "#]]
499 .assert_eq(&dump);
500
501 sim.sim.mcrz(&[0, 1, 2], std::f64::consts::PI / -7.0, 3);
502 for i in 0..4 {
503 sim.sim.mcx(&[i + 4], i);
504 sim.sim.h(i + 4);
505 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
506 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
507 }
508}
509
510#[test]
511fn test_base_mcrz_3_control() {
512 let mut sim = SparseSim::default();
513 let dump = test_expression_with_lib_and_profile_and_sim(
514 indoc! {"{
515 let qs = QIR.Runtime.AllocateQubitArray(4);
516 let aux = QIR.Runtime.AllocateQubitArray(4);
517 for i in 0..3 {
518 H(aux[i]);
519 CNOT(aux[i], qs[i]);
520 }
521 Controlled Rz(qs[0..2], (Std.Math.PI() / 7.0, qs[3]));
522 Std.Diagnostics.DumpMachine();
523 let result : Result[] = [];
524 result
525 }"},
526 "",
527 Profile::Base,
528 &mut sim,
529 &Value::Array(Vec::new().into()),
530 );
531 expect![[r#"
532 STATE:
533 |00000000⟩: 0.2500+0.0000𝑖
534 |00010001⟩: 0.2500+0.0000𝑖
535 |00100010⟩: 0.2500+0.0000𝑖
536 |00110011⟩: 0.2500+0.0000𝑖
537 |01000100⟩: 0.2500+0.0000𝑖
538 |01010101⟩: 0.2500+0.0000𝑖
539 |01100110⟩: 0.2500+0.0000𝑖
540 |01110111⟩: 0.2500+0.0000𝑖
541 |10001000⟩: 0.2500+0.0000𝑖
542 |10011001⟩: 0.2500+0.0000𝑖
543 |10101010⟩: 0.2500+0.0000𝑖
544 |10111011⟩: 0.2500+0.0000𝑖
545 |11001100⟩: 0.2500+0.0000𝑖
546 |11011101⟩: 0.2500+0.0000𝑖
547 |11101110⟩: 0.2437−0.0556𝑖
548 |11111111⟩: 0.2437+0.0556𝑖
549 "#]]
550 .assert_eq(&dump);
551
552 sim.sim.mcrz(&[0, 1, 2], std::f64::consts::PI / -7.0, 3);
553 for i in 0..4 {
554 sim.sim.mcx(&[i + 4], i);
555 sim.sim.h(i + 4);
556 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
557 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
558 }
559}
560
561#[test]
562fn test_mcrx_1_control() {
563 let mut sim = SparseSim::default();
564 let dump = test_expression_with_lib_and_profile_and_sim(
565 indoc! {"{
566 let qs = QIR.Runtime.AllocateQubitArray(2);
567 let aux = QIR.Runtime.AllocateQubitArray(2);
568 for i in 0..1 {
569 H(aux[i]);
570 CNOT(aux[i], qs[i]);
571 }
572 Controlled Rx(qs[0..0], (Std.Math.PI() / 7.0, qs[1]));
573 Std.Diagnostics.DumpMachine();
574 }"},
575 "",
576 Profile::Unrestricted,
577 &mut sim,
578 &Value::unit(),
579 );
580 expect![[r#"
581 STATE:
582 |0000⟩: 0.5000+0.0000𝑖
583 |0101⟩: 0.5000+0.0000𝑖
584 |1010⟩: 0.4875+0.0000𝑖
585 |1011⟩: 0.0000−0.1113𝑖
586 |1110⟩: 0.0000−0.1113𝑖
587 |1111⟩: 0.4875+0.0000𝑖
588 "#]]
589 .assert_eq(&dump);
590
591 sim.sim.mcrx(&[0], std::f64::consts::PI / -7.0, 1);
592 for i in 0..2 {
593 sim.sim.mcx(&[i + 2], i);
594 sim.sim.h(i + 2);
595 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
596 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
597 }
598}
599
600#[test]
601fn test_mcry_1_control() {
602 let mut sim = SparseSim::default();
603 let dump = test_expression_with_lib_and_profile_and_sim(
604 indoc! {"{
605 let qs = QIR.Runtime.AllocateQubitArray(2);
606 let aux = QIR.Runtime.AllocateQubitArray(2);
607 for i in 0..1 {
608 H(aux[i]);
609 CNOT(aux[i], qs[i]);
610 }
611 Controlled Ry(qs[0..0], (Std.Math.PI() / 7.0, qs[1]));
612 Std.Diagnostics.DumpMachine();
613 }"},
614 "",
615 Profile::Unrestricted,
616 &mut sim,
617 &Value::unit(),
618 );
619 expect![[r#"
620 STATE:
621 |0000⟩: 0.5000+0.0000𝑖
622 |0101⟩: 0.5000+0.0000𝑖
623 |1010⟩: 0.4875+0.0000𝑖
624 |1011⟩: −0.1113+0.0000𝑖
625 |1110⟩: 0.1113+0.0000𝑖
626 |1111⟩: 0.4875+0.0000𝑖
627 "#]]
628 .assert_eq(&dump);
629
630 sim.sim.mcry(&[0], std::f64::consts::PI / -7.0, 1);
631 for i in 0..2 {
632 sim.sim.mcx(&[i + 2], i);
633 sim.sim.h(i + 2);
634 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
635 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
636 }
637}
638
639#[test]
640fn test_mcs_1_control() {
641 let mut sim = SparseSim::default();
642 let dump = test_expression_with_lib_and_profile_and_sim(
643 indoc! {"{
644 let qs = QIR.Runtime.AllocateQubitArray(2);
645 let aux = QIR.Runtime.AllocateQubitArray(2);
646 for i in 0..1 {
647 H(aux[i]);
648 CNOT(aux[i], qs[i]);
649 }
650 Controlled S(qs[0..0], qs[1]);
651 Std.Diagnostics.DumpMachine();
652 }"},
653 "",
654 Profile::Unrestricted,
655 &mut sim,
656 &Value::unit(),
657 );
658 expect![[r#"
659 STATE:
660 |0000⟩: 0.5000+0.0000𝑖
661 |0101⟩: 0.5000+0.0000𝑖
662 |1010⟩: 0.5000+0.0000𝑖
663 |1111⟩: 0.0000+0.5000𝑖
664 "#]]
665 .assert_eq(&dump);
666
667 sim.sim.mcsadj(&[0], 1);
668 for i in 0..2 {
669 sim.sim.mcx(&[i + 2], i);
670 sim.sim.h(i + 2);
671 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
672 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
673 }
674}
675
676#[test]
677fn test_mcs_2_control() {
678 let mut sim = SparseSim::default();
679 let dump = test_expression_with_lib_and_profile_and_sim(
680 indoc! {"{
681 let qs = QIR.Runtime.AllocateQubitArray(3);
682 let aux = QIR.Runtime.AllocateQubitArray(3);
683 for i in 0..2 {
684 H(aux[i]);
685 CNOT(aux[i], qs[i]);
686 }
687 Controlled S(qs[0..1], qs[2]);
688 Std.Diagnostics.DumpMachine();
689 }"},
690 "",
691 Profile::Unrestricted,
692 &mut sim,
693 &Value::unit(),
694 );
695 expect![[r#"
696 STATE:
697 |000000⟩: 0.3536+0.0000𝑖
698 |001001⟩: 0.3536+0.0000𝑖
699 |010010⟩: 0.3536+0.0000𝑖
700 |011011⟩: 0.3536+0.0000𝑖
701 |100100⟩: 0.3536+0.0000𝑖
702 |101101⟩: 0.3536+0.0000𝑖
703 |110110⟩: 0.3536+0.0000𝑖
704 |111111⟩: 0.0000+0.3536𝑖
705 "#]]
706 .assert_eq(&dump);
707
708 sim.sim.mcsadj(&[0, 1], 2);
709 for i in 0..3 {
710 sim.sim.mcx(&[i + 3], i);
711 sim.sim.h(i + 3);
712 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
713 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
714 }
715}
716
717#[test]
718fn test_unrestricted_mcs_3_control() {
719 let mut sim = SparseSim::default();
720 let dump = test_expression_with_lib_and_profile_and_sim(
721 indoc! {"{
722 let qs = QIR.Runtime.AllocateQubitArray(4);
723 let aux = QIR.Runtime.AllocateQubitArray(4);
724 for i in 0..3 {
725 H(aux[i]);
726 CNOT(aux[i], qs[i]);
727 }
728 Controlled S(qs[0..2], qs[3]);
729 Std.Diagnostics.DumpMachine();
730 }"},
731 "",
732 Profile::Unrestricted,
733 &mut sim,
734 &Value::unit(),
735 );
736 expect![[r#"
737 STATE:
738 |00000000⟩: 0.2500+0.0000𝑖
739 |00010001⟩: 0.2500+0.0000𝑖
740 |00100010⟩: 0.2500+0.0000𝑖
741 |00110011⟩: 0.2500+0.0000𝑖
742 |01000100⟩: 0.2500+0.0000𝑖
743 |01010101⟩: 0.2500+0.0000𝑖
744 |01100110⟩: 0.2500+0.0000𝑖
745 |01110111⟩: 0.2500+0.0000𝑖
746 |10001000⟩: 0.2500+0.0000𝑖
747 |10011001⟩: 0.2500+0.0000𝑖
748 |10101010⟩: 0.2500+0.0000𝑖
749 |10111011⟩: 0.2500+0.0000𝑖
750 |11001100⟩: 0.2500+0.0000𝑖
751 |11011101⟩: 0.2500+0.0000𝑖
752 |11101110⟩: 0.2500+0.0000𝑖
753 |11111111⟩: 0.0000+0.2500𝑖
754 "#]]
755 .assert_eq(&dump);
756
757 sim.sim.mcsadj(&[0, 1, 2], 3);
758 for i in 0..4 {
759 sim.sim.mcx(&[i + 4], i);
760 sim.sim.h(i + 4);
761 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
762 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
763 }
764}
765
766#[test]
767fn test_base_mcs_3_control() {
768 let mut sim = SparseSim::default();
769 let dump = test_expression_with_lib_and_profile_and_sim(
770 indoc! {"{
771 let qs = QIR.Runtime.AllocateQubitArray(4);
772 let aux = QIR.Runtime.AllocateQubitArray(4);
773 for i in 0..3 {
774 H(aux[i]);
775 CNOT(aux[i], qs[i]);
776 }
777 Controlled S(qs[0..2], qs[3]);
778 Std.Diagnostics.DumpMachine();
779 let result : Result[] = [];
780 result
781 }"},
782 "",
783 Profile::Base,
784 &mut sim,
785 &Value::Array(Vec::new().into()),
786 );
787 expect![[r#"
788 STATE:
789 |00000000⟩: 0.2500+0.0000𝑖
790 |00010001⟩: 0.2500+0.0000𝑖
791 |00100010⟩: 0.2500+0.0000𝑖
792 |00110011⟩: 0.2500+0.0000𝑖
793 |01000100⟩: 0.2500+0.0000𝑖
794 |01010101⟩: 0.2500+0.0000𝑖
795 |01100110⟩: 0.2500+0.0000𝑖
796 |01110111⟩: 0.2500+0.0000𝑖
797 |10001000⟩: 0.2500+0.0000𝑖
798 |10011001⟩: 0.2500+0.0000𝑖
799 |10101010⟩: 0.2500+0.0000𝑖
800 |10111011⟩: 0.2500+0.0000𝑖
801 |11001100⟩: 0.2500+0.0000𝑖
802 |11011101⟩: 0.2500+0.0000𝑖
803 |11101110⟩: 0.2500+0.0000𝑖
804 |11111111⟩: 0.0000+0.2500𝑖
805 "#]]
806 .assert_eq(&dump);
807
808 sim.sim.mcsadj(&[0, 1, 2], 3);
809 for i in 0..4 {
810 sim.sim.mcx(&[i + 4], i);
811 sim.sim.h(i + 4);
812 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
813 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
814 }
815}
816
817#[test]
818fn test_unrestricted_mcs_4_control() {
819 let mut sim = SparseSim::default();
820 let dump = test_expression_with_lib_and_profile_and_sim(
821 indoc! {"{
822 let qs = QIR.Runtime.AllocateQubitArray(5);
823 let aux = QIR.Runtime.AllocateQubitArray(5);
824 for i in 0..4 {
825 H(aux[i]);
826 CNOT(aux[i], qs[i]);
827 }
828 Controlled S(qs[0..3], qs[4]);
829 Std.Diagnostics.DumpMachine();
830 }"},
831 "",
832 Profile::Unrestricted,
833 &mut sim,
834 &Value::unit(),
835 );
836 expect![[r#"
837 STATE:
838 |0000000000⟩: 0.1768+0.0000𝑖
839 |0000100001⟩: 0.1768+0.0000𝑖
840 |0001000010⟩: 0.1768+0.0000𝑖
841 |0001100011⟩: 0.1768+0.0000𝑖
842 |0010000100⟩: 0.1768+0.0000𝑖
843 |0010100101⟩: 0.1768+0.0000𝑖
844 |0011000110⟩: 0.1768+0.0000𝑖
845 |0011100111⟩: 0.1768+0.0000𝑖
846 |0100001000⟩: 0.1768+0.0000𝑖
847 |0100101001⟩: 0.1768+0.0000𝑖
848 |0101001010⟩: 0.1768+0.0000𝑖
849 |0101101011⟩: 0.1768+0.0000𝑖
850 |0110001100⟩: 0.1768+0.0000𝑖
851 |0110101101⟩: 0.1768+0.0000𝑖
852 |0111001110⟩: 0.1768+0.0000𝑖
853 |0111101111⟩: 0.1768+0.0000𝑖
854 |1000010000⟩: 0.1768+0.0000𝑖
855 |1000110001⟩: 0.1768+0.0000𝑖
856 |1001010010⟩: 0.1768+0.0000𝑖
857 |1001110011⟩: 0.1768+0.0000𝑖
858 |1010010100⟩: 0.1768+0.0000𝑖
859 |1010110101⟩: 0.1768+0.0000𝑖
860 |1011010110⟩: 0.1768+0.0000𝑖
861 |1011110111⟩: 0.1768+0.0000𝑖
862 |1100011000⟩: 0.1768+0.0000𝑖
863 |1100111001⟩: 0.1768+0.0000𝑖
864 |1101011010⟩: 0.1768+0.0000𝑖
865 |1101111011⟩: 0.1768+0.0000𝑖
866 |1110011100⟩: 0.1768+0.0000𝑖
867 |1110111101⟩: 0.1768+0.0000𝑖
868 |1111011110⟩: 0.1768+0.0000𝑖
869 |1111111111⟩: 0.0000+0.1768𝑖
870 "#]]
871 .assert_eq(&dump);
872
873 sim.sim.mcsadj(&[0, 1, 2, 3], 4);
874 for i in 0..5 {
875 sim.sim.mcx(&[i + 5], i);
876 sim.sim.h(i + 5);
877 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
878 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
879 }
880}
881
882#[test]
883fn test_base_mcs_4_control() {
884 let mut sim = SparseSim::default();
885 let dump = test_expression_with_lib_and_profile_and_sim(
886 indoc! {"{
887 let qs = QIR.Runtime.AllocateQubitArray(5);
888 let aux = QIR.Runtime.AllocateQubitArray(5);
889 for i in 0..4 {
890 H(aux[i]);
891 CNOT(aux[i], qs[i]);
892 }
893 Controlled S(qs[0..3], qs[4]);
894 Std.Diagnostics.DumpMachine();
895 let result : Result[] = [];
896 result
897 }"},
898 "",
899 Profile::Base,
900 &mut sim,
901 &Value::Array(Vec::new().into()),
902 );
903 expect![[r#"
904 STATE:
905 |0000000000⟩: 0.1768+0.0000𝑖
906 |0000100001⟩: 0.1768+0.0000𝑖
907 |0001000010⟩: 0.1768+0.0000𝑖
908 |0001100011⟩: 0.1768+0.0000𝑖
909 |0010000100⟩: 0.1768+0.0000𝑖
910 |0010100101⟩: 0.1768+0.0000𝑖
911 |0011000110⟩: 0.1768+0.0000𝑖
912 |0011100111⟩: 0.1768+0.0000𝑖
913 |0100001000⟩: 0.1768+0.0000𝑖
914 |0100101001⟩: 0.1768+0.0000𝑖
915 |0101001010⟩: 0.1768+0.0000𝑖
916 |0101101011⟩: 0.1768+0.0000𝑖
917 |0110001100⟩: 0.1768+0.0000𝑖
918 |0110101101⟩: 0.1768+0.0000𝑖
919 |0111001110⟩: 0.1768+0.0000𝑖
920 |0111101111⟩: 0.1768+0.0000𝑖
921 |1000010000⟩: 0.1768+0.0000𝑖
922 |1000110001⟩: 0.1768+0.0000𝑖
923 |1001010010⟩: 0.1768+0.0000𝑖
924 |1001110011⟩: 0.1768+0.0000𝑖
925 |1010010100⟩: 0.1768+0.0000𝑖
926 |1010110101⟩: 0.1768+0.0000𝑖
927 |1011010110⟩: 0.1768+0.0000𝑖
928 |1011110111⟩: 0.1768+0.0000𝑖
929 |1100011000⟩: 0.1768+0.0000𝑖
930 |1100111001⟩: 0.1768+0.0000𝑖
931 |1101011010⟩: 0.1768+0.0000𝑖
932 |1101111011⟩: 0.1768+0.0000𝑖
933 |1110011100⟩: 0.1768+0.0000𝑖
934 |1110111101⟩: 0.1768+0.0000𝑖
935 |1111011110⟩: 0.1768+0.0000𝑖
936 |1111111111⟩: 0.0000+0.1768𝑖
937 "#]]
938 .assert_eq(&dump);
939
940 sim.sim.mcsadj(&[0, 1, 2, 3], 4);
941 for i in 0..5 {
942 sim.sim.mcx(&[i + 5], i);
943 sim.sim.h(i + 5);
944 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
945 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
946 }
947}
948
949#[test]
950fn test_mcsadj_1_control() {
951 let mut sim = SparseSim::default();
952 let dump = test_expression_with_lib_and_profile_and_sim(
953 indoc! {"{
954 let qs = QIR.Runtime.AllocateQubitArray(2);
955 let aux = QIR.Runtime.AllocateQubitArray(2);
956 for i in 0..1 {
957 H(aux[i]);
958 CNOT(aux[i], qs[i]);
959 }
960 Controlled Adjoint S(qs[0..0], qs[1]);
961 Std.Diagnostics.DumpMachine();
962 }"},
963 "",
964 Profile::Unrestricted,
965 &mut sim,
966 &Value::unit(),
967 );
968 expect![[r#"
969 STATE:
970 |0000⟩: 0.5000+0.0000𝑖
971 |0101⟩: 0.5000+0.0000𝑖
972 |1010⟩: 0.5000+0.0000𝑖
973 |1111⟩: 0.0000−0.5000𝑖
974 "#]]
975 .assert_eq(&dump);
976
977 sim.sim.mcs(&[0], 1);
978 for i in 0..2 {
979 sim.sim.mcx(&[i + 2], i);
980 sim.sim.h(i + 2);
981 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
982 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
983 }
984}
985
986#[test]
987fn test_mcsadj_2_control() {
988 let mut sim = SparseSim::default();
989 let dump = test_expression_with_lib_and_profile_and_sim(
990 indoc! {"{
991 let qs = QIR.Runtime.AllocateQubitArray(3);
992 let aux = QIR.Runtime.AllocateQubitArray(3);
993 for i in 0..2 {
994 H(aux[i]);
995 CNOT(aux[i], qs[i]);
996 }
997 Controlled Adjoint S(qs[0..1], qs[2]);
998 Std.Diagnostics.DumpMachine();
999 }"},
1000 "",
1001 Profile::Unrestricted,
1002 &mut sim,
1003 &Value::unit(),
1004 );
1005 expect![[r#"
1006 STATE:
1007 |000000⟩: 0.3536+0.0000𝑖
1008 |001001⟩: 0.3536+0.0000𝑖
1009 |010010⟩: 0.3536+0.0000𝑖
1010 |011011⟩: 0.3536+0.0000𝑖
1011 |100100⟩: 0.3536+0.0000𝑖
1012 |101101⟩: 0.3536+0.0000𝑖
1013 |110110⟩: 0.3536+0.0000𝑖
1014 |111111⟩: 0.0000−0.3536𝑖
1015 "#]]
1016 .assert_eq(&dump);
1017
1018 sim.sim.mcs(&[0, 1], 2);
1019 for i in 0..3 {
1020 sim.sim.mcx(&[i + 3], i);
1021 sim.sim.h(i + 3);
1022 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
1023 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1024 }
1025}
1026
1027#[test]
1028fn test_unrestricted_mcsadj_3_control() {
1029 let mut sim = SparseSim::default();
1030 let dump = test_expression_with_lib_and_profile_and_sim(
1031 indoc! {"{
1032 let qs = QIR.Runtime.AllocateQubitArray(4);
1033 let aux = QIR.Runtime.AllocateQubitArray(4);
1034 for i in 0..3 {
1035 H(aux[i]);
1036 CNOT(aux[i], qs[i]);
1037 }
1038 Controlled Adjoint S(qs[0..2], qs[3]);
1039 Std.Diagnostics.DumpMachine();
1040 }"},
1041 "",
1042 Profile::Unrestricted,
1043 &mut sim,
1044 &Value::unit(),
1045 );
1046 expect![[r#"
1047 STATE:
1048 |00000000⟩: 0.2500+0.0000𝑖
1049 |00010001⟩: 0.2500+0.0000𝑖
1050 |00100010⟩: 0.2500+0.0000𝑖
1051 |00110011⟩: 0.2500+0.0000𝑖
1052 |01000100⟩: 0.2500+0.0000𝑖
1053 |01010101⟩: 0.2500+0.0000𝑖
1054 |01100110⟩: 0.2500+0.0000𝑖
1055 |01110111⟩: 0.2500+0.0000𝑖
1056 |10001000⟩: 0.2500+0.0000𝑖
1057 |10011001⟩: 0.2500+0.0000𝑖
1058 |10101010⟩: 0.2500+0.0000𝑖
1059 |10111011⟩: 0.2500+0.0000𝑖
1060 |11001100⟩: 0.2500+0.0000𝑖
1061 |11011101⟩: 0.2500+0.0000𝑖
1062 |11101110⟩: 0.2500+0.0000𝑖
1063 |11111111⟩: 0.0000−0.2500𝑖
1064 "#]]
1065 .assert_eq(&dump);
1066
1067 sim.sim.mcs(&[0, 1, 2], 3);
1068 for i in 0..4 {
1069 sim.sim.mcx(&[i + 4], i);
1070 sim.sim.h(i + 4);
1071 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1072 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1073 }
1074}
1075
1076#[test]
1077fn test_base_mcsadj_3_control() {
1078 let mut sim = SparseSim::default();
1079 let dump = test_expression_with_lib_and_profile_and_sim(
1080 indoc! {"{
1081 let qs = QIR.Runtime.AllocateQubitArray(4);
1082 let aux = QIR.Runtime.AllocateQubitArray(4);
1083 for i in 0..3 {
1084 H(aux[i]);
1085 CNOT(aux[i], qs[i]);
1086 }
1087 Controlled Adjoint S(qs[0..2], qs[3]);
1088 Std.Diagnostics.DumpMachine();
1089 let result : Result[] = [];
1090 result
1091 }"},
1092 "",
1093 Profile::Base,
1094 &mut sim,
1095 &Value::Array(Vec::new().into()),
1096 );
1097 expect![[r#"
1098 STATE:
1099 |00000000⟩: 0.2500+0.0000𝑖
1100 |00010001⟩: 0.2500+0.0000𝑖
1101 |00100010⟩: 0.2500+0.0000𝑖
1102 |00110011⟩: 0.2500+0.0000𝑖
1103 |01000100⟩: 0.2500+0.0000𝑖
1104 |01010101⟩: 0.2500+0.0000𝑖
1105 |01100110⟩: 0.2500+0.0000𝑖
1106 |01110111⟩: 0.2500+0.0000𝑖
1107 |10001000⟩: 0.2500+0.0000𝑖
1108 |10011001⟩: 0.2500+0.0000𝑖
1109 |10101010⟩: 0.2500+0.0000𝑖
1110 |10111011⟩: 0.2500+0.0000𝑖
1111 |11001100⟩: 0.2500+0.0000𝑖
1112 |11011101⟩: 0.2500+0.0000𝑖
1113 |11101110⟩: 0.2500+0.0000𝑖
1114 |11111111⟩: 0.0000−0.2500𝑖
1115 "#]]
1116 .assert_eq(&dump);
1117
1118 sim.sim.mcs(&[0, 1, 2], 3);
1119 for i in 0..4 {
1120 sim.sim.mcx(&[i + 4], i);
1121 sim.sim.h(i + 4);
1122 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1123 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1124 }
1125}
1126
1127#[test]
1128fn test_unrestricted_mcsadj_4_control() {
1129 let mut sim = SparseSim::default();
1130 let dump = test_expression_with_lib_and_profile_and_sim(
1131 indoc! {"{
1132 let qs = QIR.Runtime.AllocateQubitArray(5);
1133 let aux = QIR.Runtime.AllocateQubitArray(5);
1134 for i in 0..4 {
1135 H(aux[i]);
1136 CNOT(aux[i], qs[i]);
1137 }
1138 Controlled Adjoint S(qs[0..3], qs[4]);
1139 Std.Diagnostics.DumpMachine();
1140 }"},
1141 "",
1142 Profile::Unrestricted,
1143 &mut sim,
1144 &Value::unit(),
1145 );
1146 expect![[r#"
1147 STATE:
1148 |0000000000⟩: 0.1768+0.0000𝑖
1149 |0000100001⟩: 0.1768+0.0000𝑖
1150 |0001000010⟩: 0.1768+0.0000𝑖
1151 |0001100011⟩: 0.1768+0.0000𝑖
1152 |0010000100⟩: 0.1768+0.0000𝑖
1153 |0010100101⟩: 0.1768+0.0000𝑖
1154 |0011000110⟩: 0.1768+0.0000𝑖
1155 |0011100111⟩: 0.1768+0.0000𝑖
1156 |0100001000⟩: 0.1768+0.0000𝑖
1157 |0100101001⟩: 0.1768+0.0000𝑖
1158 |0101001010⟩: 0.1768+0.0000𝑖
1159 |0101101011⟩: 0.1768+0.0000𝑖
1160 |0110001100⟩: 0.1768+0.0000𝑖
1161 |0110101101⟩: 0.1768+0.0000𝑖
1162 |0111001110⟩: 0.1768+0.0000𝑖
1163 |0111101111⟩: 0.1768+0.0000𝑖
1164 |1000010000⟩: 0.1768+0.0000𝑖
1165 |1000110001⟩: 0.1768+0.0000𝑖
1166 |1001010010⟩: 0.1768+0.0000𝑖
1167 |1001110011⟩: 0.1768+0.0000𝑖
1168 |1010010100⟩: 0.1768+0.0000𝑖
1169 |1010110101⟩: 0.1768+0.0000𝑖
1170 |1011010110⟩: 0.1768+0.0000𝑖
1171 |1011110111⟩: 0.1768+0.0000𝑖
1172 |1100011000⟩: 0.1768+0.0000𝑖
1173 |1100111001⟩: 0.1768+0.0000𝑖
1174 |1101011010⟩: 0.1768+0.0000𝑖
1175 |1101111011⟩: 0.1768+0.0000𝑖
1176 |1110011100⟩: 0.1768+0.0000𝑖
1177 |1110111101⟩: 0.1768+0.0000𝑖
1178 |1111011110⟩: 0.1768+0.0000𝑖
1179 |1111111111⟩: 0.0000−0.1768𝑖
1180 "#]]
1181 .assert_eq(&dump);
1182
1183 sim.sim.mcs(&[0, 1, 2, 3], 4);
1184 for i in 0..5 {
1185 sim.sim.mcx(&[i + 5], i);
1186 sim.sim.h(i + 5);
1187 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1188 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1189 }
1190}
1191
1192#[test]
1193fn test_base_mcsadj_4_control() {
1194 let mut sim = SparseSim::default();
1195 let dump = test_expression_with_lib_and_profile_and_sim(
1196 indoc! {"{
1197 let qs = QIR.Runtime.AllocateQubitArray(5);
1198 let aux = QIR.Runtime.AllocateQubitArray(5);
1199 for i in 0..4 {
1200 H(aux[i]);
1201 CNOT(aux[i], qs[i]);
1202 }
1203 Controlled Adjoint S(qs[0..3], qs[4]);
1204 Std.Diagnostics.DumpMachine();
1205 let result : Result[] = [];
1206 result
1207 }"},
1208 "",
1209 Profile::Base,
1210 &mut sim,
1211 &Value::Array(Vec::new().into()),
1212 );
1213 expect![[r#"
1214 STATE:
1215 |0000000000⟩: 0.1768+0.0000𝑖
1216 |0000100001⟩: 0.1768+0.0000𝑖
1217 |0001000010⟩: 0.1768+0.0000𝑖
1218 |0001100011⟩: 0.1768+0.0000𝑖
1219 |0010000100⟩: 0.1768+0.0000𝑖
1220 |0010100101⟩: 0.1768+0.0000𝑖
1221 |0011000110⟩: 0.1768+0.0000𝑖
1222 |0011100111⟩: 0.1768+0.0000𝑖
1223 |0100001000⟩: 0.1768+0.0000𝑖
1224 |0100101001⟩: 0.1768+0.0000𝑖
1225 |0101001010⟩: 0.1768+0.0000𝑖
1226 |0101101011⟩: 0.1768+0.0000𝑖
1227 |0110001100⟩: 0.1768+0.0000𝑖
1228 |0110101101⟩: 0.1768+0.0000𝑖
1229 |0111001110⟩: 0.1768+0.0000𝑖
1230 |0111101111⟩: 0.1768+0.0000𝑖
1231 |1000010000⟩: 0.1768+0.0000𝑖
1232 |1000110001⟩: 0.1768+0.0000𝑖
1233 |1001010010⟩: 0.1768+0.0000𝑖
1234 |1001110011⟩: 0.1768+0.0000𝑖
1235 |1010010100⟩: 0.1768+0.0000𝑖
1236 |1010110101⟩: 0.1768+0.0000𝑖
1237 |1011010110⟩: 0.1768+0.0000𝑖
1238 |1011110111⟩: 0.1768+0.0000𝑖
1239 |1100011000⟩: 0.1768+0.0000𝑖
1240 |1100111001⟩: 0.1768+0.0000𝑖
1241 |1101011010⟩: 0.1768+0.0000𝑖
1242 |1101111011⟩: 0.1768+0.0000𝑖
1243 |1110011100⟩: 0.1768+0.0000𝑖
1244 |1110111101⟩: 0.1768+0.0000𝑖
1245 |1111011110⟩: 0.1768+0.0000𝑖
1246 |1111111111⟩: 0.0000−0.1768𝑖
1247 "#]]
1248 .assert_eq(&dump);
1249
1250 sim.sim.mcs(&[0, 1, 2, 3], 4);
1251 for i in 0..5 {
1252 sim.sim.mcx(&[i + 5], i);
1253 sim.sim.h(i + 5);
1254 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1255 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1256 }
1257}
1258
1259#[test]
1260fn test_mcsx_0_control() {
1261 let mut sim = SparseSim::default();
1262 let dump = test_expression_with_lib_and_profile_and_sim(
1263 indoc! {"{
1264 let qs = QIR.Runtime.AllocateQubitArray(1);
1265 let aux = QIR.Runtime.AllocateQubitArray(1);
1266 H(aux[0]);
1267 CNOT(aux[0], qs[0]);
1268 Controlled SX([], qs[0]);
1269 Std.Diagnostics.DumpMachine();
1270 }"},
1271 "",
1272 Profile::Unrestricted,
1273 &mut sim,
1274 &Value::unit(),
1275 );
1276 expect![[r#"
1277 STATE:
1278 |00⟩: 0.3536+0.3536𝑖
1279 |01⟩: 0.3536−0.3536𝑖
1280 |10⟩: 0.3536−0.3536𝑖
1281 |11⟩: 0.3536+0.3536𝑖
1282 "#]]
1283 .assert_eq(&dump);
1284
1285 sim.sim.h(0);
1286 sim.sim.sadj(0);
1287 sim.sim.h(0);
1288 sim.sim.mcx(&[1], 0);
1289 sim.sim.h(1);
1290 assert!(sim.sim.qubit_is_zero(1), "qubit 1 is not zero");
1291 assert!(sim.sim.qubit_is_zero(0), "qubit 0 is not zero");
1292}
1293
1294#[test]
1295fn test_mcsx_1_control() {
1296 let mut sim = SparseSim::default();
1297 let dump = test_expression_with_lib_and_profile_and_sim(
1298 indoc! {"{
1299 let qs = QIR.Runtime.AllocateQubitArray(2);
1300 let aux = QIR.Runtime.AllocateQubitArray(2);
1301 for i in 0..1 {
1302 H(aux[i]);
1303 CNOT(aux[i], qs[i]);
1304 }
1305 Controlled SX(qs[0..0], qs[1]);
1306 Std.Diagnostics.DumpMachine();
1307 }"},
1308 "",
1309 Profile::Unrestricted,
1310 &mut sim,
1311 &Value::unit(),
1312 );
1313 expect![[r#"
1314 STATE:
1315 |0000⟩: 0.5000+0.0000𝑖
1316 |0101⟩: 0.5000+0.0000𝑖
1317 |1010⟩: 0.2500+0.2500𝑖
1318 |1011⟩: 0.2500−0.2500𝑖
1319 |1110⟩: 0.2500−0.2500𝑖
1320 |1111⟩: 0.2500+0.2500𝑖
1321 "#]]
1322 .assert_eq(&dump);
1323
1324 sim.sim.mch(&[0], 1);
1325 sim.sim.mcsadj(&[0], 1);
1326 sim.sim.mch(&[0], 1);
1327 for i in 0..2 {
1328 sim.sim.mcx(&[i + 2], i);
1329 sim.sim.h(i + 2);
1330 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
1331 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1332 }
1333}
1334
1335#[test]
1336fn test_mcsx_2_control() {
1337 let mut sim = SparseSim::default();
1338 let dump = test_expression_with_lib_and_profile_and_sim(
1339 indoc! {"{
1340 let qs = QIR.Runtime.AllocateQubitArray(3);
1341 let aux = QIR.Runtime.AllocateQubitArray(3);
1342 for i in 0..2 {
1343 H(aux[i]);
1344 CNOT(aux[i], qs[i]);
1345 }
1346 Controlled SX(qs[0..1], qs[2]);
1347 Std.Diagnostics.DumpMachine();
1348 }"},
1349 "",
1350 Profile::Unrestricted,
1351 &mut sim,
1352 &Value::unit(),
1353 );
1354 expect![[r#"
1355 STATE:
1356 |000000⟩: 0.3536+0.0000𝑖
1357 |001001⟩: 0.3536+0.0000𝑖
1358 |010010⟩: 0.3536+0.0000𝑖
1359 |011011⟩: 0.3536+0.0000𝑖
1360 |100100⟩: 0.3536+0.0000𝑖
1361 |101101⟩: 0.3536+0.0000𝑖
1362 |110110⟩: 0.1768+0.1768𝑖
1363 |110111⟩: 0.1768−0.1768𝑖
1364 |111110⟩: 0.1768−0.1768𝑖
1365 |111111⟩: 0.1768+0.1768𝑖
1366 "#]]
1367 .assert_eq(&dump);
1368
1369 sim.sim.mch(&[0, 1], 2);
1370 sim.sim.mcsadj(&[0, 1], 2);
1371 sim.sim.mch(&[0, 1], 2);
1372 for i in 0..3 {
1373 sim.sim.mcx(&[i + 3], i);
1374 sim.sim.h(i + 3);
1375 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
1376 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1377 }
1378}
1379
1380#[test]
1381fn test_unrestricted_mcsx_3_control() {
1382 let mut sim = SparseSim::default();
1383 let dump = test_expression_with_lib_and_profile_and_sim(
1384 indoc! {"{
1385 let qs = QIR.Runtime.AllocateQubitArray(4);
1386 let aux = QIR.Runtime.AllocateQubitArray(4);
1387 for i in 0..3 {
1388 H(aux[i]);
1389 CNOT(aux[i], qs[i]);
1390 }
1391 Controlled SX(qs[0..2], qs[3]);
1392 Std.Diagnostics.DumpMachine();
1393 }"},
1394 "",
1395 Profile::Unrestricted,
1396 &mut sim,
1397 &Value::unit(),
1398 );
1399 expect![[r#"
1400 STATE:
1401 |00000000⟩: 0.2500+0.0000𝑖
1402 |00010001⟩: 0.2500+0.0000𝑖
1403 |00100010⟩: 0.2500+0.0000𝑖
1404 |00110011⟩: 0.2500+0.0000𝑖
1405 |01000100⟩: 0.2500+0.0000𝑖
1406 |01010101⟩: 0.2500+0.0000𝑖
1407 |01100110⟩: 0.2500+0.0000𝑖
1408 |01110111⟩: 0.2500+0.0000𝑖
1409 |10001000⟩: 0.2500+0.0000𝑖
1410 |10011001⟩: 0.2500+0.0000𝑖
1411 |10101010⟩: 0.2500+0.0000𝑖
1412 |10111011⟩: 0.2500+0.0000𝑖
1413 |11001100⟩: 0.2500+0.0000𝑖
1414 |11011101⟩: 0.2500+0.0000𝑖
1415 |11101110⟩: 0.1250+0.1250𝑖
1416 |11101111⟩: 0.1250−0.1250𝑖
1417 |11111110⟩: 0.1250−0.1250𝑖
1418 |11111111⟩: 0.1250+0.1250𝑖
1419 "#]]
1420 .assert_eq(&dump);
1421
1422 sim.sim.mch(&[0, 1, 2], 3);
1423 sim.sim.mcsadj(&[0, 1, 2], 3);
1424 sim.sim.mch(&[0, 1, 2], 3);
1425 for i in 0..4 {
1426 sim.sim.mcx(&[i + 4], i);
1427 sim.sim.h(i + 4);
1428 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1429 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1430 }
1431}
1432
1433#[test]
1434fn test_base_mcsx_3_control() {
1435 let mut sim = SparseSim::default();
1436 let dump = test_expression_with_lib_and_profile_and_sim(
1437 indoc! {"{
1438 let qs = QIR.Runtime.AllocateQubitArray(4);
1439 let aux = QIR.Runtime.AllocateQubitArray(4);
1440 for i in 0..3 {
1441 H(aux[i]);
1442 CNOT(aux[i], qs[i]);
1443 }
1444 Controlled SX(qs[0..2], qs[3]);
1445 Std.Diagnostics.DumpMachine();
1446 let result : Result[] = [];
1447 result
1448 }"},
1449 "",
1450 Profile::Base,
1451 &mut sim,
1452 &Value::Array(Vec::new().into()),
1453 );
1454 expect![[r#"
1455 STATE:
1456 |00000000⟩: 0.2500+0.0000𝑖
1457 |00010001⟩: 0.2500+0.0000𝑖
1458 |00100010⟩: 0.2500+0.0000𝑖
1459 |00110011⟩: 0.2500+0.0000𝑖
1460 |01000100⟩: 0.2500+0.0000𝑖
1461 |01010101⟩: 0.2500+0.0000𝑖
1462 |01100110⟩: 0.2500+0.0000𝑖
1463 |01110111⟩: 0.2500+0.0000𝑖
1464 |10001000⟩: 0.2500+0.0000𝑖
1465 |10011001⟩: 0.2500+0.0000𝑖
1466 |10101010⟩: 0.2500+0.0000𝑖
1467 |10111011⟩: 0.2500+0.0000𝑖
1468 |11001100⟩: 0.2500+0.0000𝑖
1469 |11011101⟩: 0.2500+0.0000𝑖
1470 |11101110⟩: 0.1250+0.1250𝑖
1471 |11101111⟩: 0.1250−0.1250𝑖
1472 |11111110⟩: 0.1250−0.1250𝑖
1473 |11111111⟩: 0.1250+0.1250𝑖
1474 "#]]
1475 .assert_eq(&dump);
1476
1477 sim.sim.mch(&[0, 1, 2], 3);
1478 sim.sim.mcsadj(&[0, 1, 2], 3);
1479 sim.sim.mch(&[0, 1, 2], 3);
1480 for i in 0..4 {
1481 sim.sim.mcx(&[i + 4], i);
1482 sim.sim.h(i + 4);
1483 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1484 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1485 }
1486}
1487
1488#[test]
1489fn test_unrestricted_mcsx_4_control() {
1490 let mut sim = SparseSim::default();
1491 let dump = test_expression_with_lib_and_profile_and_sim(
1492 indoc! {"{
1493 let qs = QIR.Runtime.AllocateQubitArray(5);
1494 let aux = QIR.Runtime.AllocateQubitArray(5);
1495 for i in 0..4 {
1496 H(aux[i]);
1497 CNOT(aux[i], qs[i]);
1498 }
1499 Controlled SX(qs[0..3], qs[4]);
1500 Std.Diagnostics.DumpMachine();
1501 }"},
1502 "",
1503 Profile::Unrestricted,
1504 &mut sim,
1505 &Value::unit(),
1506 );
1507 expect![[r#"
1508 STATE:
1509 |0000000000⟩: 0.1768+0.0000𝑖
1510 |0000100001⟩: 0.1768+0.0000𝑖
1511 |0001000010⟩: 0.1768+0.0000𝑖
1512 |0001100011⟩: 0.1768+0.0000𝑖
1513 |0010000100⟩: 0.1768+0.0000𝑖
1514 |0010100101⟩: 0.1768+0.0000𝑖
1515 |0011000110⟩: 0.1768+0.0000𝑖
1516 |0011100111⟩: 0.1768+0.0000𝑖
1517 |0100001000⟩: 0.1768+0.0000𝑖
1518 |0100101001⟩: 0.1768+0.0000𝑖
1519 |0101001010⟩: 0.1768+0.0000𝑖
1520 |0101101011⟩: 0.1768+0.0000𝑖
1521 |0110001100⟩: 0.1768+0.0000𝑖
1522 |0110101101⟩: 0.1768+0.0000𝑖
1523 |0111001110⟩: 0.1768+0.0000𝑖
1524 |0111101111⟩: 0.1768+0.0000𝑖
1525 |1000010000⟩: 0.1768+0.0000𝑖
1526 |1000110001⟩: 0.1768+0.0000𝑖
1527 |1001010010⟩: 0.1768+0.0000𝑖
1528 |1001110011⟩: 0.1768+0.0000𝑖
1529 |1010010100⟩: 0.1768+0.0000𝑖
1530 |1010110101⟩: 0.1768+0.0000𝑖
1531 |1011010110⟩: 0.1768+0.0000𝑖
1532 |1011110111⟩: 0.1768+0.0000𝑖
1533 |1100011000⟩: 0.1768+0.0000𝑖
1534 |1100111001⟩: 0.1768+0.0000𝑖
1535 |1101011010⟩: 0.1768+0.0000𝑖
1536 |1101111011⟩: 0.1768+0.0000𝑖
1537 |1110011100⟩: 0.1768+0.0000𝑖
1538 |1110111101⟩: 0.1768+0.0000𝑖
1539 |1111011110⟩: 0.0884+0.0884𝑖
1540 |1111011111⟩: 0.0884−0.0884𝑖
1541 |1111111110⟩: 0.0884−0.0884𝑖
1542 |1111111111⟩: 0.0884+0.0884𝑖
1543 "#]]
1544 .assert_eq(&dump);
1545
1546 sim.sim.mch(&[0, 1, 2, 3], 4);
1547 sim.sim.mcsadj(&[0, 1, 2, 3], 4);
1548 sim.sim.mch(&[0, 1, 2, 3], 4);
1549 for i in 0..5 {
1550 sim.sim.mcx(&[i + 5], i);
1551 sim.sim.h(i + 5);
1552 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1553 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1554 }
1555}
1556
1557#[test]
1558fn test_base_mcsx_4_control() {
1559 let mut sim = SparseSim::default();
1560 let dump = test_expression_with_lib_and_profile_and_sim(
1561 indoc! {"{
1562 let qs = QIR.Runtime.AllocateQubitArray(5);
1563 let aux = QIR.Runtime.AllocateQubitArray(5);
1564 for i in 0..4 {
1565 H(aux[i]);
1566 CNOT(aux[i], qs[i]);
1567 }
1568 Controlled SX(qs[0..3], qs[4]);
1569 Std.Diagnostics.DumpMachine();
1570 let result : Result[] = [];
1571 result
1572 }"},
1573 "",
1574 Profile::Base,
1575 &mut sim,
1576 &Value::Array(Vec::new().into()),
1577 );
1578 expect![[r#"
1579 STATE:
1580 |0000000000⟩: 0.1768+0.0000𝑖
1581 |0000100001⟩: 0.1768+0.0000𝑖
1582 |0001000010⟩: 0.1768+0.0000𝑖
1583 |0001100011⟩: 0.1768+0.0000𝑖
1584 |0010000100⟩: 0.1768+0.0000𝑖
1585 |0010100101⟩: 0.1768+0.0000𝑖
1586 |0011000110⟩: 0.1768+0.0000𝑖
1587 |0011100111⟩: 0.1768+0.0000𝑖
1588 |0100001000⟩: 0.1768+0.0000𝑖
1589 |0100101001⟩: 0.1768+0.0000𝑖
1590 |0101001010⟩: 0.1768+0.0000𝑖
1591 |0101101011⟩: 0.1768+0.0000𝑖
1592 |0110001100⟩: 0.1768+0.0000𝑖
1593 |0110101101⟩: 0.1768+0.0000𝑖
1594 |0111001110⟩: 0.1768+0.0000𝑖
1595 |0111101111⟩: 0.1768+0.0000𝑖
1596 |1000010000⟩: 0.1768+0.0000𝑖
1597 |1000110001⟩: 0.1768+0.0000𝑖
1598 |1001010010⟩: 0.1768+0.0000𝑖
1599 |1001110011⟩: 0.1768+0.0000𝑖
1600 |1010010100⟩: 0.1768+0.0000𝑖
1601 |1010110101⟩: 0.1768+0.0000𝑖
1602 |1011010110⟩: 0.1768+0.0000𝑖
1603 |1011110111⟩: 0.1768+0.0000𝑖
1604 |1100011000⟩: 0.1768+0.0000𝑖
1605 |1100111001⟩: 0.1768+0.0000𝑖
1606 |1101011010⟩: 0.1768+0.0000𝑖
1607 |1101111011⟩: 0.1768+0.0000𝑖
1608 |1110011100⟩: 0.1768+0.0000𝑖
1609 |1110111101⟩: 0.1768+0.0000𝑖
1610 |1111011110⟩: 0.0884+0.0884𝑖
1611 |1111011111⟩: 0.0884−0.0884𝑖
1612 |1111111110⟩: 0.0884−0.0884𝑖
1613 |1111111111⟩: 0.0884+0.0884𝑖
1614 "#]]
1615 .assert_eq(&dump);
1616
1617 sim.sim.mch(&[0, 1, 2, 3], 4);
1618 sim.sim.mcsadj(&[0, 1, 2, 3], 4);
1619 sim.sim.mch(&[0, 1, 2, 3], 4);
1620 for i in 0..5 {
1621 sim.sim.mcx(&[i + 5], i);
1622 sim.sim.h(i + 5);
1623 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1624 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1625 }
1626}
1627
1628#[test]
1629fn test_mcsxadj_0_control() {
1630 let mut sim = SparseSim::default();
1631 let dump = test_expression_with_lib_and_profile_and_sim(
1632 indoc! {"{
1633 let qs = QIR.Runtime.AllocateQubitArray(1);
1634 let aux = QIR.Runtime.AllocateQubitArray(1);
1635 H(aux[0]);
1636 CNOT(aux[0], qs[0]);
1637 Adjoint Controlled SX([], qs[0]);
1638 Std.Diagnostics.DumpMachine();
1639 }"},
1640 "",
1641 Profile::Unrestricted,
1642 &mut sim,
1643 &Value::unit(),
1644 );
1645 expect![[r#"
1646 STATE:
1647 |00⟩: 0.3536−0.3536𝑖
1648 |01⟩: 0.3536+0.3536𝑖
1649 |10⟩: 0.3536+0.3536𝑖
1650 |11⟩: 0.3536−0.3536𝑖
1651 "#]]
1652 .assert_eq(&dump);
1653
1654 sim.sim.h(0);
1655 sim.sim.s(0);
1656 sim.sim.h(0);
1657 sim.sim.mcx(&[1], 0);
1658 sim.sim.h(1);
1659 assert!(sim.sim.qubit_is_zero(1), "qubit 1 is not zero");
1660 assert!(sim.sim.qubit_is_zero(0), "qubit 0 is not zero");
1661}
1662
1663#[test]
1664fn test_mcsxadj_1_control() {
1665 let mut sim = SparseSim::default();
1666 let dump = test_expression_with_lib_and_profile_and_sim(
1667 indoc! {"{
1668 let qs = QIR.Runtime.AllocateQubitArray(2);
1669 let aux = QIR.Runtime.AllocateQubitArray(2);
1670 for i in 0..1 {
1671 H(aux[i]);
1672 CNOT(aux[i], qs[i]);
1673 }
1674 Controlled Adjoint SX(qs[0..0], qs[1]);
1675 Std.Diagnostics.DumpMachine();
1676 }"},
1677 "",
1678 Profile::Unrestricted,
1679 &mut sim,
1680 &Value::unit(),
1681 );
1682 expect![[r#"
1683 STATE:
1684 |0000⟩: 0.5000+0.0000𝑖
1685 |0101⟩: 0.5000+0.0000𝑖
1686 |1010⟩: 0.2500−0.2500𝑖
1687 |1011⟩: 0.2500+0.2500𝑖
1688 |1110⟩: 0.2500+0.2500𝑖
1689 |1111⟩: 0.2500−0.2500𝑖
1690 "#]]
1691 .assert_eq(&dump);
1692
1693 sim.sim.mch(&[0], 1);
1694 sim.sim.mcs(&[0], 1);
1695 sim.sim.mch(&[0], 1);
1696 for i in 0..2 {
1697 sim.sim.mcx(&[i + 2], i);
1698 sim.sim.h(i + 2);
1699 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
1700 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1701 }
1702}
1703
1704#[test]
1705fn test_mcsxadj_2_control() {
1706 let mut sim = SparseSim::default();
1707 let dump = test_expression_with_lib_and_profile_and_sim(
1708 indoc! {"{
1709 let qs = QIR.Runtime.AllocateQubitArray(3);
1710 let aux = QIR.Runtime.AllocateQubitArray(3);
1711 for i in 0..2 {
1712 H(aux[i]);
1713 CNOT(aux[i], qs[i]);
1714 }
1715 Controlled Adjoint SX(qs[0..1], qs[2]);
1716 Std.Diagnostics.DumpMachine();
1717 }"},
1718 "",
1719 Profile::Unrestricted,
1720 &mut sim,
1721 &Value::unit(),
1722 );
1723 expect![[r#"
1724 STATE:
1725 |000000⟩: 0.3536+0.0000𝑖
1726 |001001⟩: 0.3536+0.0000𝑖
1727 |010010⟩: 0.3536+0.0000𝑖
1728 |011011⟩: 0.3536+0.0000𝑖
1729 |100100⟩: 0.3536+0.0000𝑖
1730 |101101⟩: 0.3536+0.0000𝑖
1731 |110110⟩: 0.1768−0.1768𝑖
1732 |110111⟩: 0.1768+0.1768𝑖
1733 |111110⟩: 0.1768+0.1768𝑖
1734 |111111⟩: 0.1768−0.1768𝑖
1735 "#]]
1736 .assert_eq(&dump);
1737
1738 sim.sim.mch(&[0, 1], 2);
1739 sim.sim.mcs(&[0, 1], 2);
1740 sim.sim.mch(&[0, 1], 2);
1741 for i in 0..3 {
1742 sim.sim.mcx(&[i + 3], i);
1743 sim.sim.h(i + 3);
1744 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
1745 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1746 }
1747}
1748
1749#[test]
1750fn test_unrestricted_mcsxadj_3_control() {
1751 let mut sim = SparseSim::default();
1752 let dump = test_expression_with_lib_and_profile_and_sim(
1753 indoc! {"{
1754 let qs = QIR.Runtime.AllocateQubitArray(4);
1755 let aux = QIR.Runtime.AllocateQubitArray(4);
1756 for i in 0..3 {
1757 H(aux[i]);
1758 CNOT(aux[i], qs[i]);
1759 }
1760 Controlled Adjoint SX(qs[0..2], qs[3]);
1761 Std.Diagnostics.DumpMachine();
1762 }"},
1763 "",
1764 Profile::Unrestricted,
1765 &mut sim,
1766 &Value::unit(),
1767 );
1768 expect![[r#"
1769 STATE:
1770 |00000000⟩: 0.2500+0.0000𝑖
1771 |00010001⟩: 0.2500+0.0000𝑖
1772 |00100010⟩: 0.2500+0.0000𝑖
1773 |00110011⟩: 0.2500+0.0000𝑖
1774 |01000100⟩: 0.2500+0.0000𝑖
1775 |01010101⟩: 0.2500+0.0000𝑖
1776 |01100110⟩: 0.2500+0.0000𝑖
1777 |01110111⟩: 0.2500+0.0000𝑖
1778 |10001000⟩: 0.2500+0.0000𝑖
1779 |10011001⟩: 0.2500+0.0000𝑖
1780 |10101010⟩: 0.2500+0.0000𝑖
1781 |10111011⟩: 0.2500+0.0000𝑖
1782 |11001100⟩: 0.2500+0.0000𝑖
1783 |11011101⟩: 0.2500+0.0000𝑖
1784 |11101110⟩: 0.1250−0.1250𝑖
1785 |11101111⟩: 0.1250+0.1250𝑖
1786 |11111110⟩: 0.1250+0.1250𝑖
1787 |11111111⟩: 0.1250−0.1250𝑖
1788 "#]]
1789 .assert_eq(&dump);
1790
1791 sim.sim.mch(&[0, 1, 2], 3);
1792 sim.sim.mcs(&[0, 1, 2], 3);
1793 sim.sim.mch(&[0, 1, 2], 3);
1794 for i in 0..4 {
1795 sim.sim.mcx(&[i + 4], i);
1796 sim.sim.h(i + 4);
1797 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1798 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1799 }
1800}
1801
1802#[test]
1803fn test_base_mcsxadj_3_control() {
1804 let mut sim = SparseSim::default();
1805 let dump = test_expression_with_lib_and_profile_and_sim(
1806 indoc! {"{
1807 let qs = QIR.Runtime.AllocateQubitArray(4);
1808 let aux = QIR.Runtime.AllocateQubitArray(4);
1809 for i in 0..3 {
1810 H(aux[i]);
1811 CNOT(aux[i], qs[i]);
1812 }
1813 Controlled Adjoint SX(qs[0..2], qs[3]);
1814 Std.Diagnostics.DumpMachine();
1815 let result : Result[] = [];
1816 result
1817 }"},
1818 "",
1819 Profile::Base,
1820 &mut sim,
1821 &Value::Array(Vec::new().into()),
1822 );
1823 expect![[r#"
1824 STATE:
1825 |00000000⟩: 0.2500+0.0000𝑖
1826 |00010001⟩: 0.2500+0.0000𝑖
1827 |00100010⟩: 0.2500+0.0000𝑖
1828 |00110011⟩: 0.2500+0.0000𝑖
1829 |01000100⟩: 0.2500+0.0000𝑖
1830 |01010101⟩: 0.2500+0.0000𝑖
1831 |01100110⟩: 0.2500+0.0000𝑖
1832 |01110111⟩: 0.2500+0.0000𝑖
1833 |10001000⟩: 0.2500+0.0000𝑖
1834 |10011001⟩: 0.2500+0.0000𝑖
1835 |10101010⟩: 0.2500+0.0000𝑖
1836 |10111011⟩: 0.2500+0.0000𝑖
1837 |11001100⟩: 0.2500+0.0000𝑖
1838 |11011101⟩: 0.2500+0.0000𝑖
1839 |11101110⟩: 0.1250−0.1250𝑖
1840 |11101111⟩: 0.1250+0.1250𝑖
1841 |11111110⟩: 0.1250+0.1250𝑖
1842 |11111111⟩: 0.1250−0.1250𝑖
1843 "#]]
1844 .assert_eq(&dump);
1845
1846 sim.sim.mch(&[0, 1, 2], 3);
1847 sim.sim.mcs(&[0, 1, 2], 3);
1848 sim.sim.mch(&[0, 1, 2], 3);
1849 for i in 0..4 {
1850 sim.sim.mcx(&[i + 4], i);
1851 sim.sim.h(i + 4);
1852 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
1853 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1854 }
1855}
1856
1857#[test]
1858fn test_unrestricted_mcsxadj_4_control() {
1859 let mut sim = SparseSim::default();
1860 let dump = test_expression_with_lib_and_profile_and_sim(
1861 indoc! {"{
1862 let qs = QIR.Runtime.AllocateQubitArray(5);
1863 let aux = QIR.Runtime.AllocateQubitArray(5);
1864 for i in 0..4 {
1865 H(aux[i]);
1866 CNOT(aux[i], qs[i]);
1867 }
1868 Controlled Adjoint SX(qs[0..3], qs[4]);
1869 Std.Diagnostics.DumpMachine();
1870 }"},
1871 "",
1872 Profile::Unrestricted,
1873 &mut sim,
1874 &Value::unit(),
1875 );
1876 expect![[r#"
1877 STATE:
1878 |0000000000⟩: 0.1768+0.0000𝑖
1879 |0000100001⟩: 0.1768+0.0000𝑖
1880 |0001000010⟩: 0.1768+0.0000𝑖
1881 |0001100011⟩: 0.1768+0.0000𝑖
1882 |0010000100⟩: 0.1768+0.0000𝑖
1883 |0010100101⟩: 0.1768+0.0000𝑖
1884 |0011000110⟩: 0.1768+0.0000𝑖
1885 |0011100111⟩: 0.1768+0.0000𝑖
1886 |0100001000⟩: 0.1768+0.0000𝑖
1887 |0100101001⟩: 0.1768+0.0000𝑖
1888 |0101001010⟩: 0.1768+0.0000𝑖
1889 |0101101011⟩: 0.1768+0.0000𝑖
1890 |0110001100⟩: 0.1768+0.0000𝑖
1891 |0110101101⟩: 0.1768+0.0000𝑖
1892 |0111001110⟩: 0.1768+0.0000𝑖
1893 |0111101111⟩: 0.1768+0.0000𝑖
1894 |1000010000⟩: 0.1768+0.0000𝑖
1895 |1000110001⟩: 0.1768+0.0000𝑖
1896 |1001010010⟩: 0.1768+0.0000𝑖
1897 |1001110011⟩: 0.1768+0.0000𝑖
1898 |1010010100⟩: 0.1768+0.0000𝑖
1899 |1010110101⟩: 0.1768+0.0000𝑖
1900 |1011010110⟩: 0.1768+0.0000𝑖
1901 |1011110111⟩: 0.1768+0.0000𝑖
1902 |1100011000⟩: 0.1768+0.0000𝑖
1903 |1100111001⟩: 0.1768+0.0000𝑖
1904 |1101011010⟩: 0.1768+0.0000𝑖
1905 |1101111011⟩: 0.1768+0.0000𝑖
1906 |1110011100⟩: 0.1768+0.0000𝑖
1907 |1110111101⟩: 0.1768+0.0000𝑖
1908 |1111011110⟩: 0.0884−0.0884𝑖
1909 |1111011111⟩: 0.0884+0.0884𝑖
1910 |1111111110⟩: 0.0884+0.0884𝑖
1911 |1111111111⟩: 0.0884−0.0884𝑖
1912 "#]]
1913 .assert_eq(&dump);
1914
1915 sim.sim.mch(&[0, 1, 2, 3], 4);
1916 sim.sim.mcs(&[0, 1, 2, 3], 4);
1917 sim.sim.mch(&[0, 1, 2, 3], 4);
1918 for i in 0..5 {
1919 sim.sim.mcx(&[i + 5], i);
1920 sim.sim.h(i + 5);
1921 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1922 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1923 }
1924}
1925
1926#[test]
1927fn test_base_mcsxadj_4_control() {
1928 let mut sim = SparseSim::default();
1929 let dump = test_expression_with_lib_and_profile_and_sim(
1930 indoc! {"{
1931 let qs = QIR.Runtime.AllocateQubitArray(5);
1932 let aux = QIR.Runtime.AllocateQubitArray(5);
1933 for i in 0..4 {
1934 H(aux[i]);
1935 CNOT(aux[i], qs[i]);
1936 }
1937 Controlled Adjoint SX(qs[0..3], qs[4]);
1938 Std.Diagnostics.DumpMachine();
1939 let result : Result[] = [];
1940 result
1941 }"},
1942 "",
1943 Profile::Base,
1944 &mut sim,
1945 &Value::Array(Vec::new().into()),
1946 );
1947 expect![[r#"
1948 STATE:
1949 |0000000000⟩: 0.1768+0.0000𝑖
1950 |0000100001⟩: 0.1768+0.0000𝑖
1951 |0001000010⟩: 0.1768+0.0000𝑖
1952 |0001100011⟩: 0.1768+0.0000𝑖
1953 |0010000100⟩: 0.1768+0.0000𝑖
1954 |0010100101⟩: 0.1768+0.0000𝑖
1955 |0011000110⟩: 0.1768+0.0000𝑖
1956 |0011100111⟩: 0.1768+0.0000𝑖
1957 |0100001000⟩: 0.1768+0.0000𝑖
1958 |0100101001⟩: 0.1768+0.0000𝑖
1959 |0101001010⟩: 0.1768+0.0000𝑖
1960 |0101101011⟩: 0.1768+0.0000𝑖
1961 |0110001100⟩: 0.1768+0.0000𝑖
1962 |0110101101⟩: 0.1768+0.0000𝑖
1963 |0111001110⟩: 0.1768+0.0000𝑖
1964 |0111101111⟩: 0.1768+0.0000𝑖
1965 |1000010000⟩: 0.1768+0.0000𝑖
1966 |1000110001⟩: 0.1768+0.0000𝑖
1967 |1001010010⟩: 0.1768+0.0000𝑖
1968 |1001110011⟩: 0.1768+0.0000𝑖
1969 |1010010100⟩: 0.1768+0.0000𝑖
1970 |1010110101⟩: 0.1768+0.0000𝑖
1971 |1011010110⟩: 0.1768+0.0000𝑖
1972 |1011110111⟩: 0.1768+0.0000𝑖
1973 |1100011000⟩: 0.1768+0.0000𝑖
1974 |1100111001⟩: 0.1768+0.0000𝑖
1975 |1101011010⟩: 0.1768+0.0000𝑖
1976 |1101111011⟩: 0.1768+0.0000𝑖
1977 |1110011100⟩: 0.1768+0.0000𝑖
1978 |1110111101⟩: 0.1768+0.0000𝑖
1979 |1111011110⟩: 0.0884−0.0884𝑖
1980 |1111011111⟩: 0.0884+0.0884𝑖
1981 |1111111110⟩: 0.0884+0.0884𝑖
1982 |1111111111⟩: 0.0884−0.0884𝑖
1983 "#]]
1984 .assert_eq(&dump);
1985
1986 sim.sim.mch(&[0, 1, 2, 3], 4);
1987 sim.sim.mcs(&[0, 1, 2, 3], 4);
1988 sim.sim.mch(&[0, 1, 2, 3], 4);
1989 for i in 0..5 {
1990 sim.sim.mcx(&[i + 5], i);
1991 sim.sim.h(i + 5);
1992 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
1993 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
1994 }
1995}
1996
1997#[test]
1998fn test_mct_1_control() {
1999 let mut sim = SparseSim::default();
2000 let dump = test_expression_with_lib_and_profile_and_sim(
2001 indoc! {"{
2002 let qs = QIR.Runtime.AllocateQubitArray(2);
2003 let aux = QIR.Runtime.AllocateQubitArray(2);
2004 for i in 0..1 {
2005 H(aux[i]);
2006 CNOT(aux[i], qs[i]);
2007 }
2008 Controlled T(qs[0..0], qs[1]);
2009 Std.Diagnostics.DumpMachine();
2010 }"},
2011 "",
2012 Profile::Unrestricted,
2013 &mut sim,
2014 &Value::unit(),
2015 );
2016 expect![[r#"
2017 STATE:
2018 |0000⟩: 0.5000+0.0000𝑖
2019 |0101⟩: 0.5000+0.0000𝑖
2020 |1010⟩: 0.5000+0.0000𝑖
2021 |1111⟩: 0.3536+0.3536𝑖
2022 "#]]
2023 .assert_eq(&dump);
2024
2025 sim.sim.mctadj(&[0], 1);
2026 for i in 0..2 {
2027 sim.sim.mcx(&[i + 2], i);
2028 sim.sim.h(i + 2);
2029 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
2030 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2031 }
2032}
2033
2034#[test]
2035fn test_mct_2_control() {
2036 let mut sim = SparseSim::default();
2037 let dump = test_expression_with_lib_and_profile_and_sim(
2038 indoc! {"{
2039 let qs = QIR.Runtime.AllocateQubitArray(3);
2040 let aux = QIR.Runtime.AllocateQubitArray(3);
2041 for i in 0..2 {
2042 H(aux[i]);
2043 CNOT(aux[i], qs[i]);
2044 }
2045 Controlled T(qs[0..1], qs[2]);
2046 Std.Diagnostics.DumpMachine();
2047 }"},
2048 "",
2049 Profile::Unrestricted,
2050 &mut sim,
2051 &Value::unit(),
2052 );
2053 expect![[r#"
2054 STATE:
2055 |000000⟩: 0.3536+0.0000𝑖
2056 |001001⟩: 0.3536+0.0000𝑖
2057 |010010⟩: 0.3536+0.0000𝑖
2058 |011011⟩: 0.3536+0.0000𝑖
2059 |100100⟩: 0.3536+0.0000𝑖
2060 |101101⟩: 0.3536+0.0000𝑖
2061 |110110⟩: 0.3536+0.0000𝑖
2062 |111111⟩: 0.2500+0.2500𝑖
2063 "#]]
2064 .assert_eq(&dump);
2065
2066 sim.sim.mctadj(&[0, 1], 2);
2067 for i in 0..3 {
2068 sim.sim.mcx(&[i + 3], i);
2069 sim.sim.h(i + 3);
2070 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
2071 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2072 }
2073}
2074
2075#[test]
2076fn test_unrestricted_mct_3_control() {
2077 let mut sim = SparseSim::default();
2078 let dump = test_expression_with_lib_and_profile_and_sim(
2079 indoc! {"{
2080 let qs = QIR.Runtime.AllocateQubitArray(4);
2081 let aux = QIR.Runtime.AllocateQubitArray(4);
2082 for i in 0..3 {
2083 H(aux[i]);
2084 CNOT(aux[i], qs[i]);
2085 }
2086 Controlled T(qs[0..2], qs[3]);
2087 Std.Diagnostics.DumpMachine();
2088 }"},
2089 "",
2090 Profile::Unrestricted,
2091 &mut sim,
2092 &Value::unit(),
2093 );
2094 expect![[r#"
2095 STATE:
2096 |00000000⟩: 0.2500+0.0000𝑖
2097 |00010001⟩: 0.2500+0.0000𝑖
2098 |00100010⟩: 0.2500+0.0000𝑖
2099 |00110011⟩: 0.2500+0.0000𝑖
2100 |01000100⟩: 0.2500+0.0000𝑖
2101 |01010101⟩: 0.2500+0.0000𝑖
2102 |01100110⟩: 0.2500+0.0000𝑖
2103 |01110111⟩: 0.2500+0.0000𝑖
2104 |10001000⟩: 0.2500+0.0000𝑖
2105 |10011001⟩: 0.2500+0.0000𝑖
2106 |10101010⟩: 0.2500+0.0000𝑖
2107 |10111011⟩: 0.2500+0.0000𝑖
2108 |11001100⟩: 0.2500+0.0000𝑖
2109 |11011101⟩: 0.2500+0.0000𝑖
2110 |11101110⟩: 0.2500+0.0000𝑖
2111 |11111111⟩: 0.1768+0.1768𝑖
2112 "#]]
2113 .assert_eq(&dump);
2114
2115 sim.sim.mctadj(&[0, 1, 2], 3);
2116 for i in 0..4 {
2117 sim.sim.mcx(&[i + 4], i);
2118 sim.sim.h(i + 4);
2119 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2120 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2121 }
2122}
2123
2124#[test]
2125fn test_base_mct_3_control() {
2126 let mut sim = SparseSim::default();
2127 let dump = test_expression_with_lib_and_profile_and_sim(
2128 indoc! {"{
2129 let qs = QIR.Runtime.AllocateQubitArray(4);
2130 let aux = QIR.Runtime.AllocateQubitArray(4);
2131 for i in 0..3 {
2132 H(aux[i]);
2133 CNOT(aux[i], qs[i]);
2134 }
2135 Controlled T(qs[0..2], qs[3]);
2136 Std.Diagnostics.DumpMachine();
2137 let result : Result[] = [];
2138 result
2139 }"},
2140 "",
2141 Profile::Base,
2142 &mut sim,
2143 &Value::Array(Vec::new().into()),
2144 );
2145 expect![[r#"
2146 STATE:
2147 |00000000⟩: 0.2500+0.0000𝑖
2148 |00010001⟩: 0.2500+0.0000𝑖
2149 |00100010⟩: 0.2500+0.0000𝑖
2150 |00110011⟩: 0.2500+0.0000𝑖
2151 |01000100⟩: 0.2500+0.0000𝑖
2152 |01010101⟩: 0.2500+0.0000𝑖
2153 |01100110⟩: 0.2500+0.0000𝑖
2154 |01110111⟩: 0.2500+0.0000𝑖
2155 |10001000⟩: 0.2500+0.0000𝑖
2156 |10011001⟩: 0.2500+0.0000𝑖
2157 |10101010⟩: 0.2500+0.0000𝑖
2158 |10111011⟩: 0.2500+0.0000𝑖
2159 |11001100⟩: 0.2500+0.0000𝑖
2160 |11011101⟩: 0.2500+0.0000𝑖
2161 |11101110⟩: 0.2500+0.0000𝑖
2162 |11111111⟩: 0.1768+0.1768𝑖
2163 "#]]
2164 .assert_eq(&dump);
2165
2166 sim.sim.mctadj(&[0, 1, 2], 3);
2167 for i in 0..4 {
2168 sim.sim.mcx(&[i + 4], i);
2169 sim.sim.h(i + 4);
2170 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2171 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2172 }
2173}
2174
2175#[test]
2176fn test_unrestricted_mct_4_control() {
2177 let mut sim = SparseSim::default();
2178 let dump = test_expression_with_lib_and_profile_and_sim(
2179 indoc! {"{
2180 let qs = QIR.Runtime.AllocateQubitArray(5);
2181 let aux = QIR.Runtime.AllocateQubitArray(5);
2182 for i in 0..4 {
2183 H(aux[i]);
2184 CNOT(aux[i], qs[i]);
2185 }
2186 Controlled T(qs[0..3], qs[4]);
2187 Std.Diagnostics.DumpMachine();
2188 }"},
2189 "",
2190 Profile::Unrestricted,
2191 &mut sim,
2192 &Value::unit(),
2193 );
2194 expect![[r#"
2195 STATE:
2196 |0000000000⟩: 0.1768+0.0000𝑖
2197 |0000100001⟩: 0.1768+0.0000𝑖
2198 |0001000010⟩: 0.1768+0.0000𝑖
2199 |0001100011⟩: 0.1768+0.0000𝑖
2200 |0010000100⟩: 0.1768+0.0000𝑖
2201 |0010100101⟩: 0.1768+0.0000𝑖
2202 |0011000110⟩: 0.1768+0.0000𝑖
2203 |0011100111⟩: 0.1768+0.0000𝑖
2204 |0100001000⟩: 0.1768+0.0000𝑖
2205 |0100101001⟩: 0.1768+0.0000𝑖
2206 |0101001010⟩: 0.1768+0.0000𝑖
2207 |0101101011⟩: 0.1768+0.0000𝑖
2208 |0110001100⟩: 0.1768+0.0000𝑖
2209 |0110101101⟩: 0.1768+0.0000𝑖
2210 |0111001110⟩: 0.1768+0.0000𝑖
2211 |0111101111⟩: 0.1768+0.0000𝑖
2212 |1000010000⟩: 0.1768+0.0000𝑖
2213 |1000110001⟩: 0.1768+0.0000𝑖
2214 |1001010010⟩: 0.1768+0.0000𝑖
2215 |1001110011⟩: 0.1768+0.0000𝑖
2216 |1010010100⟩: 0.1768+0.0000𝑖
2217 |1010110101⟩: 0.1768+0.0000𝑖
2218 |1011010110⟩: 0.1768+0.0000𝑖
2219 |1011110111⟩: 0.1768+0.0000𝑖
2220 |1100011000⟩: 0.1768+0.0000𝑖
2221 |1100111001⟩: 0.1768+0.0000𝑖
2222 |1101011010⟩: 0.1768+0.0000𝑖
2223 |1101111011⟩: 0.1768+0.0000𝑖
2224 |1110011100⟩: 0.1768+0.0000𝑖
2225 |1110111101⟩: 0.1768+0.0000𝑖
2226 |1111011110⟩: 0.1768+0.0000𝑖
2227 |1111111111⟩: 0.1250+0.1250𝑖
2228 "#]]
2229 .assert_eq(&dump);
2230
2231 sim.sim.mctadj(&[0, 1, 2, 3], 4);
2232 for i in 0..5 {
2233 sim.sim.mcx(&[i + 5], i);
2234 sim.sim.h(i + 5);
2235 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2236 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2237 }
2238}
2239
2240#[test]
2241fn test_base_mct_4_control() {
2242 let mut sim = SparseSim::default();
2243 let dump = test_expression_with_lib_and_profile_and_sim(
2244 indoc! {"{
2245 let qs = QIR.Runtime.AllocateQubitArray(5);
2246 let aux = QIR.Runtime.AllocateQubitArray(5);
2247 for i in 0..4 {
2248 H(aux[i]);
2249 CNOT(aux[i], qs[i]);
2250 }
2251 Controlled T(qs[0..3], qs[4]);
2252 Std.Diagnostics.DumpMachine();
2253 let result : Result[] = [];
2254 result
2255 }"},
2256 "",
2257 Profile::Base,
2258 &mut sim,
2259 &Value::Array(Vec::new().into()),
2260 );
2261 expect![[r#"
2262 STATE:
2263 |0000000000⟩: 0.1768+0.0000𝑖
2264 |0000100001⟩: 0.1768+0.0000𝑖
2265 |0001000010⟩: 0.1768+0.0000𝑖
2266 |0001100011⟩: 0.1768+0.0000𝑖
2267 |0010000100⟩: 0.1768+0.0000𝑖
2268 |0010100101⟩: 0.1768+0.0000𝑖
2269 |0011000110⟩: 0.1768+0.0000𝑖
2270 |0011100111⟩: 0.1768+0.0000𝑖
2271 |0100001000⟩: 0.1768+0.0000𝑖
2272 |0100101001⟩: 0.1768+0.0000𝑖
2273 |0101001010⟩: 0.1768+0.0000𝑖
2274 |0101101011⟩: 0.1768+0.0000𝑖
2275 |0110001100⟩: 0.1768+0.0000𝑖
2276 |0110101101⟩: 0.1768+0.0000𝑖
2277 |0111001110⟩: 0.1768+0.0000𝑖
2278 |0111101111⟩: 0.1768+0.0000𝑖
2279 |1000010000⟩: 0.1768+0.0000𝑖
2280 |1000110001⟩: 0.1768+0.0000𝑖
2281 |1001010010⟩: 0.1768+0.0000𝑖
2282 |1001110011⟩: 0.1768+0.0000𝑖
2283 |1010010100⟩: 0.1768+0.0000𝑖
2284 |1010110101⟩: 0.1768+0.0000𝑖
2285 |1011010110⟩: 0.1768+0.0000𝑖
2286 |1011110111⟩: 0.1768+0.0000𝑖
2287 |1100011000⟩: 0.1768+0.0000𝑖
2288 |1100111001⟩: 0.1768+0.0000𝑖
2289 |1101011010⟩: 0.1768+0.0000𝑖
2290 |1101111011⟩: 0.1768+0.0000𝑖
2291 |1110011100⟩: 0.1768+0.0000𝑖
2292 |1110111101⟩: 0.1768+0.0000𝑖
2293 |1111011110⟩: 0.1768+0.0000𝑖
2294 |1111111111⟩: 0.1250+0.1250𝑖
2295 "#]]
2296 .assert_eq(&dump);
2297
2298 sim.sim.mctadj(&[0, 1, 2, 3], 4);
2299 for i in 0..5 {
2300 sim.sim.mcx(&[i + 5], i);
2301 sim.sim.h(i + 5);
2302 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2303 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2304 }
2305}
2306
2307#[test]
2308fn test_mctadj_1_control() {
2309 let mut sim = SparseSim::default();
2310 let dump = test_expression_with_lib_and_profile_and_sim(
2311 indoc! {"{
2312 let qs = QIR.Runtime.AllocateQubitArray(2);
2313 let aux = QIR.Runtime.AllocateQubitArray(2);
2314 for i in 0..1 {
2315 H(aux[i]);
2316 CNOT(aux[i], qs[i]);
2317 }
2318 Controlled Adjoint T(qs[0..0], qs[1]);
2319 Std.Diagnostics.DumpMachine();
2320 }"},
2321 "",
2322 Profile::Unrestricted,
2323 &mut sim,
2324 &Value::unit(),
2325 );
2326 expect![[r#"
2327 STATE:
2328 |0000⟩: 0.5000+0.0000𝑖
2329 |0101⟩: 0.5000+0.0000𝑖
2330 |1010⟩: 0.5000+0.0000𝑖
2331 |1111⟩: 0.3536−0.3536𝑖
2332 "#]]
2333 .assert_eq(&dump);
2334
2335 sim.sim.mct(&[0], 1);
2336 for i in 0..2 {
2337 sim.sim.mcx(&[i + 2], i);
2338 sim.sim.h(i + 2);
2339 assert!(sim.sim.qubit_is_zero(i + 2), "qubit {} is not zero", i + 2);
2340 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2341 }
2342}
2343
2344#[test]
2345fn test_mctadj_2_control() {
2346 let mut sim = SparseSim::default();
2347 let dump = test_expression_with_lib_and_profile_and_sim(
2348 indoc! {"{
2349 let qs = QIR.Runtime.AllocateQubitArray(3);
2350 let aux = QIR.Runtime.AllocateQubitArray(3);
2351 for i in 0..2 {
2352 H(aux[i]);
2353 CNOT(aux[i], qs[i]);
2354 }
2355 Controlled Adjoint T(qs[0..1], qs[2]);
2356 Std.Diagnostics.DumpMachine();
2357 }"},
2358 "",
2359 Profile::Unrestricted,
2360 &mut sim,
2361 &Value::unit(),
2362 );
2363 expect![[r#"
2364 STATE:
2365 |000000⟩: 0.3536+0.0000𝑖
2366 |001001⟩: 0.3536+0.0000𝑖
2367 |010010⟩: 0.3536+0.0000𝑖
2368 |011011⟩: 0.3536+0.0000𝑖
2369 |100100⟩: 0.3536+0.0000𝑖
2370 |101101⟩: 0.3536+0.0000𝑖
2371 |110110⟩: 0.3536+0.0000𝑖
2372 |111111⟩: 0.2500−0.2500𝑖
2373 "#]]
2374 .assert_eq(&dump);
2375
2376 sim.sim.mct(&[0, 1], 2);
2377 for i in 0..3 {
2378 sim.sim.mcx(&[i + 3], i);
2379 sim.sim.h(i + 3);
2380 assert!(sim.sim.qubit_is_zero(i + 3), "qubit {} is not zero", i + 3);
2381 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2382 }
2383}
2384
2385#[test]
2386fn test_unrestricted_mctadj_3_control() {
2387 let mut sim = SparseSim::default();
2388 let dump = test_expression_with_lib_and_profile_and_sim(
2389 indoc! {"{
2390 let qs = QIR.Runtime.AllocateQubitArray(4);
2391 let aux = QIR.Runtime.AllocateQubitArray(4);
2392 for i in 0..3 {
2393 H(aux[i]);
2394 CNOT(aux[i], qs[i]);
2395 }
2396 Controlled Adjoint T(qs[0..2], qs[3]);
2397 Std.Diagnostics.DumpMachine();
2398 }"},
2399 "",
2400 Profile::Unrestricted,
2401 &mut sim,
2402 &Value::unit(),
2403 );
2404 expect![[r#"
2405 STATE:
2406 |00000000⟩: 0.2500+0.0000𝑖
2407 |00010001⟩: 0.2500+0.0000𝑖
2408 |00100010⟩: 0.2500+0.0000𝑖
2409 |00110011⟩: 0.2500+0.0000𝑖
2410 |01000100⟩: 0.2500+0.0000𝑖
2411 |01010101⟩: 0.2500+0.0000𝑖
2412 |01100110⟩: 0.2500+0.0000𝑖
2413 |01110111⟩: 0.2500+0.0000𝑖
2414 |10001000⟩: 0.2500+0.0000𝑖
2415 |10011001⟩: 0.2500+0.0000𝑖
2416 |10101010⟩: 0.2500+0.0000𝑖
2417 |10111011⟩: 0.2500+0.0000𝑖
2418 |11001100⟩: 0.2500+0.0000𝑖
2419 |11011101⟩: 0.2500+0.0000𝑖
2420 |11101110⟩: 0.2500+0.0000𝑖
2421 |11111111⟩: 0.1768−0.1768𝑖
2422 "#]]
2423 .assert_eq(&dump);
2424
2425 sim.sim.mct(&[0, 1, 2], 3);
2426 for i in 0..4 {
2427 sim.sim.mcx(&[i + 4], i);
2428 sim.sim.h(i + 4);
2429 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2430 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2431 }
2432}
2433
2434#[test]
2435fn test_base_mctadj_3_control() {
2436 let mut sim = SparseSim::default();
2437 let dump = test_expression_with_lib_and_profile_and_sim(
2438 indoc! {"{
2439 let qs = QIR.Runtime.AllocateQubitArray(4);
2440 let aux = QIR.Runtime.AllocateQubitArray(4);
2441 for i in 0..3 {
2442 H(aux[i]);
2443 CNOT(aux[i], qs[i]);
2444 }
2445 Controlled Adjoint T(qs[0..2], qs[3]);
2446 Std.Diagnostics.DumpMachine();
2447 let result : Result[] = [];
2448 result
2449 }"},
2450 "",
2451 Profile::Base,
2452 &mut sim,
2453 &Value::Array(Vec::new().into()),
2454 );
2455 expect![[r#"
2456 STATE:
2457 |00000000⟩: 0.2500+0.0000𝑖
2458 |00010001⟩: 0.2500+0.0000𝑖
2459 |00100010⟩: 0.2500+0.0000𝑖
2460 |00110011⟩: 0.2500+0.0000𝑖
2461 |01000100⟩: 0.2500+0.0000𝑖
2462 |01010101⟩: 0.2500+0.0000𝑖
2463 |01100110⟩: 0.2500+0.0000𝑖
2464 |01110111⟩: 0.2500+0.0000𝑖
2465 |10001000⟩: 0.2500+0.0000𝑖
2466 |10011001⟩: 0.2500+0.0000𝑖
2467 |10101010⟩: 0.2500+0.0000𝑖
2468 |10111011⟩: 0.2500+0.0000𝑖
2469 |11001100⟩: 0.2500+0.0000𝑖
2470 |11011101⟩: 0.2500+0.0000𝑖
2471 |11101110⟩: 0.2500+0.0000𝑖
2472 |11111111⟩: 0.1768−0.1768𝑖
2473 "#]]
2474 .assert_eq(&dump);
2475
2476 sim.sim.mct(&[0, 1, 2], 3);
2477 for i in 0..4 {
2478 sim.sim.mcx(&[i + 4], i);
2479 sim.sim.h(i + 4);
2480 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2481 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2482 }
2483}
2484
2485#[test]
2486fn test_unrestricted_mctadj_4_control() {
2487 let mut sim = SparseSim::default();
2488 let dump = test_expression_with_lib_and_profile_and_sim(
2489 indoc! {"{
2490 let qs = QIR.Runtime.AllocateQubitArray(5);
2491 let aux = QIR.Runtime.AllocateQubitArray(5);
2492 for i in 0..4 {
2493 H(aux[i]);
2494 CNOT(aux[i], qs[i]);
2495 }
2496 Controlled Adjoint T(qs[0..3], qs[4]);
2497 Std.Diagnostics.DumpMachine();
2498 }"},
2499 "",
2500 Profile::Unrestricted,
2501 &mut sim,
2502 &Value::unit(),
2503 );
2504 expect![[r#"
2505 STATE:
2506 |0000000000⟩: 0.1768+0.0000𝑖
2507 |0000100001⟩: 0.1768+0.0000𝑖
2508 |0001000010⟩: 0.1768+0.0000𝑖
2509 |0001100011⟩: 0.1768+0.0000𝑖
2510 |0010000100⟩: 0.1768+0.0000𝑖
2511 |0010100101⟩: 0.1768+0.0000𝑖
2512 |0011000110⟩: 0.1768+0.0000𝑖
2513 |0011100111⟩: 0.1768+0.0000𝑖
2514 |0100001000⟩: 0.1768+0.0000𝑖
2515 |0100101001⟩: 0.1768+0.0000𝑖
2516 |0101001010⟩: 0.1768+0.0000𝑖
2517 |0101101011⟩: 0.1768+0.0000𝑖
2518 |0110001100⟩: 0.1768+0.0000𝑖
2519 |0110101101⟩: 0.1768+0.0000𝑖
2520 |0111001110⟩: 0.1768+0.0000𝑖
2521 |0111101111⟩: 0.1768+0.0000𝑖
2522 |1000010000⟩: 0.1768+0.0000𝑖
2523 |1000110001⟩: 0.1768+0.0000𝑖
2524 |1001010010⟩: 0.1768+0.0000𝑖
2525 |1001110011⟩: 0.1768+0.0000𝑖
2526 |1010010100⟩: 0.1768+0.0000𝑖
2527 |1010110101⟩: 0.1768+0.0000𝑖
2528 |1011010110⟩: 0.1768+0.0000𝑖
2529 |1011110111⟩: 0.1768+0.0000𝑖
2530 |1100011000⟩: 0.1768+0.0000𝑖
2531 |1100111001⟩: 0.1768+0.0000𝑖
2532 |1101011010⟩: 0.1768+0.0000𝑖
2533 |1101111011⟩: 0.1768+0.0000𝑖
2534 |1110011100⟩: 0.1768+0.0000𝑖
2535 |1110111101⟩: 0.1768+0.0000𝑖
2536 |1111011110⟩: 0.1768+0.0000𝑖
2537 |1111111111⟩: 0.1250−0.1250𝑖
2538 "#]]
2539 .assert_eq(&dump);
2540
2541 sim.sim.mct(&[0, 1, 2, 3], 4);
2542 for i in 0..5 {
2543 sim.sim.mcx(&[i + 5], i);
2544 sim.sim.h(i + 5);
2545 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2546 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2547 }
2548}
2549
2550#[test]
2551fn test_base_mctadj_4_control() {
2552 let mut sim = SparseSim::default();
2553 let dump = test_expression_with_lib_and_profile_and_sim(
2554 indoc! {"{
2555 let qs = QIR.Runtime.AllocateQubitArray(5);
2556 let aux = QIR.Runtime.AllocateQubitArray(5);
2557 for i in 0..4 {
2558 H(aux[i]);
2559 CNOT(aux[i], qs[i]);
2560 }
2561 Controlled Adjoint T(qs[0..3], qs[4]);
2562 Std.Diagnostics.DumpMachine();
2563 let result : Result[] = [];
2564 result
2565 }"},
2566 "",
2567 Profile::Base,
2568 &mut sim,
2569 &Value::Array(Vec::new().into()),
2570 );
2571 expect![[r#"
2572 STATE:
2573 |0000000000⟩: 0.1768+0.0000𝑖
2574 |0000100001⟩: 0.1768+0.0000𝑖
2575 |0001000010⟩: 0.1768+0.0000𝑖
2576 |0001100011⟩: 0.1768+0.0000𝑖
2577 |0010000100⟩: 0.1768+0.0000𝑖
2578 |0010100101⟩: 0.1768+0.0000𝑖
2579 |0011000110⟩: 0.1768+0.0000𝑖
2580 |0011100111⟩: 0.1768+0.0000𝑖
2581 |0100001000⟩: 0.1768+0.0000𝑖
2582 |0100101001⟩: 0.1768+0.0000𝑖
2583 |0101001010⟩: 0.1768+0.0000𝑖
2584 |0101101011⟩: 0.1768+0.0000𝑖
2585 |0110001100⟩: 0.1768+0.0000𝑖
2586 |0110101101⟩: 0.1768+0.0000𝑖
2587 |0111001110⟩: 0.1768+0.0000𝑖
2588 |0111101111⟩: 0.1768+0.0000𝑖
2589 |1000010000⟩: 0.1768+0.0000𝑖
2590 |1000110001⟩: 0.1768+0.0000𝑖
2591 |1001010010⟩: 0.1768+0.0000𝑖
2592 |1001110011⟩: 0.1768+0.0000𝑖
2593 |1010010100⟩: 0.1768+0.0000𝑖
2594 |1010110101⟩: 0.1768+0.0000𝑖
2595 |1011010110⟩: 0.1768+0.0000𝑖
2596 |1011110111⟩: 0.1768+0.0000𝑖
2597 |1100011000⟩: 0.1768+0.0000𝑖
2598 |1100111001⟩: 0.1768+0.0000𝑖
2599 |1101011010⟩: 0.1768+0.0000𝑖
2600 |1101111011⟩: 0.1768+0.0000𝑖
2601 |1110011100⟩: 0.1768+0.0000𝑖
2602 |1110111101⟩: 0.1768+0.0000𝑖
2603 |1111011110⟩: 0.1768+0.0000𝑖
2604 |1111111111⟩: 0.1250−0.1250𝑖
2605 "#]]
2606 .assert_eq(&dump);
2607
2608 sim.sim.mct(&[0, 1, 2, 3], 4);
2609 for i in 0..5 {
2610 sim.sim.mcx(&[i + 5], i);
2611 sim.sim.h(i + 5);
2612 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2613 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2614 }
2615}
2616
2617#[test]
2618fn test_unrestricted_mcx_3_control() {
2619 let mut sim = SparseSim::default();
2620 let dump = test_expression_with_lib_and_profile_and_sim(
2621 indoc! {"{
2622 let qs = QIR.Runtime.AllocateQubitArray(4);
2623 let aux = QIR.Runtime.AllocateQubitArray(4);
2624 for i in 0..3 {
2625 H(aux[i]);
2626 CNOT(aux[i], qs[i]);
2627 }
2628 Controlled X(qs[0..2], qs[3]);
2629 Std.Diagnostics.DumpMachine();
2630 }"},
2631 "",
2632 Profile::Unrestricted,
2633 &mut sim,
2634 &Value::unit(),
2635 );
2636 expect![[r#"
2637 STATE:
2638 |00000000⟩: 0.2500+0.0000𝑖
2639 |00010001⟩: 0.2500+0.0000𝑖
2640 |00100010⟩: 0.2500+0.0000𝑖
2641 |00110011⟩: 0.2500+0.0000𝑖
2642 |01000100⟩: 0.2500+0.0000𝑖
2643 |01010101⟩: 0.2500+0.0000𝑖
2644 |01100110⟩: 0.2500+0.0000𝑖
2645 |01110111⟩: 0.2500+0.0000𝑖
2646 |10001000⟩: 0.2500+0.0000𝑖
2647 |10011001⟩: 0.2500+0.0000𝑖
2648 |10101010⟩: 0.2500+0.0000𝑖
2649 |10111011⟩: 0.2500+0.0000𝑖
2650 |11001100⟩: 0.2500+0.0000𝑖
2651 |11011101⟩: 0.2500+0.0000𝑖
2652 |11101111⟩: 0.2500+0.0000𝑖
2653 |11111110⟩: 0.2500+0.0000𝑖
2654 "#]]
2655 .assert_eq(&dump);
2656
2657 sim.sim.mcx(&[0, 1, 2], 3);
2658 for i in 0..4 {
2659 sim.sim.mcx(&[i + 4], i);
2660 sim.sim.h(i + 4);
2661 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2662 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2663 }
2664}
2665
2666#[test]
2667fn test_base_mcx_3_control() {
2668 let mut sim = SparseSim::default();
2669 let dump = test_expression_with_lib_and_profile_and_sim(
2670 indoc! {"{
2671 let qs = QIR.Runtime.AllocateQubitArray(4);
2672 let aux = QIR.Runtime.AllocateQubitArray(4);
2673 for i in 0..3 {
2674 H(aux[i]);
2675 CNOT(aux[i], qs[i]);
2676 }
2677 Controlled X(qs[0..2], qs[3]);
2678 Std.Diagnostics.DumpMachine();
2679 let result : Result[] = [];
2680 result
2681 }"},
2682 "",
2683 Profile::Base,
2684 &mut sim,
2685 &Value::Array(Vec::new().into()),
2686 );
2687 expect![[r#"
2688 STATE:
2689 |00000000⟩: 0.2500+0.0000𝑖
2690 |00010001⟩: 0.2500+0.0000𝑖
2691 |00100010⟩: 0.2500+0.0000𝑖
2692 |00110011⟩: 0.2500+0.0000𝑖
2693 |01000100⟩: 0.2500+0.0000𝑖
2694 |01010101⟩: 0.2500+0.0000𝑖
2695 |01100110⟩: 0.2500+0.0000𝑖
2696 |01110111⟩: 0.2500+0.0000𝑖
2697 |10001000⟩: 0.2500+0.0000𝑖
2698 |10011001⟩: 0.2500+0.0000𝑖
2699 |10101010⟩: 0.2500+0.0000𝑖
2700 |10111011⟩: 0.2500+0.0000𝑖
2701 |11001100⟩: 0.2500+0.0000𝑖
2702 |11011101⟩: 0.2500+0.0000𝑖
2703 |11101111⟩: 0.2500+0.0000𝑖
2704 |11111110⟩: 0.2500+0.0000𝑖
2705 "#]]
2706 .assert_eq(&dump);
2707
2708 sim.sim.mcx(&[0, 1, 2], 3);
2709 for i in 0..4 {
2710 sim.sim.mcx(&[i + 4], i);
2711 sim.sim.h(i + 4);
2712 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2713 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2714 }
2715}
2716
2717#[test]
2718fn test_unrestricted_mcx_4_control() {
2719 let mut sim = SparseSim::default();
2720 let dump = test_expression_with_lib_and_profile_and_sim(
2721 indoc! {"{
2722 let qs = QIR.Runtime.AllocateQubitArray(5);
2723 let aux = QIR.Runtime.AllocateQubitArray(5);
2724 for i in 0..4 {
2725 H(aux[i]);
2726 CNOT(aux[i], qs[i]);
2727 }
2728 Controlled X(qs[0..3], qs[4]);
2729 Std.Diagnostics.DumpMachine();
2730 }"},
2731 "",
2732 Profile::Unrestricted,
2733 &mut sim,
2734 &Value::unit(),
2735 );
2736 expect![[r#"
2737 STATE:
2738 |0000000000⟩: 0.1768+0.0000𝑖
2739 |0000100001⟩: 0.1768+0.0000𝑖
2740 |0001000010⟩: 0.1768+0.0000𝑖
2741 |0001100011⟩: 0.1768+0.0000𝑖
2742 |0010000100⟩: 0.1768+0.0000𝑖
2743 |0010100101⟩: 0.1768+0.0000𝑖
2744 |0011000110⟩: 0.1768+0.0000𝑖
2745 |0011100111⟩: 0.1768+0.0000𝑖
2746 |0100001000⟩: 0.1768+0.0000𝑖
2747 |0100101001⟩: 0.1768+0.0000𝑖
2748 |0101001010⟩: 0.1768+0.0000𝑖
2749 |0101101011⟩: 0.1768+0.0000𝑖
2750 |0110001100⟩: 0.1768+0.0000𝑖
2751 |0110101101⟩: 0.1768+0.0000𝑖
2752 |0111001110⟩: 0.1768+0.0000𝑖
2753 |0111101111⟩: 0.1768+0.0000𝑖
2754 |1000010000⟩: 0.1768+0.0000𝑖
2755 |1000110001⟩: 0.1768+0.0000𝑖
2756 |1001010010⟩: 0.1768+0.0000𝑖
2757 |1001110011⟩: 0.1768+0.0000𝑖
2758 |1010010100⟩: 0.1768+0.0000𝑖
2759 |1010110101⟩: 0.1768+0.0000𝑖
2760 |1011010110⟩: 0.1768+0.0000𝑖
2761 |1011110111⟩: 0.1768+0.0000𝑖
2762 |1100011000⟩: 0.1768+0.0000𝑖
2763 |1100111001⟩: 0.1768+0.0000𝑖
2764 |1101011010⟩: 0.1768+0.0000𝑖
2765 |1101111011⟩: 0.1768+0.0000𝑖
2766 |1110011100⟩: 0.1768+0.0000𝑖
2767 |1110111101⟩: 0.1768+0.0000𝑖
2768 |1111011111⟩: 0.1768+0.0000𝑖
2769 |1111111110⟩: 0.1768+0.0000𝑖
2770 "#]]
2771 .assert_eq(&dump);
2772
2773 sim.sim.mcx(&[0, 1, 2, 3], 4);
2774 for i in 0..5 {
2775 sim.sim.mcx(&[i + 5], i);
2776 sim.sim.h(i + 5);
2777 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2778 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2779 }
2780}
2781
2782#[test]
2783fn test_base_mcx_4_control() {
2784 let mut sim = SparseSim::default();
2785 let dump = test_expression_with_lib_and_profile_and_sim(
2786 indoc! {"{
2787 let qs = QIR.Runtime.AllocateQubitArray(5);
2788 let aux = QIR.Runtime.AllocateQubitArray(5);
2789 for i in 0..4 {
2790 H(aux[i]);
2791 CNOT(aux[i], qs[i]);
2792 }
2793 Controlled X(qs[0..3], qs[4]);
2794 Std.Diagnostics.DumpMachine();
2795 let result : Result[] = [];
2796 result
2797 }"},
2798 "",
2799 Profile::Base,
2800 &mut sim,
2801 &Value::Array(Vec::new().into()),
2802 );
2803 expect![[r#"
2804 STATE:
2805 |0000000000⟩: 0.1768+0.0000𝑖
2806 |0000100001⟩: 0.1768+0.0000𝑖
2807 |0001000010⟩: 0.1768+0.0000𝑖
2808 |0001100011⟩: 0.1768+0.0000𝑖
2809 |0010000100⟩: 0.1768+0.0000𝑖
2810 |0010100101⟩: 0.1768+0.0000𝑖
2811 |0011000110⟩: 0.1768+0.0000𝑖
2812 |0011100111⟩: 0.1768+0.0000𝑖
2813 |0100001000⟩: 0.1768+0.0000𝑖
2814 |0100101001⟩: 0.1768+0.0000𝑖
2815 |0101001010⟩: 0.1768+0.0000𝑖
2816 |0101101011⟩: 0.1768+0.0000𝑖
2817 |0110001100⟩: 0.1768+0.0000𝑖
2818 |0110101101⟩: 0.1768+0.0000𝑖
2819 |0111001110⟩: 0.1768+0.0000𝑖
2820 |0111101111⟩: 0.1768+0.0000𝑖
2821 |1000010000⟩: 0.1768+0.0000𝑖
2822 |1000110001⟩: 0.1768+0.0000𝑖
2823 |1001010010⟩: 0.1768+0.0000𝑖
2824 |1001110011⟩: 0.1768+0.0000𝑖
2825 |1010010100⟩: 0.1768+0.0000𝑖
2826 |1010110101⟩: 0.1768+0.0000𝑖
2827 |1011010110⟩: 0.1768+0.0000𝑖
2828 |1011110111⟩: 0.1768+0.0000𝑖
2829 |1100011000⟩: 0.1768+0.0000𝑖
2830 |1100111001⟩: 0.1768+0.0000𝑖
2831 |1101011010⟩: 0.1768+0.0000𝑖
2832 |1101111011⟩: 0.1768+0.0000𝑖
2833 |1110011100⟩: 0.1768+0.0000𝑖
2834 |1110111101⟩: 0.1768+0.0000𝑖
2835 |1111011111⟩: 0.1768+0.0000𝑖
2836 |1111111110⟩: 0.1768+0.0000𝑖
2837 "#]]
2838 .assert_eq(&dump);
2839
2840 sim.sim.mcx(&[0, 1, 2, 3], 4);
2841 for i in 0..5 {
2842 sim.sim.mcx(&[i + 5], i);
2843 sim.sim.h(i + 5);
2844 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
2845 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2846 }
2847}
2848
2849#[test]
2850fn test_unrestricted_mcy_3_control() {
2851 let mut sim = SparseSim::default();
2852 let dump = test_expression_with_lib_and_profile_and_sim(
2853 indoc! {"{
2854 let qs = QIR.Runtime.AllocateQubitArray(4);
2855 let aux = QIR.Runtime.AllocateQubitArray(4);
2856 for i in 0..3 {
2857 H(aux[i]);
2858 CNOT(aux[i], qs[i]);
2859 }
2860 Controlled Y(qs[0..2], qs[3]);
2861 Std.Diagnostics.DumpMachine();
2862 }"},
2863 "",
2864 Profile::Unrestricted,
2865 &mut sim,
2866 &Value::unit(),
2867 );
2868 expect![[r#"
2869 STATE:
2870 |00000000⟩: 0.2500+0.0000𝑖
2871 |00010001⟩: 0.2500+0.0000𝑖
2872 |00100010⟩: 0.2500+0.0000𝑖
2873 |00110011⟩: 0.2500+0.0000𝑖
2874 |01000100⟩: 0.2500+0.0000𝑖
2875 |01010101⟩: 0.2500+0.0000𝑖
2876 |01100110⟩: 0.2500+0.0000𝑖
2877 |01110111⟩: 0.2500+0.0000𝑖
2878 |10001000⟩: 0.2500+0.0000𝑖
2879 |10011001⟩: 0.2500+0.0000𝑖
2880 |10101010⟩: 0.2500+0.0000𝑖
2881 |10111011⟩: 0.2500+0.0000𝑖
2882 |11001100⟩: 0.2500+0.0000𝑖
2883 |11011101⟩: 0.2500+0.0000𝑖
2884 |11101111⟩: 0.0000−0.2500𝑖
2885 |11111110⟩: 0.0000+0.2500𝑖
2886 "#]]
2887 .assert_eq(&dump);
2888
2889 sim.sim.mcy(&[0, 1, 2], 3);
2890 for i in 0..4 {
2891 sim.sim.mcx(&[i + 4], i);
2892 sim.sim.h(i + 4);
2893 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2894 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2895 }
2896}
2897
2898#[test]
2899fn test_base_mcy_3_control() {
2900 let mut sim = SparseSim::default();
2901 let dump = test_expression_with_lib_and_profile_and_sim(
2902 indoc! {"{
2903 let qs = QIR.Runtime.AllocateQubitArray(4);
2904 let aux = QIR.Runtime.AllocateQubitArray(4);
2905 for i in 0..3 {
2906 H(aux[i]);
2907 CNOT(aux[i], qs[i]);
2908 }
2909 Controlled Y(qs[0..2], qs[3]);
2910 Std.Diagnostics.DumpMachine();
2911 let result : Result[] = [];
2912 result
2913 }"},
2914 "",
2915 Profile::Base,
2916 &mut sim,
2917 &Value::Array(Vec::new().into()),
2918 );
2919 expect![[r#"
2920 STATE:
2921 |00000000⟩: 0.2500+0.0000𝑖
2922 |00010001⟩: 0.2500+0.0000𝑖
2923 |00100010⟩: 0.2500+0.0000𝑖
2924 |00110011⟩: 0.2500+0.0000𝑖
2925 |01000100⟩: 0.2500+0.0000𝑖
2926 |01010101⟩: 0.2500+0.0000𝑖
2927 |01100110⟩: 0.2500+0.0000𝑖
2928 |01110111⟩: 0.2500+0.0000𝑖
2929 |10001000⟩: 0.2500+0.0000𝑖
2930 |10011001⟩: 0.2500+0.0000𝑖
2931 |10101010⟩: 0.2500+0.0000𝑖
2932 |10111011⟩: 0.2500+0.0000𝑖
2933 |11001100⟩: 0.2500+0.0000𝑖
2934 |11011101⟩: 0.2500+0.0000𝑖
2935 |11101111⟩: 0.0000−0.2500𝑖
2936 |11111110⟩: 0.0000+0.2500𝑖
2937 "#]]
2938 .assert_eq(&dump);
2939
2940 sim.sim.mcy(&[0, 1, 2], 3);
2941 for i in 0..4 {
2942 sim.sim.mcx(&[i + 4], i);
2943 sim.sim.h(i + 4);
2944 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
2945 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
2946 }
2947}
2948
2949#[test]
2950fn test_unrestricted_mcy_4_control() {
2951 let mut sim = SparseSim::default();
2952 let dump = test_expression_with_lib_and_profile_and_sim(
2953 indoc! {"{
2954 let qs = QIR.Runtime.AllocateQubitArray(5);
2955 let aux = QIR.Runtime.AllocateQubitArray(5);
2956 for i in 0..4 {
2957 H(aux[i]);
2958 CNOT(aux[i], qs[i]);
2959 }
2960 Controlled Y(qs[0..3], qs[4]);
2961 Std.Diagnostics.DumpMachine();
2962 }"},
2963 "",
2964 Profile::Unrestricted,
2965 &mut sim,
2966 &Value::unit(),
2967 );
2968 expect![[r#"
2969 STATE:
2970 |0000000000⟩: 0.1768+0.0000𝑖
2971 |0000100001⟩: 0.1768+0.0000𝑖
2972 |0001000010⟩: 0.1768+0.0000𝑖
2973 |0001100011⟩: 0.1768+0.0000𝑖
2974 |0010000100⟩: 0.1768+0.0000𝑖
2975 |0010100101⟩: 0.1768+0.0000𝑖
2976 |0011000110⟩: 0.1768+0.0000𝑖
2977 |0011100111⟩: 0.1768+0.0000𝑖
2978 |0100001000⟩: 0.1768+0.0000𝑖
2979 |0100101001⟩: 0.1768+0.0000𝑖
2980 |0101001010⟩: 0.1768+0.0000𝑖
2981 |0101101011⟩: 0.1768+0.0000𝑖
2982 |0110001100⟩: 0.1768+0.0000𝑖
2983 |0110101101⟩: 0.1768+0.0000𝑖
2984 |0111001110⟩: 0.1768+0.0000𝑖
2985 |0111101111⟩: 0.1768+0.0000𝑖
2986 |1000010000⟩: 0.1768+0.0000𝑖
2987 |1000110001⟩: 0.1768+0.0000𝑖
2988 |1001010010⟩: 0.1768+0.0000𝑖
2989 |1001110011⟩: 0.1768+0.0000𝑖
2990 |1010010100⟩: 0.1768+0.0000𝑖
2991 |1010110101⟩: 0.1768+0.0000𝑖
2992 |1011010110⟩: 0.1768+0.0000𝑖
2993 |1011110111⟩: 0.1768+0.0000𝑖
2994 |1100011000⟩: 0.1768+0.0000𝑖
2995 |1100111001⟩: 0.1768+0.0000𝑖
2996 |1101011010⟩: 0.1768+0.0000𝑖
2997 |1101111011⟩: 0.1768+0.0000𝑖
2998 |1110011100⟩: 0.1768+0.0000𝑖
2999 |1110111101⟩: 0.1768+0.0000𝑖
3000 |1111011111⟩: 0.0000−0.1768𝑖
3001 |1111111110⟩: 0.0000+0.1768𝑖
3002 "#]]
3003 .assert_eq(&dump);
3004
3005 sim.sim.mcy(&[0, 1, 2, 3], 4);
3006 for i in 0..5 {
3007 sim.sim.mcx(&[i + 5], i);
3008 sim.sim.h(i + 5);
3009 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
3010 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3011 }
3012}
3013
3014#[test]
3015fn test_base_mcy_4_control() {
3016 let mut sim = SparseSim::default();
3017 let dump = test_expression_with_lib_and_profile_and_sim(
3018 indoc! {"{
3019 let qs = QIR.Runtime.AllocateQubitArray(5);
3020 let aux = QIR.Runtime.AllocateQubitArray(5);
3021 for i in 0..4 {
3022 H(aux[i]);
3023 CNOT(aux[i], qs[i]);
3024 }
3025 Controlled Y(qs[0..3], qs[4]);
3026 Std.Diagnostics.DumpMachine();
3027 let result : Result[] = [];
3028 result
3029 }"},
3030 "",
3031 Profile::Base,
3032 &mut sim,
3033 &Value::Array(Vec::new().into()),
3034 );
3035 expect![[r#"
3036 STATE:
3037 |0000000000⟩: 0.1768+0.0000𝑖
3038 |0000100001⟩: 0.1768+0.0000𝑖
3039 |0001000010⟩: 0.1768+0.0000𝑖
3040 |0001100011⟩: 0.1768+0.0000𝑖
3041 |0010000100⟩: 0.1768+0.0000𝑖
3042 |0010100101⟩: 0.1768+0.0000𝑖
3043 |0011000110⟩: 0.1768+0.0000𝑖
3044 |0011100111⟩: 0.1768+0.0000𝑖
3045 |0100001000⟩: 0.1768+0.0000𝑖
3046 |0100101001⟩: 0.1768+0.0000𝑖
3047 |0101001010⟩: 0.1768+0.0000𝑖
3048 |0101101011⟩: 0.1768+0.0000𝑖
3049 |0110001100⟩: 0.1768+0.0000𝑖
3050 |0110101101⟩: 0.1768+0.0000𝑖
3051 |0111001110⟩: 0.1768+0.0000𝑖
3052 |0111101111⟩: 0.1768+0.0000𝑖
3053 |1000010000⟩: 0.1768+0.0000𝑖
3054 |1000110001⟩: 0.1768+0.0000𝑖
3055 |1001010010⟩: 0.1768+0.0000𝑖
3056 |1001110011⟩: 0.1768+0.0000𝑖
3057 |1010010100⟩: 0.1768+0.0000𝑖
3058 |1010110101⟩: 0.1768+0.0000𝑖
3059 |1011010110⟩: 0.1768+0.0000𝑖
3060 |1011110111⟩: 0.1768+0.0000𝑖
3061 |1100011000⟩: 0.1768+0.0000𝑖
3062 |1100111001⟩: 0.1768+0.0000𝑖
3063 |1101011010⟩: 0.1768+0.0000𝑖
3064 |1101111011⟩: 0.1768+0.0000𝑖
3065 |1110011100⟩: 0.1768+0.0000𝑖
3066 |1110111101⟩: 0.1768+0.0000𝑖
3067 |1111011111⟩: 0.0000−0.1768𝑖
3068 |1111111110⟩: 0.0000+0.1768𝑖
3069 "#]]
3070 .assert_eq(&dump);
3071
3072 sim.sim.mcy(&[0, 1, 2, 3], 4);
3073 for i in 0..5 {
3074 sim.sim.mcx(&[i + 5], i);
3075 sim.sim.h(i + 5);
3076 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
3077 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3078 }
3079}
3080
3081#[test]
3082fn test_unrestricted_mcz_3_control() {
3083 let mut sim = SparseSim::default();
3084 let dump = test_expression_with_lib_and_profile_and_sim(
3085 indoc! {"{
3086 let qs = QIR.Runtime.AllocateQubitArray(4);
3087 let aux = QIR.Runtime.AllocateQubitArray(4);
3088 for i in 0..3 {
3089 H(aux[i]);
3090 CNOT(aux[i], qs[i]);
3091 }
3092 Controlled Z(qs[0..2], qs[3]);
3093 Std.Diagnostics.DumpMachine();
3094 }"},
3095 "",
3096 Profile::Unrestricted,
3097 &mut sim,
3098 &Value::unit(),
3099 );
3100 expect![[r#"
3101 STATE:
3102 |00000000⟩: 0.2500+0.0000𝑖
3103 |00010001⟩: 0.2500+0.0000𝑖
3104 |00100010⟩: 0.2500+0.0000𝑖
3105 |00110011⟩: 0.2500+0.0000𝑖
3106 |01000100⟩: 0.2500+0.0000𝑖
3107 |01010101⟩: 0.2500+0.0000𝑖
3108 |01100110⟩: 0.2500+0.0000𝑖
3109 |01110111⟩: 0.2500+0.0000𝑖
3110 |10001000⟩: 0.2500+0.0000𝑖
3111 |10011001⟩: 0.2500+0.0000𝑖
3112 |10101010⟩: 0.2500+0.0000𝑖
3113 |10111011⟩: 0.2500+0.0000𝑖
3114 |11001100⟩: 0.2500+0.0000𝑖
3115 |11011101⟩: 0.2500+0.0000𝑖
3116 |11101110⟩: 0.2500+0.0000𝑖
3117 |11111111⟩: −0.2500+0.0000𝑖
3118 "#]]
3119 .assert_eq(&dump);
3120
3121 sim.sim.mcz(&[0, 1, 2], 3);
3122 for i in 0..4 {
3123 sim.sim.mcx(&[i + 4], i);
3124 sim.sim.h(i + 4);
3125 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
3126 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3127 }
3128}
3129
3130#[test]
3131fn test_base_mcz_3_control() {
3132 let mut sim = SparseSim::default();
3133 let dump = test_expression_with_lib_and_profile_and_sim(
3134 indoc! {"{
3135 let qs = QIR.Runtime.AllocateQubitArray(4);
3136 let aux = QIR.Runtime.AllocateQubitArray(4);
3137 for i in 0..3 {
3138 H(aux[i]);
3139 CNOT(aux[i], qs[i]);
3140 }
3141 Controlled Z(qs[0..2], qs[3]);
3142 Std.Diagnostics.DumpMachine();
3143 let result : Result[] = [];
3144 result
3145 }"},
3146 "",
3147 Profile::Base,
3148 &mut sim,
3149 &Value::Array(Vec::new().into()),
3150 );
3151 expect![[r#"
3152 STATE:
3153 |00000000⟩: 0.2500+0.0000𝑖
3154 |00010001⟩: 0.2500+0.0000𝑖
3155 |00100010⟩: 0.2500+0.0000𝑖
3156 |00110011⟩: 0.2500+0.0000𝑖
3157 |01000100⟩: 0.2500+0.0000𝑖
3158 |01010101⟩: 0.2500+0.0000𝑖
3159 |01100110⟩: 0.2500+0.0000𝑖
3160 |01110111⟩: 0.2500+0.0000𝑖
3161 |10001000⟩: 0.2500+0.0000𝑖
3162 |10011001⟩: 0.2500+0.0000𝑖
3163 |10101010⟩: 0.2500+0.0000𝑖
3164 |10111011⟩: 0.2500+0.0000𝑖
3165 |11001100⟩: 0.2500+0.0000𝑖
3166 |11011101⟩: 0.2500+0.0000𝑖
3167 |11101110⟩: 0.2500+0.0000𝑖
3168 |11111111⟩: −0.2500+0.0000𝑖
3169 "#]]
3170 .assert_eq(&dump);
3171
3172 sim.sim.mcz(&[0, 1, 2], 3);
3173 for i in 0..4 {
3174 sim.sim.mcx(&[i + 4], i);
3175 sim.sim.h(i + 4);
3176 assert!(sim.sim.qubit_is_zero(i + 4), "qubit {} is not zero", i + 4);
3177 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3178 }
3179}
3180
3181#[test]
3182fn test_unrestricted_mcz_4_control() {
3183 let mut sim = SparseSim::default();
3184 let dump = test_expression_with_lib_and_profile_and_sim(
3185 indoc! {"{
3186 let qs = QIR.Runtime.AllocateQubitArray(5);
3187 let aux = QIR.Runtime.AllocateQubitArray(5);
3188 for i in 0..4 {
3189 H(aux[i]);
3190 CNOT(aux[i], qs[i]);
3191 }
3192 Controlled Z(qs[0..3], qs[4]);
3193 Std.Diagnostics.DumpMachine();
3194 }"},
3195 "",
3196 Profile::Unrestricted,
3197 &mut sim,
3198 &Value::unit(),
3199 );
3200 expect![[r#"
3201 STATE:
3202 |0000000000⟩: 0.1768+0.0000𝑖
3203 |0000100001⟩: 0.1768+0.0000𝑖
3204 |0001000010⟩: 0.1768+0.0000𝑖
3205 |0001100011⟩: 0.1768+0.0000𝑖
3206 |0010000100⟩: 0.1768+0.0000𝑖
3207 |0010100101⟩: 0.1768+0.0000𝑖
3208 |0011000110⟩: 0.1768+0.0000𝑖
3209 |0011100111⟩: 0.1768+0.0000𝑖
3210 |0100001000⟩: 0.1768+0.0000𝑖
3211 |0100101001⟩: 0.1768+0.0000𝑖
3212 |0101001010⟩: 0.1768+0.0000𝑖
3213 |0101101011⟩: 0.1768+0.0000𝑖
3214 |0110001100⟩: 0.1768+0.0000𝑖
3215 |0110101101⟩: 0.1768+0.0000𝑖
3216 |0111001110⟩: 0.1768+0.0000𝑖
3217 |0111101111⟩: 0.1768+0.0000𝑖
3218 |1000010000⟩: 0.1768+0.0000𝑖
3219 |1000110001⟩: 0.1768+0.0000𝑖
3220 |1001010010⟩: 0.1768+0.0000𝑖
3221 |1001110011⟩: 0.1768+0.0000𝑖
3222 |1010010100⟩: 0.1768+0.0000𝑖
3223 |1010110101⟩: 0.1768+0.0000𝑖
3224 |1011010110⟩: 0.1768+0.0000𝑖
3225 |1011110111⟩: 0.1768+0.0000𝑖
3226 |1100011000⟩: 0.1768+0.0000𝑖
3227 |1100111001⟩: 0.1768+0.0000𝑖
3228 |1101011010⟩: 0.1768+0.0000𝑖
3229 |1101111011⟩: 0.1768+0.0000𝑖
3230 |1110011100⟩: 0.1768+0.0000𝑖
3231 |1110111101⟩: 0.1768+0.0000𝑖
3232 |1111011110⟩: 0.1768+0.0000𝑖
3233 |1111111111⟩: −0.1768+0.0000𝑖
3234 "#]]
3235 .assert_eq(&dump);
3236
3237 sim.sim.mcz(&[0, 1, 2, 3], 4);
3238 for i in 0..5 {
3239 sim.sim.mcx(&[i + 5], i);
3240 sim.sim.h(i + 5);
3241 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
3242 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3243 }
3244}
3245
3246#[test]
3247fn test_base_mcz_4_control() {
3248 let mut sim = SparseSim::default();
3249 let dump = test_expression_with_lib_and_profile_and_sim(
3250 indoc! {"{
3251 let qs = QIR.Runtime.AllocateQubitArray(5);
3252 let aux = QIR.Runtime.AllocateQubitArray(5);
3253 for i in 0..4 {
3254 H(aux[i]);
3255 CNOT(aux[i], qs[i]);
3256 }
3257 Controlled Z(qs[0..3], qs[4]);
3258 Std.Diagnostics.DumpMachine();
3259 let result : Result[] = [];
3260 result
3261 }"},
3262 "",
3263 Profile::Base,
3264 &mut sim,
3265 &Value::Array(Vec::new().into()),
3266 );
3267 expect![[r#"
3268 STATE:
3269 |0000000000⟩: 0.1768+0.0000𝑖
3270 |0000100001⟩: 0.1768+0.0000𝑖
3271 |0001000010⟩: 0.1768+0.0000𝑖
3272 |0001100011⟩: 0.1768+0.0000𝑖
3273 |0010000100⟩: 0.1768+0.0000𝑖
3274 |0010100101⟩: 0.1768+0.0000𝑖
3275 |0011000110⟩: 0.1768+0.0000𝑖
3276 |0011100111⟩: 0.1768+0.0000𝑖
3277 |0100001000⟩: 0.1768+0.0000𝑖
3278 |0100101001⟩: 0.1768+0.0000𝑖
3279 |0101001010⟩: 0.1768+0.0000𝑖
3280 |0101101011⟩: 0.1768+0.0000𝑖
3281 |0110001100⟩: 0.1768+0.0000𝑖
3282 |0110101101⟩: 0.1768+0.0000𝑖
3283 |0111001110⟩: 0.1768+0.0000𝑖
3284 |0111101111⟩: 0.1768+0.0000𝑖
3285 |1000010000⟩: 0.1768+0.0000𝑖
3286 |1000110001⟩: 0.1768+0.0000𝑖
3287 |1001010010⟩: 0.1768+0.0000𝑖
3288 |1001110011⟩: 0.1768+0.0000𝑖
3289 |1010010100⟩: 0.1768+0.0000𝑖
3290 |1010110101⟩: 0.1768+0.0000𝑖
3291 |1011010110⟩: 0.1768+0.0000𝑖
3292 |1011110111⟩: 0.1768+0.0000𝑖
3293 |1100011000⟩: 0.1768+0.0000𝑖
3294 |1100111001⟩: 0.1768+0.0000𝑖
3295 |1101011010⟩: 0.1768+0.0000𝑖
3296 |1101111011⟩: 0.1768+0.0000𝑖
3297 |1110011100⟩: 0.1768+0.0000𝑖
3298 |1110111101⟩: 0.1768+0.0000𝑖
3299 |1111011110⟩: 0.1768+0.0000𝑖
3300 |1111111111⟩: −0.1768+0.0000𝑖
3301 "#]]
3302 .assert_eq(&dump);
3303
3304 sim.sim.mcz(&[0, 1, 2, 3], 4);
3305 for i in 0..5 {
3306 sim.sim.mcx(&[i + 5], i);
3307 sim.sim.h(i + 5);
3308 assert!(sim.sim.qubit_is_zero(i + 5), "qubit {} is not zero", i + 5);
3309 assert!(sim.sim.qubit_is_zero(i), "qubit {i} is not zero");
3310 }
3311}
3312
3313#[test]
3314fn global_phase_correct_for_r1() {
3315 let dump = test_expression(
3316 indoc! {"
3317 {
3318 open Std.Math;
3319 open Std.Diagnostics;
3320 use q = Qubit();
3321 H(q);
3322 R1(PI() / 2.0, q);
3323 Adjoint S(q);
3324 H(q);
3325 DumpMachine();
3326 Reset(q);
3327 }
3328 "},
3329 &Value::unit(),
3330 );
3331
3332 expect![[r#"
3333 STATE:
3334 |0⟩: 1.0000+0.0000𝑖
3335 "#]]
3336 .assert_eq(&dump);
3337}
3338
3339#[test]
3340fn global_phase_correct_for_adjoint_r1() {
3341 let dump = test_expression(
3342 indoc! {"
3343 {
3344 open Std.Math;
3345 open Std.Diagnostics;
3346 use q = Qubit();
3347 H(q);
3348 Adjoint R1(PI() / 2.0, q);
3349 S(q);
3350 H(q);
3351 DumpMachine();
3352 Reset(q);
3353 }
3354 "},
3355 &Value::unit(),
3356 );
3357
3358 expect![[r#"
3359 STATE:
3360 |0⟩: 1.0000+0.0000𝑖
3361 "#]]
3362 .assert_eq(&dump);
3363}
3364
3365#[test]
3366fn global_phase_correct_for_singly_controlled_r1() {
3367 let dump = test_expression(
3368 indoc! {"
3369 {
3370 open Std.Math;
3371 open Std.Diagnostics;
3372 use ctls = Qubit[1];
3373 use q = Qubit();
3374 for c in ctls {
3375 H(c);
3376 }
3377 H(q);
3378 Controlled R1(ctls, (PI() / 2.0, q));
3379 Controlled Adjoint S(ctls, q);
3380 H(q);
3381 for c in ctls {
3382 H(c);
3383 }
3384 DumpMachine();
3385 Reset(q);
3386 ResetAll(ctls);
3387 }
3388 "},
3389 &Value::unit(),
3390 );
3391
3392 expect![[r#"
3393 STATE:
3394 |00⟩: 1.0000+0.0000𝑖
3395 "#]]
3396 .assert_eq(&dump);
3397}
3398
3399#[test]
3400fn global_phase_correct_for_singly_controlled_adjoint_r1() {
3401 let dump = test_expression(
3402 indoc! {"
3403 {
3404 open Std.Math;
3405 open Std.Diagnostics;
3406 use ctls = Qubit[1];
3407 use q = Qubit();
3408 for c in ctls {
3409 H(c);
3410 }
3411 H(q);
3412 Adjoint Controlled R1(ctls, (PI() / 2.0, q));
3413 Controlled S(ctls, q);
3414 H(q);
3415 for c in ctls {
3416 H(c);
3417 }
3418 DumpMachine();
3419 Reset(q);
3420 ResetAll(ctls);
3421 }
3422 "},
3423 &Value::unit(),
3424 );
3425
3426 expect![[r#"
3427 STATE:
3428 |00⟩: 1.0000+0.0000𝑖
3429 "#]]
3430 .assert_eq(&dump);
3431}
3432
3433#[test]
3434fn global_phase_correct_for_doubly_controlled_r1() {
3435 let dump = test_expression(
3436 indoc! {"
3437 {
3438 open Std.Math;
3439 open Std.Diagnostics;
3440 use ctls = Qubit[2];
3441 use q = Qubit();
3442 for c in ctls {
3443 H(c);
3444 }
3445 H(q);
3446 Controlled R1(ctls, (PI() / 2.0, q));
3447 Controlled Adjoint S(ctls, q);
3448 H(q);
3449 for c in ctls {
3450 H(c);
3451 }
3452 DumpMachine();
3453 Reset(q);
3454 ResetAll(ctls);
3455 }
3456 "},
3457 &Value::unit(),
3458 );
3459
3460 expect![[r#"
3461 STATE:
3462 |000⟩: 1.0000+0.0000𝑖
3463 "#]]
3464 .assert_eq(&dump);
3465}
3466
3467#[test]
3468fn global_phase_correct_for_doubly_controlled_adjoint_r1() {
3469 let dump = test_expression(
3470 indoc! {"
3471 {
3472 open Std.Math;
3473 open Std.Diagnostics;
3474 use ctls = Qubit[2];
3475 use q = Qubit();
3476 for c in ctls {
3477 H(c);
3478 }
3479 H(q);
3480 Adjoint Controlled R1(ctls, (PI() / 2.0, q));
3481 Controlled S(ctls, q);
3482 H(q);
3483 for c in ctls {
3484 H(c);
3485 }
3486 DumpMachine();
3487 Reset(q);
3488 ResetAll(ctls);
3489 }
3490 "},
3491 &Value::unit(),
3492 );
3493
3494 expect![[r#"
3495 STATE:
3496 |000⟩: 1.0000+0.0000𝑖
3497 "#]]
3498 .assert_eq(&dump);
3499}
3500
3501#[test]
3502fn global_phase_correct_for_triply_controlled_r1() {
3503 let dump = test_expression(
3504 indoc! {"
3505 {
3506 open Std.Math;
3507 open Std.Diagnostics;
3508 use ctls = Qubit[3];
3509 use q = Qubit();
3510 for c in ctls {
3511 H(c);
3512 }
3513 H(q);
3514 Controlled R1(ctls, (PI() / 2.0, q));
3515 Controlled Adjoint S(ctls, q);
3516 H(q);
3517 for c in ctls {
3518 H(c);
3519 }
3520 DumpMachine();
3521 Reset(q);
3522 ResetAll(ctls);
3523 }
3524 "},
3525 &Value::unit(),
3526 );
3527
3528 expect![[r#"
3529 STATE:
3530 |0000⟩: 1.0000+0.0000𝑖
3531 "#]]
3532 .assert_eq(&dump);
3533}
3534
3535#[test]
3536fn global_phase_correct_for_triply_controlled_adjoint_r1() {
3537 let dump = test_expression(
3538 indoc! {"
3539 {
3540 open Std.Math;
3541 open Std.Diagnostics;
3542 use ctls = Qubit[3];
3543 use q = Qubit();
3544 for c in ctls {
3545 H(c);
3546 }
3547 H(q);
3548 Adjoint Controlled R1(ctls, (PI() / 2.0, q));
3549 Controlled S(ctls, q);
3550 H(q);
3551 for c in ctls {
3552 H(c);
3553 }
3554 DumpMachine();
3555 Reset(q);
3556 ResetAll(ctls);
3557 }
3558 "},
3559 &Value::unit(),
3560 );
3561
3562 expect![[r#"
3563 STATE:
3564 |0000⟩: 1.0000+0.0000𝑖
3565 "#]]
3566 .assert_eq(&dump);
3567}
3568
3569#[test]
3570fn test_exp() {
3571 let dump = test_expression(
3572 indoc! {r#"
3573 {
3574 open Std.Math;
3575 open Std.Diagnostics;
3576 for p in [PauliX, PauliY, PauliZ, PauliI] {
3577 for i in 1 .. 4 {
3578 Message($"Exp with {p} on {i} qubits:");
3579 use qs = Qubit[i];
3580 for q in qs {
3581 H(q);
3582 }
3583 Exp(Repeated(p, i), PI() / 7.0, qs);
3584 DumpMachine();
3585 ResetAll(qs);
3586 }
3587 }
3588 }
3589 "#},
3590 &Value::unit(),
3591 );
3592
3593 expect![[r#"
3594 Exp with PauliX on 1 qubits:
3595 STATE:
3596 |0⟩: 0.6371+0.3068𝑖
3597 |1⟩: 0.6371+0.3068𝑖
3598 Exp with PauliX on 2 qubits:
3599 STATE:
3600 |00⟩: 0.4505+0.2169𝑖
3601 |01⟩: 0.4505+0.2169𝑖
3602 |10⟩: 0.4505+0.2169𝑖
3603 |11⟩: 0.4505+0.2169𝑖
3604 Exp with PauliX on 3 qubits:
3605 STATE:
3606 |000⟩: 0.3185+0.1534𝑖
3607 |001⟩: 0.3185+0.1534𝑖
3608 |010⟩: 0.3185+0.1534𝑖
3609 |011⟩: 0.3185+0.1534𝑖
3610 |100⟩: 0.3185+0.1534𝑖
3611 |101⟩: 0.3185+0.1534𝑖
3612 |110⟩: 0.3185+0.1534𝑖
3613 |111⟩: 0.3185+0.1534𝑖
3614 Exp with PauliX on 4 qubits:
3615 STATE:
3616 |0000⟩: 0.2252+0.1085𝑖
3617 |0001⟩: 0.2252+0.1085𝑖
3618 |0010⟩: 0.2252+0.1085𝑖
3619 |0011⟩: 0.2252+0.1085𝑖
3620 |0100⟩: 0.2252+0.1085𝑖
3621 |0101⟩: 0.2252+0.1085𝑖
3622 |0110⟩: 0.2252+0.1085𝑖
3623 |0111⟩: 0.2252+0.1085𝑖
3624 |1000⟩: 0.2252+0.1085𝑖
3625 |1001⟩: 0.2252+0.1085𝑖
3626 |1010⟩: 0.2252+0.1085𝑖
3627 |1011⟩: 0.2252+0.1085𝑖
3628 |1100⟩: 0.2252+0.1085𝑖
3629 |1101⟩: 0.2252+0.1085𝑖
3630 |1110⟩: 0.2252+0.1085𝑖
3631 |1111⟩: 0.2252+0.1085𝑖
3632 Exp with PauliY on 1 qubits:
3633 STATE:
3634 |0⟩: 0.9439+0.0000𝑖
3635 |1⟩: 0.3303+0.0000𝑖
3636 Exp with PauliY on 2 qubits:
3637 STATE:
3638 |00⟩: 0.4505−0.2169𝑖
3639 |01⟩: 0.4505+0.2169𝑖
3640 |10⟩: 0.4505+0.2169𝑖
3641 |11⟩: 0.4505−0.2169𝑖
3642 Exp with PauliY on 3 qubits:
3643 STATE:
3644 |000⟩: 0.1651+0.0000𝑖
3645 |001⟩: 0.4719+0.0000𝑖
3646 |010⟩: 0.4719+0.0000𝑖
3647 |011⟩: 0.1651+0.0000𝑖
3648 |100⟩: 0.4719+0.0000𝑖
3649 |101⟩: 0.1651+0.0000𝑖
3650 |110⟩: 0.1651+0.0000𝑖
3651 |111⟩: 0.4719+0.0000𝑖
3652 Exp with PauliY on 4 qubits:
3653 STATE:
3654 |0000⟩: 0.2252+0.1085𝑖
3655 |0001⟩: 0.2252−0.1085𝑖
3656 |0010⟩: 0.2252−0.1085𝑖
3657 |0011⟩: 0.2252+0.1085𝑖
3658 |0100⟩: 0.2252−0.1085𝑖
3659 |0101⟩: 0.2252+0.1085𝑖
3660 |0110⟩: 0.2252+0.1085𝑖
3661 |0111⟩: 0.2252−0.1085𝑖
3662 |1000⟩: 0.2252−0.1085𝑖
3663 |1001⟩: 0.2252+0.1085𝑖
3664 |1010⟩: 0.2252+0.1085𝑖
3665 |1011⟩: 0.2252−0.1085𝑖
3666 |1100⟩: 0.2252+0.1085𝑖
3667 |1101⟩: 0.2252−0.1085𝑖
3668 |1110⟩: 0.2252−0.1085𝑖
3669 |1111⟩: 0.2252+0.1085𝑖
3670 Exp with PauliZ on 1 qubits:
3671 STATE:
3672 |0⟩: 0.6371+0.3068𝑖
3673 |1⟩: 0.6371−0.3068𝑖
3674 Exp with PauliZ on 2 qubits:
3675 STATE:
3676 |00⟩: 0.4505+0.2169𝑖
3677 |01⟩: 0.4505−0.2169𝑖
3678 |10⟩: 0.4505−0.2169𝑖
3679 |11⟩: 0.4505+0.2169𝑖
3680 Exp with PauliZ on 3 qubits:
3681 STATE:
3682 |000⟩: 0.3185+0.1534𝑖
3683 |001⟩: 0.3185−0.1534𝑖
3684 |010⟩: 0.3185−0.1534𝑖
3685 |011⟩: 0.3185+0.1534𝑖
3686 |100⟩: 0.3185−0.1534𝑖
3687 |101⟩: 0.3185+0.1534𝑖
3688 |110⟩: 0.3185+0.1534𝑖
3689 |111⟩: 0.3185−0.1534𝑖
3690 Exp with PauliZ on 4 qubits:
3691 STATE:
3692 |0000⟩: 0.2252+0.1085𝑖
3693 |0001⟩: 0.2252−0.1085𝑖
3694 |0010⟩: 0.2252−0.1085𝑖
3695 |0011⟩: 0.2252+0.1085𝑖
3696 |0100⟩: 0.2252−0.1085𝑖
3697 |0101⟩: 0.2252+0.1085𝑖
3698 |0110⟩: 0.2252+0.1085𝑖
3699 |0111⟩: 0.2252−0.1085𝑖
3700 |1000⟩: 0.2252−0.1085𝑖
3701 |1001⟩: 0.2252+0.1085𝑖
3702 |1010⟩: 0.2252+0.1085𝑖
3703 |1011⟩: 0.2252−0.1085𝑖
3704 |1100⟩: 0.2252+0.1085𝑖
3705 |1101⟩: 0.2252−0.1085𝑖
3706 |1110⟩: 0.2252−0.1085𝑖
3707 |1111⟩: 0.2252+0.1085𝑖
3708 Exp with PauliI on 1 qubits:
3709 STATE:
3710 |0⟩: 0.6371+0.3068𝑖
3711 |1⟩: 0.6371+0.3068𝑖
3712 Exp with PauliI on 2 qubits:
3713 STATE:
3714 |00⟩: 0.4505+0.2169𝑖
3715 |01⟩: 0.4505+0.2169𝑖
3716 |10⟩: 0.4505+0.2169𝑖
3717 |11⟩: 0.4505+0.2169𝑖
3718 Exp with PauliI on 3 qubits:
3719 STATE:
3720 |000⟩: 0.3185+0.1534𝑖
3721 |001⟩: 0.3185+0.1534𝑖
3722 |010⟩: 0.3185+0.1534𝑖
3723 |011⟩: 0.3185+0.1534𝑖
3724 |100⟩: 0.3185+0.1534𝑖
3725 |101⟩: 0.3185+0.1534𝑖
3726 |110⟩: 0.3185+0.1534𝑖
3727 |111⟩: 0.3185+0.1534𝑖
3728 Exp with PauliI on 4 qubits:
3729 STATE:
3730 |0000⟩: 0.2252+0.1085𝑖
3731 |0001⟩: 0.2252+0.1085𝑖
3732 |0010⟩: 0.2252+0.1085𝑖
3733 |0011⟩: 0.2252+0.1085𝑖
3734 |0100⟩: 0.2252+0.1085𝑖
3735 |0101⟩: 0.2252+0.1085𝑖
3736 |0110⟩: 0.2252+0.1085𝑖
3737 |0111⟩: 0.2252+0.1085𝑖
3738 |1000⟩: 0.2252+0.1085𝑖
3739 |1001⟩: 0.2252+0.1085𝑖
3740 |1010⟩: 0.2252+0.1085𝑖
3741 |1011⟩: 0.2252+0.1085𝑖
3742 |1100⟩: 0.2252+0.1085𝑖
3743 |1101⟩: 0.2252+0.1085𝑖
3744 |1110⟩: 0.2252+0.1085𝑖
3745 |1111⟩: 0.2252+0.1085𝑖
3746 "#]]
3747 .assert_eq(&dump);
3748}
3749
3750#[test]
3751fn test_exp_mixed_paulis() {
3752 let dump = test_expression(
3753 indoc! {r#"
3754 {
3755 open Std.Math;
3756 open Std.Diagnostics;
3757 use qs = Qubit[3];
3758 for q in qs {
3759 H(q);
3760 }
3761 Exp([PauliX, PauliI, PauliY], PI() / 7.0, qs);
3762 DumpMachine();
3763 ResetAll(qs);
3764 }
3765 "#},
3766 &Value::unit(),
3767 );
3768
3769 expect![[r#"
3770 STATE:
3771 |000⟩: 0.4719+0.0000𝑖
3772 |001⟩: 0.1651+0.0000𝑖
3773 |010⟩: 0.4719+0.0000𝑖
3774 |011⟩: 0.1651+0.0000𝑖
3775 |100⟩: 0.4719+0.0000𝑖
3776 |101⟩: 0.1651+0.0000𝑖
3777 |110⟩: 0.4719+0.0000𝑖
3778 |111⟩: 0.1651+0.0000𝑖
3779 "#]]
3780 .assert_eq(&dump);
3781}
3782
3783#[test]
3784fn test_rxx() {
3785 let dump = test_expression(
3786 indoc! {"
3787 Std.Diagnostics.DumpOperation(
3788 2,
3789 qs => Rxx(Std.Math.PI() / 3.0, qs[0], qs[1])
3790 )
3791 "},
3792 &Value::unit(),
3793 );
3794
3795 expect![[r#"
3796 MATRIX:
3797 0.8660+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000−0.5000𝑖
3798 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000−0.5000𝑖 0.0000+0.0000𝑖
3799 0.0000+0.0000𝑖 0.0000−0.5000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖
3800 0.0000−0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖
3801 "#]]
3802 .assert_eq(&dump);
3803}
3804
3805#[test]
3806fn test_rxx_one_control() {
3807 let dump = test_expression(
3808 indoc! {"
3809 Std.Diagnostics.DumpOperation(
3810 3,
3811 qs => Controlled Rxx([qs[0]], (Std.Math.PI() / 3.0, qs[1], qs[2]))
3812 )
3813 "},
3814 &Value::unit(),
3815 );
3816
3817 expect![[r#"
3818 MATRIX:
3819 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3820 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3821 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3822 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3823 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000−0.5000𝑖
3824 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000−0.5000𝑖 0.0000+0.0000𝑖
3825 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000−0.5000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖
3826 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000−0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖
3827 "#]]
3828 .assert_eq(&dump);
3829}
3830
3831#[test]
3832fn test_ryy() {
3833 let dump = test_expression(
3834 indoc! {"
3835 Std.Diagnostics.DumpOperation(
3836 2,
3837 qs => Ryy(Std.Math.PI() / 3.0, qs[0], qs[1])
3838 )
3839 "},
3840 &Value::unit(),
3841 );
3842
3843 expect![[r#"
3844 MATRIX:
3845 0.8660+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.5000𝑖
3846 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000−0.5000𝑖 0.0000+0.0000𝑖
3847 0.0000+0.0000𝑖 0.0000−0.5000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖
3848 0.0000+0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖
3849 "#]]
3850 .assert_eq(&dump);
3851}
3852
3853#[test]
3854fn test_ryy_one_control() {
3855 let dump = test_expression(
3856 indoc! {"
3857 Std.Diagnostics.DumpOperation(
3858 3,
3859 qs => Controlled Ryy([qs[0]], (Std.Math.PI() / 3.0, qs[1], qs[2]))
3860 )
3861 "},
3862 &Value::unit(),
3863 );
3864
3865 expect![[r#"
3866 MATRIX:
3867 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3868 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3869 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3870 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3871 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.5000𝑖
3872 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖 0.0000−0.5000𝑖 0.0000+0.0000𝑖
3873 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000−0.5000𝑖 0.8660+0.0000𝑖 0.0000+0.0000𝑖
3874 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.0000𝑖
3875 "#]]
3876 .assert_eq(&dump);
3877}
3878
3879#[test]
3880fn test_rzz() {
3881 let dump = test_expression(
3882 indoc! {"
3883 Std.Diagnostics.DumpOperation(
3884 2,
3885 qs => Rzz(Std.Math.PI() / 3.0, qs[0], qs[1])
3886 )
3887 "},
3888 &Value::unit(),
3889 );
3890
3891 expect![[r#"
3892 MATRIX:
3893 0.8660−0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3894 0.0000+0.0000𝑖 0.8660+0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3895 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.5000𝑖 0.0000+0.0000𝑖
3896 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660−0.5000𝑖
3897 "#]]
3898 .assert_eq(&dump);
3899}
3900
3901#[test]
3902fn test_rzz_one_control() {
3903 let dump = test_expression(
3904 indoc! {"
3905 Std.Diagnostics.DumpOperation(
3906 3,
3907 qs => Controlled Rzz([qs[0]], (Std.Math.PI() / 3.0, qs[1], qs[2]))
3908 )
3909 "},
3910 &Value::unit(),
3911 );
3912
3913 expect![[r#"
3914 MATRIX:
3915 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3916 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3917 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3918 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 1.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3919 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660−0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3920 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.5000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖
3921 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660+0.5000𝑖 0.0000+0.0000𝑖
3922 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.0000+0.0000𝑖 0.8660−0.5000𝑖
3923 "#]]
3924 .assert_eq(&dump);
3925}
3926
3927#[test]
3928fn test_apply_unitary_with_h_matrix() {
3929 let dump = test_expression(
3930 indoc! {"
3931 {
3932 open Std.Math;
3933 open Std.Diagnostics;
3934 use q = Qubit();
3935 let one_sqrt_2 = new Complex { Real = 1.0 / Sqrt(2.0), Imag = 0.0 };
3936 ApplyUnitary(
3937 [
3938 [one_sqrt_2, one_sqrt_2],
3939 [one_sqrt_2, NegationC(one_sqrt_2)]
3940 ],
3941 [q]
3942 );
3943 DumpMachine();
3944 Reset(q);
3945 }
3946 "},
3947 &Value::unit(),
3948 );
3949
3950 expect![[r#"
3951 STATE:
3952 |0⟩: 0.7071+0.0000𝑖
3953 |1⟩: 0.7071+0.0000𝑖
3954 "#]]
3955 .assert_eq(&dump);
3956}
3957
3958#[test]
3959fn test_apply_unitary_with_swap_matrix() {
3960 let dump = test_expression(
3961 indoc! {"
3962 {
3963 open Std.Math;
3964 open Std.Diagnostics;
3965 use qs = Qubit[2];
3966 H(qs[0]);
3967 DumpMachine();
3968 let one = new Complex { Real = 1.0, Imag = 0.0 };
3969 let zero = new Complex { Real = 0.0, Imag = 0.0 };
3970 ApplyUnitary(
3971 [
3972 [one, zero, zero, zero],
3973 [zero, zero, one, zero],
3974 [zero, one, zero, zero],
3975 [zero, zero, zero, one]
3976 ],
3977 qs
3978 );
3979 DumpMachine();
3980 ResetAll(qs);
3981 }
3982 "},
3983 &Value::unit(),
3984 );
3985
3986 expect![[r#"
3987 STATE:
3988 |00⟩: 0.7071+0.0000𝑖
3989 |10⟩: 0.7071+0.0000𝑖
3990 STATE:
3991 |00⟩: 0.7071+0.0000𝑖
3992 |01⟩: 0.7071+0.0000𝑖
3993 "#]]
3994 .assert_eq(&dump);
3995}
3996
3997#[test]
3998fn test_apply_unitary_fails_when_matrix_not_square() {
3999 let err = test_expression_fails(indoc! {"
4000 {
4001 open Std.Math;
4002 open Std.Diagnostics;
4003 use q = Qubit();
4004 ApplyUnitary(
4005 [
4006 [new Complex { Real = 1.0, Imag = 0.0 }],
4007 [new Complex { Real = 0.0, Imag = 0.0 }]
4008 ],
4009 [q]
4010 );
4011 DumpMachine();
4012 Reset(q);
4013 }
4014 "});
4015
4016 expect!["program failed: matrix passed to ApplyUnitary must be square."].assert_eq(&err);
4017}
4018
4019#[test]
4020fn test_apply_unitary_fails_when_matrix_wrong_size() {
4021 let err = test_expression_fails(indoc! {"
4022 {
4023 open Std.Math;
4024 open Std.Diagnostics;
4025 use qs = Qubit[2];
4026 let one_sqrt_2 = new Complex { Real = 1.0 / Sqrt(2.0), Imag = 0.0 };
4027 ApplyUnitary(
4028 [
4029 [one_sqrt_2, one_sqrt_2],
4030 [one_sqrt_2, NegationC(one_sqrt_2)]
4031 ],
4032 qs
4033 );
4034 DumpMachine();
4035 ResetAll(qs);
4036 }
4037 "});
4038
4039 expect!["program failed: matrix passed to ApplyUnitary must have dimensions 2^Length(qubits)."]
4040 .assert_eq(&err);
4041}
4042
4043#[test]
4044fn test_apply_unitary_fails_when_matrix_not_unitary() {
4045 let err = test_expression_fails(indoc! {"
4046 {
4047 open Std.Math;
4048 open Std.Diagnostics;
4049 use q = Qubit();
4050 let zero = new Complex { Real = 0.0, Imag = 0.0 };
4051 ApplyUnitary(
4052 [
4053 [zero, zero],
4054 [zero, zero]
4055 ],
4056 [q]
4057 );
4058 DumpMachine();
4059 Reset(q);
4060 }
4061 "});
4062
4063 expect!["intrinsic callable `Apply` failed: matrix is not unitary"].assert_eq(&err);
4064}
4065