microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fedimser/permutation

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/compiler/qsc_circuit/src/circuit_to_qsharp/tests.rs

667lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::*;
5use expect_test::{Expect, expect};
6
7fn check(contents: &str, expect: &Expect) {
8 let actual = match serde_json::from_str::<Circuit>(contents) {
9 Ok(circuit) => build_operation_def("Test", &circuit),
10 Err(e) => format!("Error: {e}"),
11 };
12 expect.assert_eq(&actual);
13}
14
15fn check_circuit_group(contents: &str, expect: &Expect) {
16 let actual = match circuits_to_qsharp("Test", contents) {
17 Ok(circuit) => circuit,
18 Err(e) => e,
19 };
20 expect.assert_eq(&actual);
21}
22
23#[test]
24fn qsharp_from_circuit() {
25 check_circuit_group(
26 r#"
27{
28 "version": 1,
29 "circuits": [
30 {
31 "componentGrid": [
32 {
33 "components": [
34 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
35 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
36 ]
37 },
38 {
39 "components": [
40 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
41 { "kind": "unitary", "gate": "X", "targets": [{ "qubit": 1 }] }
42 ]
43 }
44 ],
45 "qubits": [{ "id": 0 }, { "id": 1 }]
46 }
47 ]
48}"#,
49 &expect![[r#"
50 /// Expects a qubit register of at least 2 qubits.
51 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
52 if Length(qs) < 2 {
53 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
54 }
55 H(qs[0]);
56 S(qs[1]);
57 Z(qs[0]);
58 X(qs[1]);
59 }
60
61 "#]],
62 );
63}
64
65#[test]
66fn circuit_with_controlled_gate() {
67 check(
68 r#"
69{
70 "componentGrid": [
71 {
72 "components": [
73 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
74 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
75 ]
76 },
77 {
78 "components": [
79 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
80 ]
81 },
82 {
83 "components": [
84 {
85 "kind": "unitary",
86 "gate": "X",
87 "controls": [{ "qubit": 0 }],
88 "targets": [{ "qubit": 1 }]
89 }
90 ]
91 }
92 ],
93 "qubits": [{ "id": 0 }, { "id": 1 }]
94}"#,
95 &expect![[r#"
96 /// Expects a qubit register of at least 2 qubits.
97 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
98 if Length(qs) < 2 {
99 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
100 }
101 H(qs[0]);
102 S(qs[1]);
103 Z(qs[0]);
104 Controlled X([qs[0]], qs[1]);
105 }
106
107 "#]],
108 );
109}
110
111#[test]
112fn circuit_with_adjoint_gate() {
113 check(
114 r#"
115{
116 "componentGrid": [
117 {
118 "components": [
119 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
120 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
121 ]
122 },
123 {
124 "components": [
125 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
126 ]
127 },
128 {
129 "components": [
130 {
131 "kind": "unitary",
132 "gate": "X",
133 "isAdjoint": true,
134 "targets": [{ "qubit": 1 }]
135 }
136 ]
137 }
138 ],
139 "qubits": [{ "id": 0 }, { "id": 1 }]
140}"#,
141 &expect![[r#"
142 /// Expects a qubit register of at least 2 qubits.
143 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
144 if Length(qs) < 2 {
145 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
146 }
147 H(qs[0]);
148 S(qs[1]);
149 Z(qs[0]);
150 Adjoint X(qs[1]);
151 }
152
153 "#]],
154 );
155}
156
157#[test]
158fn circuit_with_controlled_adjoint_gate() {
159 check(
160 r#"
161{
162 "componentGrid": [
163 {
164 "components": [
165 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
166 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
167 ]
168 },
169 {
170 "components": [
171 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
172 ]
173 },
174 {
175 "components": [
176 {
177 "kind": "unitary",
178 "gate": "X",
179 "isAdjoint": true,
180 "controls": [{ "qubit": 0 }],
181 "targets": [{ "qubit": 1 }]
182 }
183 ]
184 }
185 ],
186 "qubits": [{ "id": 0 }, { "id": 1 }]
187}"#,
188 &expect![[r#"
189 /// Expects a qubit register of at least 2 qubits.
190 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
191 if Length(qs) < 2 {
192 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
193 }
194 H(qs[0]);
195 S(qs[1]);
196 Z(qs[0]);
197 Controlled Adjoint X([qs[0]], qs[1]);
198 }
199
200 "#]],
201 );
202}
203
204#[test]
205fn circuit_with_rz_gate() {
206 check(
207 r#"
208{
209 "componentGrid": [
210 {
211 "components": [
212 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
213 ]
214 },
215 {
216 "components": [
217 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
218 { "kind": "unitary", "gate": "Rz", "targets": [{ "qubit": 1 }], "args": ["1.2"] }
219 ]
220 }
221 ],
222 "qubits": [{ "id": 0 }, { "id": 1 }]
223}"#,
224 &expect![[r#"
225 /// Expects a qubit register of at least 2 qubits.
226 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
227 if Length(qs) < 2 {
228 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
229 }
230 H(qs[0]);
231 Z(qs[0]);
232 Rz(1.2, qs[1]);
233 }
234
235 "#]],
236 );
237}
238
239#[test]
240fn circuit_with_controlled_gate_multiple_args() {
241 check(
242 r#"
243{
244 "componentGrid": [
245 {
246 "components": [
247 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
248 ]
249 },
250 {
251 "components": [
252 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
253 ]
254 },
255 {
256 "components": [
257 {
258 "kind": "unitary",
259 "gate": "Rz",
260 "controls": [{ "qubit": 0 }],
261 "targets": [{ "qubit": 1 }],
262 "args": ["1.2"]
263 }
264 ]
265 }
266 ],
267 "qubits": [{ "id": 0 }, { "id": 1 }]
268}"#,
269 &expect![[r#"
270 /// Expects a qubit register of at least 2 qubits.
271 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
272 if Length(qs) < 2 {
273 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
274 }
275 H(qs[0]);
276 Z(qs[0]);
277 Controlled Rz([qs[0]], (1.2, qs[1]));
278 }
279
280 "#]],
281 );
282}
283
284#[test]
285fn circuit_with_pi_arg() {
286 check(
287 r#"
288{
289 "componentGrid": [
290 {
291 "components": [
292 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
293 ]
294 },
295 {
296 "components": [
297 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
298 { "kind": "unitary", "gate": "Rz", "targets": [{ "qubit": 1 }], "args": ["π / 2.0"] }
299 ]
300 },
301 {
302 "components": [
303 { "kind": "unitary", "gate": "Rx", "targets": [{ "qubit": 1 }], "args": ["π / 4.0"] }
304 ]
305 }
306 ],
307 "qubits": [{ "id": 0 }, { "id": 1 }]
308}"#,
309 &expect![[r#"
310 /// Expects a qubit register of at least 2 qubits.
311 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
312 if Length(qs) < 2 {
313 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
314 }
315 let π = Std.Math.PI();
316 H(qs[0]);
317 Z(qs[0]);
318 Rz(π / 2.0, qs[1]);
319 Rx(π / 4.0, qs[1]);
320 }
321
322 "#]],
323 );
324}
325
326#[test]
327fn circuit_with_measurement_gate() {
328 check(
329 r#"
330{
331 "componentGrid": [
332 {
333 "components": [
334 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
335 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
336 ]
337 },
338 {
339 "components": [
340 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
341 ]
342 },
343 {
344 "components": [
345 {
346 "kind": "measurement",
347 "gate": "Measure",
348 "qubits": [{ "qubit": 0 }],
349 "results": [{ "qubit": 0, "result": 0 }]
350 }
351 ]
352 }
353 ],
354 "qubits": [
355 { "id": 0, "numResults": 1 },
356 { "id": 1 }
357 ]
358}"#,
359 &expect![[r#"
360 /// Expects a qubit register of at least 2 qubits.
361 operation Test(qs : Qubit[]) : Result {
362 if Length(qs) < 2 {
363 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
364 }
365 H(qs[0]);
366 S(qs[1]);
367 Z(qs[0]);
368 let c0_0 = M(qs[0]);
369 return c0_0;
370 }
371
372 "#]],
373 );
374}
375
376#[test]
377fn circuit_with_multiple_measurement_gates() {
378 check(
379 r#"
380{
381 "componentGrid": [
382 {
383 "components": [
384 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] },
385 { "kind": "unitary", "gate": "S", "targets": [{ "qubit": 1 }] }
386 ]
387 },
388 {
389 "components": [
390 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] }
391 ]
392 },
393 {
394 "components": [
395 {
396 "kind": "measurement",
397 "gate": "Measure",
398 "qubits": [{ "qubit": 0 }],
399 "results": [{ "qubit": 0, "result": 0 }]
400 },
401 {
402 "kind": "measurement",
403 "gate": "Measure",
404 "qubits": [{ "qubit": 1 }],
405 "results": [{ "qubit": 1, "result": 0 }]
406 }
407 ]
408 },
409 {
410 "components": [
411 {
412 "kind": "measurement",
413 "gate": "Measure",
414 "qubits": [{ "qubit": 0 }],
415 "results": [{ "qubit": 0, "result": 1 }]
416 }
417 ]
418 }
419 ],
420 "qubits": [
421 { "id": 0, "numResults": 2 },
422 { "id": 1, "numResults": 1 }
423 ]
424}"#,
425 &expect![[r#"
426 /// Expects a qubit register of at least 2 qubits.
427 operation Test(qs : Qubit[]) : Result[] {
428 if Length(qs) < 2 {
429 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
430 }
431 H(qs[0]);
432 S(qs[1]);
433 Z(qs[0]);
434 let c0_0 = M(qs[0]);
435 let c1_0 = M(qs[1]);
436 let c0_1 = M(qs[0]);
437 return [c0_0, c0_1, c1_0];
438 }
439
440 "#]],
441 );
442}
443
444#[test]
445fn empty_circuit() {
446 check(
447 r#"
448{
449 "componentGrid": [],
450 "qubits": []
451}"#,
452 &expect![[r#"
453 operation Test() : Unit is Ctl + Adj {
454 }
455
456 "#]],
457 );
458}
459
460#[test]
461fn empty_circuit_with_qubits() {
462 check(
463 r#"
464{
465 "componentGrid": [],
466 "qubits": [{ "id": 0 }, { "id": 1 }]
467}"#,
468 &expect![[r#"
469 /// Expects a qubit register of at least 2 qubits.
470 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
471 }
472
473 "#]],
474 );
475}
476
477#[test]
478fn circuit_with_qubit_missing_num_results() {
479 check(
480 r#"
481{
482 "componentGrid": [
483 {
484 "components": [
485 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
486 ]
487 }
488 ],
489 "qubits": [
490 { "id": 0 }
491 ]
492}"#,
493 &expect![[r#"
494 /// Expects a qubit register of at least 1 qubits.
495 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
496 if Length(qs) < 1 {
497 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 1 qubits.";
498 }
499 H(qs[0]);
500 }
501
502 "#]],
503 );
504}
505
506#[test]
507fn circuit_with_ket_gates() {
508 check(
509 #[allow(clippy::unicode_not_nfc)]
510 r#"
511{
512 "componentGrid": [
513 {
514 "components": [
515 { "kind": "ket", "gate": "0", "targets": [{ "qubit": 0 }] },
516 { "kind": "ket", "gate": "1", "targets": [{ "qubit": 1 }] }
517 ]
518 }
519 ],
520 "qubits": [
521 { "id": 0 },
522 { "id": 1 }
523 ]
524}"#,
525 &expect![[r#"
526 /// Expects a qubit register of at least 2 qubits.
527 operation Test(qs : Qubit[]) : Unit {
528 if Length(qs) < 2 {
529 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
530 }
531 Reset(qs[0]);
532 fail "Unsupported ket operation: |1〉";
533 }
534
535 "#]],
536 );
537}
538
539#[test]
540fn circuit_with_int_args() {
541 check(
542 r#"
543{
544 "componentGrid": [
545 {
546 "components": [
547 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
548 ]
549 },
550 {
551 "components": [
552 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
553 { "kind": "unitary", "gate": "Rz", "targets": [{ "qubit": 1 }], "args": ["π / 2"] }
554 ]
555 },
556 {
557 "components": [
558 { "kind": "unitary", "gate": "Rx", "targets": [{ "qubit": 1 }], "args": [".4 + 4. / 2"] }
559 ]
560 }
561 ],
562 "qubits": [{ "id": 0 }, { "id": 1 }]
563}"#,
564 &expect![[r#"
565 /// Expects a qubit register of at least 2 qubits.
566 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
567 if Length(qs) < 2 {
568 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
569 }
570 let π = Std.Math.PI();
571 H(qs[0]);
572 Z(qs[0]);
573 Rz(π / 2., qs[1]);
574 Rx(.4 + 4. / 2., qs[1]);
575 }
576
577 "#]],
578 );
579}
580
581#[test]
582fn circuit_with_sqrt_x_gate() {
583 check(
584 r#"
585{
586 "componentGrid": [
587 {
588 "components": [
589 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
590 ]
591 },
592 {
593 "components": [
594 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
595 { "kind": "unitary", "gate": "SX", "targets": [{ "qubit": 1 }] }
596 ]
597 },
598 {
599 "components": [
600 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 1 }] }
601 ]
602 }
603 ],
604 "qubits": [{ "id": 0 }, { "id": 1 }]
605}"#,
606 &expect![[r#"
607 /// Expects a qubit register of at least 2 qubits.
608 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
609 if Length(qs) < 2 {
610 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
611 }
612 H(qs[0]);
613 Z(qs[0]);
614 SX(qs[1]);
615 Z(qs[1]);
616 }
617
618 "#]],
619 );
620}
621
622#[test]
623fn circuit_with_ctrl_adj_sqrt_x_gate() {
624 check(
625 r#"
626{
627 "componentGrid": [
628 {
629 "components": [
630 { "kind": "unitary", "gate": "H", "targets": [{ "qubit": 0 }] }
631 ]
632 },
633 {
634 "components": [
635 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 0 }] },
636 {
637 "kind": "unitary",
638 "gate": "SX",
639 "isAdjoint": true,
640 "controls": [{ "qubit": 1 }],
641 "targets": [{ "qubit": 0 }]
642 }
643 ]
644 },
645 {
646 "components": [
647 { "kind": "unitary", "gate": "Z", "targets": [{ "qubit": 1 }] }
648 ]
649 }
650 ],
651 "qubits": [{ "id": 0 }, { "id": 1 }]
652}"#,
653 &expect![[r#"
654 /// Expects a qubit register of at least 2 qubits.
655 operation Test(qs : Qubit[]) : Unit is Ctl + Adj {
656 if Length(qs) < 2 {
657 fail "Invalid number of qubits. Operation Test expects a qubit register of at least 2 qubits.";
658 }
659 H(qs[0]);
660 Z(qs[0]);
661 Controlled Adjoint SX([qs[1]], qs[0]);
662 Z(qs[1]);
663 }
664
665 "#]],
666 );
667}
668