* @note circuits is reversible, so it's one to one * input positive 0 or negative 0, output are both postivie 0, so ancil is different for reversibility */
| 117 | * input positive 0 or negative 0, output are both postivie 0, so ancil is different for reversibility |
| 118 | */ |
| 119 | QCircuit QComplement_V2(QVec &a, QVec &aux) |
| 120 | { |
| 121 | /* |
| 122 | we proposed circute for two's complement based on QCLA adder |
| 123 | filp a then add one bit b_0 which is |1>, if a is negative, otherwise keep not changed |
| 124 | */ |
| 125 | /* aux should be |0...0>, not checked here */ |
| 126 | /* highest bit of a is sign */ |
| 127 | QVec unsign_a(a.begin(), a.end() - 1); |
| 128 | Qubit *sign = a.back(); |
| 129 | |
| 130 | int n = a.size(); |
| 131 | |
| 132 | /* sizeof(z) = n, sizeof(x) = n - log n, total auxiliary size at least 2 * n + 1 - log2(n) */ |
| 133 | std::stringstream error_msg("auxiliary bits size should at leat 2 * n + 1 - std::floor(std::log2(n)) = "); |
| 134 | error_msg << int(2 * n - std::floor(std::log2(n))); |
| 135 | QPANDA_ASSERT(aux.size() < int(2 * n - std::floor(std::log2(n))), error_msg.str()); |
| 136 | |
| 137 | /* |
| 138 | z[i+1] = g[i, i + 1] |
| 139 | a[i] = p[i, i + 1] for i > 0 |
| 140 | x for ancillary space to save p[i,j], j>i+1 |
| 141 | */ |
| 142 | QVec z(aux.begin(), aux.begin() + n); |
| 143 | QVec x(aux.begin() + n, aux.begin() + int(2 * n - std::floor(std::log2(n)))); |
| 144 | |
| 145 | /* resue z[0] as b_0 */ |
| 146 | Qubit *b_0 = z[0]; |
| 147 | |
| 148 | DraperQCLAAdder::Propagate p(a, x); |
| 149 | |
| 150 | QCircuit qc; |
| 151 | /* |
| 152 | step 0: |
| 153 | 1. set b_0 |1>, if sign negative |
| 154 | 2. flip bits of unsign_a, if sign negative |
| 155 | */ |
| 156 | qc << X(b_0).control(sign); |
| 157 | for (int i = 0; i < unsign_a.size(); i++) |
| 158 | { |
| 159 | qc << X(unsign_a[i]).control(sign); |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | QCLA algorithm |
| 164 | step 1: |
| 165 | g[0,1] = (a[0] * b_0) ⊕ g[0,1] |
| 166 | */ |
| 167 | if (1 < n) |
| 168 | qc << X(z[1]).control({a[0], b_0}); |
| 169 | |
| 170 | /* |
| 171 | step 2: |
| 172 | add b_0 to a_0 |
| 173 | this sets a[i] = p[i, i+1] |
| 174 | */ |
| 175 | qc << CNOT(b_0, a[0]); |
| 176 |