| 115 | |
| 116 | |
| 117 | qmatrix getFullStateOperator(vector<int> ctrls, vector<int> ctrlStates, vector<int> targs, qmatrix matrix, size_t numQubits) { |
| 118 | DEMAND( numQubits >= ctrls.size() + targs.size() ); |
| 119 | DEMAND( getPow2(targs.size()) == (qindex) matrix.size() ); |
| 120 | DEMAND( (ctrlStates.empty() || ctrlStates.size() == ctrls.size()) ); |
| 121 | |
| 122 | // construct controlled-(matrix) upon lowest order qubits |
| 123 | qmatrix full = getControlledMatrix(matrix, ctrls.size()); |
| 124 | |
| 125 | // left-pad 'full' to be numQubits large |
| 126 | if (numQubits > ctrls.size() + targs.size()) { |
| 127 | size_t pad = getPow2(numQubits - ctrls.size() - targs.size()); |
| 128 | full = getKroneckerProduct(getIdentityMatrix(pad), full); |
| 129 | } |
| 130 | |
| 131 | // apply swaps to retarget 'full' to given ctrls and targs |
| 132 | auto [swaps, unswaps] = getSwapAndUnswapMatrices(ctrls, targs, numQubits); |
| 133 | qmatrix out = unswaps * full * swaps; |
| 134 | |
| 135 | // apply NOT to all zero-controlled qubits (recurses just once) |
| 136 | qmatrix matrX = {{0,1},{1,0}}; |
| 137 | for (size_t i=0; i<ctrlStates.size(); i++) { |
| 138 | |
| 139 | if (ctrlStates[i] == 1) |
| 140 | continue; |
| 141 | |
| 142 | qmatrix fullX = getFullStateOperator({}, {}, {ctrls[i]}, matrX, numQubits); |
| 143 | out = fullX * out * fullX; |
| 144 | } |
| 145 | |
| 146 | return out; |
| 147 | } |
| 148 | |
| 149 | |
| 150 |
no test coverage detected