The Quantum Exact Simulation Toolkit v4.0.0
Loading...
Searching...
No Matches

Testing utilities which perform linear algebra routines upon reference qvector and qmatrix. These are slow, serial, un-optimised, defensively- designed routines. More...

Functions

int getBitAt (qindex num, int ind)
 
vector< int > getBits (qindex num, int numBits)
 
qindex getBitsAt (qindex num, vector< int > inds)
 
qmatrix getConjugate (qmatrix)
 
qmatrix getConjugateTranspose (qmatrix)
 
qmatrix getControlledMatrix (qmatrix matrix, int numCtrls)
 
qvector getDisceteFourierTransform (qvector in, vector< int > targs)
 
qvector getDisceteFourierTransform (qvector)
 
qmatrix getExponentialOfDiagonalMatrix (qmatrix)
 
qmatrix getExponentialOfNormalisedPauliVector (qreal arg, qreal x, qreal y, qreal z)
 
qmatrix getExponentialOfPauliMatrix (qreal arg, qmatrix pauli)
 
qcomp getInnerProduct (qvector bra, qvector ket)
 
qmatrix getKroneckerProduct (qmatrix, int count)
 
qmatrix getKroneckerProduct (qmatrix, qmatrix)
 
qmatrix getKroneckerProduct (vector< qmatrix >)
 
int getLog2 (qindex)
 
qmatrix getMixture (vector< qmatrix > densmatrs, vector< qreal > probs)
 
qmatrix getMixture (vector< qvector > statevecs, vector< qreal > probs)
 
qvector getNormalised (qvector)
 
int getNumPermutations (int n, int k)
 
qmatrix getOrthonormalisedRows (qmatrix)
 
qmatrix getOuterProduct (qvector ket, qvector bra)
 
qmatrix getPartialTrace (qmatrix matrix, vector< int > targets)
 
qindex getPow2 (int)
 
qmatrix getPowerOfDiagonalMatrix (qmatrix diag, qcomp power)
 
qmatrix getProjector (int outcome)
 
qmatrix getProjector (vector< int > targets, vector< int > outcomes, int numQubits)
 
qcomp getSum (qvector)
 
qreal getSum (vector< qreal > vec)
 
qmatrix getSuperOperator (vector< qmatrix >)
 
qcomp getTrace (qmatrix)
 
qmatrix getTranspose (qmatrix)
 
bool isApproxCPTP (vector< qmatrix >)
 
bool isApproxUnitary (qmatrix)
 
bool isDiagonal (qmatrix)
 
qvector operator* (const qmatrix &, const qvector &)
 
qindex setBitAt (qindex num, int ind, int bit)
 
qindex setBitsAt (qindex num, vector< int > inds, qindex bits)
 

Detailed Description

Testing utilities which perform linear algebra routines upon reference qvector and qmatrix. These are slow, serial, un-optimised, defensively- designed routines.

Function Documentation

◆ getBitAt()

int getBitAt ( qindex num,
int ind )

Definition at line 47 of file linalg.cpp.

47 {
48 DEMAND( num >= 0 );
49
50 return (num >> ind) & 1;
51}

◆ getBits()

vector< int > getBits ( qindex num,
int numBits )

Definition at line 54 of file linalg.cpp.

54 {
55 DEMAND( numBits > 0 );
56
57 // out ordered least to most significant
58 vector<int> out(numBits);
59
60 for (int i=0; i<numBits; i++)
61 out[i] = getBitAt(num, i);
62
63 return out;
64}

◆ getBitsAt()

qindex getBitsAt ( qindex num,
vector< int > inds )

Definition at line 67 of file linalg.cpp.

67 {
68 DEMAND( num >= 0 );
69
70 qindex out = 0;
71
72 for (size_t i=0; i<inds.size(); i++)
73 out |= getBitAt(num, inds[i]) << i;
74
75 return out;
76}

◆ getConjugate()

qmatrix getConjugate ( qmatrix m)

Definition at line 281 of file linalg.cpp.

281 {
282
283 for (auto& row : m)
284 for (auto& elem : row)
285 elem = std::conj(elem);
286
287 return m;
288}

◆ getConjugateTranspose()

qmatrix getConjugateTranspose ( qmatrix m)

Definition at line 291 of file linalg.cpp.

