microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/pip/tests/test_correlated_noise.py
101lines · modecode
| 1 | # Copyright (c) Microsoft Corporation. |
| 2 | # Licensed under the MIT License. |
| 3 | |
| 4 | import pytest |
| 5 | import sys |
| 6 | from qsharp._simulation import NoiseConfig, run_qir |
| 7 | from qsharp import Result |
| 8 | import qsharp.openqasm |
| 9 | |
| 10 | SKIP_REASON = "GPU is not available" |
| 11 | |
| 12 | gpu_info = "Unknown" |
| 13 | |
| 14 | try: |
| 15 | from qsharp._native import try_create_gpu_adapter |
| 16 | |
| 17 | gpu_info = try_create_gpu_adapter() |
| 18 | # Printing to stderr so that it is visible if CI run fails |
| 19 | print(f"*** USING GPU: {gpu_info}", file=sys.stderr) |
| 20 | GPU_AVAILABLE = True |
| 21 | except OSError as e: |
| 22 | GPU_AVAILABLE = False |
| 23 | SKIP_REASON = str(e) |
| 24 | |
| 25 | |
| 26 | CPU_SIMULATORS = ("clifford", "cpu") |
| 27 | QASM_WITH_CORRELATED_NOISE = """ |
| 28 | OPENQASM 3.0; |
| 29 | include "stdgates.inc"; |
| 30 | |
| 31 | @qdk.qir.noise_intrinsic |
| 32 | gate test_noise_intrinsic q0, q1, q2 {} |
| 33 | |
| 34 | qubit[3] qs; |
| 35 | x qs[1]; |
| 36 | test_noise_intrinsic qs[0], qs[1], qs[2]; |
| 37 | bit[3] res = measure qs; |
| 38 | """ |
| 39 | |
| 40 | QIR_WITH_CORRELATED_NOISE = qsharp.openqasm.compile( |
| 41 | QASM_WITH_CORRELATED_NOISE, |
| 42 | output_semantics=qsharp.openqasm.OutputSemantics.OpenQasm, |
| 43 | target_profile=qsharp.TargetProfile.Base, |
| 44 | ) |
| 45 | |
| 46 | |
| 47 | def test_noiseless_simulation(): |
| 48 | for type in CPU_SIMULATORS: |
| 49 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=None, type=type) |
| 50 | assert output == [[Result.Zero, Result.One, Result.Zero]] |
| 51 | |
| 52 | |
| 53 | @pytest.mark.skipif(not GPU_AVAILABLE, reason=SKIP_REASON) |
| 54 | def test_noiseless_simulation_gpu(): |
| 55 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=None, type="gpu") |
| 56 | assert output == [[Result.Zero, Result.One, Result.Zero]] |
| 57 | |
| 58 | |
| 59 | def test_noisy_simulation(): |
| 60 | noise = NoiseConfig() |
| 61 | table = noise.intrinsic("test_noise_intrinsic", 3) |
| 62 | table.yyy = 1.0 |
| 63 | for type in CPU_SIMULATORS: |
| 64 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=noise, type=type) |
| 65 | assert output == [[Result.One, Result.Zero, Result.One]] |
| 66 | |
| 67 | |
| 68 | @pytest.mark.skipif(not GPU_AVAILABLE, reason=SKIP_REASON) |
| 69 | def test_noisy_simulation_gpu(): |
| 70 | noise = NoiseConfig() |
| 71 | table = noise.intrinsic("test_noise_intrinsic", 3) |
| 72 | table.yyy = 1.0 |
| 73 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=noise, type="gpu") |
| 74 | assert output == [[Result.One, Result.Zero, Result.One]] |
| 75 | |
| 76 | |
| 77 | def test_load_csv_dir(): |
| 78 | noise = NoiseConfig() |
| 79 | noise.load_csv_dir("./csv_dir_test") |
| 80 | for type in CPU_SIMULATORS: |
| 81 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=noise, type=type) |
| 82 | assert output == [[Result.One, Result.Zero, Result.One]] |
| 83 | |
| 84 | |
| 85 | @pytest.mark.skipif(not GPU_AVAILABLE, reason=SKIP_REASON) |
| 86 | def test_load_csv_dir_gpu(): |
| 87 | noise = NoiseConfig() |
| 88 | noise.load_csv_dir("./csv_dir_test") |
| 89 | output = run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=noise, type="gpu") |
| 90 | assert output == [[Result.One, Result.Zero, Result.One]] |
| 91 | |
| 92 | |
| 93 | def test_noisy_simulation_with_missing_gates_fails(): |
| 94 | """ |
| 95 | This failure happens before the list of QIR instructions makes it to |
| 96 | any specific simulator. So, we don't need separate tests for all of them. |
| 97 | """ |
| 98 | noise = NoiseConfig() |
| 99 | with pytest.raises(ValueError) as excinfo: |
| 100 | run_qir(QIR_WITH_CORRELATED_NOISE, shots=1, noise=noise, type="cpu") |
| 101 | assert "Missing noise intrinsic: test_noise_intrinsic" in str(excinfo.value) |
| 102 | |