The Quantum Exact Simulation Toolkit v4.3.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 getDiscreteFourierTransform (qvector in, bool inverse)
 
qvector getDiscreteFourierTransform (qvector in, vector< int > targs, bool inverse)
 
qmatrix getExponentialOfDiagonalMatrix (qmatrix)
 
qmatrix getExponentialOfNormalisedPauliVector (qreal arg, qreal x, qreal y, qreal z)
 
qmatrix getExponentialOfPauliMatrix (qcomp 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)
 
qindex 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 48 of file linalg.cpp.

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

◆ getBits()

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

Definition at line 55 of file linalg.cpp.

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

◆ getBitsAt()

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

Definition at line 68 of file linalg.cpp.

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

◆ getConjugate()

qmatrix getConjugate ( qmatrix m)

Definition at line 283 of file linalg.cpp.

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

◆ getConjugateTranspose()

qmatrix getConjugateTranspose ( qmatrix m)

Definition at line 293 of file linalg.cpp.

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

◆ getControlledMatrix()

qmatrix getControlledMatrix ( qmatrix matrix,
int numCtrls )

Definition at line 453 of file linalg.cpp.

453 {
454
455 size_t dim = getPow2(numCtrls) * matrix.size();
456 size_t off = dim - matrix.size();
457
458 qmatrix out = getIdentityMatrix(dim);
459 setSubMatrix(out, matrix, off, off);
460
461 return out;
462}
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

◆ getDiscreteFourierTransform() [1/2]

qvector getDiscreteFourierTransform ( qvector in,
bool inverse )

Definition at line 162 of file linalg.cpp.

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

◆ getDiscreteFourierTransform() [2/2]

qvector getDiscreteFourierTransform ( qvector in,
vector< int > targs,
bool inverse )

Definition at line 181 of file linalg.cpp.

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

◆ getExponentialOfDiagonalMatrix()

qmatrix getExponentialOfDiagonalMatrix ( qmatrix m)

Definition at line 338 of file linalg.cpp.

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

◆ getExponentialOfNormalisedPauliVector()

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

Definition at line 359 of file linalg.cpp.

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

◆ getExponentialOfPauliMatrix()

qmatrix getExponentialOfPauliMatrix ( qcomp arg,
qmatrix pauli )

Definition at line 350 of file linalg.cpp.

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

◆ getInnerProduct()

qcomp getInnerProduct ( qvector bra,
qvector ket )

Definition at line 210 of file linalg.cpp.

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

◆ getKroneckerProduct() [1/3]

qmatrix getKroneckerProduct ( qmatrix m,
int count )

Definition at line 561 of file linalg.cpp.

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

◆ getKroneckerProduct() [2/3]

qmatrix getKroneckerProduct ( qmatrix a,
qmatrix b )

Definition at line 525 of file linalg.cpp.

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

◆ getKroneckerProduct() [3/3]

qmatrix getKroneckerProduct ( vector< qmatrix > matrices)

Definition at line 549 of file linalg.cpp.

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

◆ getLog2()

int getLog2 ( qindex a)

Definition at line 29 of file linalg.cpp.

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

◆ getMixture() [1/2]

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

Definition at line 465 of file linalg.cpp.

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

◆ getMixture() [2/2]

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

Definition at line 476 of file linalg.cpp.

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

◆ getNormalised()

qvector getNormalised ( qvector vec)

Definition at line 145 of file linalg.cpp.

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

◆ getNumPermutations()

qindex getNumPermutations ( int n,
int k )

Definition at line 97 of file linalg.cpp.

97 {
98 DEMAND( n >= k );
99
100 constexpr auto max = std::numeric_limits<qindex>::max();
101
102 // P(n, k) = n! / (n-k)!
103 qindex p = 1;
104 for (int t=n-k+1; t<=n; t++)
105 p *= (p < max / t)? t : 0; // set to 0 on overflow
106
107 return p;
108}

◆ getOrthonormalisedRows()

qmatrix getOrthonormalisedRows ( qmatrix matr)

Definition at line 377 of file linalg.cpp.

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

◆ getOuterProduct()

qmatrix getOuterProduct ( qvector ket,
qvector bra )

Definition at line 222 of file linalg.cpp.

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

◆ getPartialTrace()

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

Definition at line 424 of file linalg.cpp.

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

◆ getPow2()

qindex getPow2 ( int a)

Definition at line 41 of file linalg.cpp.

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

◆ getPowerOfDiagonalMatrix()

qmatrix getPowerOfDiagonalMatrix ( qmatrix diag,
qcomp power )

Definition at line 311 of file linalg.cpp.

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

◆ getProjector() [1/2]

qmatrix getProjector ( int outcome)

Definition at line 402 of file linalg.cpp.

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

◆ getProjector() [2/2]

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

Definition at line 411 of file linalg.cpp.

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

◆ getSum() [1/2]

qcomp getSum ( qvector vec)

Definition at line 117 of file linalg.cpp.

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

◆ getSum() [2/2]

qreal getSum ( vector< qreal > vec)

Definition at line 134 of file linalg.cpp.

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

◆ getSuperOperator()

qmatrix getSuperOperator ( vector< qmatrix > matrices)

Definition at line 486 of file linalg.cpp.

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

◆ getTrace()

qcomp getTrace ( qmatrix m)

Definition at line 261 of file linalg.cpp.

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

◆ getTranspose()

qmatrix getTranspose ( qmatrix m)

Definition at line 271 of file linalg.cpp.

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

◆ isApproxCPTP()

bool isApproxCPTP ( vector< qmatrix > matrices)

Definition at line 579 of file linalg.cpp.

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

◆ isApproxUnitary()

bool isApproxUnitary ( qmatrix m)

Definition at line 252 of file linalg.cpp.

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

◆ isDiagonal()

bool isDiagonal ( qmatrix m)

Definition at line 241 of file linalg.cpp.

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

◆ operator*()

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

Definition at line 506 of file linalg.cpp.

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

◆ setBitAt()

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

Definition at line 80 of file linalg.cpp.

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

◆ setBitsAt()

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

Definition at line 88 of file linalg.cpp.

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