microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.18.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/pip/tests/test_qsharp.py

781lines ยท modecode

1# Copyright (c) Microsoft Corporation.
2# Licensed under the MIT License.
3
4from textwrap import dedent
5import pytest
6import qsharp
7import qsharp.code
8import qsharp.utils
9from contextlib import redirect_stdout
10import io
11
12# Tests for the Python library for Q#
13
14
15def test_stdout() -> None:
16 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
17 f = io.StringIO()
18 with redirect_stdout(f):
19 result = qsharp.eval('Message("Hello, world!")')
20
21 assert result is None
22 assert f.getvalue() == "Hello, world!\n"
23
24
25def test_stdout_multiple_lines() -> None:
26 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
27 f = io.StringIO()
28 with redirect_stdout(f):
29 qsharp.eval(
30 """
31 use q = Qubit();
32 Microsoft.Quantum.Diagnostics.DumpMachine();
33 Message("Hello!");
34 """
35 )
36
37 assert f.getvalue() == "STATE:\n|0โŸฉ: 1.0000+0.0000๐‘–\nHello!\n"
38
39
40def test_captured_stdout() -> None:
41 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
42 f = io.StringIO()
43 with redirect_stdout(f):
44 result = qsharp.eval(
45 '{Message("Hello, world!"); Message("Goodbye!")}', save_events=True
46 )
47 assert f.getvalue() == ""
48 assert len(result["messages"]) == 2
49 assert result["messages"][0] == "Hello, world!"
50 assert result["messages"][1] == "Goodbye!"
51
52
53def test_captured_matrix() -> None:
54 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
55 f = io.StringIO()
56 with redirect_stdout(f):
57 result = qsharp.eval(
58 "Std.Diagnostics.DumpOperation(1, qs => H(qs[0]))",
59 save_events=True,
60 )
61 assert f.getvalue() == ""
62 assert len(result["matrices"]) == 1
63 assert (
64 str(result["matrices"][0])
65 == "MATRIX:\n 0.7071+0.0000๐‘– 0.7071+0.0000๐‘–\n 0.7071+0.0000๐‘– โˆ’0.7071+0.0000๐‘–"
66 )
67
68
69def test_quantum_seed() -> None:
70 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
71 qsharp.set_quantum_seed(42)
72 value1 = qsharp.eval(
73 "{ use qs = Qubit[32]; for q in qs { H(q); }; Microsoft.Quantum.Measurement.MResetEachZ(qs) }"
74 )
75 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
76 qsharp.set_quantum_seed(42)
77 value2 = qsharp.eval(
78 "{ use qs = Qubit[32]; for q in qs { H(q); }; Microsoft.Quantum.Measurement.MResetEachZ(qs) }"
79 )
80 assert value1 == value2
81 qsharp.set_quantum_seed(None)
82 value3 = qsharp.eval(
83 "{ use qs = Qubit[32]; for q in qs { H(q); }; Microsoft.Quantum.Measurement.MResetEachZ(qs) }"
84 )
85 assert value1 != value3
86
87
88def test_classical_seed() -> None:
89 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
90 qsharp.set_classical_seed(42)
91 value1 = qsharp.eval(
92 "{ mutable res = []; for _ in 0..15{ set res += [(Microsoft.Quantum.Random.DrawRandomInt(0, 100), Microsoft.Quantum.Random.DrawRandomDouble(0.0, 1.0))]; }; res }"
93 )
94 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
95 qsharp.set_classical_seed(42)
96 value2 = qsharp.eval(
97 "{ mutable res = []; for _ in 0..15{ set res += [(Microsoft.Quantum.Random.DrawRandomInt(0, 100), Microsoft.Quantum.Random.DrawRandomDouble(0.0, 1.0))]; }; res }"
98 )
99 assert value1 == value2
100 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
101 qsharp.set_classical_seed(None)
102 value3 = qsharp.eval(
103 "{ mutable res = []; for _ in 0..15{ set res += [(Microsoft.Quantum.Random.DrawRandomInt(0, 100), Microsoft.Quantum.Random.DrawRandomDouble(0.0, 1.0))]; }; res }"
104 )
105 assert value1 != value3
106
107
108def test_dump_machine() -> None:
109 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
110 qsharp.eval(
111 """
112 use q1 = Qubit();
113 use q2 = Qubit();
114 X(q1);
115 """
116 )
117 state_dump = qsharp.dump_machine()
118 assert state_dump.qubit_count == 2
119 assert len(state_dump) == 1
120 assert state_dump[2] == complex(1.0, 0.0)
121 assert state_dump.as_dense_state() == [0, 0, 1, 0]
122 qsharp.eval("X(q2);")
123 state_dump = qsharp.dump_machine()
124 assert state_dump.qubit_count == 2
125 assert len(state_dump) == 1
126 assert state_dump[3] == complex(1.0, 0.0)
127 assert state_dump.as_dense_state() == [0, 0, 0, 1]
128 qsharp.eval("H(q1);")
129 state_dump = qsharp.dump_machine()
130 assert state_dump.qubit_count == 2
131 assert len(state_dump) == 2
132 # Check that the state dump correctly supports iteration and membership checks
133 for idx in state_dump:
134 assert idx in state_dump
135 # Check that the state dump is correct and equivalence check ignores global phase, allowing passing
136 # in of different, potentially unnormalized states. The state should be
137 # |01โŸฉ: 0.7071+0.0000๐‘–, |11โŸฉ: โˆ’0.7071+0.0000๐‘–
138 assert state_dump.check_eq({1: complex(0.7071, 0.0), 3: complex(-0.7071, 0.0)})
139 assert state_dump.as_dense_state() == [
140 0,
141 0.7071067811865476,
142 0,
143 -0.7071067811865476,
144 ]
145 assert state_dump.check_eq({1: complex(0.0, 0.7071), 3: complex(0.0, -0.7071)})
146 assert state_dump.check_eq({1: complex(0.5, 0.0), 3: complex(-0.5, 0.0)})
147 assert state_dump.check_eq(
148 {1: complex(0.7071, 0.0), 3: complex(-0.7071, 0.0), 0: complex(0.0, 0.0)}
149 )
150 assert state_dump.check_eq([0.0, 0.5, 0.0, -0.5])
151 assert state_dump.check_eq([0.0, 0.5001, 0.00001, -0.5], tolerance=1e-3)
152 assert state_dump.check_eq(
153 [complex(0.0, 0.0), complex(0.0, -0.5), complex(0.0, 0.0), complex(0.0, 0.5)]
154 )
155 assert not state_dump.check_eq({1: complex(0.7071, 0.0), 3: complex(0.7071, 0.0)})
156 assert not state_dump.check_eq({1: complex(0.5, 0.0), 3: complex(0.0, 0.5)})
157 assert not state_dump.check_eq({2: complex(0.5, 0.0), 3: complex(-0.5, 0.0)})
158 assert not state_dump.check_eq([0.0, 0.5001, 0.0, -0.5], tolerance=1e-6)
159 # Reset the qubits and apply a small rotation to q1, to confirm that tolerance applies to the dump
160 # itself and not just the state.
161 qsharp.eval("ResetAll([q1, q2]);")
162 qsharp.eval("Ry(0.0001, q1);")
163 state_dump = qsharp.dump_machine()
164 assert state_dump.qubit_count == 2
165 assert len(state_dump) == 2
166 assert not state_dump.check_eq([1.0])
167 assert state_dump.check_eq([0.99999999875, 0.0, 4.999999997916667e-05])
168 assert state_dump.check_eq([1.0], tolerance=1e-4)
169
170
171def test_dump_operation() -> None:
172 qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted)
173 res = qsharp.utils.dump_operation("qs => ()", 1)
174 assert res == [
175 [complex(1.0, 0.0), complex(0.0, 0.0)],
176 [complex(0.0, 0.0), complex(1.0, 0.0)],
177 ]
178 res = qsharp.utils.dump_operation("qs => H(qs[0])", 1)
179 assert res == [
180 [complex(0.707107, 0.0), complex(0.707107, 0.0)],
181 [complex(0.707107, 0.0), complex(-0.707107, 0.0)],
182 ]
183 res = qsharp.utils.dump_operation("qs => CNOT(qs[0], qs[1])", 2)
184 assert res == [
185 [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)],
186 [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)],
187 [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)],
188 [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)],
189 ]
190 res = qsharp.utils.dump_operation("qs => CCNOT(qs[0], qs[1], qs[2])", 3)
191 assert res == [
192 [
193 complex(1.0, 0.0),
194 complex(0.0, 0.0),
195 complex(0.0, 0.0),
196 complex(0.0, 0.0),
197 complex(0.0, 0.0),
198 complex(0.0, 0.0),
199 complex(0.0, 0.0),
200 complex(0.0, 0.0),
201 ],
202 [
203 complex(0.0, 0.0),
204 complex(1.0, 0.0),
205 complex(0.0, 0.0),
206 complex(0.0, 0.0),
207 complex(0.0, 0.0),
208 complex(0.0, 0.0),
209 complex(0.0, 0.0),
210 complex(0.0, 0.0),
211 ],
212 [
213 complex(0.0, 0.0),
214 complex(0.0, 0.0),
215 complex(1.0, 0.0),
216 complex(0.0, 0.0),
217 complex(0.0, 0.0),
218 complex(0.0, 0.0),
219 complex(0.0, 0.0),
220 complex(0.0, 0.0),
221 ],
222 [
223 complex(0.0, 0.0),
224 complex(0.0, 0.0),
225 complex(0.0, 0.0),
226 complex(1.0, 0.0),
227 complex(0.0, 0.0),
228 complex(0.0, 0.0),
229 complex(0.0, 0.0),
230 complex(0.0, 0.0),
231 ],
232 [
233 complex(0.0, 0.0),
234 complex(0.0, 0.0),
235 complex(0.0, 0.0),
236 complex(0.0, 0.0),
237 complex(1.0, 0.0),
238 complex(0.0, 0.0),
239 complex(0.0, 0.0),
240 complex(0.0, 0.0),
241 ],
242 [
243 complex(0.0, 0.0),
244 complex(0.0, 0.0),
245 complex(0.0, 0.0),
246 complex(0.0, 0.0),
247 complex(0.0, 0.0),
248 complex(1.0, 0.0),
249 complex(0.0, 0.0),
250 complex(0.0, 0.0),
251 ],
252 [
253 complex(0.0, 0.0),
254 complex(0.0, 0.0),
255 complex(0.0, 0.0),
256 complex(0.0, 0.0),
257 complex(0.0, 0.0),
258 complex(0.0, 0.0),
259 complex(0.0, 0.0),
260 complex(1.0, 0.0),
261 ],
262 [
263 complex(0.0, 0.0),
264 complex(0.0, 0.0),
265 complex(0.0, 0.0),
266 complex(0.0, 0.0),
267 complex(0.0, 0.0),
268 complex(0.0, 0.0),
269 complex(1.0, 0.0),
270 complex(0.0, 0.0),
271 ],
272 ]
273 qsharp.eval(
274 "operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }"
275 )
276 res = qsharp.utils.dump_operation("ApplySWAP", 2)
277 assert res == [
278 [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)],
279 [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)],
280 [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)],
281 [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)],
282 ]
283 res = qsharp.utils.dump_operation("qs => ()", 8)
284 for i in range(8):
285 for j in range(8):
286 if i == j:
287 assert res[i][j] == complex(1.0, 0.0)
288 else:
289 assert res[i][j] == complex(0.0, 0.0)
290
291
292def test_run_with_noise_produces_noisy_results() -> None:
293 qsharp.init()
294 qsharp.set_quantum_seed(0)
295 result = qsharp.run(
296 "{ mutable errors=0; for _ in 0..100 { use q1=Qubit(); use q2=Qubit(); H(q1); CNOT(q1, q2); if MResetZ(q1) != MResetZ(q2) { set errors+=1; } } errors }",
297 shots=1,
298 noise=qsharp.BitFlipNoise(0.1),
299 )
300 assert result[0] > 5
301 result = qsharp.run(
302 "{ mutable errors=0; for _ in 0..100 { use q=Qubit(); if MResetZ(q) != Zero { set errors+=1; } } errors }",
303 shots=1,
304 noise=qsharp.BitFlipNoise(0.1),
305 )
306 assert result[0] > 5
307
308
309def test_compile_qir_input_data() -> None:
310 qsharp.init(target_profile=qsharp.TargetProfile.Base)
311 qsharp.eval("operation Program() : Result { use q = Qubit(); return M(q) }")
312 operation = qsharp.compile("Program()")
313 qir = operation._repr_qir_()
314 assert isinstance(qir, bytes)
315
316
317def test_compile_qir_str() -> None:
318 qsharp.init(target_profile=qsharp.TargetProfile.Base)
319 qsharp.eval("operation Program() : Result { use q = Qubit(); return MResetZ(q); }")
320 operation = qsharp.compile("Program()")
321 qir = str(operation)
322 assert "define void @ENTRYPOINT__main()" in qir
323 assert '"required_num_qubits"="1" "required_num_results"="1"' in qir
324
325
326def test_compile_qir_str_from_python_callable() -> None:
327 qsharp.init(target_profile=qsharp.TargetProfile.Base)
328 qsharp.eval("operation Program() : Result { use q = Qubit(); return MResetZ(q); }")
329 operation = qsharp.compile(qsharp.code.Program)
330 qir = str(operation)
331 assert "define void @ENTRYPOINT__main()" in qir
332 assert '"required_num_qubits"="1" "required_num_results"="1"' in qir
333
334
335def test_compile_qir_str_from_python_callable_with_single_arg() -> None:
336 qsharp.init(target_profile=qsharp.TargetProfile.Base)
337 qsharp.eval(
338 "operation Program(nQubits : Int) : Result[] { use qs = Qubit[nQubits]; MResetEachZ(qs) }"
339 )
340 operation = qsharp.compile(qsharp.code.Program, 5)
341 qir = str(operation)
342 assert "define void @ENTRYPOINT__main()" in qir
343 assert (
344 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 4 to %Result*), i8* null)"
345 in qir
346 )
347 assert '"required_num_qubits"="5" "required_num_results"="5"' in qir
348
349
350def test_compile_qir_str_from_python_callable_with_array_arg() -> None:
351 qsharp.init(target_profile=qsharp.TargetProfile.Base)
352 qsharp.eval(
353 "operation Program(nQubits : Int[]) : Result[] { use qs = Qubit[nQubits[1]]; MResetEachZ(qs) }"
354 )
355 operation = qsharp.compile(qsharp.code.Program, [5, 3])
356 qir = str(operation)
357 assert "define void @ENTRYPOINT__main()" in qir
358 assert (
359 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)"
360 in qir
361 )
362 assert (
363 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 4 to %Result*), i8* null)"
364 not in qir
365 )
366 assert '"required_num_qubits"="3" "required_num_results"="3"' in qir
367
368
369def test_compile_qir_str_from_python_callable_with_multiple_args() -> None:
370 qsharp.init(target_profile=qsharp.TargetProfile.Base)
371 qsharp.eval(
372 "operation Program(nQubits : Int, nResults : Int) : Result[] { use qs = Qubit[nQubits]; MResetEachZ(qs)[...nResults-1] }"
373 )
374 operation = qsharp.compile(qsharp.code.Program, 5, 3)
375 qir = str(operation)
376 assert "define void @ENTRYPOINT__main()" in qir
377 assert (
378 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)"
379 in qir
380 )
381 assert (
382 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 4 to %Result*), i8* null)"
383 not in qir
384 )
385 assert '"required_num_qubits"="5" "required_num_results"="5"' in qir
386
387
388def test_compile_qir_str_from_python_callable_with_multiple_args_passed_as_tuple() -> (
389 None
390):
391 qsharp.init(target_profile=qsharp.TargetProfile.Base)
392 qsharp.eval(
393 "operation Program(nQubits : Int, nResults : Int) : Result[] { use qs = Qubit[nQubits]; MResetEachZ(qs)[...nResults-1] }"
394 )
395 args = (5, 3)
396 operation = qsharp.compile(qsharp.code.Program, args)
397 qir = str(operation)
398 assert "define void @ENTRYPOINT__main()" in qir
399 assert (
400 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)"
401 in qir
402 )
403 assert (
404 "call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 4 to %Result*), i8* null)"
405 not in qir
406 )
407 assert '"required_num_qubits"="5" "required_num_results"="5"' in qir
408
409
410def test_init_from_provider_name() -> None:
411 config = qsharp.init(target_name="ionq.simulator")
412 assert config._config["targetProfile"] == "base"
413 config = qsharp.init(target_name="rigetti.sim.qvm")
414 assert config._config["targetProfile"] == "base"
415 config = qsharp.init(target_name="quantinuum.sim")
416 assert config._config["targetProfile"] == "adaptive_ri"
417 config = qsharp.init(target_name="Quantinuum")
418 assert config._config["targetProfile"] == "adaptive_ri"
419 config = qsharp.init(target_name="IonQ")
420 assert config._config["targetProfile"] == "base"
421
422
423def test_run_with_result(capsys) -> None:
424 qsharp.init()
425 qsharp.eval('operation Foo() : Result { Message("Hello, world!"); Zero }')
426 results = qsharp.run("Foo()", 3)
427 assert results == [qsharp.Result.Zero, qsharp.Result.Zero, qsharp.Result.Zero]
428 stdout = capsys.readouterr().out
429 assert stdout == "Hello, world!\nHello, world!\nHello, world!\n"
430
431
432def test_run_with_result_from_callable(capsys) -> None:
433 qsharp.init()
434 qsharp.eval(
435 'operation Foo() : Result { Message("Hello, world!"); use q = Qubit(); M(q) }'
436 )
437 results = qsharp.run(qsharp.code.Foo, 3)
438 assert results == [qsharp.Result.Zero, qsharp.Result.Zero, qsharp.Result.Zero]
439 stdout = capsys.readouterr().out
440 assert stdout == "Hello, world!\nHello, world!\nHello, world!\n"
441
442
443def test_run_with_result_from_callable_while_global_qubits_allocated(capsys) -> None:
444 qsharp.init()
445 qsharp.eval("use q = Qubit();")
446 qsharp.eval(
447 'operation Foo() : Result { Message("Hello, world!"); use q = Qubit(); M(q) }'
448 )
449 results = qsharp.run(qsharp.code.Foo, 3)
450 assert results == [qsharp.Result.Zero, qsharp.Result.Zero, qsharp.Result.Zero]
451 stdout = capsys.readouterr().out
452 assert stdout == "Hello, world!\nHello, world!\nHello, world!\n"
453
454
455def test_run_with_result_callback(capsys) -> None:
456 def on_result(result):
457 nonlocal called
458 called = True
459 assert result["result"] == qsharp.Result.Zero
460 assert str(result["events"]) == "[Hello, world!]"
461
462 called = False
463 qsharp.init()
464 qsharp.eval('operation Foo() : Result { Message("Hello, world!"); Zero }')
465 results = qsharp.run("Foo()", 3, on_result=on_result, save_events=True)
466 assert (
467 str(results)
468 == "[{'result': Zero, 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}, {'result': Zero, 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}, {'result': Zero, 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}]"
469 )
470 stdout = capsys.readouterr().out
471 assert stdout == ""
472 assert called
473
474
475def test_run_with_result_callback_from_callable_with_args(capsys) -> None:
476 def on_result(result):
477 nonlocal called
478 called = True
479 assert result["result"] == [qsharp.Result.Zero, qsharp.Result.Zero]
480 assert str(result["events"]) == "[Hello, world!]"
481
482 called = False
483 qsharp.init()
484 qsharp.eval(
485 'operation Foo(nResults : Int) : Result[] { Message("Hello, world!"); Repeated(Zero, nResults) }'
486 )
487 results = qsharp.run(qsharp.code.Foo, 3, 2, on_result=on_result, save_events=True)
488 assert (
489 str(results)
490 == "[{'result': [Zero, Zero], 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}, {'result': [Zero, Zero], 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}, {'result': [Zero, Zero], 'events': [Hello, world!], 'messages': ['Hello, world!'], 'matrices': [], 'dumps': []}]"
491 )
492 stdout = capsys.readouterr().out
493 assert stdout == ""
494 assert called
495
496
497def test_run_with_invalid_shots_produces_error() -> None:
498 qsharp.init()
499 qsharp.eval('operation Foo() : Result { Message("Hello, world!"); Zero }')
500 try:
501 qsharp.run("Foo()", -1)
502 except ValueError as e:
503 assert str(e) == "The number of shots must be greater than 0."
504 else:
505 assert False
506
507 try:
508 qsharp.run("Foo()", 0)
509 except ValueError as e:
510 assert str(e) == "The number of shots must be greater than 0."
511 else:
512 assert False
513
514
515def test_callables_exposed_into_env() -> None:
516 qsharp.init()
517 qsharp.eval("function Four() : Int { 4 }")
518 assert qsharp.code.Four() == 4, "callable should be available"
519 qsharp.eval("function Add(a : Int, b : Int) : Int { a + b }")
520 assert qsharp.code.Four() == 4, "first callable should still be available"
521 assert qsharp.code.Add(2, 3) == 5, "second callable should be available"
522 # After init, the callables should be cleared and no longer available
523 qsharp.init()
524 with pytest.raises(AttributeError):
525 qsharp.code.Four()
526
527
528def test_callable_exposed_into_env_complex_types() -> None:
529 qsharp.eval(
530 "function Complicated(a : Int, b : (Double, BigInt)) : ((Double, BigInt), Int) { (b, a) }"
531 )
532 assert qsharp.code.Complicated(2, (3.0, 4000000000000000000000)) == (
533 (3.0, 4000000000000000000000),
534 2,
535 ), "callables that take complex types should marshall them correctly"
536
537
538def test_callable_exposed_into_env_with_array() -> None:
539 qsharp.init()
540 qsharp.eval("function Smallest(a : Int[]) : Int { Std.Math.Min(a)}")
541 assert (
542 qsharp.code.Smallest([1, 2, 3, 0, 4, 5]) == 0
543 ), "callable that takes array should work"
544
545
546def test_callable_with_int_exposed_into_env_fails_incorrect_types() -> None:
547 qsharp.init()
548 qsharp.eval("function Identity(a : Int) : Int { a }")
549 assert qsharp.code.Identity(4) == 4
550 with pytest.raises(TypeError):
551 qsharp.code.Identity("4")
552 with pytest.raises(TypeError):
553 qsharp.code.Identity(4.0)
554 with pytest.raises(OverflowError):
555 qsharp.code.Identity(4000000000000000000000)
556 with pytest.raises(TypeError):
557 qsharp.code.Identity([4])
558
559
560def test_callable_with_double_exposed_into_env_fails_incorrect_types() -> None:
561 qsharp.init()
562 qsharp.eval("function Identity(a : Double) : Double { a }")
563 assert qsharp.code.Identity(4.0) == 4.0
564 assert qsharp.code.Identity(4) == 4.0
565 with pytest.raises(TypeError):
566 qsharp.code.Identity("4")
567 with pytest.raises(TypeError):
568 qsharp.code.Identity([4])
569
570
571def test_callable_with_bigint_exposed_into_env_fails_incorrect_types() -> None:
572 qsharp.init()
573 qsharp.eval("function Identity(a : BigInt) : BigInt { a }")
574 assert qsharp.code.Identity(4000000000000000000000) == 4000000000000000000000
575 with pytest.raises(TypeError):
576 qsharp.code.Identity("4")
577 with pytest.raises(TypeError):
578 qsharp.code.Identity(4.0)
579
580
581def test_callable_with_string_exposed_into_env_fails_incorrect_types() -> None:
582 qsharp.init()
583 qsharp.eval("function Identity(a : String) : String { a }")
584 assert qsharp.code.Identity("4") == "4"
585 with pytest.raises(TypeError):
586 qsharp.code.Identity(4)
587 with pytest.raises(TypeError):
588 qsharp.code.Identity(4.0)
589 with pytest.raises(TypeError):
590 qsharp.code.Identity([4])
591
592
593def test_callable_with_bool_exposed_into_env_fails_incorrect_types() -> None:
594 qsharp.init()
595 qsharp.eval("function Identity(a : Bool) : Bool { a }")
596 assert qsharp.code.Identity(True) == True
597 with pytest.raises(TypeError):
598 qsharp.code.Identity("4")
599 with pytest.raises(TypeError):
600 qsharp.code.Identity(4)
601 with pytest.raises(TypeError):
602 qsharp.code.Identity(4.0)
603 with pytest.raises(TypeError):
604 qsharp.code.Identity([4])
605
606
607def test_callable_with_array_exposed_into_env_fails_incorrect_types() -> None:
608 qsharp.init()
609 qsharp.eval("function Identity(a : Int[]) : Int[] { a }")
610 assert qsharp.code.Identity([4, 5, 6]) == [4, 5, 6]
611 assert qsharp.code.Identity([]) == []
612 assert qsharp.code.Identity((4, 5, 6)) == [4, 5, 6]
613 with pytest.raises(TypeError):
614 qsharp.code.Identity(4)
615 with pytest.raises(TypeError):
616 qsharp.code.Identity("4")
617 with pytest.raises(TypeError):
618 qsharp.code.Identity(4.0)
619 with pytest.raises(TypeError):
620 qsharp.code.Identity([1, 2, 3.0])
621
622
623def test_callable_with_tuple_exposed_into_env_fails_incorrect_types() -> None:
624 qsharp.init()
625 qsharp.eval("function Identity(a : (Int, Double)) : (Int, Double) { a }")
626 assert qsharp.code.Identity((4, 5.0)) == (4, 5.0)
627 assert qsharp.code.Identity((4, 5)) == (4, 5.0)
628 assert qsharp.code.Identity([4, 5.0]) == (4, 5.0)
629 with pytest.raises(qsharp.QSharpError):
630 qsharp.code.Identity((4, 5, 6))
631 with pytest.raises(TypeError):
632 qsharp.code.Identity(4)
633 with pytest.raises(TypeError):
634 qsharp.code.Identity("4")
635 with pytest.raises(TypeError):
636 qsharp.code.Identity(4.0)
637 with pytest.raises(TypeError):
638 qsharp.code.Identity([4.0, 5])
639
640
641def test_callables_in_namespaces_exposed_into_env_submodules_and_removed_on_reinit() -> (
642 None
643):
644 qsharp.init()
645 # callables should be created with their namespaces
646 qsharp.eval("namespace Test { function Four() : Int { 4 } }")
647 qsharp.eval("function Identity(a : Int) : Int { a }")
648 # should be able to import callables from env and namespace submodule
649 from qsharp.code import Identity
650 from qsharp.code.Test import Four
651
652 assert Identity(4) == 4
653 assert Four() == 4
654 qsharp.init()
655 # namespaces should be removed
656 with pytest.raises(AttributeError):
657 qsharp.code.Test
658 with pytest.raises(AttributeError):
659 qsharp.code.Identity()
660 # imported callables should fail gracefully
661 with pytest.raises(qsharp.QSharpError):
662 Four()
663
664
665def test_callables_with_unsupported_types_raise_errors_on_call() -> None:
666 qsharp.init()
667 qsharp.eval("function Unsupported(a : Int, q : Qubit) : Unit { }")
668 with pytest.raises(qsharp.QSharpError, match="unsupported input type: `Qubit`"):
669 qsharp.code.Unsupported()
670
671
672def test_callables_with_unsupported_types_in_tuples_raise_errors_on_call() -> None:
673 qsharp.init()
674 qsharp.eval("function Unsupported(q : (Int, Qubit)[]) : Unit { }")
675 with pytest.raises(qsharp.QSharpError, match="unsupported input type: `Qubit`"):
676 qsharp.code.Unsupported()
677
678
679def test_callables_with_unsupported_return_types_raise_errors_on_call() -> None:
680 qsharp.init()
681 qsharp.eval('function Unsupported() : Qubit { fail "won\'t be called" }')
682 with pytest.raises(qsharp.QSharpError, match="unsupported output type: `Qubit`"):
683 qsharp.code.Unsupported()
684
685
686def test_callables_with_unsupported_udt_types_raise_errors_on_call() -> None:
687 qsharp.init()
688 qsharp.eval("function Unsupported(a : Std.Math.Complex) : Unit { }")
689 with pytest.raises(
690 qsharp.QSharpError, match='unsupported input type: `UDT<"Complex":'
691 ):
692 qsharp.code.Unsupported()
693
694
695def test_callable_with_unsupported_udt_return_types_raise_errors_on_call() -> None:
696 qsharp.init()
697 qsharp.eval('function Unsupported() : Std.Math.Complex { fail "won\'t be called" }')
698 with pytest.raises(
699 qsharp.QSharpError, match='unsupported output type: `UDT<"Complex":'
700 ):
701 qsharp.code.Unsupported()
702
703
704def test_struct_call_constructor_not_exposed_into_env() -> None:
705 qsharp.init()
706 qsharp.eval("struct CustomUDT { a : Int }")
707 with pytest.raises(AttributeError):
708 qsharp.code.CustomUDT
709
710
711def test_lambdas_not_exposed_into_env() -> None:
712 qsharp.init()
713 qsharp.eval("a -> a + 1")
714 assert not hasattr(qsharp.code, "<lambda>")
715 qsharp.eval("q => I(q)")
716 assert not hasattr(qsharp.code, "<lambda>")
717
718
719def test_circuit_from_callable() -> None:
720 qsharp.init()
721 qsharp.eval(
722 """
723 operation Foo() : Unit {
724 use q1 = Qubit();
725 use q2 = Qubit();
726 X(q1);
727 }
728 """
729 )
730 circuit = qsharp.circuit(qsharp.code.Foo)
731 assert str(circuit) == dedent(
732 """\
733 q_0 โ”€โ”€ X โ”€โ”€
734 q_1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€
735 """
736 )
737
738
739def test_circuit_from_callable_with_args() -> None:
740 qsharp.init()
741 qsharp.eval(
742 """
743 operation Foo(nQubits : Int) : Unit {
744 use qs = Qubit[nQubits];
745 ApplyToEach(X, qs);
746 }
747 """
748 )
749 circuit = qsharp.circuit(qsharp.code.Foo, 2)
750 assert str(circuit) == dedent(
751 """\
752 q_0 โ”€โ”€ X โ”€โ”€
753 q_1 โ”€โ”€ X โ”€โ”€
754 """
755 )
756
757
758def test_circuit_with_measure_from_callable() -> None:
759 qsharp.init()
760 qsharp.eval("operation Foo() : Result { use q = Qubit(); H(q); return M(q) }")
761 circuit = qsharp.circuit(qsharp.code.Foo)
762 assert str(circuit) == dedent(
763 """\
764 q_0 โ”€โ”€ H โ”€โ”€โ”€โ”€ M โ”€โ”€
765 โ•˜โ•โ•โ•
766 """
767 )
768
769
770def test_swap_label_circuit_from_callable() -> None:
771 qsharp.init()
772 qsharp.eval(
773 "operation Foo() : Unit { use q1 = Qubit(); use q2 = Qubit(); X(q1); Relabel([q1, q2], [q2, q1]); X(q2); }"
774 )
775 circuit = qsharp.circuit(qsharp.code.Foo)
776 assert str(circuit) == dedent(
777 """\
778 q_0 โ”€โ”€ X โ”€โ”€โ”€โ”€ X โ”€โ”€
779 q_1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
780 """
781 )
782