microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/pipeline-issue-debugging

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/pip/tests/test_clifford_simulator.py

247lines · modecode

1# Copyright (c) Microsoft Corporation.
2# Licensed under the MIT License.
3
4from pathlib import Path
5import pyqir
6
7import qsharp
8from qsharp._simulation import run_qir_clifford, NoiseConfig
9from qsharp._device._atom import NeutralAtomDevice
10from qsharp._device._atom._decomp import DecomposeRzAnglesToCliffordGates
11from qsharp._device._atom._validate import ValidateNoConditionalBranches
12from qsharp import TargetProfile, Result
13
14current_file_path = Path(__file__)
15# Get the directory of the current file
16current_dir = current_file_path.parent
17
18# Tests for the Q# noisy simulator.
19
20
21def transform_to_clifford(input) -> str:
22 native_qir = NeutralAtomDevice().compile(input)
23 module = pyqir.Module.from_ir(pyqir.Context(), str(native_qir))
24 ValidateNoConditionalBranches().run(module)
25 DecomposeRzAnglesToCliffordGates().run(module)
26 return str(module)
27
28
29def read_file(file_name: str) -> str:
30 return Path(file_name).read_text(encoding="utf-8")
31
32
33def read_file_relative(file_name: str) -> str:
34 return Path(current_dir / file_name).read_text(encoding="utf-8")
35
36
37def test_smoke():
38 qsharp.init(target_profile=TargetProfile.Base)
39 qsharp.eval(read_file_relative("CliffordIsing.qs"))
40
41 input = qsharp.compile(
42 "IsingModel2DEvolution(5, 5, PI() / 2.0, PI() / 2.0, 5.0, 5)"
43 )
44 input = transform_to_clifford(input)
45 output = run_qir_clifford(input, 10, NoiseConfig())
46 print(output)
47
48
49def test_1224_clifford_ising():
50 qsharp.init(target_profile=TargetProfile.Base)
51 qsharp.eval(read_file_relative("CliffordIsing.qs"))
52
53 input = qsharp.compile(
54 "IsingModel2DEvolution(20, 50, PI() / 2.0, PI() / 2.0, 5.0, 5)"
55 )
56 qir = transform_to_clifford(input)
57
58 output = run_qir_clifford(qir, 1, NoiseConfig())
59
60 print(output)
61
62
63def test_million():
64 qsharp.init(target_profile=TargetProfile.Base)
65 qsharp.eval(read_file_relative("CliffordCalls.qs"))
66
67 ir = qsharp.compile("Main()")
68 output = run_qir_clifford(str(ir), 1, NoiseConfig())
69 print(output)
70
71
72def test_s_noise_inherits_from_rz():
73 qsharp.init(target_profile=TargetProfile.Base)
74 qsharp.eval("operation Main() : Result { use q = Qubit(); S(q); MResetZ(q) }")
75 ir = qsharp.compile("Main()")
76 noise = NoiseConfig()
77 noise.rz.x = 1.0
78 output = run_qir_clifford(str(ir), 1, noise)
79 assert output == [Result.One]
80
81
82def test_z_noise_inherits_from_rz():
83 qsharp.init(target_profile=TargetProfile.Base)
84 qsharp.eval("operation Main() : Result { use q = Qubit(); Z(q); MResetZ(q) }")
85 ir = qsharp.compile("Main()")
86 noise = NoiseConfig()
87 noise.rz.x = 1.0
88 output = run_qir_clifford(str(ir), 1, noise)
89 assert output == [Result.One]
90
91
92def test_s_adj_noise_inherits_from_rz():
93 qsharp.init(target_profile=TargetProfile.Base)
94 qsharp.eval(
95 "operation Main() : Result { use q = Qubit(); Adjoint S(q); MResetZ(q) }"
96 )
97 ir = qsharp.compile("Main()")
98 noise = NoiseConfig()
99 noise.rz.x = 1.0
100 output = run_qir_clifford(str(ir), 1, noise)
101 assert output == [Result.One]
102
103
104def test_program_with_branching_fails():
105 qsharp.init(target_profile=TargetProfile.Adaptive_RI)
106 qsharp.eval(
107 """
108 operation Main() : Result {
109 use q = Qubit();
110 H(q);
111 if (MResetZ(q) == One) {
112 X(q);
113 }
114 return MResetZ(q);
115 }
116 """
117 )
118 ir = qsharp.compile("Main()")
119 try:
120 run_qir_clifford(str(ir), 1, NoiseConfig())
121 assert False, "Expected ValueError for branching control flow"
122 except ValueError as e:
123 assert (
124 "simulation of programs with branching control flow is not supported"
125 in str(e)
126 )
127
128
129def test_program_with_unconditional_branching_succeeds():
130 qir = """
131%Result = type opaque
132%Qubit = type opaque
133
134@empty_tag = internal constant [1 x i8] c"\\00"
135@0 = internal constant [6 x i8] c"0_a0r\\00"
136@1 = internal constant [6 x i8] c"1_a1r\\00"
137
138define i64 @ENTRYPOINT__main() #0 {
139block_0:
140 call void @__quantum__rt__initialize(i8* null)
141 br label %block_1
142block_1:
143 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
144 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
145 br label %block_2
146block_2:
147 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
148 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
149 br label %block_3
150block_3:
151 call void @__quantum__rt__array_record_output(i64 2, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @empty_tag, i64 0, i64 0))
152 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @0, i64 0, i64 0))
153 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @1, i64 0, i64 0))
154 ret i64 0
155}
156
157declare void @__quantum__rt__initialize(i8*)
158
159declare void @__quantum__qis__h__body(%Qubit*)
160
161declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
162
163declare void @__quantum__rt__array_record_output(i64, i8*)
164
165declare void @__quantum__rt__result_record_output(%Result*, i8*)
166
167declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
168
169attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
170attributes #1 = { "irreversible" }
171
172; module flags
173
174!llvm.module.flags = !{!0, !1, !2, !3}
175
176!0 = !{i32 1, !"qir_major_version", i32 1}
177!1 = !{i32 7, !"qir_minor_version", i32 0}
178!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
179!3 = !{i32 1, !"dynamic_result_management", i1 false}
180"""
181
182 output = run_qir_clifford(qir, 1, NoiseConfig())
183 assert output == [[Result.Zero, Result.Zero]] or output == [
184 [Result.One, Result.One]
185 ]
186
187
188def test_cy_direct_qir():
189 qir = """
190%Result = type opaque
191%Qubit = type opaque
192
193@empty_tag = internal constant [1 x i8] c"\\00"
194@0 = internal constant [6 x i8] c"0_a0r\\00"
195@1 = internal constant [6 x i8] c"1_a1r\\00"
196
197define i64 @ENTRYPOINT__main() #0 {
198block_0:
199 call void @__quantum__rt__initialize(i8* null)
200 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
201 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
202 call void @__quantum__qis__s__body(%Qubit* inttoptr (i64 1 to %Qubit*))
203 call void @__quantum__qis__cy__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
204 call void @__quantum__qis__s__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
205 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
206 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
207 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
208 call void @__quantum__rt__array_record_output(i64 2, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @empty_tag, i64 0, i64 0))
209 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @0, i64 0, i64 0))
210 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @1, i64 0, i64 0))
211 ret i64 0
212}
213
214declare void @__quantum__rt__initialize(i8*)
215
216declare void @__quantum__qis__h__body(%Qubit*)
217
218declare void @__quantum__qis__s__body(%Qubit*)
219
220declare void @__quantum__qis__s__adj(%Qubit*)
221
222declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
223
224declare void @__quantum__rt__array_record_output(i64, i8*)
225
226declare void @__quantum__rt__result_record_output(%Result*, i8*)
227
228declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
229
230attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="2" }
231attributes #1 = { "irreversible" }
232
233; module flags
234
235!llvm.module.flags = !{!0, !1, !2, !3}
236
237!0 = !{i32 1, !"qir_major_version", i32 1}
238!1 = !{i32 7, !"qir_minor_version", i32 0}
239!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
240!3 = !{i32 1, !"dynamic_result_management", i1 false}
241"""
242
243 # Do not go through Neutral Atom device compilation since we want to test CY.
244 output = run_qir_clifford(qir, 50, NoiseConfig())
245 # This test should deterministically produce Zero.
246 # If CZ or CX is executed instead of CY, then some measurements will produce One.
247 assert all(shot[1] == Result.Zero for shot in output)