microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
sccarda/PythonApiDocs

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/chemistry/src/Tests.qs

399lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import Std.Arrays.IndexRange;
5import Std.Arrays.Mapped;
6import Std.Arrays.Reversed;
7import Std.Convert.ComplexAsComplexPolar;
8import Std.Convert.IntAsDouble;
9import Std.Diagnostics.*;
10import Std.Math.*;
11import Std.StatePreparation.ApproximatelyPreparePureStateCP;
12
13import JordanWigner.ClusterOperatorEvolutionSet.JWClusterOperatorPQRSTermSigns;
14import JordanWigner.ClusterOperatorEvolutionSet.ComputeJWBitString;
15import JordanWigner.ClusterOperatorEvolutionSet.ComputeJWPauliZString;
16import JordanWigner.OptimizedBEOperator.OptimizedBEXY;
17import JordanWigner.OptimizedBEOperator.SelectZ;
18import JordanWigner.StatePreparation.PrepareSparseMultiConfigurationalState;
19import JordanWigner.StatePreparation.PrepareUnitaryCoupledClusterState;
20import JordanWigner.Data.JWInputState;
21
22@Config(Unrestricted)
23@Test()
24operation PrepareSparseMultiConfigurationalState0Test() : Unit {
25 let nQubits = 6;
26 let expectedResult = 39;
27 let excitations = [
28 NewJordanWignerInputState(0.1, 0.0, [0, 1, 2, 5])
29 ];
30
31 use qubits = Qubit[nQubits];
32 PrepareSparseMultiConfigurationalState(qs => I(qs[0]), excitations, qubits);
33
34 Fact(MeasureInteger(qubits) == expectedResult, "PrepareSparseMultiConfigurationalState0Test failed.");
35}
36
37@Config(Unrestricted)
38operation OptimizedBEOperatorZeroTestHelper(pauliBasis : Pauli, targetRegisterSize : Int, targetIndex : Int) : Unit {
39 let indexRegisterSize = Ceiling(Lg(IntAsDouble(targetRegisterSize)));
40 use pauliBasisQubit = Qubit();
41 use indexRegister = Qubit[indexRegisterSize];
42 use targetRegister = Qubit[targetRegisterSize];
43
44 // Choose X or Y operator.
45 if pauliBasis == PauliX {
46 // no op
47 } elif pauliBasis == PauliY {
48 X(pauliBasisQubit);
49 }
50
51 // Create indexRegister state.
52 ApplyXorInPlace(targetIndex, indexRegister);
53
54 // Initialize targetRegister states in |0>
55 OptimizedBEXY(pauliBasisQubit, indexRegister, targetRegister);
56
57 for idxTest in 0..targetRegisterSize - 1 {
58 let testQubit = targetRegister[idxTest];
59
60 if targetIndex > idxTest {
61
62 // Test Z Pauli
63 // |0> -> |0>
64 // |+> -> |->
65 Message($"Test Z Pauli on qubit {idxTest}");
66 Fact(CheckZero(testQubit), $"Error: Test {idxTest} {idxTest} Z Pauli |0>");
67 } elif targetIndex == idxTest {
68
69 // Test X Pauli
70 // |0> -> |1>
71 // |+> -> |+>
72
73 // Test Y Pauli
74 // |0> -> i|1>
75 // |+> -> -i|->
76 Message($"Test X or Y Pauli on qubit {idxTest}");
77 within {
78 X(testQubit);
79 } apply {
80 Fact(CheckZero(testQubit), $"Error: Test {idxTest} X or Y Pauli |0>");
81 }
82 } else {
83
84 // Test Identify Pauli
85 // |0> -> |0>
86 // |+> -> |+>
87 Message($"Test ZI Pauli on qubit {idxTest}");
88 Fact(CheckZero(testQubit), $"Error: Test {idxTest} I Pauli |0>");
89 }
90 }
91
92 OptimizedBEXY(pauliBasisQubit, indexRegister, targetRegister);
93 Adjoint ApplyXorInPlace(targetIndex, indexRegister);
94
95 // Choose X or Y operator.
96 if pauliBasis == PauliX {
97 // no op
98 } elif pauliBasis == PauliY {
99 X(pauliBasisQubit);
100 }
101}
102
103@Config(Unrestricted)
104@Test()
105operation OptimizedBEOperatorZeroTest() : Unit {
106 let paulis = [PauliX, PauliY];
107 let targetRegisterSize = 7;
108
109 for idxPauli in 0..1 {
110 let pauliBasis = paulis[idxPauli];
111
112 for targetIndex in 0..targetRegisterSize - 1 {
113 Message($"pauliBasis {pauliBasis}; targetIndex {targetIndex}");
114 OptimizedBEOperatorZeroTestHelper(pauliBasis, targetRegisterSize, targetIndex);
115 }
116 }
117}
118
119@Config(Unrestricted)
120operation OptimizedBEOperatorPlusTestHelper(pauliBasis : Pauli, targetRegisterSize : Int, targetIndex : Int) : Unit {
121 let indexRegisterSize = Ceiling(Lg(IntAsDouble(targetRegisterSize)));
122 use pauliBasisQubit = Qubit();
123 use indexRegister = Qubit[indexRegisterSize];
124 use targetRegister = Qubit[targetRegisterSize];
125 // Choose X or Y operator.
126 if (pauliBasis == PauliX) {
127 // no op
128 } elif pauliBasis == PauliY {
129 X(pauliBasisQubit);
130 }
131
132 // Create indexRegister state.
133 ApplyXorInPlace(targetIndex, indexRegister);
134
135 // Initialize targetRegister states in |+>
136 ApplyToEachCA(H, targetRegister);
137 OptimizedBEXY(pauliBasisQubit, indexRegister, targetRegister);
138 for idxTest in 0..targetRegisterSize - 1 {
139 let testQubit = targetRegister[idxTest];
140 if (targetIndex > idxTest) {
141 // Test Z Pauli
142 // |0> -> |0>
143 // |+> -> |->
144 Message($"Test Z Pauli on qubit {idxTest}");
145 within {
146 H(testQubit);
147 X(testQubit);
148 } apply {
149 Fact(CheckZero(testQubit), $"Error: Test {idxTest} Z Pauli |->");
150 }
151 } elif (targetIndex == idxTest) {
152 // Test X Pauli
153 // |0> -> |1>
154 // |+> -> |+>
155 if (pauliBasis == PauliX) {
156 Message($"Test X Pauli on qubit {idxTest}");
157 within {
158 H(testQubit);
159 } apply {
160 Fact(CheckZero(testQubit), $"Error: Test {idxTest} X Pauli |+>");
161 }
162 }
163
164 // Test Y Pauli
165 // |0> -> i|1>
166 // |+> -> -i|->
167 if (pauliBasis == PauliY) {
168 Message($"Test Y Pauli on qubit {idxTest}");
169 within {
170 H(testQubit);
171 X(testQubit);
172 } apply {
173 Fact(CheckZero(testQubit), $"Error: Test {idxTest} Y Pauli |+>");
174 }
175 }
176
177 } else {
178 // Test Identify Pauli
179 // |0> -> |0>
180 // |+> -> |+>
181 Message($"Test I Pauli on qubit {idxTest}");
182 within {
183 H(testQubit);
184 } apply {
185 Fact(CheckZero(testQubit), $"Error: Test {idxTest} I Pauli |+>");
186 }
187 }
188 }
189 OptimizedBEXY(pauliBasisQubit, indexRegister, targetRegister);
190 ApplyToEachCA(H, targetRegister);
191
192 (Adjoint ApplyXorInPlace)(targetIndex, indexRegister);
193
194 // Choose X or Y operator.
195 if pauliBasis == PauliX {
196 // no op
197 } elif pauliBasis == PauliY {
198 X(pauliBasisQubit);
199 }
200}
201
202@Config(Unrestricted)
203@Test()
204operation OptimizedBEOperatorPlusTest() : Unit {
205
206 let paulis = [PauliX, PauliY];
207 let targetRegisterSize = 7;
208
209 for idxPauli in 0..1 {
210 let pauliBasis = paulis[idxPauli];
211
212 for targetIndex in 0..targetRegisterSize - 1 {
213 Message($"pauliBasis {pauliBasis}; targetIndex {targetIndex}");
214 OptimizedBEOperatorPlusTestHelper(pauliBasis, targetRegisterSize, targetIndex);
215 }
216 }
217}
218
219@Config(Unrestricted)
220@Test()
221operation SelectZTest() : Unit {
222 let targetRegisterSize = 7;
223 let indexRegisterSize = Ceiling(Lg(IntAsDouble(targetRegisterSize)));
224
225 use targetRegister = Qubit[targetRegisterSize];
226 use indexRegister = Qubit[indexRegisterSize];
227 for idxTest in 0..targetRegisterSize - 1 {
228 H(targetRegister[idxTest]);
229 ApplyXorInPlace(idxTest, indexRegister);
230 SelectZ(indexRegister, targetRegister);
231 within {
232 H(targetRegister[idxTest]);
233 X(targetRegister[idxTest]);
234 } apply {
235 Fact(CheckZero(targetRegister[idxTest]), $"Error: Test {idxTest} X Pauli |+>");
236 }
237 Z(targetRegister[idxTest]);
238 Adjoint ApplyXorInPlace(idxTest, indexRegister);
239 H(targetRegister[idxTest]);
240 }
241}
242
243@Config(Unrestricted)
244function JordanWignerClusterOperatorPQRSTermSignsTestHelper(idx : Int) : (Int[], Double[], Double) {
245 let cases = [
246 ([1, 2, 3, 4], [1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0], 1.0),
247 ([2, 1, 4, 3], [1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0], 1.0),
248 ([3, 4, 1, 2], [1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0],-1.0),
249 ([2, 1, 3, 4], [1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0],-1.0),
250 ([1, 3, 2, 4], [-1.0,-1.0,-1.0, 1.0,-1.0, 1.0, 1.0, 1.0], 1.0),
251 ([4, 2, 3, 1], [-1.0,-1.0,-1.0, 1.0,-1.0, 1.0, 1.0, 1.0],-1.0),
252 ([1, 4, 2, 3], [1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0,-1.0], 1.0),
253 ([2, 3, 4, 1], [1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0,-1.0], 1.0)
254 ];
255 return cases[idx];
256}
257
258@Config(Unrestricted)
259@Test()
260function JordanWignerClusterOperatorPQRSTermSignsTest() : Unit {
261 for idx in 0..7 {
262 let (testCase, expectedSigns, expectedGlobalSign) = JordanWignerClusterOperatorPQRSTermSignsTestHelper(idx);
263 let (sortedIndices, signs, globalSign) = JWClusterOperatorPQRSTermSigns(testCase);
264
265 let p = sortedIndices[0];
266 let q = sortedIndices[1];
267 let r = sortedIndices[2];
268 let s = sortedIndices[3];
269
270 Fact(p < q and q < r and r < s, "Expected p < q < r < s.");
271 NearEqualityFactD(globalSign, expectedGlobalSign);
272 for i in IndexRange(signs) {
273 NearEqualityFactD(signs[i], expectedSigns[i]);
274 }
275 }
276}
277
278@Config(Unrestricted)
279function DoublesToComplexPolar(input : Double[]) : ComplexPolar[] {
280 Std.Arrays.Mapped(re -> ComplexAsComplexPolar(new Complex { Real = re, Imag = 0.0 }), input)
281}
282
283@Config(Unrestricted)
284operation JordanWignerUCCTermTestHelper(nQubits : Int, excitations : Int[], term : JWInputState[], result : Double[]) : Unit {
285 use qubits = Qubit[nQubits];
286 for idx in excitations {
287 X(qubits[idx]);
288 }
289 PrepareUnitaryCoupledClusterState(qs => I(qs[0]), term, 1.0, qubits);
290 DumpRegister(qubits);
291 Adjoint ApproximatelyPreparePureStateCP(0.0, DoublesToComplexPolar(result), Reversed(qubits));
292 Fact(CheckAllZero(qubits), "Expected qubits to all be in ground state.");
293 ResetAll(qubits);
294}
295
296@Config(Unrestricted)
297@Test()
298operation JordanWignerUCCSTermTest() : Unit {
299 // test using Exp(2.0 (a^\dag_1 a_3 - h.c.))
300 let term0 = [NewJordanWignerInputState(2.0, 0.0, [1, 3])];
301 let state0 = [0., 0.,-0.416147, 0., 0., 0., 0., 0.,-0.909297, 0., 0., 0., 0., 0., 0., 0.];
302 JordanWignerUCCTermTestHelper(4, [1], term0, state0);
303
304 // test using Exp(2.0 (a^\dag_3 a_1 - h.c.))
305 let term1 = [NewJordanWignerInputState(2.0, 0.0, [3, 1])];
306 let state1 = [0., 0.,-0.416147, 0., 0., 0., 0., 0., 0.909297, 0., 0., 0., 0., 0., 0., 0.];
307 JordanWignerUCCTermTestHelper(4, [1], term1, state1);
308}
309
310@Config(Unrestricted)
311@Test()
312operation JordanWignerUCCDTermPQRSTest() : Unit {
313 // test using Exp(2.0 (a^\dag_0 a^\dag_1 a_3 a_4 - h.c.))
314 let term0 = [NewJordanWignerInputState(2.0, 0.0, [0, 1, 2, 4])];
315 let state0 = [0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.909297, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.];
316 JordanWignerUCCTermTestHelper(5, [0, 1], term0, state0);
317
318 // test using Exp(2.0 (a^\dag_0 a^\dag_1 a_3 a_4 - h.c.))
319 let term1 = [NewJordanWignerInputState(2.0, 0.0, [0, 1, 2, 4])];
320 let state1 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.909297, 0., 0., 0.];
321 JordanWignerUCCTermTestHelper(5, [0, 1, 3], term1, state1);
322
323 // test using Exp(2.0 (a^\dag_1 a^\dag_0 a_2 a_4 - h.c.))
324 let term2 = [NewJordanWignerInputState(2.0, 0.0, [1, 0, 2, 4])];
325 let state2 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.909297, 0., 0., 0.];
326 JordanWignerUCCTermTestHelper(5, [0, 1, 3], term2, state2);
327
328 // test using Exp(2.0 (a^\dag_1 a^\dag_0 a_2 a_4 - h.c.))
329 let term3 = [NewJordanWignerInputState(-2.0, 0.0, [4, 2, 1, 0])];
330 let state3 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.909297, 0., 0., 0.];
331 JordanWignerUCCTermTestHelper(5, [0, 1, 3], term2, state2);
332}
333
334@Config(Unrestricted)
335// @Test()
336operation JordanWignerUCCDTermPRQSTest() : Unit {
337 let term0 = [NewJordanWignerInputState(2.0, 0.0, [2, 0, 4, 1])];
338 let state0 = [0., 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.909297, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.];
339 JordanWignerUCCTermTestHelper(5, [0, 2], term0, state0);
340
341 let term1 = [NewJordanWignerInputState(2.0, 0.0, [2, 0, 4, 1])];
342 let state1 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,-0.909297, 0., 0., 0., 0., 0.];
343 JordanWignerUCCTermTestHelper(5, [0, 2, 3], term1, state1);
344}
345
346@Config(Unrestricted)
347@Test()
348operation JordanWignerUCCDTermPRSQTest() : Unit {
349 let term3 = [NewJordanWignerInputState(2.0, 0.0, [0, 4, 2, 3])];
350 let state3 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.909297, 0., 0., 0., 0.,-0.416147, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.];
351 JordanWignerUCCTermTestHelper(5, [0, 4], term3, state3);
352}
353
354@Config(Unrestricted)
355@Test()
356function ComputeJordanWignerBitString_0Test() : Unit {
357 let nFermions = 5;
358 let fermionIndices = [0, 3];
359 let expectedBitString = [false, true, true, false, false];
360 let bitString = ComputeJWBitString(nFermions, fermionIndices);
361 Fact(bitString == expectedBitString, "Bit strings not equal");
362}
363
364@Config(Unrestricted)
365@Test()
366function ComputeJordanWignerBitString_1Test() : Unit {
367 let nFermions = 7;
368 let fermionIndices = [0, 4, 2, 6];
369 let expectedBitString = [false, true, false, false, false, true, false];
370 let bitString = ComputeJWBitString(nFermions, fermionIndices);
371 Fact(bitString == expectedBitString, "Bit strings not equal");
372}
373
374@Config(Unrestricted)
375@Test()
376function ComputeJordanWignerPauliZString_0Test() : Unit {
377 let nFermions = 7;
378 let fermionIndices = [0, 4, 2, 6];
379 let expectedBitString = [PauliI, PauliZ, PauliI, PauliI, PauliI, PauliZ, PauliI];
380 let bitString = ComputeJWPauliZString(nFermions, fermionIndices);
381 Fact(bitString == expectedBitString, "Bit strings not equal");
382}
383
384
385@Config(Unrestricted)
386function NearEqualityFactD(actual : Double, expected : Double) : Unit {
387 let tolerance = 1e-10;
388 let delta = actual - expected;
389 if (delta > tolerance or delta < -tolerance) {
390 fail $"Values were not equal within tolerance\nActual: {actual}, Expected: {expected}, Tolerance: {tolerance}";
391 }
392}
393
394function NewJordanWignerInputState(re : Double, im : Double, indices : Int[]) : JWInputState {
395 new JWInputState {
396 Amplitude = new Complex { Real = re, Imag = im },
397 FermionIndices = indices
398 }
399}
400