microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
source/pip/tests-integration/test_base_qir.py
128lines · modecode
| 1 | # Copyright (c) Microsoft Corporation. |
| 2 | # Licensed under the MIT License. |
| 3 | |
| 4 | import pytest |
| 5 | |
| 6 | import qsharp |
| 7 | |
| 8 | try: |
| 9 | from pyqir import ( |
| 10 | Call, |
| 11 | Context, |
| 12 | Module, |
| 13 | Opcode, |
| 14 | qubit_id, |
| 15 | result_id, |
| 16 | required_num_qubits, |
| 17 | required_num_results, |
| 18 | ) |
| 19 | |
| 20 | PYQIR_AVAILABLE = True |
| 21 | except ImportError: |
| 22 | PYQIR_AVAILABLE = False |
| 23 | |
| 24 | SKIP_REASON = "PyQIR is not available" |
| 25 | |
| 26 | |
| 27 | @pytest.mark.skipif(not PYQIR_AVAILABLE, reason=SKIP_REASON) |
| 28 | def test_compile_qir_input_data() -> None: |
| 29 | qsharp.init(target_profile=qsharp.TargetProfile.Base) |
| 30 | qsharp.eval("operation Program() : Result { use q = Qubit(); return M(q) }") |
| 31 | operation = qsharp.compile("Program()") |
| 32 | qir = operation._repr_qir_() |
| 33 | assert isinstance(qir, bytes) |
| 34 | module = Module.from_ir(Context(), qir.decode(), "module") |
| 35 | assert len(module.functions) == 4 |
| 36 | assert module.functions[0].name == "ENTRYPOINT__main" |
| 37 | func = module.functions[0] |
| 38 | assert len(func.basic_blocks) == 1 |
| 39 | assert len(func.basic_blocks[0].instructions) == 4 |
| 40 | call_m = func.basic_blocks[0].instructions[1] |
| 41 | assert isinstance(call_m, Call) |
| 42 | assert call_m.callee.name == "__quantum__qis__m__body" |
| 43 | assert len(call_m.args) == 2 |
| 44 | assert qubit_id(call_m.args[0]) == 0 |
| 45 | assert result_id(call_m.args[1]) == 0 |
| 46 | record_res = func.basic_blocks[0].instructions[2] |
| 47 | assert isinstance(record_res, Call) |
| 48 | assert len(record_res.args) == 2 |
| 49 | assert record_res.callee.name == "__quantum__rt__result_record_output" |
| 50 | assert result_id(record_res.args[0]) == 0 |
| 51 | assert func.basic_blocks[0].instructions[3].opcode == Opcode.RET |
| 52 | |
| 53 | |
| 54 | @pytest.mark.skipif(not PYQIR_AVAILABLE, reason=SKIP_REASON) |
| 55 | def test_compile_qir_all_gates() -> None: |
| 56 | qsharp.init(target_profile=qsharp.TargetProfile.Base) |
| 57 | operation = qsharp.compile( |
| 58 | "{\ |
| 59 | use (q1, q2, q3) = (Qubit(), Qubit(), Qubit());\ |
| 60 | CCNOT(q1, q2, q3);\ |
| 61 | CX(q1, q2);\ |
| 62 | CY(q1, q2);\ |
| 63 | CZ(q1, q2);\ |
| 64 | Rx(0.0, q1);\ |
| 65 | Rxx(0.0, q1, q2);\ |
| 66 | Ry(0.0, q1);\ |
| 67 | Ryy(0.0, q1, q2);\ |
| 68 | Rz(0.0, q1);\ |
| 69 | Rzz(0.0, q1, q2);\ |
| 70 | H(q1);\ |
| 71 | S(q1);\ |
| 72 | Adjoint S(q1);\ |
| 73 | SX(q1); \ |
| 74 | T(q1);\ |
| 75 | Adjoint T(q1);\ |
| 76 | X(q1);\ |
| 77 | Y(q1);\ |
| 78 | Z(q1);\ |
| 79 | SWAP(q1, q2);\ |
| 80 | Reset(q1);\ |
| 81 | (M(q1),\ |
| 82 | Microsoft.Quantum.Measurement.MResetZ(q1))\ |
| 83 | }" |
| 84 | ) |
| 85 | qir = operation._repr_qir_() |
| 86 | assert isinstance(qir, bytes) |
| 87 | module = Module.from_ir(Context(), qir.decode(), "module") |
| 88 | assert len(module.functions) == 25 |
| 89 | assert module.functions[0].name == "ENTRYPOINT__main" |
| 90 | func = module.functions[0] |
| 91 | assert len(func.basic_blocks) == 1 |
| 92 | assert len(func.basic_blocks[0].instructions) == 28 |
| 93 | |
| 94 | def check_call(i: int, name: str, num_args: int) -> None: |
| 95 | call = func.basic_blocks[0].instructions[i + 1] |
| 96 | assert isinstance(call, Call) |
| 97 | assert call.callee.name == name |
| 98 | assert len(call.args) == num_args |
| 99 | |
| 100 | check_call(0, "__quantum__qis__ccx__body", 3) |
| 101 | check_call(1, "__quantum__qis__cx__body", 2) |
| 102 | check_call(2, "__quantum__qis__cy__body", 2) |
| 103 | check_call(3, "__quantum__qis__cz__body", 2) |
| 104 | check_call(4, "__quantum__qis__rx__body", 2) |
| 105 | check_call(5, "__quantum__qis__rxx__body", 3) |
| 106 | check_call(6, "__quantum__qis__ry__body", 2) |
| 107 | check_call(7, "__quantum__qis__ryy__body", 3) |
| 108 | check_call(8, "__quantum__qis__rz__body", 2) |
| 109 | check_call(9, "__quantum__qis__rzz__body", 3) |
| 110 | check_call(10, "__quantum__qis__h__body", 1) |
| 111 | check_call(11, "__quantum__qis__s__body", 1) |
| 112 | check_call(12, "__quantum__qis__s__adj", 1) |
| 113 | check_call(13, "__quantum__qis__sx__body", 1) |
| 114 | check_call(14, "__quantum__qis__t__body", 1) |
| 115 | check_call(15, "__quantum__qis__t__adj", 1) |
| 116 | check_call(16, "__quantum__qis__x__body", 1) |
| 117 | check_call(17, "__quantum__qis__y__body", 1) |
| 118 | check_call(18, "__quantum__qis__z__body", 1) |
| 119 | check_call(19, "__quantum__qis__swap__body", 2) |
| 120 | check_call(20, "__quantum__qis__cx__body", 2) |
| 121 | check_call(21, "__quantum__qis__m__body", 2) |
| 122 | check_call(22, "__quantum__qis__m__body", 2) |
| 123 | check_call(23, "__quantum__rt__tuple_record_output", 2) |
| 124 | check_call(24, "__quantum__rt__result_record_output", 2) |
| 125 | check_call(25, "__quantum__rt__result_record_output", 2) |
| 126 | |
| 127 | assert required_num_qubits(module.functions[0]) == 5 |
| 128 | assert required_num_results(module.functions[0]) == 2 |
| 129 | |