microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
3fc684b157698c92d12be32ea3c6f7b3521de2b3

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/tests/src/tests.rs

850lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::test_expression;
5use indoc::indoc;
6use num_bigint::BigInt;
7use qsc::interpret::Value;
8
9//
10// Canon namespace
11//
12
13#[test]
14fn check_apply_to_each() {
15 test_expression(
16 indoc! {r#"{
17 use register = Qubit[3];
18 Microsoft.Quantum.Canon.ApplyToEach(X, register);
19 let results = Microsoft.Quantum.Measurement.MeasureEachZ(register);
20 ResetAll(register);
21 results
22 }"#},
23 &Value::Array(
24 vec![
25 Value::Result(true),
26 Value::Result(true),
27 Value::Result(true),
28 ]
29 .into(),
30 ),
31 );
32}
33
34#[test]
35fn check_apply_to_each_a() {
36 test_expression(
37 indoc! {r#"{
38 use register = Qubit[3];
39 Microsoft.Quantum.Canon.ApplyToEach(X, register);
40 Adjoint Microsoft.Quantum.Canon.ApplyToEachA(X, register);
41 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
42 results
43 }"#},
44 &Value::Array(
45 vec![
46 Value::Result(false),
47 Value::Result(false),
48 Value::Result(false),
49 ]
50 .into(),
51 ),
52 );
53}
54
55#[test]
56fn check_apply_to_each_c_applied() {
57 test_expression(
58 indoc! {r#"{
59 use control = Qubit();
60 use register = Qubit[3];
61 Controlled Microsoft.Quantum.Canon.ApplyToEachC([control], (X, register));
62 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
63 Reset(control);
64 results
65 }"#},
66 &Value::Array(
67 vec![
68 Value::Result(false),
69 Value::Result(false),
70 Value::Result(false),
71 ]
72 .into(),
73 ),
74 );
75}
76
77#[test]
78fn check_apply_to_each_c_not_applied() {
79 test_expression(
80 indoc! {r#"{
81 use control = Qubit();
82 use register = Qubit[3];
83 X(control);
84 Controlled Microsoft.Quantum.Canon.ApplyToEachC([control], (X, register));
85 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
86 Reset(control);
87 results
88 }"#},
89 &Value::Array(
90 vec![
91 Value::Result(true),
92 Value::Result(true),
93 Value::Result(true),
94 ]
95 .into(),
96 ),
97 );
98}
99
100#[test]
101fn check_apply_to_each_ca_applied() {
102 test_expression(
103 indoc! {r#"{
104 use control = Qubit();
105 use register = Qubit[3];
106 Microsoft.Quantum.Canon.ApplyToEach(X, register);
107 Controlled Adjoint Microsoft.Quantum.Canon.ApplyToEachCA([control], (X, register));
108 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
109 Reset(control);
110 results
111 }"#},
112 &Value::Array(
113 vec![
114 Value::Result(true),
115 Value::Result(true),
116 Value::Result(true),
117 ]
118 .into(),
119 ),
120 );
121}
122
123#[test]
124fn check_apply_to_each_ca_not_applied() {
125 test_expression(
126 indoc! {r#"{
127 use control = Qubit();
128 use register = Qubit[3];
129 X(control);
130 Microsoft.Quantum.Canon.ApplyToEach(X, register);
131 Controlled Adjoint Microsoft.Quantum.Canon.ApplyToEachCA([control], (X, register));
132 let results = Microsoft.Quantum.Measurement.MResetEachZ(register);
133 Reset(control);
134 results
135 }"#},
136 &Value::Array(
137 vec![
138 Value::Result(false),
139 Value::Result(false),
140 Value::Result(false),
141 ]
142 .into(),
143 ),
144 );
145}
146
147//
148// Sign, Abs, Min, Max, etc.
149//
150
151#[test]
152fn check_sign_i() {
153 test_expression("Microsoft.Quantum.Math.SignI(0)", &Value::Int(0));
154 test_expression("Microsoft.Quantum.Math.SignI(1000)", &Value::Int(1));
155 test_expression("Microsoft.Quantum.Math.SignI(-1000)", &Value::Int(-1));
156}
157
158#[test]
159fn check_sign_d() {
160 test_expression("Microsoft.Quantum.Math.SignD(0.0)", &Value::Int(0));
161 test_expression("Microsoft.Quantum.Math.SignD(0.005)", &Value::Int(1));
162 test_expression("Microsoft.Quantum.Math.SignD(-0.005)", &Value::Int(-1));
163}
164
165#[test]
166fn check_sign_l() {
167 test_expression("Microsoft.Quantum.Math.SignL(0L)", &Value::Int(0));
168 test_expression(
169 "Microsoft.Quantum.Math.SignL(9999999999999999999999999999999999999999L)",
170 &Value::Int(1),
171 );
172 test_expression(
173 "Microsoft.Quantum.Math.SignL(-9999999999999999999999999999999999999999L)",
174 &Value::Int(-1),
175 );
176}
177
178#[test]
179fn check_abs_i() {
180 test_expression("Microsoft.Quantum.Math.AbsI(0)", &Value::Int(0));
181 test_expression("Microsoft.Quantum.Math.AbsI(1000)", &Value::Int(1000));
182 test_expression("Microsoft.Quantum.Math.AbsI(-1000)", &Value::Int(1000));
183}
184
185#[test]
186fn check_abs_d() {
187 test_expression("Microsoft.Quantum.Math.AbsD(0.0)", &Value::Double(0.0));
188 test_expression("Microsoft.Quantum.Math.AbsD(0.005)", &Value::Double(0.005));
189 test_expression("Microsoft.Quantum.Math.AbsD(-0.005)", &Value::Double(0.005));
190}
191
192#[test]
193fn check_abs_l() {
194 test_expression(
195 "Microsoft.Quantum.Math.AbsL(0L)",
196 &Value::BigInt(BigInt::from(0)),
197 );
198 test_expression(
199 "Microsoft.Quantum.Math.AbsL(9999L)",
200 &Value::BigInt(BigInt::from(9999)),
201 );
202 test_expression(
203 "Microsoft.Quantum.Math.AbsL(-9999L)",
204 &Value::BigInt(BigInt::from(9999)),
205 );
206}
207
208#[test]
209fn check_max_i() {
210 test_expression("Microsoft.Quantum.Math.MaxI(-5,7)", &Value::Int(7));
211 test_expression("Microsoft.Quantum.Math.MaxI(-7,0)", &Value::Int(0));
212}
213
214#[test]
215fn check_max_d() {
216 test_expression("Microsoft.Quantum.Math.MaxD(-5.0,7.0)", &Value::Double(7.0));
217 test_expression("Microsoft.Quantum.Math.MaxD(-7.0,0.0)", &Value::Double(0.0));
218}
219
220#[test]
221fn check_max_l() {
222 test_expression(
223 "Microsoft.Quantum.Math.MaxL(-5L,7L)",
224 &Value::BigInt(BigInt::from(7)),
225 );
226 test_expression(
227 "Microsoft.Quantum.Math.MaxL(-7L,0L)",
228 &Value::BigInt(BigInt::from(0)),
229 );
230}
231
232#[test]
233fn check_min_i() {
234 test_expression("Microsoft.Quantum.Math.MinI(-5,7)", &Value::Int(-5));
235 test_expression("Microsoft.Quantum.Math.MinI(-7,0)", &Value::Int(-7));
236}
237
238#[test]
239fn check_min_d() {
240 test_expression(
241 "Microsoft.Quantum.Math.MinD(-5.0,7.0)",
242 &Value::Double(-5.0),
243 );
244 test_expression(
245 "Microsoft.Quantum.Math.MinD(-7.0,0.0)",
246 &Value::Double(-7.0),
247 );
248}
249
250#[test]
251fn check_min_l() {
252 test_expression(
253 "Microsoft.Quantum.Math.MinL(-5L,7L)",
254 &Value::BigInt(BigInt::from(-5)),
255 );
256 test_expression(
257 "Microsoft.Quantum.Math.MinL(-7L,0L)",
258 &Value::BigInt(BigInt::from(-7)),
259 );
260}
261
262//
263// Trigonometric functions
264//
265
266#[test]
267fn check_pi() {
268 test_expression(
269 "Microsoft.Quantum.Math.PI()",
270 &Value::Double(std::f64::consts::PI),
271 );
272}
273
274#[test]
275fn check_e() {
276 test_expression(
277 "Microsoft.Quantum.Math.E()",
278 &Value::Double(std::f64::consts::E),
279 );
280}
281
282#[test]
283fn check_arccosh() {
284 test_expression("Microsoft.Quantum.Math.ArcCosh(1.0)", &Value::Double(0.0));
285}
286
287#[test]
288fn check_arcsinh() {
289 test_expression("Microsoft.Quantum.Math.ArcSinh(0.0)", &Value::Double(0.0));
290}
291
292#[test]
293fn check_arctanh() {
294 test_expression("Microsoft.Quantum.Math.ArcTanh(0.0)", &Value::Double(0.0));
295}
296
297//
298// Sqrt, Log, exp, etc.
299//
300
301#[test]
302fn check_log10() {
303 test_expression("Microsoft.Quantum.Math.Log10(1.0)", &Value::Double(0.0));
304 test_expression("Microsoft.Quantum.Math.Log10(10.0)", &Value::Double(1.0));
305}
306
307#[test]
308fn check_lg() {
309 test_expression("Microsoft.Quantum.Math.Lg(1.0)", &Value::Double(0.0));
310 test_expression("Microsoft.Quantum.Math.Lg(2.0)", &Value::Double(1.0));
311}
312
313#[test]
314fn check_ceiling() {
315 test_expression("Microsoft.Quantum.Math.Ceiling(3.1)", &Value::Int(4));
316 test_expression("Microsoft.Quantum.Math.Ceiling(-3.7)", &Value::Int(-3));
317}
318
319#[test]
320fn check_floor() {
321 test_expression("Microsoft.Quantum.Math.Floor(3.7)", &Value::Int(3));
322 test_expression("Microsoft.Quantum.Math.Floor(-3.1)", &Value::Int(-4));
323}
324
325#[test]
326fn check_round() {
327 test_expression("Microsoft.Quantum.Math.Round(3.1)", &Value::Int(3));
328 test_expression("Microsoft.Quantum.Math.Round(-3.7)", &Value::Int(-4));
329}
330
331//
332// Modular arithmetic
333//
334
335#[test]
336fn check_modulus_i() {
337 test_expression("Microsoft.Quantum.Math.ModulusI(20, 3)", &Value::Int(2));
338 test_expression("Microsoft.Quantum.Math.ModulusI(-20, 3)", &Value::Int(1));
339}
340
341#[test]
342fn check_modulus_l() {
343 test_expression(
344 "Microsoft.Quantum.Math.ModulusL(20L, 3L)",
345 &Value::BigInt(BigInt::from(2)),
346 );
347 test_expression(
348 "Microsoft.Quantum.Math.ModulusL(-20L, 3L)",
349 &Value::BigInt(BigInt::from(1)),
350 );
351}
352
353#[test]
354fn check_exp_mod_i() {
355 test_expression("Microsoft.Quantum.Math.ExpModI(1,10,10)", &Value::Int(1));
356 test_expression("Microsoft.Quantum.Math.ExpModI(10,0,10)", &Value::Int(1));
357 test_expression("Microsoft.Quantum.Math.ExpModI(2,10,10)", &Value::Int(4));
358}
359
360#[test]
361fn check_exp_mod_l() {
362 test_expression(
363 "Microsoft.Quantum.Math.ExpModL(1L,10L,10L)",
364 &Value::BigInt(BigInt::from(1)),
365 );
366 test_expression(
367 "Microsoft.Quantum.Math.ExpModL(10L,0L,10L)",
368 &Value::BigInt(BigInt::from(1)),
369 );
370 test_expression(
371 "Microsoft.Quantum.Math.ExpModL(2L,10L,10L)",
372 &Value::BigInt(BigInt::from(4)),
373 );
374}
375
376#[test]
377fn check_inverse_mod_i() {
378 test_expression("Microsoft.Quantum.Math.InverseModI(2,5)", &Value::Int(3));
379 test_expression("Microsoft.Quantum.Math.InverseModI(3,10)", &Value::Int(7));
380 test_expression("Microsoft.Quantum.Math.InverseModI(-1,5)", &Value::Int(4));
381}
382
383#[test]
384fn check_inverse_mod_l() {
385 test_expression(
386 "Microsoft.Quantum.Math.InverseModL(2L,5L)",
387 &Value::BigInt(BigInt::from(3)),
388 );
389 test_expression(
390 "Microsoft.Quantum.Math.InverseModL(3L,10L)",
391 &Value::BigInt(BigInt::from(7)),
392 );
393 test_expression(
394 "Microsoft.Quantum.Math.InverseModL(-1L,5L)",
395 &Value::BigInt(BigInt::from(4)),
396 );
397}
398
399//
400// GCD, etc.
401//
402#[test]
403fn check_gcd_i() {
404 test_expression(
405 "Microsoft.Quantum.Math.GreatestCommonDivisorI(0,0)",
406 &Value::Int(0),
407 );
408 test_expression(
409 "Microsoft.Quantum.Math.GreatestCommonDivisorI(2*3*5,2*3*7)",
410 &Value::Int(2 * 3),
411 );
412 test_expression(
413 "Microsoft.Quantum.Math.GreatestCommonDivisorI(39088169,63245986)",
414 &Value::Int(1),
415 );
416}
417
418#[test]
419fn check_gcd_l() {
420 test_expression(
421 "Microsoft.Quantum.Math.GreatestCommonDivisorL(0L,0L)",
422 &Value::BigInt(BigInt::from(0)),
423 );
424 test_expression(
425 "Microsoft.Quantum.Math.GreatestCommonDivisorL(2L*3L*5L,2L*3L*7L)",
426 &Value::BigInt(BigInt::from(2 * 3)),
427 );
428 test_expression("Microsoft.Quantum.Math.GreatestCommonDivisorL(222232244629420445529739893461909967206666939096499764990979600L,359579325206583560961765665172189099052367214309267232255589801L)", &Value::BigInt(
429 BigInt::from(1)));
430}
431
432#[test]
433fn check_cfc_i() {
434 // NOTE: It is not important if the function returns -3/-4 or 3/4,
435 // we can ignore this implementation details or update a function
436 // to return canonical result.
437 test_expression(
438 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 2)",
439 &Value::Tuple(vec![Value::Int(-1), Value::Int(-1)].into()),
440 );
441 test_expression(
442 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 3)",
443 &Value::Tuple(vec![Value::Int(2), Value::Int(3)].into()),
444 );
445 test_expression(
446 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 4)",
447 &Value::Tuple(vec![Value::Int(-3), Value::Int(-4)].into()),
448 );
449 test_expression(
450 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 7)",
451 &Value::Tuple(vec![Value::Int(5), Value::Int(7)].into()),
452 );
453 test_expression(
454 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 25)",
455 &Value::Tuple(vec![Value::Int(-18), Value::Int(-25)].into()),
456 );
457}
458
459#[test]
460fn check_fst_snd() {
461 test_expression("Fst(7,6)", &Value::Int(7));
462 test_expression("Snd(7,6)", &Value::Int(6));
463}
464
465#[test]
466fn check_bitsize_i() {
467 test_expression("Microsoft.Quantum.Math.BitSizeI(0)", &Value::Int(0));
468 test_expression("Microsoft.Quantum.Math.BitSizeI(1)", &Value::Int(1));
469 test_expression("Microsoft.Quantum.Math.BitSizeI(2)", &Value::Int(2));
470 test_expression("Microsoft.Quantum.Math.BitSizeI(3)", &Value::Int(2));
471 test_expression(
472 "Microsoft.Quantum.Math.BitSizeI(0x7FFFFFFFFFFFFFFF)",
473 &Value::Int(63),
474 );
475}
476
477//
478// Core namespace
479//
480
481#[test]
482fn check_repeated() {
483 test_expression("Repeated(Zero, 0)", &Value::Array(vec![].into()));
484 test_expression(
485 "Repeated(One, 1)",
486 &Value::Array(vec![Value::Result(true)].into()),
487 );
488 test_expression(
489 "Repeated(1, 2)",
490 &Value::Array(vec![Value::Int(1), Value::Int(1)].into()),
491 );
492 test_expression(
493 "Repeated(true, 3)",
494 &Value::Array(vec![Value::Bool(true), Value::Bool(true), Value::Bool(true)].into()),
495 );
496}
497
498#[test]
499fn check_apply_xor_in_place() {
500 test_expression(
501 {
502 "{
503 use a = Qubit[3];
504 mutable result = [];
505 within {
506 Microsoft.Quantum.Arithmetic.ApplyXorInPlace(3, a);
507 }
508 apply {
509 set result = [M(a[0]),M(a[1]),M(a[2])];
510 }
511 return result;
512 }"
513 },
514 &Value::Array(
515 vec![
516 Value::Result(true),
517 Value::Result(true),
518 Value::Result(false),
519 ]
520 .into(),
521 ),
522 );
523}
524
525#[test]
526fn check_measure_integer() {
527 test_expression(
528 {
529 "{
530 open Microsoft.Quantum.Arithmetic;
531 use q = Qubit[16];
532 ApplyXorInPlace(45967, q);
533 let result = MeasureInteger(q);
534 ResetAll(q);
535 return result;
536 }"
537 },
538 &Value::Int(45967),
539 );
540}
541
542#[test]
543fn check_apply_cnot_chain_2() {
544 test_expression(
545 {
546 "{
547 use a = Qubit[2];
548 mutable result = [];
549 within {
550 X(a[0]);
551 X(a[1]);
552 ApplyCNOTChain(a);
553 }
554 apply {
555 set result = [M(a[0]),M(a[1])];
556 }
557 return result;
558 }"
559 },
560 &Value::Array(vec![Value::Result(true), Value::Result(false)].into()),
561 );
562}
563
564#[test]
565fn check_apply_cnot_chain_3() {
566 test_expression(
567 {
568 "{
569 use a = Qubit[3];
570 mutable result = [];
571 within {
572 X(a[0]);
573 ApplyCNOTChain(a);
574 }
575 apply {
576 set result = [M(a[0]),M(a[1]),M(a[2])];
577 }
578 return result;
579 }"
580 },
581 &Value::Array(
582 vec![
583 Value::Result(true),
584 Value::Result(true),
585 Value::Result(true),
586 ]
587 .into(),
588 ),
589 );
590}
591
592#[test]
593fn check_apply_p() {
594 test_expression(
595 {
596 "{
597 open Microsoft.Quantum.Measurement;
598 use q = Qubit[3];
599 ApplyP(PauliX, q[0]);
600 H(q[1]); ApplyP(PauliY, q[1]);
601 H(q[2]); S(q[2]); ApplyP(PauliZ, q[2]);
602 return [MResetZ(q[0]),MResetX(q[1]),MResetY(q[2])];
603 }"
604 },
605 &Value::Array(
606 vec![
607 Value::Result(true),
608 Value::Result(true),
609 Value::Result(true),
610 ]
611 .into(),
612 ),
613 );
614}
615
616#[test]
617fn check_apply_pauli() {
618 test_expression(
619 {
620 "{
621 open Microsoft.Quantum.Measurement;
622 use q = Qubit[3];
623 H(q[1]);
624 H(q[2]); S(q[2]);
625 ApplyPauli([PauliX, PauliY, PauliZ], q);
626 return [MResetZ(q[0]),MResetX(q[1]),MResetY(q[2])];
627 }"
628 },
629 &Value::Array(
630 vec![
631 Value::Result(true),
632 Value::Result(true),
633 Value::Result(true),
634 ]
635 .into(),
636 ),
637 );
638}
639
640#[test]
641fn check_apply_pauli_from_bit_string() {
642 test_expression(
643 {
644 "{
645 open Microsoft.Quantum.Measurement;
646 use q = Qubit[3];
647 ApplyPauliFromBitString(PauliX, false, [true, false, true], q);
648 return MResetEachZ(q);
649 }"
650 },
651 &Value::Array(
652 vec![
653 Value::Result(false),
654 Value::Result(true),
655 Value::Result(false),
656 ]
657 .into(),
658 ),
659 );
660}
661
662#[test]
663fn check_apply_cnot_chain_3a() {
664 test_expression(
665 {
666 "{
667 use a = Qubit[3];
668 mutable result = [];
669 within {
670 X(a[0]);
671 X(a[2]);
672 ApplyCNOTChain(a);
673 }
674 apply {
675 set result = [M(a[0]),M(a[1]),M(a[2])];
676 }
677 return result;
678 }"
679 },
680 &Value::Array(
681 vec![
682 Value::Result(true),
683 Value::Result(true),
684 Value::Result(false),
685 ]
686 .into(),
687 ),
688 );
689}
690
691#[test]
692fn check_add_i_nc() {
693 test_expression(
694 {
695 "{ // RippleCarryAdderNoCarryTTK case
696 use x = Qubit[4];
697 use y = Qubit[4];
698 open Microsoft.Quantum.Arithmetic;
699 ApplyXorInPlace(3, x);
700 ApplyXorInPlace(5, y);
701 AddI(x,y); // 3+5=8
702 let result = [M(y[0]),M(y[1]),M(y[2]),M(y[3])];
703 ResetAll(x+y);
704 return result;
705 }"
706 },
707 &Value::Array(
708 vec![
709 Value::Result(false),
710 Value::Result(false),
711 Value::Result(false),
712 Value::Result(true), // 3+5=8
713 ]
714 .into(),
715 ),
716 );
717}
718
719#[test]
720fn check_add_i_c() {
721 test_expression(
722 {
723 "{ // RippleCarryAdderTTK case
724 use x = Qubit[4];
725 use y = Qubit[5];
726 open Microsoft.Quantum.Arithmetic;
727 ApplyXorInPlace(7, x);
728 ApplyXorInPlace(11, y);
729 AddI(x,y); // 7+11=18
730 let result = [M(y[0]),M(y[1]),M(y[2]),M(y[3]),M(y[4])];
731 ResetAll(x+y);
732 return result;
733 }"
734 },
735 &Value::Array(
736 vec![
737 Value::Result(false),
738 Value::Result(true), // 2
739 Value::Result(false),
740 Value::Result(false),
741 Value::Result(true), // 16
742 ]
743 .into(),
744 ), // 10010b = 18
745 );
746}
747
748#[test]
749fn check_add_i_1_1() {
750 test_expression(
751 {
752 "{ // Shortest case
753 use x = Qubit[1];
754 use y = Qubit[1];
755 open Microsoft.Quantum.Arithmetic;
756 X(x[0]);
757 AddI(x,y);
758 let result = M(y[0]);
759 ResetAll(x+y);
760 return result;
761 }"
762 },
763 &Value::Result(true),
764 );
765}
766
767#[test]
768fn check_add_i_1_2() {
769 test_expression(
770 {
771 "{ // Shortest unequal length case
772 use x = Qubit[1];
773 use y = Qubit[2];
774 open Microsoft.Quantum.Arithmetic;
775 X(x[0]);
776 X(y[0]);
777 AddI(x,y);
778 let result = [M(y[0]),M(y[1])];
779 ResetAll(x+y);
780 return result;
781 }"
782 },
783 &Value::Array(
784 vec![
785 Value::Result(false),
786 Value::Result(true), // 2
787 ]
788 .into(),
789 ),
790 );
791}
792
793#[test]
794fn check_exp_with_cnot() {
795 // This decomposition only holds if the magnitude of the angle used in Exp is correct and if the
796 // sign convention between Rx, Rz, and Exp is consistent.
797 test_expression(
798 indoc! {r#"{
799 open Microsoft.Quantum.Diagnostics;
800 open Microsoft.Quantum.Math;
801
802 use (aux, control, target) = (Qubit(), Qubit(), Qubit());
803 within {
804 H(aux);
805 CNOT(aux, control);
806 CNOT(aux, target);
807 }
808 apply {
809 let theta = PI() / 4.0;
810 Rx(-2.0 * theta, target);
811 Rz(-2.0 * theta, control);
812 Adjoint Exp([PauliZ, PauliX], theta, [control, target]);
813
814 Adjoint CNOT(control, target);
815 }
816
817 CheckAllZero([aux, control, target])
818 }"#},
819 &Value::Bool(true),
820 );
821}
822
823#[test]
824fn check_exp_with_swap() {
825 // This decomposition only holds if the magnitude of the angle used in Exp is correct.
826 test_expression(
827 indoc! {r#"{
828 open Microsoft.Quantum.Diagnostics;
829 open Microsoft.Quantum.Math;
830
831 use (aux, qs) = (Qubit(), Qubit[2]);
832 within {
833 H(aux);
834 CNOT(aux, qs[0]);
835 CNOT(aux, qs[1]);
836 }
837 apply {
838 let theta = PI() / 4.0;
839 Exp([PauliX, PauliX], theta, qs);
840 Exp([PauliY, PauliY], theta, qs);
841 Exp([PauliZ, PauliZ], theta, qs);
842
843 Adjoint SWAP(qs[0], qs[1]);
844 }
845
846 CheckAllZero([aux] + qs)
847 }"#},
848 &Value::Bool(true),
849 );
850}
851