291 {
292 DEMAND( m.size() > 0 );
293
294 // unlike most functions which assume qmatrix
295 // is square, this one cheekily handles when
296 // 'm' is non-square, since necessary for
297 // computing partial traces
298
299 qmatrix out(m[0].size(), qvector(m.size()));
300
301 for (size_t r=0; r<out.size(); r++)
302 for (size_t c=0; c<out[0].size(); c++)
303 out[r][c] = std::conj(m[c][r]);
304
305 return out;
306}

◆ getControlledMatrix()

qmatrix getControlledMatrix ( qmatrix matrix,
int numCtrls )

Definition at line 451 of file linalg.cpp.

451 {
452
453 size_t dim = getPow2(numCtrls) * matrix.size();
454 size_t off = dim - matrix.size();
455
456 qmatrix out = getIdentityMatrix(dim);
457 setSubMatrix(out, matrix, off, off);
458
459 return out;
460}
qmatrix getIdentityMatrix(size_t dim)
Definition qmatrix.cpp:30
void setSubMatrix(qmatrix &dest, qmatrix sub, size_t r, size_t c)
Definition qmatrix.cpp:203

◆ getDisceteFourierTransform() [1/2]

qvector getDisceteFourierTransform ( qvector in,
vector< int > targs )

Definition at line 179 of file linalg.cpp.

179 {
180 DEMAND( in.size() > 0 );
181
182 size_t dim = in.size();
183 qvector out = getZeroVector(dim);
184
185 qindex len = getPow2(targs.size());
186 qreal pi = 3.14159265358979323846;
187 qreal a = 1 / std::sqrt(len);
188 qreal b = 2 * pi / len;
189
190 for (size_t i=0; i<dim; i++) {
191 size_t x = getBitsAt(i, targs);
192 for (size_t y=0; y<len; y++) {
193 qindex j = setBitsAt(i, targs, y);
194 out[j] += a * std::exp(b * x * y * 1_i) * in[i];
195 }
196 }
197
198 return out;
199}

◆ getDisceteFourierTransform() [2/2]

qvector getDisceteFourierTransform ( qvector in)

Definition at line 160 of file linalg.cpp.

160 {
161 DEMAND( in.size() > 0 );
162
163 size_t dim = in.size();
164 qvector out = getZeroVector(dim);
165
166 // PI must be accurate here
167 qreal pi = 3.14159265358979323846;
168 qreal a = 1 / std::sqrt(dim);
169 qreal b = 2 * pi / dim;
170
171 for (size_t x=0; x<dim; x++)
172 for (size_t y=0; y<dim; y++)
173 out[x] += a * std::exp(b * x * y * 1_i) * in[y];
174
175 return out;
176}

◆ getExponentialOfDiagonalMatrix()

qmatrix getExponentialOfDiagonalMatrix ( qmatrix m)

Definition at line 336 of file linalg.cpp.

336 {
337 DEMAND( isDiagonal(m) );
338
339 qmatrix out = getZeroMatrix(m.size());
340
341 for (size_t i=0; i<m.size(); i++)
342 out[i][i] = std::exp(m[i][i]);
343
344 return out;
345}
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18

◆ getExponentialOfNormalisedPauliVector()

qmatrix getExponentialOfNormalisedPauliVector ( qreal arg,
qreal x,
qreal y,
qreal z )

Definition at line 357 of file linalg.cpp.

357 {
358
359 // exp(-arg/2 i [x^ X + y^ Y + z^ Z])
360 qreal n = std::sqrt(x*x + y*y + z*z);
361 x /= n;
362 y /= n;
363 z /= n;
364
365 qmatrix id = getIdentityMatrix(2);
366 qmatrix out = std::cos(arg/2)*id - 1_i*std::sin(arg/2)*(
367 x * getPauliMatrix(1) +
368 y * getPauliMatrix(2) +
369 z * getPauliMatrix(3));
370
371 return out;
372}

◆ getExponentialOfPauliMatrix()

qmatrix getExponentialOfPauliMatrix ( qreal arg,
qmatrix pauli )

Definition at line 348 of file linalg.cpp.

348 {
349
350 // exp(-i arg/2 m) where m = prod(paulis)
351 qmatrix id = getIdentityMatrix(m.size());
352 qmatrix out = std::cos(arg/2)*id - 1_i*std::sin(arg/2)*m;
353 return out;
354}

◆ getInnerProduct()

qcomp getInnerProduct ( qvector bra,
qvector ket )

Definition at line 208 of file linalg.cpp.

208 {
209 DEMAND( bra.size() == ket.size() );
210
211 qcomp out = 0;
212
213 for (size_t i=0; i<bra.size(); i++)
214 out += std::conj(bra[i]) * ket[i];
215
216 return out;
217}

