microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cesarzc/try-rca-array-assign-improvement

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/circuit_tests.rs

1056lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::unicode_not_nfc)]
5
6use super::{CircuitEntryPoint, Debugger, Interpreter};
7use crate::target::Profile;
8use expect_test::expect;
9use miette::Diagnostic;
10use qsc_data_structures::language_features::LanguageFeatures;
11use qsc_eval::output::GenericReceiver;
12use qsc_frontend::compile::SourceMap;
13use qsc_passes::PackageType;
14
15fn interpreter(code: &str, profile: Profile) -> Interpreter {
16 let sources = SourceMap::new([("test.qs".into(), code.into())], None);
17 let (std_id, store) = crate::compile::package_store_with_stdlib(profile.into());
18 Interpreter::new(
19 sources,
20 PackageType::Exe,
21 profile.into(),
22 LanguageFeatures::default(),
23 store,
24 &[(std_id, None)],
25 )
26 .expect("interpreter creation should succeed")
27}
28
29#[test]
30fn empty() {
31 let mut interpreter = interpreter(
32 r#"
33 namespace Test {
34 @EntryPoint()
35 operation Main() : Unit {
36 Message("hi");
37 }
38 }
39 "#,
40 Profile::Unrestricted,
41 );
42
43 let circ = interpreter
44 .circuit(CircuitEntryPoint::EntryPoint, false)
45 .expect("circuit generation should succeed");
46
47 expect![].assert_eq(&circ.to_string());
48}
49
50#[test]
51fn one_gate() {
52 let mut interpreter = interpreter(
53 r"
54 namespace Test {
55 @EntryPoint()
56 operation Main() : Unit {
57 use q = Qubit();
58 H(q);
59 }
60 }
61 ",
62 Profile::Unrestricted,
63 );
64
65 let circ = interpreter
66 .circuit(CircuitEntryPoint::EntryPoint, false)
67 .expect("circuit generation should succeed");
68
69 expect![[r"
70 q_0 ── H ──
71 "]]
72 .assert_eq(&circ.to_string());
73}
74
75#[test]
76fn toffoli() {
77 let mut interpreter = interpreter(
78 r"
79 namespace Test {
80 @EntryPoint()
81 operation Main() : Unit {
82 use q = Qubit[3];
83 CCNOT(q[0], q[1], q[2]);
84 }
85 }
86 ",
87 Profile::Unrestricted,
88 );
89
90 let circ = interpreter
91 .circuit(CircuitEntryPoint::EntryPoint, false)
92 .expect("circuit generation should succeed");
93
94 expect![[r"
95 q_0 ── ● ──
96 q_1 ── ● ──
97 q_2 ── X ──
98 "]]
99 .assert_eq(&circ.to_string());
100}
101
102#[test]
103fn rotation_gate() {
104 let mut interpreter = interpreter(
105 r"
106 namespace Test {
107 @EntryPoint()
108 operation Main() : Unit {
109 use q = Qubit();
110 Rx(Microsoft.Quantum.Math.PI()/2.0, q);
111 }
112 }
113 ",
114 Profile::Unrestricted,
115 );
116
117 let circ = interpreter
118 .circuit(CircuitEntryPoint::EntryPoint, false)
119 .expect("circuit generation should succeed");
120
121 // The wire isn't visible here since the gate label is longer
122 // than the static column width, but we can live with it.
123 expect![[r"
124 q_0 rx(1.5708)
125 "]]
126 .assert_eq(&circ.to_string());
127}
128
129#[test]
130fn classical_for_loop() {
131 let mut interpreter = interpreter(
132 r"
133 namespace Test {
134 @EntryPoint()
135 operation Main() : Unit {
136 use q = Qubit();
137 for i in 0..5 {
138 X(q);
139 }
140 }
141 }
142 ",
143 Profile::Unrestricted,
144 );
145
146 let circ = interpreter
147 .circuit(CircuitEntryPoint::EntryPoint, false)
148 .expect("circuit generation should succeed");
149
150 expect![[r"
151 q_0 ── X ──── X ──── X ──── X ──── X ──── X ──
152 "]]
153 .assert_eq(&circ.to_string());
154}
155
156#[test]
157fn m_base_profile() {
158 let mut interpreter = interpreter(
159 r"
160 namespace Test {
161 open Microsoft.Quantum.Measurement;
162 @EntryPoint()
163 operation Main() : Result[] {
164 use q = Qubit();
165 H(q);
166 [M(q)]
167 }
168 }
169 ",
170 Profile::Base,
171 );
172
173 let circ = interpreter
174 .circuit(CircuitEntryPoint::EntryPoint, false)
175 .expect("circuit generation should succeed");
176
177 expect![[r"
178 q_0 ── H ──── Z ────────────────
179 q_1 ── H ──── ● ──── H ──── M ──
180 ╘═══
181 "]]
182 .assert_eq(&circ.to_string());
183}
184
185#[test]
186fn m_unrestricted_profile() {
187 let mut interpreter = interpreter(
188 r"
189 namespace Test {
190 open Microsoft.Quantum.Measurement;
191 @EntryPoint()
192 operation Main() : Result[] {
193 use q = Qubit();
194 H(q);
195 [M(q)]
196 }
197 }
198 ",
199 Profile::Unrestricted,
200 );
201
202 let circ = interpreter
203 .circuit(CircuitEntryPoint::EntryPoint, false)
204 .expect("circuit generation should succeed");
205
206 expect![[r"
207 q_0 ── H ──── M ──
208 ╘═══
209 "]]
210 .assert_eq(&circ.to_string());
211}
212
213#[test]
214fn mresetz_unrestricted_profile() {
215 let mut interpreter = interpreter(
216 r"
217 namespace Test {
218 open Microsoft.Quantum.Measurement;
219 @EntryPoint()
220 operation Main() : Result[] {
221 use q = Qubit();
222 H(q);
223 [MResetZ(q)]
224 }
225 }
226 ",
227 Profile::Unrestricted,
228 );
229
230 let circ = interpreter
231 .circuit(CircuitEntryPoint::EntryPoint, false)
232 .expect("circuit generation should succeed");
233
234 expect![[r"
235 q_0 ── H ──── M ─── |0〉 ─
236 ╘══════════
237 "]]
238 .assert_eq(&circ.to_string());
239}
240
241#[test]
242fn mresetz_base_profile() {
243 let mut interpreter = interpreter(
244 r"
245 namespace Test {
246 open Microsoft.Quantum.Measurement;
247 @EntryPoint()
248 operation Main() : Result[] {
249 use q = Qubit();
250 H(q);
251 [MResetZ(q)]
252 }
253 }
254 ",
255 Profile::Base,
256 );
257
258 let circ = interpreter
259 .circuit(CircuitEntryPoint::EntryPoint, false)
260 .expect("circuit generation should succeed");
261
262 expect![[r"
263 q_0 ── H ──── M ──
264 ╘═══
265 "]]
266 .assert_eq(&circ.to_string());
267}
268
269#[test]
270fn unrestricted_profile_result_comparison() {
271 let mut interpreter = interpreter(
272 r"
273 namespace Test {
274 open Microsoft.Quantum.Measurement;
275 @EntryPoint()
276 operation Main() : Result[] {
277 use q1 = Qubit();
278 use q2 = Qubit();
279 H(q1);
280 H(q2);
281 let r1 = M(q1);
282 let r2 = M(q2);
283 if (r1 == r2) {
284 X(q1);
285 }
286 ResetAll([q1, q2]);
287 [r1, r2]
288 }
289 }
290 ",
291 Profile::Unrestricted,
292 );
293
294 interpreter.set_quantum_seed(Some(2));
295
296 let circuit_err = interpreter
297 .circuit(CircuitEntryPoint::EntryPoint, false)
298 .expect_err("circuit should return error")
299 .pop()
300 .expect("error should exist");
301
302 expect!["Qsc.Eval.ResultComparisonUnsupported"].assert_eq(
303 &circuit_err
304 .code()
305 .expect("error code should exist")
306 .to_string(),
307 );
308
309 let circuit = interpreter.get_circuit();
310 expect![""].assert_eq(&circuit.to_string());
311
312 let mut out = std::io::sink();
313 let mut r = GenericReceiver::new(&mut out);
314
315 // Result comparisons are okay when tracing
316 // circuit with the simulator.
317 let circ = interpreter
318 .circuit(CircuitEntryPoint::EntryPoint, true)
319 .expect("circuit generation should succeed");
320
321 expect![[r"
322 q_0 ── H ──── M ──── X ─── |0〉 ─
323 ╘═════════════════
324 q_1 ── H ──── M ─── |0〉 ────────
325 ╘═════════════════
326 "]]
327 .assert_eq(&circ.to_string());
328
329 // Result comparisons are also okay if calling
330 // get_circuit() after incremental evaluation,
331 // because we're using the current simulator
332 // state.
333 interpreter
334 .eval_fragments(&mut r, "Test.Main();")
335 .expect("eval should succeed");
336
337 let circuit = interpreter.get_circuit();
338 expect![[r"
339 q_0 ── H ──── M ──── X ─── |0〉 ─
340 ╘═════════════════
341 q_1 ── H ──── M ─── |0〉 ────────
342 ╘═════════════════
343 "]]
344 .assert_eq(&circuit.to_string());
345}
346
347#[test]
348fn custom_intrinsic() {
349 let mut interpreter = interpreter(
350 r"
351 namespace Test {
352 operation foo(q: Qubit): Unit {
353 body intrinsic;
354 }
355
356 @EntryPoint()
357 operation Main() : Unit {
358 use q = Qubit();
359 foo(q);
360 }
361 }",
362 Profile::Unrestricted,
363 );
364
365 let circ = interpreter
366 .circuit(CircuitEntryPoint::EntryPoint, false)
367 .expect("circuit generation should succeed");
368
369 expect![[r"
370 q_0 ─ foo ─
371 "]]
372 .assert_eq(&circ.to_string());
373}
374
375#[test]
376fn custom_intrinsic_classical_arg() {
377 let mut interpreter = interpreter(
378 r"
379 namespace Test {
380 operation foo(n: Int): Unit {
381 body intrinsic;
382 }
383
384 @EntryPoint()
385 operation Main() : Unit {
386 use q = Qubit();
387 X(q);
388 foo(4);
389 }
390 }",
391 Profile::Unrestricted,
392 );
393
394 let circ = interpreter
395 .circuit(CircuitEntryPoint::EntryPoint, false)
396 .expect("circuit generation should succeed");
397
398 // A custom intrinsic that doesn't take qubits just doesn't
399 // show up on the circuit.
400 expect![[r"
401 q_0 ── X ──
402 "]]
403 .assert_eq(&circ.to_string());
404}
405
406#[test]
407fn custom_intrinsic_one_classical_arg() {
408 let mut interpreter = interpreter(
409 r"
410 namespace Test {
411 operation foo(n: Int, q: Qubit): Unit {
412 body intrinsic;
413 }
414
415 @EntryPoint()
416 operation Main() : Unit {
417 use q = Qubit();
418 X(q);
419 foo(4, q);
420 }
421 }",
422 Profile::Unrestricted,
423 );
424
425 let circ = interpreter
426 .circuit(CircuitEntryPoint::EntryPoint, false)
427 .expect("circuit generation should succeed");
428
429 // A custom intrinsic that doesn't take qubits just doesn't
430 // show up on the circuit.
431 expect![[r"
432 q_0 ── X ── foo(4)
433 "]]
434 .assert_eq(&circ.to_string());
435}
436
437#[test]
438fn custom_intrinsic_mixed_args() {
439 let mut interpreter = interpreter(
440 r"
441 namespace Test {
442 open Microsoft.Quantum.ResourceEstimation;
443
444 @EntryPoint()
445 operation Main() : Unit {
446 use qs = Qubit[10];
447 AccountForEstimates(
448 [
449 AuxQubitCount(1),
450 TCount(2),
451 RotationCount(3),
452 RotationDepth(4),
453 CczCount(5),
454 MeasurementCount(6),
455 ],
456 PSSPCLayout(),
457 qs);
458 }
459 }",
460 Profile::Unrestricted,
461 );
462
463 let circ = interpreter
464 .circuit(CircuitEntryPoint::EntryPoint, false)
465 .expect("circuit generation should succeed");
466
467 // This is one gate that spans ten target wires, even though the
468 // text visualization doesn't convey that clearly.
469 expect![[r"
470 q_0 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
471 q_1 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
472 q_2 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
473 q_3 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
474 q_4 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
475 q_5 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
476 q_6 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
477 q_7 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
478 q_8 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
479 q_9 AccountForEstimatesInternal([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)], 1)
480 "]]
481 .assert_eq(&circ.to_string());
482
483 assert_eq!(circ.operations.len(), 1);
484}
485
486#[test]
487fn operation_with_qubits() {
488 let mut interpreter = interpreter(
489 r"
490 namespace Test {
491 @EntryPoint()
492 operation Main() : Result[] { [] }
493
494 operation Test(q1: Qubit, q2: Qubit) : Result[] {
495 H(q1);
496 CNOT(q1, q2);
497 [M(q1), M(q2)]
498 }
499
500 }",
501 Profile::Unrestricted,
502 );
503
504 let circ = interpreter
505 .circuit(CircuitEntryPoint::Operation("Test.Test".into()), false)
506 .expect("circuit generation should succeed");
507
508 expect![[r"
509 q_0 ── H ──── ● ──── M ──
510 │ ╘═══
511 q_1 ───────── X ──── M ──
512 ╘═══
513 "]]
514 .assert_eq(&circ.to_string());
515}
516
517#[test]
518fn operation_with_qubits_base_profile() {
519 let mut interpreter = interpreter(
520 r"
521 namespace Test {
522 @EntryPoint()
523 operation Main() : Result[] { [] }
524
525 operation Test(q1: Qubit, q2: Qubit) : Result[] {
526 H(q1);
527 CNOT(q1, q2);
528 [M(q1), M(q2)]
529 }
530
531 }",
532 Profile::Base,
533 );
534
535 let circ = interpreter
536 .circuit(CircuitEntryPoint::Operation("Test.Test".into()), false)
537 .expect("circuit generation should succeed");
538
539 expect![[r"
540 q_0 ── H ──── ● ──── Z ──────────────────────────────
541 q_1 ───────── X ─────┼──────────── Z ────────────────
542 q_2 ── H ─────────── ● ──── H ─────┼───── M ─────────
543 │ ╘══════════
544 q_3 ── H ───────────────────────── ● ──── H ──── M ──
545 ╘═══
546 "]]
547 .assert_eq(&circ.to_string());
548}
549
550#[test]
551fn operation_with_qubit_arrays() {
552 let mut interpreter = interpreter(
553 r"
554 namespace Test {
555 @EntryPoint()
556 operation Main() : Result[] { [] }
557
558 open Microsoft.Quantum.Measurement;
559 operation Test(q1: Qubit[], q2: Qubit[][], q3: Qubit[][][], q: Qubit) : Result[] {
560 for q in q1 {
561 H(q);
562 }
563 for qs in q2 {
564 for q in qs {
565 X(q);
566 }
567 }
568 for qss in q3 {
569 for qs in qss {
570 for q in qs {
571 Y(q);
572 }
573 }
574 }
575 X(q);
576 MeasureEachZ(q1)
577 }
578 }",
579 Profile::Unrestricted,
580 );
581
582 let circ = interpreter
583 .circuit(CircuitEntryPoint::Operation("Test.Test".into()), false)
584 .expect("circuit generation should succeed");
585
586 expect![[r"
587 q_0 ── H ──── M ──
588 ╘═══
589 q_1 ── H ──── M ──
590 ╘═══
591 q_2 ── X ─────────
592 q_3 ── X ─────────
593 q_4 ── X ─────────
594 q_5 ── X ─────────
595 q_6 ── Y ─────────
596 q_7 ── Y ─────────
597 q_8 ── Y ─────────
598 q_9 ── Y ─────────
599 q_10 ── Y ─────────
600 q_11 ── Y ─────────
601 q_12 ── Y ─────────
602 q_13 ── Y ─────────
603 q_14 ── X ─────────
604 "]]
605 .assert_eq(&circ.to_string());
606}
607
608#[test]
609fn adjoint_operation() {
610 let mut interpreter = interpreter(
611 r"
612 namespace Test {
613 @EntryPoint()
614 operation Main() : Result[] { [] }
615
616 operation Foo (q : Qubit) : Unit
617 is Adj + Ctl {
618
619 body (...) {
620 X(q);
621 }
622
623 adjoint (...) {
624 Y(q);
625 }
626
627 controlled (cs, ...) {
628 }
629 }
630
631 }",
632 Profile::Unrestricted,
633 );
634
635 let circ = interpreter
636 .circuit(
637 CircuitEntryPoint::Operation("Adjoint Test.Foo".into()),
638 false,
639 )
640 .expect("circuit generation should succeed");
641
642 expect![[r"
643 q_0 ── Y ──
644 "]]
645 .assert_eq(&circ.to_string());
646}
647
648#[test]
649fn lambda() {
650 let mut interpreter = interpreter(
651 r"
652 namespace Test {
653 @EntryPoint()
654 operation Main() : Result[] { [] }
655 }",
656 Profile::Unrestricted,
657 );
658
659 let circ = interpreter
660 .circuit(CircuitEntryPoint::Operation("q => H(q)".into()), false)
661 .expect("circuit generation should succeed");
662
663 expect![[r"
664 q_0 ── H ──
665 "]]
666 .assert_eq(&circ.to_string());
667}
668
669#[test]
670fn controlled_operation() {
671 let mut interpreter = interpreter(
672 r"
673 namespace Test {
674 @EntryPoint()
675 operation Main() : Result[] { [] }
676
677 operation SWAP (q1 : Qubit, q2 : Qubit) : Unit
678 is Adj + Ctl {
679
680 body (...) {
681 CNOT(q1, q2);
682 CNOT(q2, q1);
683 CNOT(q1, q2);
684 }
685
686 adjoint (...) {
687 SWAP(q1, q2);
688 }
689
690 controlled (cs, ...) {
691 CNOT(q1, q2);
692 Controlled CNOT(cs, (q2, q1));
693 CNOT(q1, q2);
694 }
695 }
696
697 }",
698 Profile::Unrestricted,
699 );
700
701 let circ_err = interpreter
702 .circuit(
703 CircuitEntryPoint::Operation("Controlled Test.SWAP".into()),
704 false,
705 )
706 .expect_err("circuit generation should fail");
707
708 // Controlled operations are not supported at the moment.
709 // We don't generate an accurate call signature with the tuple arguments.
710 expect![[r"
711 [
712 Circuit(
713 ControlledUnsupported,
714 ),
715 ]
716 "]]
717 .assert_debug_eq(&circ_err);
718}
719
720#[test]
721#[allow(clippy::too_many_lines)]
722fn internal_operation() {
723 let mut interpreter = interpreter(
724 r"
725 namespace Test {
726 @EntryPoint()
727 operation Main() : Result[] { [] }
728
729 internal operation Test(q1: Qubit, q2: Qubit) : Result[] {
730 H(q1);
731 CNOT(q1, q2);
732 [M(q1), M(q2)]
733 }
734 }",
735 Profile::Unrestricted,
736 );
737
738 let circ_err = interpreter
739 .circuit(CircuitEntryPoint::Operation("Test.Test".into()), false)
740 .expect("circuit generation should not fail");
741
742 expect![[r#"
743 Circuit {
744 operations: [
745 Operation {
746 gate: "H",
747 display_args: None,
748 is_controlled: false,
749 is_adjoint: false,
750 is_measurement: false,
751 controls: [],
752 targets: [
753 Register {
754 q_id: 0,
755 type: 0,
756 c_id: None,
757 },
758 ],
759 children: [],
760 },
761 Operation {
762 gate: "X",
763 display_args: None,
764 is_controlled: true,
765 is_adjoint: false,
766 is_measurement: false,
767 controls: [
768 Register {
769 q_id: 0,
770 type: 0,
771 c_id: None,
772 },
773 ],
774 targets: [
775 Register {
776 q_id: 1,
777 type: 0,
778 c_id: None,
779 },
780 ],
781 children: [],
782 },
783 Operation {
784 gate: "Measure",
785 display_args: None,
786 is_controlled: false,
787 is_adjoint: false,
788 is_measurement: true,
789 controls: [
790 Register {
791 q_id: 0,
792 type: 0,
793 c_id: None,
794 },
795 ],
796 targets: [
797 Register {
798 q_id: 0,
799 type: 1,
800 c_id: Some(
801 0,
802 ),
803 },
804 ],
805 children: [],
806 },
807 Operation {
808 gate: "Measure",
809 display_args: None,
810 is_controlled: false,
811 is_adjoint: false,
812 is_measurement: true,
813 controls: [
814 Register {
815 q_id: 1,
816 type: 0,
817 c_id: None,
818 },
819 ],
820 targets: [
821 Register {
822 q_id: 1,
823 type: 1,
824 c_id: Some(
825 0,
826 ),
827 },
828 ],
829 children: [],
830 },
831 ],
832 qubits: [
833 Qubit {
834 id: 0,
835 num_children: 1,
836 },
837 Qubit {
838 id: 1,
839 num_children: 1,
840 },
841 ],
842 }
843 "#]]
844 .assert_debug_eq(&circ_err);
845}
846
847#[test]
848fn operation_with_non_qubit_args() {
849 let mut interpreter = interpreter(
850 r"
851 namespace Test {
852 @EntryPoint()
853 operation Main() : Result[] { [] }
854
855 operation Test(q1: Qubit, q2: Qubit, i: Int) : Unit {
856 }
857
858 }",
859 Profile::Unrestricted,
860 );
861
862 let circ_err = interpreter
863 .circuit(CircuitEntryPoint::Operation("Test.Test".into()), false)
864 .expect_err("circuit generation should fail");
865
866 expect![[r"
867 [
868 Circuit(
869 NoQubitParameters,
870 ),
871 ]
872 "]]
873 .assert_debug_eq(&circ_err);
874}
875
876/// Tests that invoke circuit generation throught the debugger.
877mod debugger_stepping {
878 use super::Debugger;
879 use crate::target::Profile;
880 use expect_test::expect;
881 use qsc_data_structures::language_features::LanguageFeatures;
882 use qsc_data_structures::line_column::Encoding;
883 use qsc_eval::{output::GenericReceiver, StepAction, StepResult};
884 use qsc_frontend::compile::SourceMap;
885 use std::fmt::Write;
886
887 /// Steps through the code in the debugger and collects the
888 /// circuit representation at each step.
889 fn generate_circuit_steps(code: &str, profile: Profile) -> String {
890 let sources = SourceMap::new([("test.qs".into(), code.into())], None);
891 let (std_id, store) = crate::compile::package_store_with_stdlib(profile.into());
892 let mut debugger = Debugger::new(
893 sources,
894 profile.into(),
895 Encoding::Utf8,
896 LanguageFeatures::default(),
897 store,
898 &[(std_id, None)],
899 )
900 .expect("debugger creation should succeed");
901
902 debugger.interpreter.set_quantum_seed(Some(2));
903
904 let mut out = std::io::sink();
905 let mut r = GenericReceiver::new(&mut out);
906
907 let mut circs = String::new();
908 let mut result = debugger
909 .eval_step(&mut r, &[], StepAction::In)
910 .expect("step should succeed");
911
912 write!(&mut circs, "step:\n{}", debugger.circuit()).expect("write should succeed");
913 while !matches!(result, StepResult::Return(_)) {
914 result = debugger
915 .eval_step(&mut r, &[], StepAction::Next)
916 .expect("step should succeed");
917
918 write!(&mut circs, "step:\n{}", debugger.circuit()).expect("write should succeed");
919 }
920 circs
921 }
922
923 #[test]
924 fn base_profile() {
925 let circs = generate_circuit_steps(
926 r"
927 namespace Test {
928 open Microsoft.Quantum.Measurement;
929 @EntryPoint()
930 operation Main() : Result[] {
931 use q = Qubit();
932 H(q);
933 let r = M(q);
934 Reset(q);
935 [r]
936 }
937 }
938 ",
939 Profile::Base,
940 );
941
942 // Surprising but expected: Reset gates would *not* normally
943 // be generated in Base Profile, but they are here, since
944 // when running in tandem with the simulator, the resulting
945 // circuit is intended to match the calls into the simulator.
946 //
947 // Note the circuit still looks different than what would be
948 // generated in Unrestricted Profile for the same code,
949 // due to conditional compilation in the standard library.
950 expect![["
951 step:
952 step:
953 q_0
954 step:
955 q_0 ── H ──
956 step:
957 q_0 ── H ──── Z ───────────────────────
958 q_1 ── H ──── ● ──── H ──── M ─── |0〉 ─
959 ╘══════════
960 step:
961 q_0 ── H ──── Z ─── |0〉 ───────────────
962 q_1 ── H ──── ● ──── H ──── M ─── |0〉 ─
963 ╘══════════
964 step:
965 q_0 ── H ──── Z ─── |0〉 ───────────────
966 q_1 ── H ──── ● ──── H ──── M ─── |0〉 ─
967 ╘══════════
968 "]]
969 .assert_eq(&circs);
970 }
971
972 #[test]
973 fn unrestricted_profile() {
974 let circs = generate_circuit_steps(
975 r"
976 namespace Test {
977 open Microsoft.Quantum.Measurement;
978 @EntryPoint()
979 operation Main() : Result[] {
980 use q = Qubit();
981 H(q);
982 let r = M(q);
983 Reset(q);
984 [r]
985 }
986 }
987 ",
988 Profile::Unrestricted,
989 );
990
991 expect![[r"
992 step:
993 step:
994 q_0
995 step:
996 q_0 ── H ──
997 step:
998 q_0 ── H ──── M ──
999 ╘═══
1000 step:
1001 q_0 ── H ──── M ─── |0〉 ─
1002 ╘══════════
1003 step:
1004 q_0 ── H ──── M ─── |0〉 ─
1005 ╘══════════
1006 "]]
1007 .assert_eq(&circs);
1008 }
1009
1010 #[test]
1011 fn unrestricted_profile_result_comparison() {
1012 let circs = generate_circuit_steps(
1013 r"
1014 namespace Test {
1015 open Microsoft.Quantum.Measurement;
1016 @EntryPoint()
1017 operation Main() : Result[] {
1018 use q = Qubit();
1019 H(q);
1020 let r = M(q);
1021 if (r == One) {
1022 X(q);
1023 }
1024 [r]
1025 }
1026 }
1027 ",
1028 Profile::Unrestricted,
1029 );
1030
1031 // We set the random seed in the test to account for
1032 // the nondeterministic output. Since the debugger is running
1033 // the real simulator, the circuit is going to vary from run to run
1034 // depending on measurement outcomes.
1035 expect![[r"
1036 step:
1037 step:
1038 q_0
1039 step:
1040 q_0 ── H ──
1041 step:
1042 q_0 ── H ──── M ──
1043 ╘═══
1044 step:
1045 q_0 ── H ──── M ──
1046 ╘═══
1047 step:
1048 q_0 ── H ──── M ──── X ──
1049 ╘══════════
1050 step:
1051 q_0 ── H ──── M ──── X ──
1052 ╘══════════
1053 "]]
1054 .assert_eq(&circs);
1055 }
1056}
1057