-
Notifications
You must be signed in to change notification settings - Fork 172
Expand file tree
/
Copy pathutilities.hpp
More file actions
401 lines (268 loc) · 11.1 KB
/
utilities.hpp
File metadata and controls
401 lines (268 loc) · 11.1 KB
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/** @file
* Miscellaneous utility signatures needed internally,
* which are not performance critical (i.e. not used
* in hot loops). These include qubit and state index
* logic, matrix algebra, and channel parameters. This
* header also defines several compile-time type-trait
* functions needed for internal generic functions.
*
* @author Tyson Jones
*/
#ifndef UTILITIES_HPP
#define UTILITIES_HPP
#include "quest/include/types.h"
#include "quest/include/qureg.h"
#include "quest/include/paulis.h"
#include "quest/include/matrices.h"
#include "quest/include/channels.h"
#include "quest/include/environment.h"
#include <type_traits>
#include <functional>
#include <string>
#include <vector>
#include <array>
using std::is_same_v;
using std::vector;
/*
* QUBIT PROCESSING
*/
bool util_isQubitInSuffix(int qubit, Qureg qureg);
bool util_isBraQubitInSuffix(int ketQubit, Qureg qureg);
bool util_areAllQubitsInSuffix(vector<int> qubits, Qureg qureg);
int util_getBraQubit(int ketQubit, Qureg qureg);
int util_getPrefixInd(int qubit, Qureg qureg);
int util_getPrefixBraInd(int ketQubit, Qureg qureg);
std::array<vector<int>,2> util_getPrefixAndSuffixQubits(vector<int> qubits, Qureg qureg);
int util_getRankBitOfQubit(int ketQubit, Qureg qureg);
int util_getRankBitOfBraQubit(int ketQubit, Qureg qureg);
int util_getRankWithQubitFlipped(int ketQubit, Qureg qureg);
int util_getRankWithQubitsFlipped(vector<int> prefixQubits, Qureg qureg);
int util_getRankWithBraQubitFlipped(int ketQubit, Qureg qureg);
int util_getRankWithBraQubitsFlipped(vector<int> ketQubits, Qureg qureg);
vector<int> util_getBraQubits(vector<int> ketQubits, Qureg qureg);
vector<int> util_getNonTargetedQubits(int* targets, int numTargets, int numQubits);
vector<int> util_getVector(int* qubits, int numQubits);
vector<int> util_getConcatenated(vector<int> list1, vector<int> list2);
vector<int> util_getSorted(vector<int> list);
vector<int> util_getSorted(vector<int> ctrls, vector<int> targs);
qindex util_getBitMask(vector<int> qubits);
qindex util_getBitMask(vector<int> qubits, vector<int> states);
qindex util_getBitMask(vector<int> ctrls, vector<int> ctrlStates, vector<int> targs, vector<int> targStates);
/*
* INDEX ALGEBRA
*/
qindex util_getGlobalIndexOfFirstLocalAmp(Qureg qureg);
qindex util_getGlobalColumnOfFirstLocalAmp(Qureg qureg);
qindex util_getLocalIndexOfGlobalIndex(Qureg qureg, qindex globalInd);
qindex util_getLocalIndexOfFirstDiagonalAmp(Qureg qureg);
qindex util_getGlobalFlatIndex(Qureg qureg, qindex globalRow, qindex globalCol);
int util_getRankContainingIndex(Qureg qureg, qindex globalInd);
int util_getRankContainingColumn(Qureg qureg, qindex globalCol);
int util_getRankContainingIndex(FullStateDiagMatr matr, qindex globalInd);
qindex util_getNextPowerOf2(qindex number);
qcomp util_getElemFromNestedPtrs(void* in, qindex* inds, int numInds);
/*
* SCALAR ALGEBRA
*/
bool util_isStrictlyInteger(qreal num);
bool util_isApproxReal(qcomp num, qreal epsilon);
qcomp util_getPowerOfI(size_t exponent);
/*
* STRUCT TYPING
*
* defined here in the header since templated, and which use compile-time inspection.
*/
template <class T> constexpr bool util_isQuregType() { return is_same_v<T, Qureg>; }
template <class T> constexpr bool util_isCompMatr1() { return is_same_v<T, CompMatr1>; }
template <class T> constexpr bool util_isCompMatr2() { return is_same_v<T, CompMatr2>; }
template <class T> constexpr bool util_isCompMatr () { return is_same_v<T, CompMatr >; }
template <class T> constexpr bool util_isDiagMatr1() { return is_same_v<T, DiagMatr1>; }
template <class T> constexpr bool util_isDiagMatr2() { return is_same_v<T, DiagMatr2>; }
template <class T> constexpr bool util_isDiagMatr () { return is_same_v<T, DiagMatr >; }
template <class T> constexpr bool util_isFullStateDiagMatr () { return is_same_v<T, FullStateDiagMatr >; }
template<class T>
constexpr bool util_isDenseMatrixType() {
// CompMatr, SuperOp and (in are sense) KrausMaps are "dense", storing all 2D elements
if constexpr (
is_same_v<T, CompMatr1> ||
is_same_v<T, CompMatr2> ||
is_same_v<T, CompMatr> ||
is_same_v<T, KrausMap> ||
is_same_v<T, SuperOp>
)
return true;
// DiagMatr are "sparse", storing only the diagonals
if constexpr (
is_same_v<T, DiagMatr1> ||
is_same_v<T, DiagMatr2> ||
is_same_v<T, DiagMatr> ||
is_same_v<T, FullStateDiagMatr>
)
return false;
// this line is reached if the type is not a matrix
return false;
}
template<class T>
constexpr bool util_isFixedSizeMatrixType() {
return (
is_same_v<T, CompMatr1> ||
is_same_v<T, CompMatr2> ||
is_same_v<T, DiagMatr1> ||
is_same_v<T, DiagMatr2>
);
}
template<class T>
constexpr bool util_isHeapMatrixType() {
// all non-fixed size matrices are stored in the heap (never the stack)
return ! util_isFixedSizeMatrixType<T>();
}
template<class T>
constexpr bool util_isDistributableType() {
return (is_same_v<T, FullStateDiagMatr> || is_same_v<T, Qureg>);
}
template<class T>
bool util_isDistributedMatrix(T matr) {
if constexpr (util_isDistributableType<T>())
return matr.isDistributed;
return false;
}
template<class T>
bool util_isGpuAcceleratedMatrix(T matr) {
if constexpr (util_isFullStateDiagMatr<T>())
return matr.isGpuAccelerated;
if constexpr (util_isHeapMatrixType<T>())
return getQuESTEnv().isGpuAccelerated;
return false;
}
template<class T>
std::string util_getMatrixTypeName() {
if constexpr (is_same_v<T, CompMatr1>) return "CompMatr1";
if constexpr (is_same_v<T, CompMatr2>) return "CompMatr2";
if constexpr (is_same_v<T, CompMatr >) return "CompMatr" ;
if constexpr (is_same_v<T, DiagMatr1>) return "DiagMatr1";
if constexpr (is_same_v<T, DiagMatr2>) return "DiagMatr2";
if constexpr (is_same_v<T, DiagMatr >) return "DiagMatr" ;
if constexpr (is_same_v<T, FullStateDiagMatr>)
return "FullStateDiagMatr";
// these types do not need to have this function called, but
// we include them for completeness
if constexpr (is_same_v<T, KrausMap >) return "KrausMap" ;
if constexpr (is_same_v<T, SuperOp >) return "SuperOp" ;
// no need to create a new error for this situation
return "UnrecognisedMatrix";
}
template<class T>
qindex util_getMatrixDim(T matr) {
if constexpr (util_isDenseMatrixType<T>())
return matr.numRows;
else
return matr.numElems;
}
// T can be CompMatr, DiagMatr, FullStateDiagMatr, SuperOp (but NOT KrausMap)
template<class T>
qcomp* util_getGpuMemPtr(T matr) {
// 2D CUDA structures are always stored as 1D
if constexpr (util_isDenseMatrixType<T>())
return matr.gpuElemsFlat;
else
return matr.gpuElems;
}
/*
* VECTOR REDUCTION
*/
qreal util_getSum(vector<qreal> list);
/*
* MATRIX CONJUGATION
*/
CompMatr1 util_getConj(CompMatr1 matrix);
CompMatr2 util_getConj(CompMatr2 matrix);
DiagMatr1 util_getConj(DiagMatr1 matrix);
DiagMatr2 util_getConj(DiagMatr2 matrix);
void util_setConj(CompMatr matrix);
void util_setConj(DiagMatr matrix);
/*
* MATRIX PROPERTIES
*/
bool util_isUnitary(CompMatr1 matrix, qreal epsilon);
bool util_isUnitary(CompMatr2 matrix, qreal epsilon);
bool util_isUnitary(CompMatr matrix, qreal epsilon);
bool util_isUnitary(DiagMatr1 matrix, qreal epsilon);
bool util_isUnitary(DiagMatr2 matrix, qreal epsilon);
bool util_isUnitary(DiagMatr matrix, qreal epsilon);
bool util_isUnitary(FullStateDiagMatr matrix, qreal epsilon);
bool util_isHermitian(CompMatr1 matrix, qreal epsilon);
bool util_isHermitian(CompMatr2 matrix, qreal epsilon);
bool util_isHermitian(CompMatr matrix, qreal epsilon);
bool util_isHermitian(DiagMatr1 matrix, qreal epsilon);
bool util_isHermitian(DiagMatr2 matrix, qreal epsilon);
bool util_isHermitian(DiagMatr matrix, qreal epsilon);
bool util_isHermitian(FullStateDiagMatr matrix, qreal epsilon);
bool util_isApproxNonZero(DiagMatr1 matrix, qreal epsilon);
bool util_isApproxNonZero(DiagMatr2 matrix, qreal epsilon);
bool util_isApproxNonZero(DiagMatr matrix, qreal epsilon);
bool util_isApproxNonZero(FullStateDiagMatr matrix, qreal epsilon);
bool util_isStrictlyNonNegative(DiagMatr1 matrix);
bool util_isStrictlyNonNegative(DiagMatr2 matrix);
bool util_isStrictlyNonNegative(DiagMatr matrix);
bool util_isStrictlyNonNegative(FullStateDiagMatr matrix);
/*
* PAULI STR SUM PROPERTIES
*/
bool util_isHermitian(PauliStrSum sum, qreal epsilon);
/*
* KRAUS MAP AND SUPEROPERATOR PROPERTIES
*/
bool util_isCPTP(KrausMap map, qreal epsilon);
void util_setSuperoperator(qcomp** superop, vector<vector<vector<qcomp>>> matrices, int numMatrices, int numQubits);
void util_setSuperoperator(qcomp** superop, qcomp*** matrices, int numMatrices, int numQubits);
/*
* STRUCT PROPERTY CACHING
*/
int* util_allocEpsilonSensitiveHeapFlag();
void util_deallocEpsilonSensitiveHeapFlag(int* ptr);
void util_setEpsilonSensitiveHeapFlagsToUnknown();
void util_setFlagToUnknown(int* ptr);
/*
* DISTRIBUTED ELEMENTS INDEXING
*/
struct util_VectorIndexRange {
// the first local index of this node's amps which are in the queried distributed range
qindex localDistribStartInd;
// the corresponding local index of the non-distributed (i.e. duplicated on every node) data structure
qindex localDuplicStartInd;
// the number of this node's amps which are within the queried distributed range
qindex numElems;
};
bool util_areAnyVectorElemsWithinNode(int rank, qindex numElemsPerNode, qindex startInd, qindex numInds);
util_VectorIndexRange util_getLocalIndRangeOfVectorElemsWithinNode(int rank, qindex numElemsPerNode, qindex elemStartInd, qindex numInds);
/*
* GATE PARAMETERS
*/
qreal util_getPhaseFromGateAngle(qreal angle);
/*
* DECOHERENCE FACTORS
*/
struct util_Scalars { qreal c1; qreal c2; qreal c3; qreal c4; };
qreal util_getOneQubitDephasingFactor(qreal prob);
qreal util_getTwoQubitDephasingTerm(qreal prob);
util_Scalars util_getOneQubitDepolarisingFactors(qreal prob);
util_Scalars util_getTwoQubitDepolarisingFactors(qreal prob);
util_Scalars util_getOneQubitDampingFactors(qreal prob);
util_Scalars util_getOneQubitPauliChannelFactors(qreal pI, qreal pX, qreal pY, qreal pZ);
qreal util_getMaxProbOfOneQubitDephasing();
qreal util_getMaxProbOfTwoQubitDephasing();
qreal util_getMaxProbOfOneQubitDepolarising();
qreal util_getMaxProbOfTwoQubitDepolarising();
/*
* TEMPORARY MEMORY ALLOCATION
*/
void util_tryAllocVector(vector<qreal> &vec, qindex size, std::function<void()> errFunc);
void util_tryAllocVector(vector<qcomp> &vec, qindex size, std::function<void()> errFunc);
void util_tryAllocVector(vector<qcomp*> &vec, qindex size, std::function<void()> errFunc);
void util_tryAllocVector(vector<unsigned> &vec, qindex size, std::function<void()> errFunc);
// cuQuantum needs a vector<double> overload, which we additionally define when qreal!=double. Gross!
#if FLOAT_PRECISION != 2
void util_tryAllocVector(vector<double> &vec, qindex size, std::function<void()> errFunc);
#endif
void util_tryAllocMatrix(vector<vector<qcomp>> &vec, qindex numRows, qindex numCols, std::function<void()> errFunc);
#endif // UTILITIES_HPP