◆ getKroneckerProduct() [1/3]

qmatrix getKroneckerProduct ( qmatrix m,
int count )

Definition at line 559 of file linalg.cpp.

559 {
560 DEMAND( count >= 1 );
561
562 qmatrix out = getIdentityMatrix(1);
563
564 for (int n=0; n<count; n++)
565 out = getKroneckerProduct(out, m);
566
567 return out;
568}
qmatrix getKroneckerProduct(qmatrix a, qmatrix b)
Definition linalg.cpp:523

◆ getKroneckerProduct() [2/3]

qmatrix getKroneckerProduct ( qmatrix a,
qmatrix b )

Definition at line 523 of file linalg.cpp.

523 {
524
525 // we permit the matrices to be non-square which is
526 // pretty cheeky (since qmatrix is assumed square with
527 // a 2^N dimension by most other functions), but is
528 // necessary for us to compute partial traces
529
530 size_t aRows = a.size();
531 size_t bRows = b.size();
532 size_t aCols = a[0].size();
533 size_t bCols = b[0].size();
534
535 qmatrix out(aRows * bRows, qvector(aCols * bCols));
536
537 for (size_t r=0; r<bRows; r++)
538 for (size_t c=0; c<bCols; c++)
539 for (size_t i=0; i<aRows; i++)
540 for (size_t j=0; j<aCols; j++)
541 out[r+bRows*i][c+bCols*j] = a[i][j] * b[r][c];
542
543 return out;
544}

◆ getKroneckerProduct() [3/3]

qmatrix getKroneckerProduct ( vector< qmatrix > matrices)

Definition at line 547 of file linalg.cpp.

547 {
548
549 qmatrix out = getIdentityMatrix(1);
550
551 // matrices[n-1] (x) ... (x) matrices[0]
552 for (auto& m : matrices)
553 out = getKroneckerProduct(m, out);
554
555 return out;
556}

◆ getLog2()

int getLog2 ( qindex a)

Definition at line 28 of file linalg.cpp.

28 {
29 DEMAND( a >= 0 );
30 DEMAND( (a & (a - 1)) == 0 ); // is pow2
31
32 int n = 0;
33 while (a >>= 1)
34 n++;
35
36 return n;
37}

◆ getMixture() [1/2]

qmatrix getMixture ( vector< qmatrix > densmatrs,
vector< qreal > probs )

Definition at line 463 of file linalg.cpp.

463 {
464 DEMAND( densmatrs.size() > 0 );
465
466 qmatrix out = getZeroMatrix(densmatrs[0].size());
467 for (size_t i=0; i<densmatrs.size(); i++)
468 out += probs[i] * densmatrs[i];
469
470 return out;
471}

◆ getMixture() [2/2]

qmatrix getMixture ( vector< qvector > statevecs,
vector< qreal > probs )

Definition at line 474 of file linalg.cpp.

474 {
475
476 vector<qmatrix> densmatrs(statevecs.size());
477 for (size_t i=0; i<statevecs.size(); i++)
478 densmatrs[i] = getOuterProduct(statevecs[i], statevecs[i]);
479
480 return getMixture(densmatrs, probs);
481}

◆ getNormalised()

qvector getNormalised ( qvector vec)

Definition at line 143 of file linalg.cpp.

143 {
144
145 // prob[i] = abs(vec[i])^2
146 vector<qreal> probs(vec.size());
147 for (size_t i=0; i<vec.size(); i++)
148 probs[i] = std::norm(vec[i]);
149
150 // normalise vector
151 qreal norm = getSum(probs);
152 qreal fac = 1 / std::sqrt(norm);
153 for (auto& x : vec)
154 x *= fac;
155
156 return vec;
157}

◆ getNumPermutations()

int getNumPermutations ( int n,
int k )

Definition at line 96 of file linalg.cpp.

96 {
97 DEMAND( n >= k );
98 DEMAND( n <= 11 ); // else int overflow
99
100 // P(n, k) = n! / (n-k)!
101 qindex p = 1;
102 for (int t=n-k+1; t<=n; t++)
103 p *= t;
104
105 return p;
106}

◆ getOrthonormalisedRows()

qmatrix getOrthonormalisedRows ( qmatrix matr)

Definition at line 375 of file linalg.cpp.

