forked from microsoft/QuantumKatas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Tasks.qs
319 lines (276 loc) · 12.2 KB
/
Tasks.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
313
314
315
316
317
318
319
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
namespace Quantum.Kata.UnitaryPatterns {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
// Welcome!
//////////////////////////////////////////////////////////////////
// The "Unitary Patterns" quantum kata is a series of exercises designed
// to get you comfortable with creating unitary transformations which can be represented
// with matrices of certain shapes (with certain pattern of zero and non-zero values).
// Each task is wrapped in one operation preceded by the description of the task.
// Each task has a unit test associated with it, which initially fails.
// Your goal is to fill in the blank (marked with // ... comment)
// with some Q# code to make the failing test pass.
// The tasks are given in approximate order of increasing difficulty;
// harder ones are marked with asterisks.
// Each task describes a matrix which your unitary needs to implement.
// The row and column indices of the matrix elements are in little-endian format (the least significant bit is stored first).
// For example, index 1 corresponds to the qubit state |10..0⟩, and to store this state in an array of qubits qs
// its first element qs[0] would have to be in state |1⟩ and the rest of the qubits would have to be in state |0⟩.
// In the example patterns provided in the tasks, X marks a "non-zero" element, and . marks a "zero" element.
// "Zero" element of a matrix is a complex number which has an absolute value of 0.001 or less,
// and "non-zero" element is a complex number which has an absolute value of 0.001 or greater.
// You can see the details of the verification in Tests.qs file, operation AssertOperationMatrixMatchesPattern.
// Note that all tasks require you to implement a unitary transformation,
// which means that you're not allowed to use any measurements.
// Task 1. Main diagonal
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements on the main diagonal and zero elements everywhere else.
// Example: For N = 2, the matrix of the transformation should look as follows:
// X...
// .X..
// ..X.
// ...X
operation MainDiagonal (qs : Qubit[]) : Unit {
// The simplest example of such a unitary transformation is represented by an identity matrix.
// This means that the operation doesn't need to do anything with the input qubits.
// Build the project and run the tests to see that T01_MainDiagonal_Test test passes.
// You are welcome to try and come up with other diagonal unitaries.
// ...
}
// Task 2. All-non-zero matrix
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with all elements non-zero.
// Example: For N = 2, the matrix of the transformation should look as follows:
// XXXX
// XXXX
// XXXX
// XXXX
operation AllNonZero (qs : Qubit[]) : Unit {
// ...
}
// Task 3. Block diagonal matrix
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// which has 2⨯2 blocks of non-zero elements on the main diagonal and zero elements everywhere else.
// Example: For N = 3, the matrix of the transformation should look as follows:
// XX......
// XX......
// ..XX....
// ..XX....
// ....XX..
// ....XX..
// ......XX
// ......XX
operation BlockDiagonal (qs : Qubit[]) : Unit {
// ...
}
// Task 4. Quarters
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements in top left and bottom right quarters
// and zero elements everywhere else.
// Example: For N = 3, the matrix of the transformation should look as follows:
// XXXX....
// XXXX....
// XXXX....
// XXXX....
// ....XXXX
// ....XXXX
// ....XXXX
// ....XXXX
operation Quarters (qs : Qubit[]) : Unit {
// Hint: represent this matrix as a tensor product of a 2⨯2 diagonal matrix and a larger matrix with all non-zero elements.
// ...
}
// Task 5. Even chessboard pattern
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements in positions where row and column indices have the same parity
// and zero elements everywhere else.
// Example: For N = 2, the matrix of the transformation should look as follows:
// X.X.
// .X.X
// X.X.
// .X.X
operation EvenChessPattern (qs : Qubit[]) : Unit {
// ...
}
// Task 6. Odd chessboard pattern
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements in positions where row and column indices have different parity
// and zero elements everywhere else.
// Example: For N = 2, the matrix of the transformation should look as follows:
// .X.X
// X.X.
// .X.X
// X.X.
operation OddChessPattern (qs : Qubit[]) : Unit {
// ...
}
// Task 7. Anti-diagonal
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements on the anti-diagonal and zero elements everywhere else.
// Example: For N = 2, the matrix of the transformation should look as follows:
// ...X
// ..X.
// .X..
// X...
operation Antidiagonal (qs : Qubit[]) : Unit {
// ...
}
// Task 8. 2⨯2 chessboard pattern
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// in which zero and non-zero elements form a chessboard pattern with 2⨯2 squares,
// with the top left square occupied by non-zero elements.
// Example: For N = 3, the matrix of the transformation should look as follows:
// XX..XX..
// XX..XX..
// ..XX..XX
// ..XX..XX
// XX..XX..
// XX..XX..
// ..XX..XX
// ..XX..XX
operation ChessPattern2x2 (qs : Qubit[]) : Unit {
// ...
}
// Task 9. Two patterns
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with all zero elements in the top right and bottom left quarters,
// an anti-diagonal pattern from task 1.6 in the top left quarter,
// and an all-non-zero pattern from task 1.2 in the bottom right quarter.
// Example: For N = 2, the matrix of the transformation should look as follows:
// .X..
// X...
// ..XX
// ..XX
operation TwoPatterns (qs : Qubit[]) : Unit {
// ...
}
// Task 10. Increasing blocks
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix defined recursively:
// * for N = 1 the matrix has non-zero elements on the main diagonal and zero elements everywhere else,
// * for larger N the matrix has all zero elements in the top right and bottom left quarters,
// the matrix for N-1 in the top left quarter,
// and all non-zero elements in the bottom right quarter.
// Example: For N = 3, the matrix of the transformation should look as follows:
// X.......
// .X......
// ..XX....
// ..XX....
// ....XXXX
// ....XXXX
// ....XXXX
// ....XXXX
operation IncreasingBlocks (qs : Qubit[]) : Unit {
// ...
}
// Task 11. X-Wing fighter
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements on the main diagonal and the anti-diagonal
// and zero elements everywhere else.
// Example: For N = 3, the matrix should look as follows:
// X......X
// .X....X.
// ..X..X..
// ...XX...
// ...XX...
// ..X..X..
// .X....X.
// X......X
operation XWing_Fighter (qs : Qubit[]) : Unit {
// ...
}
// Task 12. Rhombus
// Input: N qubits in an arbitrary state.
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements forming a rhombus of width 1 with sides parallel to main diagonals.
// Example: For N = 2, the matrix of the transformation should look as follows:
// .XX.
// X..X
// X..X
// .XX.
// For N = 3, the matrix should look as follows:
// ...XX...
// ..X..X..
// .X....X.
// X......X
// X......X
// .X....X.
// ..X..X..
// ...XX...
operation Rhombus (qs : Qubit[]) : Unit {
// ...
}
// Task 13*. TIE fighter
// Input: N qubits in an arbitrary state (2 ≤ N ≤ 5).
// Goal: Implement a unitary transformation on N qubits that is represented by a matrix
// with non-zero elements in the following positions:
// - the central 2⨯2 sub-matrix;
// - the diagonals of the top right and bottom left sub-matrices of size 2ᴺ⁻¹-1
// that do not overlap with the central 2⨯2 sub-matrix;
// - the anti-diagonals of the top left and bottom right sub-matrices of size 2ᴺ⁻¹-1
// that do not overlap with the central 2⨯2 sub-matrix.
// Example: For N = 3, the matrix should look as follows:
// ..X..X..
// .X....X.
// X......X
// ...XX...
// ...XX...
// X......X
// .X....X.
// ..X..X..
operation TIE_Fighter (qs : Qubit[]) : Unit {
// ...
}
// Task 14**. Creeper
// Input: 3 qubits in an arbitrary state.
// Goal: Implement a unitary transformation on 3 qubits which is represented by a matrix
// with non-zero elements in the following pattern:
// XX....XX
// XX....XX
// ...XX...
// ...XX...
// ..X..X..
// ..X..X..
// XX....XX
// XX....XX
operation Creeper (qs : Qubit[]) : Unit {
// ...
}
// Task 15**. Hessenberg matrices
// Input: N qubits in an arbitrary state (2 ≤ N ≤ 4).
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
// with non-zero elements forming an upper diagonal matrix plus the first subdiagonal.
// This is called a 'Hessenberg matrix' https://en.wikipedia.org/wiki/Hessenberg_matrix.
// Example: For N = 2, the matrix of the transformation should look as follows:
// XXXX
// XXXX
// .XXX
// ..XX
// For N = 3, the matrix should look as follows:
// XXXXXXXX
// XXXXXXXX
// .XXXXXXX
// ..XXXXXX
// ...XXXXX
// ....XXXX
// .....XXX
// ......XX
operation Hessenberg_Matrix (qs : Qubit[]) : Unit {
// ...
}
}