forked from microsoft/QuantumKatas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Tests.qs
312 lines (233 loc) · 11.3 KB
/
Tests.qs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
// This file contains testing harness for all tasks.
// You should not modify anything in this file.
// The tasks themselves can be found in Tasks.qs file.
//////////////////////////////////////////////////////////////////////
namespace Quantum.Kata.UnitaryPatterns {
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
// ------------------------------------------------------
// Test harness: given an operation on N qubits and a function which takes two indices between 0 and 2^N-1
// and returns false if the element of the matrix at that index is 0 and true if it is non-zero,
// test that the operation implements a matrix of this shape
operation AssertOperationMatrixMatchesPattern (N : Int, op : (Qubit[] => Unit), pattern : ((Int, Int, Int) -> Bool)) : Unit {
let size = 1 <<< N;
//Message($"Testing on {N} qubits");
// ε is the threshold for probability, which is absolute value squared; the absolute value is bounded by √ε.
let ε = 0.000001;
using (qs = Qubit[N]) {
for (k in 0 .. size - 1) {
// Prepare k-th basis vector
let binary = IntAsBoolArray(k, N);
//Message($"{k}/{N} = {binary}");
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
ApplyPauliFromBitString(PauliX, true, binary, qs);
// Reset the counter of measurements done outside of the solution call
ResetOracleCallsCount();
// Apply the operation
op(qs);
// Make sure the solution didn't use any measurements
Fact(GetOracleCallsCount(M) == 0, "You are not allowed to use measurements in this task");
Fact(GetOracleCallsCount(Measure) == 0, "You are not allowed to use measurements in this task");
// Test that the result matches the k-th column
// DumpMachine($"C:/Tmp/dump{N}_{k}.txt");
for (j in 0 .. size - 1) {
let nonZero = pattern(size, j, k);
let (expected, tol) = nonZero ? (0.5 + ε, 0.5) | (0.0, ε);
AssertProbInt(j, expected, LittleEndian(qs), tol);
}
ResetAll(qs);
}
}
}
// ------------------------------------------------------
function MainDiagonal_Pattern (size : Int, row : Int, col : Int) : Bool {
return row == col;
}
operation T01_MainDiagonal_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, MainDiagonal, MainDiagonal_Pattern);
}
}
// ------------------------------------------------------
function AllNonZero_Pattern (size : Int, row : Int, col : Int) : Bool {
return true;
}
operation T02_AllNonZero_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, AllNonZero, AllNonZero_Pattern);
}
}
// ------------------------------------------------------
function BlockDiagonal_Pattern (size : Int, row : Int, col : Int) : Bool {
return row / 2 == col / 2;
}
operation T03_BlockDiagonal_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, BlockDiagonal, BlockDiagonal_Pattern);
}
}
// ------------------------------------------------------
function Quarters_Pattern (size : Int, row : Int, col : Int) : Bool {
// The indices are little-endian, with qubit 0 corresponding to the least significant bit
// and qubits 1..N-1 corresponding to most significant bits.
// The pattern of quarters corresponds to equality of the most significant bits of row and column (qubit N-1)
return row / (size / 2) == col / (size / 2);
}
operation T04_Quarters_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, Quarters, Quarters_Pattern);
}
}
// ------------------------------------------------------
function EvenChessPattern_Pattern (size : Int, row : Int, col : Int) : Bool {
// The indices are little-endian, qubit 0 corresponding to the least significant bit
// and qubits 1..N-1 corresponding to most significant bits.
// The chessboard pattern corresponds to equality of the least significant bits of row and column (qubit 0)
return row % 2 == col % 2;
}
operation T05_EvenChessPattern_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, EvenChessPattern, EvenChessPattern_Pattern);
}
}
// ------------------------------------------------------
function OddChessPattern_Pattern (size : Int, row : Int, col : Int) : Bool {
// The indices are little-endian, qubit 0 corresponding to the least significant bit
// and qubits 1..N-1 corresponding to most significant bits.
// The chessboard pattern corresponds to inequality of the least significant bits of row and column (qubit 0)
return row % 2 != col % 2;
}
operation T06_OddChessPattern_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, OddChessPattern, OddChessPattern_Pattern);
}
}
// ------------------------------------------------------
function Antidiagonal_Pattern (size : Int, row : Int, col : Int) : Bool {
return row == (size - 1) - col;
}
operation T07_Antidiagonal_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, Antidiagonal, Antidiagonal_Pattern);
}
}
// ------------------------------------------------------
function ChessPattern2x2_Pattern (size : Int, row : Int, col : Int) : Bool {
return (row / 2) % 2 == (col / 2) % 2;
}
operation T08_ChessPattern2x2_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, ChessPattern2x2, ChessPattern2x2_Pattern);
}
}
// ------------------------------------------------------
function TwoPatterns_Pattern (size : Int, row : Int, col : Int) : Bool {
// top right and bottom left quarters are all 0
let s2 = size / 2;
if (row / s2 != col / s2) {
return false;
}
if (row / s2 == 0) {
// top left quarter is an anti-diagonal
return row % s2 + col % s2 == s2 - 1;
}
// bottom right quarter is all 1
return true;
}
operation T09_TwoPatterns_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, TwoPatterns, TwoPatterns_Pattern);
}
}
// ------------------------------------------------------
function IncreasingBlocks_Pattern (size : Int, row : Int, col : Int) : Bool {
// top right and bottom left quarters are all 0
let s2 = size / 2;
if (row / s2 != col / s2) {
return false;
}
if (row / s2 == 0) {
// top left quarter is the same pattern for s2, except for the start of the recursion
if (s2 == 1) {
return true;
}
return IncreasingBlocks_Pattern(s2, row, col);
}
// bottom right quarter is all 1
return true;
}
operation T10_IncreasingBlocks_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, IncreasingBlocks, IncreasingBlocks_Pattern);
}
}
// ------------------------------------------------------
function XWing_Fighter_Pattern (size : Int, row : Int, col : Int) : Bool {
return row == col or row == (size - 1) - col;
}
operation T11_XWing_Fighter_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, XWing_Fighter, XWing_Fighter_Pattern);
}
}
// ------------------------------------------------------
function Rhombus_Pattern (size : Int, row : Int, col : Int) : Bool {
let s2 = size / 2;
return row / s2 == col / s2 and row % s2 + col % s2 == s2 - 1 or
row / s2 != col / s2 and row % s2 == col % s2;
}
operation T12_Rhombus_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, Rhombus, Rhombus_Pattern);
}
}
// ------------------------------------------------------
function TIE_Fighter_Pattern (size : Int, row : Int, col : Int) : Bool {
let s2 = size / 2;
return row / s2 == 0 and col / s2 == 0 and row % s2 + col % s2 == s2 - 2 or
row / s2 == 0 and col / s2 == 1 and col % s2 - row % s2 == 1 or
row / s2 == 1 and col / s2 == 0 and row % s2 - col % s2 == 1 or
row / s2 == 1 and col / s2 == 1 and row % s2 + col % s2 == s2 or
(row == s2 - 1 or row == s2) and (col == s2 - 1 or col == s2);
}
operation T13_TIE_Fighter_Test () : Unit {
for (n in 2 .. 5) {
AssertOperationMatrixMatchesPattern(n, TIE_Fighter, TIE_Fighter_Pattern);
}
}
// ------------------------------------------------------
function Creeper_Pattern (size : Int, row : Int, col : Int) : Bool {
let A = [ [ true, true, false, false, false, false, true, true],
[ true, true, false, false, false, false, true, true],
[ false, false, false, true, true, false, false, false],
[ false, false, false, true, true, false, false, false],
[ false, false, true, false, false, true, false, false],
[ false, false, true, false, false, true, false, false],
[ true, true, false, false, false, false, true, true],
[ true, true, false, false, false, false, true, true] ];
return size != 8 ? false | A[row][col];
}
operation T14_Creeper_Test () : Unit {
AssertOperationMatrixMatchesPattern(3, Creeper, Creeper_Pattern);
}
// ------------------------------------------------------
function Hessenberg_Matrix_Pattern (size : Int, row : Int, col : Int) : Bool {
return (row - 1) <= col;
}
operation T15_Hessenberg_Matrix_Test () : Unit {
for (n in 2 .. 4) {
AssertOperationMatrixMatchesPattern(n, Hessenberg_Matrix, Hessenberg_Matrix_Pattern);
}
}
// ------------------------------------------------------
function GetOracleCallsCount<'T> (oracle : 'T) : Int { return 0; }
function ResetOracleCallsCount () : Unit { }
function GetMaxQubitCount () : Int { return 0; }
function ResetQubitCount () : Unit { }
}