375 {
376
377 // perform the Gram-Schmidt process, processing each row of matr in-turn
378 for (size_t i=0; i<matr.size(); i++) {
379 qvector row = matr[i];
380
381 // compute new orthogonal row by subtracting proj row onto prevs
382 for (int k=i-1; k>=0; k--) {
383
384 // compute inner_product(row, prev) = row . conj(prev)
385 qcomp prod = getInnerProduct(matr[k], row);
386
387 // subtract (proj row onto prev) = (prod * prev) from final row
388 matr[i] -= prod * matr[k];
389 }
390
391 // normalise the row
392 matr[i] = getNormalised(matr[i]);
393 }
394
395 // return the new orthonormal matrix
396 return matr;
397}

◆ getOuterProduct()

qmatrix getOuterProduct ( qvector ket,
qvector bra )

Definition at line 220 of file linalg.cpp.

220 {
221 DEMAND( bra.size() == ket.size() );
222
223 qmatrix out = getZeroMatrix(bra.size());
224
225 for (size_t i=0; i<ket.size(); i++)
226 for (size_t j=0; j<ket.size(); j++)
227 out[i][j] = ket[i] * std::conj(bra[j]);
228
229 return out;
230}

◆ getPartialTrace()

qmatrix getPartialTrace ( qmatrix matrix,
vector< int > targets )

Definition at line 422 of file linalg.cpp.

422 {
423 DEMAND( in.size() > getPow2(targets.size()) );
424
425 auto numTargs = targets.size();
426 auto numQubits = getLog2(in.size());
427 auto numTargVals = getPow2(numTargs);
428
429 qmatrix out = getZeroMatrix(getPow2(numQubits - numTargs));
430
431 for (qindex v=0; v<numTargVals; v++) {
432
433 // prepare { |0>, I, I, |1>, ... }
434 vector<qmatrix> matrices(numQubits, getIdentityMatrix(2));
435 for (size_t t=0; t<numTargs; t++) {
436 int bit = getBitAt(v, t);
437 matrices[targets[t]] = {
438 {bit? 0.:1.},
439 {bit? 1.:0.}};
440 }
441
442 qmatrix ket = getKroneckerProduct(matrices);
443 qmatrix bra = getConjugateTranspose(ket);
444 out += bra * in * ket;
445 }
446
447 return out;
448}
qmatrix getConjugateTranspose(qmatrix m)
Definition linalg.cpp:291

◆ getPow2()

qindex getPow2 ( int a)

Definition at line 40 of file linalg.cpp.

40 {
41 DEMAND( a >= 0 );
42
43 return ((qindex) 1) << a;
44}

◆ getPowerOfDiagonalMatrix()

qmatrix getPowerOfDiagonalMatrix ( qmatrix diag,
qcomp power )

Definition at line 309 of file linalg.cpp.

309 {
310 DEMAND( isDiagonal(m) );
311
312 qmatrix out = getZeroMatrix(m.size());
313
314 // pow(qcomp,qcomp) introduces wildly erroneous
315 // imaginary components when both base is real
316 // and negative, and exponent is real and integer
317 // (so ergo does not produce complex numbers).
318 // We divert to real-pow in that scenario!
319
320 for (size_t i=0; i<m.size(); i++) {
321 bool mIsRe = std::imag(m[i][i]) == 0;
322 bool mIsNeg = std::real(m[i][i]) < 0;
323 bool pIsRe = std::imag(p) == 0;
324 bool pIsInt = std::trunc(std::real(p)) == std::real(p);
325
326 // use pow(qreal,qreal) or pow(qcomp,qcomp)
327 out[i][i] = (mIsRe && mIsNeg && pIsRe && pIsInt)?
328 qcomp(std::pow(std::real(m[i][i]), std::real(p)),0):
329 std::pow(m[i][i], p);
330 }
331
332 return out;
333}

◆ getProjector() [1/2]

qmatrix getProjector ( int outcome)

Definition at line 400 of file linalg.cpp.

400 {
401 DEMAND( outcome == 0 || outcome == 1 );
402
403 qmatrix out = getZeroMatrix(2);
404 out[outcome][outcome] = 1.;
405 return out;
406}

◆ getProjector() [2/2]

qmatrix getProjector ( vector< int > targets,
vector< int > outcomes,
int numQubits )

Definition at line 409 of file linalg.cpp.

409 {
410 DEMAND( targets.size() == outcomes.size() );
411 DEMAND( numQubits > *std::max_element(targets.begin(), targets.end()) );
412
413 // prepare { |0><0|, I, I, |1><1|, ... }
414 vector<qmatrix> matrices(numQubits, getIdentityMatrix(2));
415 for (size_t i=0; i<targets.size(); i++)
416 matrices[targets[i]] = getProjector(outcomes[i]);
417
418 return getKroneckerProduct(matrices);
419}

