microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cd67b36992d2ea20ba330acb56e2e9ac04c11938

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

library/std/arithmetic.qs

292lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4namespace 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