| 26 | |
| 27 | |
| 28 | qmatrix getSwapMatrix(int qb1, int qb2, int numQb) { |
| 29 | DEMAND( numQb > 1 ); |
| 30 | DEMAND( (qb1 >= 0 && qb1 < numQb) ); |
| 31 | DEMAND( (qb2 >= 0 && qb2 < numQb) ); |
| 32 | |
| 33 | if (qb1 == qb2) |
| 34 | return getIdentityMatrix(getPow2(numQb)); |
| 35 | |
| 36 | if (qb1 > qb2) |
| 37 | std::swap(qb1, qb2); |
| 38 | |
| 39 | qmatrix out; |
| 40 | |
| 41 | // qubits are either adjacent |
| 42 | if (qb2 == qb1 + 1) { |
| 43 | out = qmatrix{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}}; |
| 44 | |
| 45 | // or distant |
| 46 | } else { |
| 47 | int block = getPow2(qb2 - qb1); |
| 48 | out = getZeroMatrix(block*2); |
| 49 | qmatrix iden = getIdentityMatrix(block/2); |
| 50 | |
| 51 | // Lemma 3.1 of arxiv.org/pdf/1711.09765.pdf |
| 52 | qmatrix p0{{1,0},{0,0}}; |
| 53 | qmatrix l0{{0,1},{0,0}}; |
| 54 | qmatrix l1{{0,0},{1,0}}; |
| 55 | qmatrix p1{{0,0},{0,1}}; |
| 56 | |
| 57 | // notating a^(n+1) = identity(getPow2(n)) (otimes) a, we construct the matrix |
| 58 | // [ p0^(N) l1^N ] |
| 59 | // [ l0^(N) p1^N ] |
| 60 | // where N = qb2 - qb1 */ |
| 61 | setSubMatrix(out, getKroneckerProduct(iden, p0), 0, 0); |
| 62 | setSubMatrix(out, getKroneckerProduct(iden, l0), block, 0); |
| 63 | setSubMatrix(out, getKroneckerProduct(iden, l1), 0, block); |
| 64 | setSubMatrix(out, getKroneckerProduct(iden, p1), block, block); |
| 65 | } |
| 66 | |
| 67 | // pad swap with outer identities |
| 68 | if (qb1 > 0) |
| 69 | out = getKroneckerProduct(out, getIdentityMatrix(getPow2(qb1))); |
| 70 | |
| 71 | if (qb2 < numQb-1) |
| 72 | out = getKroneckerProduct(getIdentityMatrix(getPow2(numQb-qb2-1)), out); |
| 73 | |
| 74 | return out; |
| 75 | } |
| 76 | |
| 77 | |
| 78 | auto getSwapAndUnswapMatrices(vector<int> ctrls, vector<int> targs, size_t numQubits) { |
no test coverage detected