◆ getSum() [1/2]

qcomp getSum ( qvector vec)

Definition at line 115 of file linalg.cpp.

115 {
116
117 qcomp sum = qcomp(0,0);
118 qcomp y, t, c=sum;
119
120 // complex Kahan summation
121 for (auto& x : vec) {
122 y = x - c;
123 t = sum + y;
124 c = ( t - sum ) - y;
125 sum = t;
126 }
127
128 return sum;
129}

◆ getSum() [2/2]

qreal getSum ( vector< qreal > vec)

Definition at line 132 of file linalg.cpp.

132 {
133
134 // in = real(vec)
135 qvector in = getZeroVector(vec.size());
136 for (size_t i=0; i<in.size(); i++)
137 in[i] = qcomp(vec[i],0);
138
139 return std::real(getSum(in));
140}

◆ getSuperOperator()

qmatrix getSuperOperator ( vector< qmatrix > matrices)

Definition at line 484 of file linalg.cpp.

484 {
485 DEMAND( matrices.size() > 0 );
486
487 size_t dim = matrices[0].size();
488
489 // out = sum_m conj(m) (x) m
490 qmatrix out = getZeroMatrix(dim * dim);
491 for (auto& matr : matrices)
492 out += getKroneckerProduct(getConjugate(matr), matr);
493
494 return out;
495}

◆ getTrace()

qcomp getTrace ( qmatrix m)

Definition at line 259 of file linalg.cpp.

259 {
260
261 qcomp out = 0;
262 for (size_t r=0; r<m.size(); r++)
263 out += m[r][r];
264
265 return out;
266}

◆ getTranspose()

qmatrix getTranspose ( qmatrix m)

Definition at line 269 of file linalg.cpp.

269 {
270
271 qmatrix out = getZeroMatrix(m.size());
272
273 for (size_t r=0; r<m.size(); r++)
274 for (size_t c=0; c<m.size(); c++)
275 out[r][c] = m[c][r];
276
277 return out;
278}

◆ isApproxCPTP()

bool isApproxCPTP ( vector< qmatrix > matrices)

Definition at line 577 of file linalg.cpp.

577 {
578 DEMAND( matrices.size() >= 1 );
579
580 size_t dim = matrices[0].size();
581 qmatrix id = getIdentityMatrix(dim);
582 qmatrix sum = getZeroMatrix(dim);
583
584 for (auto& m : matrices)
585 sum += getConjugateTranspose(m) * m;
586
587 return doMatricesAgree(sum, id);
588}

◆ isApproxUnitary()

bool isApproxUnitary ( qmatrix m)

Definition at line 250 of file linalg.cpp.

250 {
251
252 // should be identity
253 qmatrix md = m * getConjugateTranspose(m);
254 qmatrix id = getIdentityMatrix(m.size());
255 return doMatricesAgree(md, id);
256}

◆ isDiagonal()

bool isDiagonal ( qmatrix m)

Definition at line 239 of file linalg.cpp.

239 {
240
241 for (size_t r=0; r<m.size(); r++)
242 for (size_t c=0; c<m.size(); c++)
243 if (r!=c && m[r][c] != 0_i)
244 return false;
245
246 return true;
247}

◆ operator*()

qvector operator* ( const qmatrix & m,
const qvector & v )

Definition at line 504 of file linalg.cpp.

504 {
505 DEMAND( m.size() == v.size() );
506
507 qvector out = getZeroVector(v.size());
508
509 for (size_t r=0; r<v.size(); r++)
510 for (size_t c=0; c<v.size(); c++)
511 out[r] += m[r][c] * v[c];
512
513 return out;
514}

◆ setBitAt()

qindex setBitAt ( qindex num,
int ind,
int bit )

Definition at line 79 of file linalg.cpp.

79 {
80 DEMAND( num >= 0 );
81
82 qindex one = 1;
83 return (num & ~(one << ind)) | (bit << ind);
84}

◆ setBitsAt()

qindex setBitsAt ( qindex num,
vector< int > inds,
qindex bits )

Definition at line 87 of file linalg.cpp.

87 {
88
89 for (size_t i=0; i<inds.size(); i++)
90 num = setBitAt(num, inds[i], getBitAt(bits, i));
91
92 return num;
93}