microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fedimser/memory-re

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/src/tests/diagnostics.rs

569lines ยท modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::tests::test_expression_fails;
5
6use super::test_expression;
7use expect_test::expect;
8use qsc::interpret::Value;
9
10#[test]
11fn check_operations_are_equal() {
12 test_expression(
13 "{
14 import Std.Diagnostics.*;
15 import Std.Arrays.*;
16 operation op1(xs: Qubit[]): Unit is Adj {
17 CCNOT(xs[0], xs[1], xs[2]);
18 }
19 operation op2(xs: Qubit[]): Unit is Adj {
20 Controlled X(Most(xs), Tail(xs));
21 }
22 operation op3(xs: Qubit[]): Unit is Adj {
23 Controlled X(Rest(xs), Head(xs));
24 }
25 [CheckOperationsAreEqual(3, op1, op2),
26 CheckOperationsAreEqual(3, op2, op1),
27 CheckOperationsAreEqual(3, op1, op3),
28 CheckOperationsAreEqual(3, op3, op1),
29 CheckOperationsAreEqual(3, op2, op3),
30 CheckOperationsAreEqual(3, op3, op2)]
31
32 }",
33 &Value::Array(
34 vec![
35 Value::Bool(true),
36 Value::Bool(true),
37 Value::Bool(false),
38 Value::Bool(false),
39 Value::Bool(false),
40 Value::Bool(false),
41 ]
42 .into(),
43 ),
44 );
45}
46
47#[test]
48fn check_dumpoperation_for_i() {
49 let output = test_expression(
50 "Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => I(qs[0]))",
51 &Value::unit(),
52 );
53 expect![[r#"
54 MATRIX:
55 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
56 0.0000+0.0000๐‘– 1.0000+0.0000๐‘–
57 "#]]
58 .assert_eq(&output);
59}
60
61#[test]
62fn check_dumpoperation_for_x() {
63 let output = test_expression(
64 "Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => X(qs[0]))",
65 &Value::unit(),
66 );
67 expect![[r#"
68 MATRIX:
69 0.0000+0.0000๐‘– 1.0000+0.0000๐‘–
70 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
71 "#]]
72 .assert_eq(&output);
73}
74
75#[test]
76fn check_dumpoperation_for_h() {
77 let output = test_expression(
78 "Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => H(qs[0]))",
79 &Value::unit(),
80 );
81 expect![[r#"
82 MATRIX:
83 0.7071+0.0000๐‘– 0.7071+0.0000๐‘–
84 0.7071+0.0000๐‘– โˆ’0.7071+0.0000๐‘–
85 "#]]
86 .assert_eq(&output);
87}
88
89#[test]
90fn check_dumpoperation_for_y() {
91 let output = test_expression(
92 "Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => Y(qs[0]))",
93 &Value::unit(),
94 );
95 expect![[r#"
96 MATRIX:
97 0.0000+0.0000๐‘– 0.0000โˆ’1.0000๐‘–
98 0.0000+1.0000๐‘– 0.0000+0.0000๐‘–
99 "#]]
100 .assert_eq(&output);
101}
102
103#[test]
104fn check_dumpoperation_for_ccnot() {
105 let output = test_expression(
106 "Microsoft.Quantum.Diagnostics.DumpOperation(3, qs => CCNOT(qs[0], qs[1], qs[2]))",
107 &Value::unit(),
108 );
109 expect![[r#"
110 MATRIX:
111 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๐‘–
112 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๐‘–
113 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๐‘–
114 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๐‘–
115 0.0000+0.0000๐‘– 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๐‘–
116 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘–
117 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๐‘– 1.0000+0.0000๐‘–
118 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
119 "#]].assert_eq(&output);
120}
121
122#[test]
123fn check_dumpoperation_with_extra_qubits_allocated() {
124 let output = test_expression(
125 "{use qs = Qubit[2]; Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => H(qs[0]))}",
126 &Value::unit(),
127 );
128 expect![[r#"
129 MATRIX:
130 0.7071+0.0000๐‘– 0.7071+0.0000๐‘–
131 0.7071+0.0000๐‘– โˆ’0.7071+0.0000๐‘–
132 "#]]
133 .assert_eq(&output);
134}
135
136#[test]
137fn check_start_stop_counting_operation_called_3_times() {
138 test_expression(
139 "{
140 import Microsoft.Quantum.Diagnostics.StartCountingOperation;
141 import Microsoft.Quantum.Diagnostics.StopCountingOperation;
142
143 operation op1() : Unit {}
144 operation op2() : Unit { op1(); }
145 StartCountingOperation(op1);
146 StartCountingOperation(op2);
147 op1(); op1(); op2();
148 (StopCountingOperation(op1), StopCountingOperation(op2))
149 }",
150 &Value::Tuple([Value::Int(3), Value::Int(1)].into(), None),
151 );
152}
153
154#[test]
155fn check_start_stop_counting_operation_called_0_times() {
156 test_expression(
157 "{
158 import Microsoft.Quantum.Diagnostics.StartCountingOperation;
159 import Microsoft.Quantum.Diagnostics.StopCountingOperation;
160
161 operation op1() : Unit {}
162 operation op2() : Unit { op1(); }
163 StartCountingOperation(op1);
164 StartCountingOperation(op2);
165 (StopCountingOperation(op1), StopCountingOperation(op2))
166 }",
167 &Value::Tuple([Value::Int(0), Value::Int(0)].into(), None),
168 );
169}
170
171#[test]
172fn check_lambda_counted_separately_from_operation() {
173 test_expression(
174 "{
175 import Microsoft.Quantum.Diagnostics.StartCountingOperation;
176 import Microsoft.Quantum.Diagnostics.StopCountingOperation;
177
178 operation op1() : Unit {}
179 StartCountingOperation(op1);
180 let lambda = () => op1();
181 StartCountingOperation(lambda);
182 op1();
183 lambda();
184 (StopCountingOperation(op1), StopCountingOperation(lambda))
185 }",
186 &Value::Tuple([Value::Int(2), Value::Int(1)].into(), None),
187 );
188}
189
190#[test]
191fn check_multiple_controls_counted_together() {
192 test_expression(
193 "{
194 import Microsoft.Quantum.Diagnostics.StartCountingOperation;
195 import Microsoft.Quantum.Diagnostics.StopCountingOperation;
196
197 operation op1() : Unit is Adj + Ctl {}
198 StartCountingOperation(Controlled op1);
199 Controlled op1([], ());
200 Controlled Controlled op1([], ([], ()));
201 Controlled Controlled Controlled op1([], ([], ([], ())));
202 (StopCountingOperation(Controlled op1))
203 }",
204 &Value::Int(3),
205 );
206}
207
208#[test]
209fn check_counting_operation_differentiates_between_body_adj_ctl() {
210 test_expression(
211 "{
212 import Microsoft.Quantum.Diagnostics.StartCountingOperation;
213 import Microsoft.Quantum.Diagnostics.StopCountingOperation;
214
215 operation op1() : Unit is Adj + Ctl {}
216 StartCountingOperation(op1);
217 StartCountingOperation(Adjoint op1);
218 StartCountingOperation(Controlled op1);
219 StartCountingOperation(Adjoint Controlled op1);
220 op1();
221 Adjoint op1(); Adjoint op1();
222 Controlled op1([], ()); Controlled op1([], ()); Controlled op1([], ());
223 Adjoint Controlled op1([], ()); Adjoint Controlled op1([], ());
224 Controlled Adjoint op1([], ()); Controlled Adjoint op1([], ());
225 (StopCountingOperation(op1), StopCountingOperation(Adjoint op1), StopCountingOperation(Controlled op1), StopCountingOperation(Adjoint Controlled op1))
226 }",
227 &Value::Tuple([Value::Int(1), Value::Int(2), Value::Int(3), Value::Int(4)].into(), None),
228 );
229}
230
231#[test]
232fn check_start_stop_counting_function_called_3_times() {
233 test_expression(
234 "{
235 import Microsoft.Quantum.Diagnostics.StartCountingFunction;
236 import Microsoft.Quantum.Diagnostics.StopCountingFunction;
237
238 function f1() : Unit {}
239 function f2() : Unit { f1(); }
240 StartCountingFunction(f1);
241 StartCountingFunction(f2);
242 f1(); f1(); f2();
243 (StopCountingFunction(f1), StopCountingFunction(f2))
244 }",
245 &Value::Tuple([Value::Int(3), Value::Int(1)].into(), None),
246 );
247}
248
249#[test]
250fn check_start_stop_counting_function_called_0_times() {
251 test_expression(
252 "{
253 import Microsoft.Quantum.Diagnostics.StartCountingFunction;
254 import Microsoft.Quantum.Diagnostics.StopCountingFunction;
255
256 function f1() : Unit {}
257 function f2() : Unit { f1(); }
258 StartCountingFunction(f1);
259 StartCountingFunction(f2);
260 (StopCountingFunction(f1), StopCountingFunction(f2))
261 }",
262 &Value::Tuple([Value::Int(0), Value::Int(0)].into(), None),
263 );
264}
265
266#[test]
267fn check_start_counting_qubits_for_one_allocation() {
268 test_expression(
269 "{
270 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
271 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
272
273 StartCountingQubits();
274 use q = Qubit();
275 StopCountingQubits()
276 }",
277 &Value::Int(1),
278 );
279}
280
281#[test]
282fn check_start_counting_qubits_for_tuple_allocation() {
283 test_expression(
284 "{
285 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
286 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
287
288 StartCountingQubits();
289 use (q0, q1) = (Qubit(), Qubit());
290 StopCountingQubits()
291 }",
292 &Value::Int(2),
293 );
294}
295
296#[test]
297fn check_start_counting_qubits_for_array_allocation() {
298 test_expression(
299 "{
300 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
301 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
302
303 StartCountingQubits();
304 use qs = Qubit[2];
305 StopCountingQubits()
306 }",
307 &Value::Int(2),
308 );
309}
310
311#[test]
312fn check_start_counting_qubits_after_allocation_gives_zero() {
313 test_expression(
314 "{
315 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
316 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
317
318 use q = Qubit();
319 StartCountingQubits();
320 StopCountingQubits()
321 }",
322 &Value::Int(0),
323 );
324}
325
326#[test]
327fn check_start_counting_qubits_sees_same_qubit_as_single_count() {
328 test_expression(
329 "{
330 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
331 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
332
333 StartCountingQubits();
334 {
335 use q = Qubit();
336 }
337 {
338 use q = Qubit();
339 }
340 StopCountingQubits()
341 }",
342 &Value::Int(1),
343 );
344}
345
346#[test]
347fn check_start_counting_qubits_works_with_manual_out_of_order_allocation_release() {
348 test_expression(
349 "{
350 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
351 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
352 import QIR.Runtime.__quantum__rt__qubit_allocate;
353 import QIR.Runtime.__quantum__rt__qubit_release;
354
355 let (q0, q1, q2) = (__quantum__rt__qubit_allocate(), __quantum__rt__qubit_allocate(), __quantum__rt__qubit_allocate());
356 StartCountingQubits();
357 __quantum__rt__qubit_release(q2);
358 use q = Qubit();
359 __quantum__rt__qubit_release(q0);
360 __quantum__rt__qubit_release(q1);
361 use qs = Qubit[2];
362 StopCountingQubits()
363 }",
364 &Value::Int(3),
365 );
366}
367
368#[test]
369fn check_counting_qubits_works_with_allocation_in_operation_calls() {
370 test_expression(
371 "{
372 import Microsoft.Quantum.Diagnostics.StartCountingQubits;
373 import Microsoft.Quantum.Diagnostics.StopCountingQubits;
374 import Microsoft.Quantum.Diagnostics.CheckOperationsAreEqual;
375
376 StartCountingQubits();
377 let numQubits = 2;
378 let equal = CheckOperationsAreEqual(2,
379 qs => SWAP(qs[0], qs[1]),
380 qs => { CNOT(qs[0], qs[1]); CNOT(qs[1], qs[0]); CNOT(qs[0], qs[1]); }
381 );
382 (true, 2 * numQubits) == (equal, StopCountingQubits())
383 }",
384 &Value::Bool(true),
385 );
386}
387
388#[test]
389fn check_dumpoperation_with_extra_qubits_in_superposition() {
390 let output = test_expression(
391 "{use qs = Qubit[2]; H(qs[0]); Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => H(qs[0])); Reset(qs[0]);}",
392 &Value::unit(),
393 );
394 expect![[r#"
395 MATRIX:
396 0.7071+0.0000๐‘– 0.7071+0.0000๐‘–
397 0.7071+0.0000๐‘– โˆ’0.7071+0.0000๐‘–
398 "#]]
399 .assert_eq(&output);
400}
401
402#[test]
403fn check_dumpoperation_with_extra_qubits_global_phase_reflected_in_matrix() {
404 let output = test_expression(
405 "{use qs = Qubit[2]; R(PauliI, Std.Math.PI() / 2.0, qs[0]); Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => H(qs[0])); Reset(qs[0]);}",
406 &Value::unit(),
407 );
408 expect![[r#"
409 MATRIX:
410 0.5000โˆ’0.5000๐‘– 0.5000โˆ’0.5000๐‘–
411 0.5000โˆ’0.5000๐‘– โˆ’0.5000+0.5000๐‘–
412 "#]]
413 .assert_eq(&output);
414}
415
416#[test]
417fn check_dumpoperation_with_extra_qubits_relative_phase_not_reflected_in_matrix() {
418 let output = test_expression(
419 "{use qs = Qubit[2]; R1(Std.Math.PI() / 2.0, qs[0]); Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => H(qs[0])); Reset(qs[0]);}",
420 &Value::unit(),
421 );
422 expect![[r#"
423 MATRIX:
424 0.7071+0.0000๐‘– 0.7071+0.0000๐‘–
425 0.7071+0.0000๐‘– โˆ’0.7071+0.0000๐‘–
426 "#]]
427 .assert_eq(&output);
428}
429
430#[test]
431fn check_dump_operation_for_r1_of_pi() {
432 let output = test_expression(
433 "Microsoft.Quantum.Diagnostics.DumpOperation(1, qs => R1(Std.Math.PI(), qs[0]))",
434 &Value::unit(),
435 );
436 expect![[r#"
437 MATRIX:
438 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
439 0.0000+0.0000๐‘– โˆ’1.0000+0.0000๐‘–
440 "#]]
441 .assert_eq(&output);
442}
443
444#[test]
445fn check_dump_operation_for_r1_of_pi_with_one_control() {
446 let output = test_expression(
447 "Microsoft.Quantum.Diagnostics.DumpOperation(2, qs => Controlled R1(qs[...0], (Std.Math.PI(), qs[1])))",
448 &Value::unit(),
449 );
450 expect![[r#"
451 MATRIX:
452 1.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘–
453 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘–
454 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
455 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– โˆ’1.0000+0.0000๐‘–
456 "#]]
457 .assert_eq(&output);
458}
459
460#[test]
461fn check_dump_operation_for_r1_of_pi_with_two_controls() {
462 let output = test_expression(
463 "Microsoft.Quantum.Diagnostics.DumpOperation(3, qs => Controlled R1(qs[...1], (Std.Math.PI(), qs[2])))",
464 &Value::unit(),
465 );
466 expect![[r#"
467 MATRIX:
468 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๐‘–
469 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๐‘–
470 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๐‘–
471 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๐‘–
472 0.0000+0.0000๐‘– 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๐‘–
473 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘–
474 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 0.0000+0.0000๐‘– 1.0000+0.0000๐‘– 0.0000+0.0000๐‘–
475 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๐‘– โˆ’1.0000+0.0000๐‘–
476 "#]].assert_eq(&output);
477}
478
479#[test]
480fn check_bit_flip_noise_values() {
481 test_expression(
482 "Std.Diagnostics.BitFlipNoise(0.3)",
483 &Value::Tuple(
484 [Value::Double(0.3), Value::Double(0.0), Value::Double(0.0)].into(),
485 None,
486 ),
487 );
488}
489
490#[test]
491fn check_phase_flip_noise_values() {
492 test_expression(
493 "Std.Diagnostics.PhaseFlipNoise(0.3)",
494 &Value::Tuple(
495 [Value::Double(0.0), Value::Double(0.0), Value::Double(0.3)].into(),
496 None,
497 ),
498 );
499}
500
501#[test]
502fn check_depolarizing_noise_values() {
503 test_expression(
504 "Std.Diagnostics.DepolarizingNoise(0.3)",
505 &Value::Tuple(
506 [Value::Double(0.1), Value::Double(0.1), Value::Double(0.1)].into(),
507 None,
508 ),
509 );
510}
511
512#[test]
513fn check_no_noise_values() {
514 test_expression(
515 "Std.Diagnostics.NoNoise()",
516 &Value::Tuple(
517 [Value::Double(0.0), Value::Double(0.0), Value::Double(0.0)].into(),
518 None,
519 ),
520 );
521}
522
523#[test]
524fn check_post_select_collapses_superposition_to_zero() {
525 test_expression(
526 "{
527 import Std.Diagnostics.PostSelectZ;
528 import Std.Diagnostics.CheckZero;
529 use q = Qubit();
530 H(q);
531 PostSelectZ(Zero, q);
532 CheckZero(q)
533 }",
534 &Value::Bool(true),
535 );
536}
537
538#[test]
539fn check_post_select_collapses_superposition_to_one() {
540 test_expression(
541 "{
542 import Std.Diagnostics.PostSelectZ;
543 import Std.Diagnostics.CheckZero;
544 use q = Qubit();
545 H(q);
546 PostSelectZ(One, q);
547 let check = CheckZero(q);
548 Reset(q);
549 check
550 }",
551 &Value::Bool(false),
552 );
553}
554
555#[test]
556fn check_post_select_fails_with_non_existent_state() {
557 let err = test_expression_fails(
558 "{
559 import Std.Diagnostics.PostSelectZ;
560 import Std.Diagnostics.CheckZero;
561 use q = Qubit();
562 PostSelectZ(One, q);
563 }",
564 );
565 expect![
566 "intrinsic callable `PostSelectZ` failed: post-selection condition has zero probability"
567 ]
568 .assert_eq(&err);
569}
570