microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9c33427155ee7a0d2f2beebc2f03d7c4609b6e4f

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/src/tests/canon.rs

761lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::{test_expression, test_expression_with_lib};
5use indoc::indoc;
6use qsc::interpret::Value;
7
8// Tests for Microsoft.Quantum.Canon namespace
9
10#[test]
11fn check_apply_to_each() {
12 test_expression(
13 indoc! {r#"{
14 use register = Qubit[3];
15 ApplyToEach(X, register);
16 let results = Microsoft.Quantum.Measurement.MeasureEachZ(register);
17 ResetAll(register);
18 results
19 }"#},
20 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
21 );
22}
23
24#[test]
25fn check_apply_to_each_a() {
26 test_expression(
27 indoc! {r#"{
28 use register = Qubit[3];
29 ApplyToEach(X, register);
30 Adjoint Microsoft.Quantum.Canon.ApplyToEachA(X, register);
31 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
32 results
33 }"#},
34 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ZERO, Value::RESULT_ZERO].into()),
35 );
36}
37
38#[test]
39fn check_apply_to_each_c_applied() {
40 test_expression(
41 indoc! {r#"{
42 use control = Qubit();
43 use register = Qubit[3];
44 Controlled Microsoft.Quantum.Canon.ApplyToEachC([control], (X, register));
45 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
46 Reset(control);
47 results
48 }"#},
49 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ZERO, Value::RESULT_ZERO].into()),
50 );
51}
52
53#[test]
54fn check_apply_to_each_c_not_applied() {
55 test_expression(
56 indoc! {r#"{
57 use control = Qubit();
58 use register = Qubit[3];
59 X(control);
60 Controlled Microsoft.Quantum.Canon.ApplyToEachC([control], (X, register));
61 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
62 Reset(control);
63 results
64 }"#},
65 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
66 );
67}
68
69#[test]
70fn check_apply_to_each_ca_applied() {
71 test_expression(
72 indoc! {r#"{
73 use control = Qubit();
74 use register = Qubit[3];
75 Microsoft.Quantum.Canon.ApplyToEach(X, register);
76 Controlled Adjoint Microsoft.Quantum.Canon.ApplyToEachCA([control], (X, register));
77 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
78 Reset(control);
79 results
80 }"#},
81 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
82 );
83}
84
85#[test]
86fn check_apply_to_each_ca_not_applied() {
87 test_expression(
88 indoc! {r#"{
89 use control = Qubit();
90 use register = Qubit[3];
91 X(control);
92 Microsoft.Quantum.Canon.ApplyToEach(X, register);
93 Controlled Adjoint Microsoft.Quantum.Canon.ApplyToEachCA([control], (X, register));
94 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
95 Reset(control);
96 results
97 }"#},
98 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ZERO, Value::RESULT_ZERO].into()),
99 );
100}
101
102#[test]
103fn check_fst_snd() {
104 test_expression("Fst(7,6)", &Value::Int(7));
105 test_expression("Snd(7,6)", &Value::Int(6));
106}
107
108#[test]
109fn check_swap_labels() {
110 test_expression(
111 "{
112 use qs = Qubit[2];
113 X(qs[0]);
114 Relabel(qs, [qs[1], qs[0]]);
115 MResetEachZ(qs)
116 }",
117 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ONE].into()),
118 );
119}
120
121#[test]
122fn check_relabel_rotational_permutation() {
123 test_expression(
124 "{
125 use qs = Qubit[3];
126 // Prepare |01+⟩
127 X(qs[1]);
128 H(qs[2]);
129 Relabel([qs[0], qs[1], qs[2]], [qs[1], qs[2], qs[0]]);
130 // Expected state is |1+0⟩, perform adjoint to get back to ground state.
131 X(qs[0]);
132 H(qs[1]);
133 // Qubit release will fail if the state is not |000⟩
134 }",
135 &Value::unit(),
136 );
137}
138
139#[test]
140fn check_relabel_rotational_permutation_alternate_expression() {
141 test_expression(
142 "{
143 use qs = Qubit[3];
144 // Prepare |01+⟩
145 X(qs[1]);
146 H(qs[2]);
147 Relabel([qs[2], qs[0], qs[1]], [qs[0], qs[1], qs[2]]);
148 // Expected state is |1+0⟩, perform adjoint to get back to ground state.
149 X(qs[0]);
150 H(qs[1]);
151 // Qubit release will fail if the state is not |000⟩
152 }",
153 &Value::unit(),
154 );
155}
156
157#[test]
158fn check_relabel_rotational_permutation_size_4() {
159 test_expression(
160 "{
161 use qs = Qubit[4];
162 // Prepare |01+0⟩
163 X(qs[1]);
164 H(qs[2]);
165 Relabel(qs, qs[2...] + qs[0..1]);
166 // Expected state is |+001⟩, perform adjoint to get back to ground state.
167 H(qs[0]);
168 X(qs[Length(qs)-1]);
169 // Qubit release will fail if the state is not |000⟩
170 }",
171 &Value::unit(),
172 );
173}
174
175#[test]
176fn check_relabel_rotational_permutation_size_5() {
177 test_expression(
178 "{
179 use qs = Qubit[5];
180 // Prepare |01+00⟩
181 X(qs[1]);
182 H(qs[2]);
183 Relabel(qs, qs[2...] + qs[0..1]);
184 // Expected state is |+0001⟩, perform adjoint to get back to ground state.
185 H(qs[0]);
186 X(qs[Length(qs)-1]);
187 // Qubit release will fail if the state is not |000⟩
188 }",
189 &Value::unit(),
190 );
191}
192
193#[test]
194fn check_relabel_rotational_permutation_size_6() {
195 test_expression(
196 "{
197 use qs = Qubit[6];
198 // Prepare |01+000⟩
199 X(qs[1]);
200 H(qs[2]);
201 Relabel(qs, qs[2...] + qs[0..1]);
202 // Expected state is |+00001⟩, perform adjoint to get back to ground state.
203 H(qs[0]);
204 X(qs[Length(qs)-1]);
205 // Qubit release will fail if the state is not |000⟩
206 }",
207 &Value::unit(),
208 );
209}
210
211#[test]
212fn check_relabel_rotational_permutation_size_7() {
213 test_expression(
214 "{
215 use qs = Qubit[7];
216 // Prepare |01+0000⟩
217 X(qs[1]);
218 H(qs[2]);
219 Relabel(qs, qs[2...] + qs[0..1]);
220 // Expected state is |+000001⟩, perform adjoint to get back to ground state.
221 H(qs[0]);
222 X(qs[Length(qs)-1]);
223 // Qubit release will fail if the state is not |000⟩
224 }",
225 &Value::unit(),
226 );
227}
228
229#[test]
230fn check_relabel_four_qubit_shuffle_permutation() {
231 test_expression(
232 "{
233 use qs = Qubit[4];
234 // Prepare |01+i⟩
235 X(qs[1]);
236 H(qs[2]);
237 H(qs[3]);
238 S(qs[3]);
239 H(qs[3]);
240 Relabel([qs[0], qs[1], qs[2], qs[3]], [qs[1], qs[0], qs[3], qs[2]]);
241 // Expected state is |10i+⟩, perform adjoint to get back to ground state.
242 X(qs[0]);
243 H(qs[2]);
244 Adjoint S(qs[2]);
245 H(qs[2]);
246 H(qs[3]);
247 // Qubit release will fail if the state is not |0000⟩
248 }",
249 &Value::unit(),
250 );
251}
252
253#[test]
254fn check_relabel_five_qubit_shuffle_permutation() {
255 test_expression(
256 "{
257 use qs = Qubit[5];
258 // Prepare |01+i-⟩
259 X(qs[1]);
260 H(qs[2]);
261 H(qs[3]);
262 S(qs[3]);
263 H(qs[3]);
264 H(qs[4]);
265 Z(qs[4]);
266 Relabel([qs[0], qs[1], qs[2], qs[3], qs[4]], [qs[1], qs[0], qs[3], qs[4], qs[2]]);
267 // Expected state is |10i-+⟩, perform adjoint to get back to ground state.
268 X(qs[0]);
269 H(qs[2]);
270 Adjoint S(qs[2]);
271 H(qs[2]);
272 Z(qs[3]);
273 H(qs[3]);
274 H(qs[4]);
275 // Qubit release will fail if the state is not |0000⟩
276 }",
277 &Value::unit(),
278 );
279}
280
281#[test]
282fn check_relabel_adjoint_undoes_permutation() {
283 test_expression(
284 "{
285 use qs = Qubit[3];
286 // Prepare |01+⟩
287 X(qs[1]);
288 H(qs[2]);
289 Relabel([qs[0], qs[1], qs[2]], [qs[1], qs[2], qs[0]]);
290 // Expected state is |1+0⟩, perform part of the adjoint to correct one of the qubits.
291 X(qs[0]);
292 Adjoint Relabel([qs[0], qs[1], qs[2]], [qs[1], qs[2], qs[0]]);
293 // Expected state is now |00+⟩, perform the rest of the adjoint to get back to ground state,
294 // using the original qubit ids.
295 H(qs[2]);
296 // Qubit release will fail if the state is not |000⟩
297 }",
298 &Value::unit(),
299 );
300}
301
302#[test]
303fn check_apply_cnot_chain_2() {
304 test_expression(
305 {
306 "{
307 use a = Qubit[2];
308 mutable result = [];
309 within {
310 X(a[0]);
311 X(a[1]);
312 ApplyCNOTChain(a);
313 }
314 apply {
315 set result = [M(a[0]),M(a[1])];
316 }
317 return result;
318 }"
319 },
320 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ZERO].into()),
321 );
322}
323
324#[test]
325fn check_apply_cnot_chain_3() {
326 test_expression(
327 {
328 "{
329 use a = Qubit[3];
330 mutable result = [];
331 within {
332 X(a[0]);
333 ApplyCNOTChain(a);
334 }
335 apply {
336 set result = [M(a[0]),M(a[1]),M(a[2])];
337 }
338 return result;
339 }"
340 },
341 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
342 );
343}
344
345#[test]
346fn check_apply_cnot_chain_3a() {
347 test_expression(
348 {
349 "{
350 use a = Qubit[3];
351 mutable result = [];
352 within {
353 X(a[0]);
354 X(a[2]);
355 ApplyCNOTChain(a);
356 }
357 apply {
358 set result = [M(a[0]),M(a[1]),M(a[2])];
359 }
360 return result;
361 }"
362 },
363 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ZERO].into()),
364 );
365}
366
367#[test]
368fn check_apply_p() {
369 test_expression(
370 {
371 "{
372 use q = Qubit[3];
373 ApplyP(PauliX, q[0]);
374 H(q[1]); ApplyP(PauliY, q[1]);
375 H(q[2]); S(q[2]); ApplyP(PauliZ, q[2]);
376 return [MResetZ(q[0]),MResetX(q[1]),MResetY(q[2])];
377 }"
378 },
379 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
380 );
381}
382
383#[test]
384fn check_apply_pauli() {
385 test_expression(
386 {
387 "{
388 use q = Qubit[3];
389 H(q[1]);
390 H(q[2]); S(q[2]);
391 ApplyPauli([PauliX, PauliY, PauliZ], q);
392 return [MResetZ(q[0]),MResetX(q[1]),MResetY(q[2])];
393 }"
394 },
395 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ONE].into()),
396 );
397}
398
399#[test]
400fn check_apply_pauli_from_bit_string() {
401 test_expression(
402 {
403 "{
404 use q = Qubit[3];
405 ApplyPauliFromBitString(PauliX, false, [true, false, true], q);
406 return MResetEachZ(q);
407 }"
408 },
409 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ONE, Value::RESULT_ZERO].into()),
410 );
411}
412
413#[test]
414fn check_apply_pauli_from_int() {
415 test_expression(
416 {
417 "{
418 use q = Qubit[3];
419 ApplyPauliFromInt(PauliX, false, 5, q);
420 return MResetEachZ(q);
421 }"
422 },
423 &Value::Array(vec![Value::RESULT_ZERO, Value::RESULT_ONE, Value::RESULT_ZERO].into()),
424 );
425}
426
427#[test]
428fn check_map_pauli_x_x() {
429 test_expression(
430 {
431 "{
432 Std.Diagnostics.CheckOperationsAreEqual(1,
433 q => MapPauliAxis(PauliX, PauliX, q[0]),
434 q => I(q[0])
435 )
436 }"
437 },
438 &Value::Bool(true),
439 );
440}
441
442#[test]
443fn check_map_pauli_y_y() {
444 test_expression(
445 {
446 "{
447 Std.Diagnostics.CheckOperationsAreEqual(1,
448 q => MapPauliAxis(PauliY, PauliY, q[0]),
449 q => I(q[0])
450 )
451 }"
452 },
453 &Value::Bool(true),
454 );
455}
456
457#[test]
458fn check_map_pauli_z_z() {
459 test_expression(
460 {
461 "{
462 Std.Diagnostics.CheckOperationsAreEqual(1,
463 q => MapPauliAxis(PauliZ, PauliZ, q[0]),
464 q => I(q[0])
465 )
466 }"
467 },
468 &Value::Bool(true),
469 );
470}
471
472#[test]
473fn check_map_pauli_x_y() {
474 test_expression(
475 {
476 "{
477 Std.Diagnostics.CheckOperationsAreEqual(1,
478 q => { within { MapPauliAxis(PauliX, PauliY, q[0]) } apply { Rx(0.1, q[0]) } },
479 q => { within { Adjoint S(q[0]) } apply { Rx(0.1, q[0]) } }
480 )
481 }"
482 },
483 &Value::Bool(true),
484 );
485}
486
487#[test]
488fn check_map_pauli_y_x() {
489 test_expression(
490 {
491 "{
492 Std.Diagnostics.CheckOperationsAreEqual(1,
493 q => { within { MapPauliAxis(PauliY, PauliX, q[0]) } apply { Ry(0.1, q[0]) } },
494 q => { within { S(q[0]) } apply { Ry(0.1, q[0]) } }
495 )
496 }"
497 },
498 &Value::Bool(true),
499 );
500}
501
502#[test]
503fn check_map_pauli_x_z() {
504 test_expression(
505 {
506 "{
507 Std.Diagnostics.CheckOperationsAreEqual(1,
508 q => { within { MapPauliAxis(PauliX, PauliZ, q[0]) } apply { Rx(0.1, q[0]) } },
509 q => { within { H(q[0]) } apply { Rx(0.1, q[0]) } }
510 )
511 }"
512 },
513 &Value::Bool(true),
514 );
515}
516
517#[test]
518fn check_map_pauli_z_x() {
519 test_expression(
520 {
521 "{
522 Std.Diagnostics.CheckOperationsAreEqual(1,
523 q => { within { MapPauliAxis(PauliZ, PauliX, q[0]) } apply { Rz(0.1, q[0]) } },
524 q => { within { H(q[0]) } apply { Rz(0.1, q[0]) } }
525 )
526 }"
527 },
528 &Value::Bool(true),
529 );
530}
531
532#[test]
533fn check_map_pauli_y_z() {
534 test_expression(
535 {
536 "{
537 Std.Diagnostics.CheckOperationsAreEqual(1,
538 q => { within { MapPauliAxis(PauliY, PauliZ, q[0]) } apply { Ry(0.1, q[0]) } },
539 q => { within { H(q[0]); Adjoint S(q[0]); H(q[0]) } apply { Ry(0.1, q[0]) } }
540 )
541 }"
542 },
543 &Value::Bool(true),
544 );
545}
546
547#[test]
548fn check_map_pauli_z_y() {
549 test_expression(
550 {
551 "{
552 Std.Diagnostics.CheckOperationsAreEqual(1,
553 q => { within { MapPauliAxis(PauliZ, PauliY, q[0]) } apply { Rz(0.1, q[0]) } },
554 q => { within { H(q[0]); S(q[0]); H(q[0]) } apply { Rz(0.1, q[0]) } }
555 )
556 }"
557 },
558 &Value::Bool(true),
559 );
560}
561
562#[test]
563fn check_apply_controlled_on_int() {
564 test_expression(
565 {
566 "{
567 use c = Qubit[3];
568 use t1 = Qubit();
569 use t2 = Qubit();
570 within {
571 X(c[0]);
572 X(c[2]);
573 } apply {
574 ApplyControlledOnInt(5, X, c, t1);
575 }
576 ApplyControlledOnInt(5, X, c, t2);
577 return [MResetZ(t1), M(t2)];
578 }"
579 },
580 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ZERO].into()),
581 );
582}
583
584#[test]
585fn check_apply_controlled_on_bitstring() {
586 test_expression(
587 {
588 "{
589 use c = Qubit[4];
590 use t1 = Qubit();
591 use t2 = Qubit();
592 within {
593 X(c[0]);
594 X(c[2]);
595 } apply {
596 ApplyControlledOnBitString([true, false, true], X, c, t1);
597 }
598 ApplyControlledOnBitString([true, false, true], X, c, t2);
599 return [MResetZ(t1), M(t2)];
600 }"
601 },
602 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ZERO].into()),
603 );
604}
605
606const QFT_LE_TEST_LIB: &str = include_str!("resources/src/qft_le.qs");
607
608#[test]
609fn check_qft_le_sample_1() {
610 test_expression_with_lib(
611 "Test.TestQFT(1)",
612 QFT_LE_TEST_LIB,
613 &Value::Tuple(vec![].into(), None),
614 );
615}
616
617#[test]
618fn check_qft_le_sample_2() {
619 test_expression_with_lib(
620 "Test.TestQFT(2)",
621 QFT_LE_TEST_LIB,
622 &Value::Tuple(vec![].into(), None),
623 );
624}
625#[test]
626fn check_qft_le_sample_3() {
627 test_expression_with_lib(
628 "Test.TestQFT(3)",
629 QFT_LE_TEST_LIB,
630 &Value::Tuple(vec![].into(), None),
631 );
632}
633#[test]
634fn check_qft_le_sample_4() {
635 test_expression_with_lib(
636 "Test.TestQFT(4)",
637 QFT_LE_TEST_LIB,
638 &Value::Tuple(vec![].into(), None),
639 );
640}
641
642const QPE_TEST_LIB: &str = include_str!("resources/src/qpe.qs");
643
644#[test]
645fn check_qpe_z() {
646 test_expression_with_lib(
647 "Test.TestQPE_Z()",
648 QPE_TEST_LIB,
649 &Value::Tuple(vec![].into(), None),
650 );
651}
652
653#[test]
654fn check_qpe_s() {
655 test_expression_with_lib(
656 "Test.TestQPE_S()",
657 QPE_TEST_LIB,
658 &Value::Tuple(vec![].into(), None),
659 );
660}
661
662#[test]
663fn check_qpe_t() {
664 test_expression_with_lib(
665 "Test.TestQPE_T()",
666 QPE_TEST_LIB,
667 &Value::Tuple(vec![].into(), None),
668 );
669}
670
671#[test]
672fn check_qpe_p() {
673 test_expression_with_lib(
674 "Test.TestQPE_P()",
675 QPE_TEST_LIB,
676 &Value::Tuple(vec![].into(), None),
677 );
678}
679
680#[test]
681fn check_swap_reverse_register() {
682 test_expression(
683 {
684 "{
685 use q = Qubit[10];
686 ApplyXorInPlace(328, q);
687 SwapReverseRegister(q);
688 let r = MeasureInteger(q);
689 ResetAll(q);
690 r
691 }"
692 },
693 &Value::Int(74),
694 );
695}
696
697#[test]
698fn check_apply_xor_in_place() {
699 test_expression(
700 {
701 "{
702 use a = Qubit[3];
703 mutable result = [];
704 within {
705 ApplyXorInPlace(3, a);
706 }
707 apply {
708 set result = [M(a[0]),M(a[1]),M(a[2])];
709 }
710 return result;
711 }"
712 },
713 &Value::Array(vec![Value::RESULT_ONE, Value::RESULT_ONE, Value::RESULT_ZERO].into()),
714 );
715}
716
717#[test]
718fn check_apply_xor_in_place_l() {
719 test_expression(
720 {
721 "{
722 use q = Qubit[100];
723 ApplyXorInPlaceL(953L <<< 50, q);
724 let result = MeasureInteger(q[50...]);
725 ResetAll(q);
726 result
727 }"
728 },
729 &Value::Int(953),
730 );
731}
732
733#[test]
734fn check_apply_operation_power_a() {
735 test_expression(
736 {
737 "{
738 use q = Qubit();
739 ApplyOperationPowerA(12, Rx(Std.Math.PI()/16.0, _), q);
740 ApplyOperationPowerA(-3, Rx(Std.Math.PI()/4.0, _), q);
741 M(q)
742 }"
743 },
744 &Value::RESULT_ZERO,
745 );
746}
747
748#[test]
749fn check_apply_operation_power_ca() {
750 test_expression(
751 {
752 "{
753 use q = Qubit();
754 ApplyOperationPowerCA(12, Rx(Std.Math.PI()/16.0, _), q);
755 ApplyOperationPowerCA(-3, Rx(Std.Math.PI()/4.0, _), q);
756 M(q)
757 }"
758 },
759 &Value::RESULT_ZERO,
760 );
761}
762