microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
library/std/arithmetic.qs
292lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | namespace Microsoft.Quantum.Arithmetic { |
| 5 | open Microsoft.Quantum.Canon; |
| 6 | open Microsoft.Quantum.Arrays; |
| 7 | open Microsoft.Quantum.Diagnostics; |
| 8 | open Microsoft.Quantum.Measurement; |
| 9 | |
| 10 | /// # Summary |
| 11 | /// Applies a bitwise-XOR operation between a classical integer and an |
| 12 | /// integer represented by a register of qubits. |
| 13 | /// |
| 14 | /// # Description |
| 15 | /// Applies `X` operations to qubits in a little-endian register based on |
| 16 | /// 1 bits in an integer. |
| 17 | /// |
| 18 | /// Let us denote `value` by a and let y be an unsigned integer encoded in `target`, |
| 19 | /// then `ApplyXorInPlace` performs an operation given by the following map: |
| 20 | /// $\ket{y}\rightarrow \ket{y\oplus a}$ , where $\oplus$ is the bitwise exclusive OR operator. |
| 21 | operation ApplyXorInPlace(value : Int, target : Qubit[]) : Unit is Adj+Ctl { |
| 22 | body(...) { |
| 23 | Fact(value >= 0, "value must be non-negative"); |
| 24 | mutable runningValue = value; |
| 25 | for q in target { |
| 26 | if (runningValue &&& 1) != 0 { |
| 27 | X(q); |
| 28 | } |
| 29 | set runningValue >>>= 1; |
| 30 | } |
| 31 | Fact(runningValue == 0, "value is too large"); |
| 32 | } |
| 33 | adjoint self; |
| 34 | } |
| 35 | |
| 36 | /// # Summary |
| 37 | /// Measures the content of a quantum register and converts |
| 38 | /// it to an integer. The measurement is performed with respect |
| 39 | /// to the standard computational basis, i.e., the eigenbasis of `PauliZ`. |
| 40 | /// |
| 41 | /// # Input |
| 42 | /// ## target |
| 43 | /// A quantum register in the little-endian encoding. |
| 44 | /// |
| 45 | /// # Output |
| 46 | /// An unsigned integer that contains the measured value of `target`. |
| 47 | /// |
| 48 | /// # Remarks |
| 49 | /// This operation resets its input register to the |00...0> state, |
| 50 | /// suitable for releasing back to a target machine. |
| 51 | @Config(Full) |
| 52 | operation MeasureInteger(target: Qubit[]): Int { |
| 53 | let nBits = Length(target); |
| 54 | Fact(nBits < 64, $"`Length(target)` must be less than 64, but was {nBits}."); |
| 55 | |
| 56 | mutable number = 0; |
| 57 | for i in 0..nBits-1 { |
| 58 | if (MResetZ(target[i]) == One) { |
| 59 | set number |||= 1 <<< i; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | number |
| 64 | } |
| 65 | |
| 66 | /// # Summary |
| 67 | /// Automatically chooses between addition with |
| 68 | /// carry and without, depending on the register size of `ys`, |
| 69 | /// which holds the result after operation is complete. |
| 70 | operation AddI (xs: Qubit[], ys: Qubit[]) : Unit is Adj + Ctl { |
| 71 | if Length(xs) == Length(ys) { |
| 72 | RippleCarryAdderNoCarryTTK(xs, ys); |
| 73 | } |
| 74 | elif Length(ys) > Length(xs) { |
| 75 | use qs = Qubit[Length(ys) - Length(xs) - 1]; |
| 76 | RippleCarryAdderTTK(xs + qs, Most(ys), Tail(ys)); |
| 77 | } |
| 78 | else { |
| 79 | fail "xs must not contain more qubits than ys!"; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /// # Summary |
| 84 | /// Reversible, in-place ripple-carry addition of two integers without carry out. |
| 85 | /// |
| 86 | /// # Description |
| 87 | /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, |
| 88 | /// the operation computes the sum of the two integers modulo $2^n$, |
| 89 | /// where $n$ is the length of the inputs arrays `xs` and `ys`, |
| 90 | /// which must be positive. It does not compute the carry out bit. |
| 91 | /// |
| 92 | /// # Input |
| 93 | /// ## xs |
| 94 | /// LittleEndian qubit register encoding the first integer summand. |
| 95 | /// ## ys |
| 96 | /// LittleEndian qubit register encoding the second integer summand, is |
| 97 | /// modified to hold the $n$ least significant bits of the sum. |
| 98 | /// |
| 99 | /// # References |
| 100 | /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum |
| 101 | /// Addition Circuits and Unbounded Fan-Out", Quantum Information and |
| 102 | /// Computation, Vol. 10, 2010. |
| 103 | /// https://arxiv.org/abs/0910.2530 |
| 104 | /// |
| 105 | /// # Remarks |
| 106 | /// This operation has the same functionality as RippleCarryAdderTTK but does |
| 107 | /// not return the carry bit. |
| 108 | operation RippleCarryAdderNoCarryTTK(xs : Qubit[], ys : Qubit[]) |
| 109 | : Unit is Adj + Ctl { |
| 110 | Fact(Length(xs) == Length(ys), |
| 111 | "Input registers must have the same number of qubits." ); |
| 112 | Fact(Length(xs) > 0, "Array should not be empty."); |
| 113 | |
| 114 | if (Length(xs) > 1) { |
| 115 | within { |
| 116 | ApplyOuterTTKAdder(xs, ys); |
| 117 | } apply { |
| 118 | ApplyInnerTTKAdderWithoutCarry(xs, ys); |
| 119 | } |
| 120 | } |
| 121 | CNOT (xs[0], ys[0]); |
| 122 | } |
| 123 | |
| 124 | /// # Summary |
| 125 | /// Reversible, in-place ripple-carry addition of two integers. |
| 126 | /// |
| 127 | /// # Description |
| 128 | /// Given two $n$-bit integers encoded in LittleEndian registers `xs` and `ys`, |
| 129 | /// and a qubit carry, the operation computes the sum of the two integers |
| 130 | /// where the $n$ least significant bits of the result are held in `ys` and |
| 131 | /// the carry out bit is xored to the qubit `carry`. |
| 132 | /// |
| 133 | /// # Input |
| 134 | /// ## xs |
| 135 | /// LittleEndian qubit register encoding the first integer summand. |
| 136 | /// ## ys |
| 137 | /// LittleEndian qubit register encoding the second integer summand, is |
| 138 | /// modified to hold the $n$ least significant bits of the sum. |
| 139 | /// ## carry |
| 140 | /// Carry qubit, is xored with the carry out bit of the addition. |
| 141 | /// |
| 142 | /// # References |
| 143 | /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum |
| 144 | /// Addition Circuits and Unbounded Fan-Out", Quantum Information and |
| 145 | /// Computation, Vol. 10, 2010. |
| 146 | /// https://arxiv.org/abs/0910.2530 |
| 147 | /// |
| 148 | /// # Remarks |
| 149 | /// This operation has the same functionality as RippleCarryAdderD and, |
| 150 | /// RippleCarryAdderCDKM but does not use any ancilla qubits. |
| 151 | operation RippleCarryAdderTTK(xs : Qubit[], ys : Qubit[], carry : Qubit) |
| 152 | : Unit is Adj + Ctl { |
| 153 | Fact(Length(xs) == Length(ys), |
| 154 | "Input registers must have the same number of qubits." ); |
| 155 | Fact(Length(xs) > 0, "Array should not be empty."); |
| 156 | |
| 157 | |
| 158 | if (Length(xs) > 1) { |
| 159 | CNOT(xs[Length(xs)-1], carry); |
| 160 | within { |
| 161 | ApplyOuterTTKAdder(xs, ys); |
| 162 | } apply { |
| 163 | ApplyInnerTTKAdder(xs, ys, carry); |
| 164 | } |
| 165 | } |
| 166 | else { |
| 167 | CCNOT(xs[0], ys[0], carry); |
| 168 | } |
| 169 | CNOT(xs[0], ys[0]); |
| 170 | } |
| 171 | |
| 172 | /// # Summary |
| 173 | /// Implements the outer operation for RippleCarryAdderTTK to conjugate |
| 174 | /// the inner operation to construct the full adder. Input registers |
| 175 | /// must be of the same size. |
| 176 | /// |
| 177 | /// # Input |
| 178 | /// ## xs |
| 179 | /// LittleEndian qubit register encoding the first integer summand |
| 180 | /// input to RippleCarryAdderTTK. |
| 181 | /// ## ys |
| 182 | /// LittleEndian qubit register encoding the second integer summand |
| 183 | /// input to RippleCarryAdderTTK. |
| 184 | /// |
| 185 | /// # References |
| 186 | /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum |
| 187 | /// Addition Circuits and Unbounded Fan-Out", Quantum Information and |
| 188 | /// Computation, Vol. 10, 2010. |
| 189 | /// https://arxiv.org/abs/0910.2530 |
| 190 | internal operation ApplyOuterTTKAdder(xs : Qubit[], ys : Qubit[]) |
| 191 | : Unit is Adj + Ctl { |
| 192 | Fact(Length(xs) == Length(ys), |
| 193 | "Input registers must have the same number of qubits." ); |
| 194 | for i in 1..Length(xs)-1 { |
| 195 | CNOT(xs[i], ys[i]); |
| 196 | } |
| 197 | for i in Length(xs)-2..-1..1 { |
| 198 | CNOT(xs[i], xs[i+1]); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | /// # Summary |
| 203 | /// Implements the inner addition function for the operation |
| 204 | /// RippleCarryAdderNoCarryTTK. This is the inner operation that is conjugated |
| 205 | /// with the outer operation to construct the full adder. |
| 206 | /// |
| 207 | /// # Input |
| 208 | /// ## xs |
| 209 | /// LittleEndian qubit register encoding the first integer summand |
| 210 | /// input to RippleCarryAdderNoCarryTTK. |
| 211 | /// ## ys |
| 212 | /// LittleEndian qubit register encoding the second integer summand |
| 213 | /// input to RippleCarryAdderNoCarryTTK. |
| 214 | /// |
| 215 | /// # References |
| 216 | /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum |
| 217 | /// Addition Circuits and Unbounded Fan-Out", Quantum Information and |
| 218 | /// Computation, Vol. 10, 2010. |
| 219 | /// https://arxiv.org/abs/0910.2530 |
| 220 | /// |
| 221 | /// # Remarks |
| 222 | /// The specified controlled operation makes use of symmetry and mutual |
| 223 | /// cancellation of operations to improve on the default implementation |
| 224 | /// that adds a control to every operation. |
| 225 | internal operation ApplyInnerTTKAdderWithoutCarry(xs : Qubit[], ys : Qubit[]) |
| 226 | : Unit is Adj + Ctl { |
| 227 | body (...) { |
| 228 | (Controlled ApplyInnerTTKAdderWithoutCarry) ([], (xs, ys)); |
| 229 | } |
| 230 | controlled ( controls, ... ) { |
| 231 | Fact(Length(xs) == Length(ys), |
| 232 | "Input registers must have the same number of qubits." ); |
| 233 | |
| 234 | for idx in 0..Length(xs) - 2 { |
| 235 | CCNOT (xs[idx], ys[idx], xs[idx + 1]); |
| 236 | } |
| 237 | for idx in Length(xs)-1..-1..1 { |
| 238 | Controlled CNOT(controls, (xs[idx], ys[idx])); |
| 239 | CCNOT(xs[idx - 1], ys[idx - 1], xs[idx]); |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | /// # Summary |
| 245 | /// Implements the inner addition function for the operation |
| 246 | /// RippleCarryAdderTTK. This is the inner operation that is conjugated |
| 247 | /// with the outer operation to construct the full adder. |
| 248 | /// |
| 249 | /// # Input |
| 250 | /// ## xs |
| 251 | /// LittleEndian qubit register encoding the first integer summand |
| 252 | /// input to RippleCarryAdderTTK. |
| 253 | /// ## ys |
| 254 | /// LittleEndian qubit register encoding the second integer summand |
| 255 | /// input to RippleCarryAdderTTK. |
| 256 | /// ## carry |
| 257 | /// Carry qubit, is xored with the most significant bit of the sum. |
| 258 | /// |
| 259 | /// # References |
| 260 | /// - Yasuhiro Takahashi, Seiichiro Tani, Noboru Kunihiro: "Quantum |
| 261 | /// Addition Circuits and Unbounded Fan-Out", Quantum Information and |
| 262 | /// Computation, Vol. 10, 2010. |
| 263 | /// https://arxiv.org/abs/0910.2530 |
| 264 | /// |
| 265 | /// # Remarks |
| 266 | /// The specified controlled operation makes use of symmetry and mutual |
| 267 | /// cancellation of operations to improve on the default implementation |
| 268 | /// that adds a control to every operation. |
| 269 | internal operation ApplyInnerTTKAdder(xs : Qubit[], ys : Qubit[], carry : Qubit) |
| 270 | : Unit is Adj + Ctl { |
| 271 | body (...) { |
| 272 | (Controlled ApplyInnerTTKAdder)([], (xs, ys, carry)); |
| 273 | } |
| 274 | controlled ( controls, ... ) { |
| 275 | Fact(Length(xs) == Length(ys), |
| 276 | "Input registers must have the same number of qubits." ); |
| 277 | Fact(Length(xs) > 0, "Array should not be empty."); |
| 278 | |
| 279 | |
| 280 | let nQubits = Length(xs); |
| 281 | for idx in 0..nQubits - 2 { |
| 282 | CCNOT(xs[idx], ys[idx], xs[idx+1]); |
| 283 | } |
| 284 | (Controlled CCNOT)(controls, (xs[nQubits-1], ys[nQubits-1], carry)); |
| 285 | for idx in nQubits - 1..-1..1 { |
| 286 | Controlled CNOT(controls, (xs[idx], ys[idx])); |
| 287 | CCNOT(xs[idx-1], ys[idx-1], xs[idx]); |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | } |
| 293 | |