microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/std/src/Std/Canon.qs

826lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4
5import QIR.Intrinsic.*;
6import Std.Intrinsic.*;
7import Std.Diagnostics.*;
8import Std.Math.*;
9
10/// # Summary
11/// Applies an operation to each element in a register.
12///
13/// # Input
14/// ## singleElementOperation
15/// Operation to apply to each element.
16/// ## register
17/// Array of elements on which to apply the given operation.
18///
19/// # Type Parameters
20/// ## 'T
21/// The target on which the operation acts.
22///
23/// # Example
24/// Prepare a three-qubit |+⟩ state:
25/// ```qsharp
26/// use register = Qubit[3];
27/// ApplyToEach(H, register);
28/// ```
29operation ApplyToEach<'T>(singleElementOperation : ('T => Unit), register : 'T[]) : Unit {
30 for item in register {
31 singleElementOperation(item);
32 }
33}
34
35/// # Summary
36/// Applies an operation to each element in a register.
37/// The modifier `A` indicates that the single-element operation is adjointable.
38///
39/// # Input
40/// ## singleElementOperation
41/// Operation to apply to each element.
42/// ## register
43/// Array of elements on which to apply the given operation.
44///
45/// # Type Parameters
46/// ## 'T
47/// The target on which the operation acts.
48///
49/// # Example
50/// Prepare a three-qubit |+⟩ state:
51/// ```qsharp
52/// use register = Qubit[3];
53/// ApplyToEach(H, register);
54/// ```
55///
56/// # See Also
57/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach)
58operation ApplyToEachA<'T>(singleElementOperation : ('T => Unit is Adj), register : 'T[]) : Unit is Adj {
59 for item in register {
60 singleElementOperation(item);
61 }
62}
63
64/// # Summary
65/// Applies an operation to each element in a register.
66/// The modifier `C` indicates that the single-element operation is controllable.
67///
68/// # Input
69/// ## singleElementOperation
70/// Operation to apply to each element.
71/// ## register
72/// Array of elements on which to apply the given operation.
73///
74/// # Type Parameters
75/// ## 'T
76/// The target on which the operation acts.
77///
78/// # Example
79/// Prepare a three-qubit |+⟩ state:
80/// ```qsharp
81/// use register = Qubit[3];
82/// ApplyToEach(H, register);
83/// ```
84///
85/// # See Also
86/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach)
87operation ApplyToEachC<'T>(singleElementOperation : ('T => Unit is Ctl), register : 'T[]) : Unit is Ctl {
88 for item in register {
89 singleElementOperation(item);
90 }
91}
92
93/// # Summary
94/// Applies an operation to each element in a register.
95/// The modifier `CA` indicates that the single-element operation is controllable and adjointable.
96///
97/// # Input
98/// ## singleElementOperation
99/// Operation to apply to each element.
100/// ## register
101/// Array of elements on which to apply the given operation.
102///
103/// # Type Parameters
104/// ## 'T
105/// The target on which the operation acts.
106///
107/// # Example
108/// Prepare a three-qubit |+⟩ state:
109/// ```qsharp
110/// use register = Qubit[3];
111/// ApplyToEach(H, register);
112/// ```
113///
114/// # See Also
115/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach)
116operation ApplyToEachCA<'T>(singleElementOperation : ('T => Unit is Adj + Ctl), register : 'T[]) : Unit is Adj + Ctl {
117 for item in register {
118 singleElementOperation(item);
119 }
120}
121
122/// # Summary
123/// Applies the controlled-X (CX) gate to a pair of qubits.
124///
125/// # Input
126/// ## control
127/// Control qubit for the CX gate.
128/// ## target
129/// Target qubit for the CX gate.
130///
131/// # Remarks
132/// This operation can be simulated by the unitary matrix
133/// $$
134/// \begin{align}
135/// \left(\begin{matrix}
136/// 1 & 0 & 0 & 0 \\\\
137/// 0 & 1 & 0 & 0 \\\\
138/// 0 & 0 & 0 & 1 \\\\
139/// 0 & 0 & 1 & 0
140/// \end{matrix}\right)
141/// \end{align},
142/// $$
143/// where rows and columns are organized as in the quantum concepts guide.
144///
145/// Equivalent to:
146/// ```qsharp
147/// Controlled X([control], target);
148/// ```
149/// and to:
150/// ```qsharp
151/// CNOT(control, target);
152/// ```
153operation CX(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
154 body ... {
155 __quantum__qis__cx__body(control, target);
156 }
157 controlled (ctls, ...) {
158 Controlled X(ctls + [control], target);
159 }
160 adjoint self;
161}
162
163/// # Summary
164/// Applies the controlled-Y (CY) gate to a pair of qubits.
165///
166/// # Input
167/// ## control
168/// Control qubit for the CY gate.
169/// ## target
170/// Target qubit for the CY gate.
171///
172/// # Remarks
173/// This operation can be simulated by the unitary matrix
174/// $$
175/// \begin{align}
176/// \left(\begin{matrix}
177/// 1 & 0 & 0 & 0 \\\\
178/// 0 & 1 & 0 & 0 \\\\
179/// 0 & 0 & 0 & -i \\\\
180/// 0 & 0 & i & 0
181/// \end{matrix}\right)
182/// \end{align},
183/// $$
184/// where rows and columns are organized as in the quantum concepts guide.
185///
186/// Equivalent to:
187/// ```qsharp
188/// Controlled Y([control], target);
189/// ```
190operation CY(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
191 body ... {
192 __quantum__qis__cy__body(control, target);
193 }
194 controlled (ctls, ...) {
195 Controlled Y(ctls + [control], target);
196 }
197 adjoint self;
198}
199
200/// # Summary
201/// Applies the controlled-Z (CZ) gate to a pair of qubits.
202///
203/// # Input
204/// ## control
205/// Control qubit for the CZ gate.
206/// ## target
207/// Target qubit for the CZ gate.
208///
209/// # Remarks
210/// This operation can be simulated by the unitary matrix
211/// $$
212/// \begin{align}
213/// \left(\begin{matrix}
214/// 1 & 0 & 0 & 0 \\\\
215/// 0 & 1 & 0 & 0 \\\\
216/// 0 & 0 & 1 & 0 \\\\
217/// 0 & 0 & 0 & -1
218/// \end{matrix}\right)
219/// \end{align},
220/// $$
221/// where rows and columns are organized as in the quantum concepts guide.
222///
223/// Equivalent to:
224/// ```qsharp
225/// Controlled Z([control], target);
226/// ```
227operation CZ(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
228 body ... {
229 __quantum__qis__cz__body(control, target);
230 }
231 controlled (ctls, ...) {
232 Controlled Z(ctls + [control], target);
233 }
234 adjoint self;
235}
236
237/// Given a pair, returns its first element.
238function Fst<'T, 'U>(pair : ('T, 'U)) : 'T {
239 let (fst, _) = pair;
240 return fst;
241}
242
243/// Given a pair, returns its second element.
244function Snd<'T, 'U>(pair : ('T, 'U)) : 'U {
245 let (_, snd) = pair;
246 return snd;
247}
248
249/// # Summary
250/// Computes the parity of a register of qubits in-place.
251///
252/// # Input
253/// ## qubits
254/// Array of qubits whose parity is to be computed and stored.
255///
256/// # Remarks
257/// This operation transforms the state of its input as
258/// $$
259/// \begin{align}
260/// \ket{q_0} \ket{q_1} \cdots \ket{q_{n - 1}} & \mapsto
261/// \ket{q_0} \ket{q_0 \oplus q_1} \ket{q_0 \oplus q_1 \oplus q_2} \cdots
262/// \ket{q_0 \oplus \cdots \oplus q_{n - 1}}.
263/// \end{align}
264/// $$
265operation ApplyCNOTChain(qubits : Qubit[]) : Unit is Adj + Ctl {
266 for i in 0..Length(qubits) - 2 {
267 CNOT(qubits[i], qubits[i + 1]);
268 }
269}
270
271/// # Summary
272/// Given a single-qubit Pauli operator, applies the corresponding operation
273/// to a single qubit.
274///
275/// # Input
276/// ## pauli
277/// The Pauli operator to be applied.
278/// ## target
279/// The qubit to which `pauli` is to be applied as an operation.
280///
281/// # Example
282/// The following are equivalent:
283/// ```qsharp
284/// ApplyP(PauliX, q);
285/// ```
286/// and
287/// ```qsharp
288/// X(q);
289/// ```
290operation ApplyP(pauli : Pauli, target : Qubit) : Unit is Adj + Ctl {
291 if pauli == PauliX { X(target); } elif pauli == PauliY { Y(target); } elif pauli == PauliZ { Z(target); }
292}
293
294/// # Summary
295/// Given a multi-qubit Pauli operator, applies the corresponding operation
296/// to a quantum register.
297///
298/// # Input
299/// ## pauli
300/// A multi-qubit Pauli operator represented as an array of single-qubit Pauli operators.
301/// ## target
302/// Register to apply the given Pauli operation on.
303///
304/// # Example
305/// The following are equivalent:
306/// ```qsharp
307/// ApplyPauli([PauliY, PauliZ, PauliX], target);
308/// ```
309/// and
310/// ```qsharp
311/// Y(target[0]);
312/// Z(target[1]);
313/// X(target[2]);
314/// ```
315operation ApplyPauli(pauli : Pauli[], target : Qubit[]) : Unit is Adj + Ctl {
316 Fact(Length(pauli) == Length(target), "`pauli` and `target` must be of the same length.");
317 for i in 0..Length(pauli) - 1 {
318 ApplyP(pauli[i], target[i]);
319 }
320}
321
322/// # Summary
323/// Applies a Pauli operator on each qubit in an array if the corresponding
324/// bit of a Boolean array matches a given input.
325///
326/// # Input
327/// ## pauli
328/// Pauli operator to apply to `qubits[idx]` where `bitApply == bits[idx]`
329/// ## bitApply
330/// apply Pauli if bit is this value
331/// ## bits
332/// Boolean register specifying which corresponding qubit in `qubits` should be operated on
333/// ## qubits
334/// Quantum register on which to selectively apply the specified Pauli operator
335///
336/// # Remarks
337/// The Boolean array and the quantum register must be of equal length.
338///
339/// # Example
340/// The following applies an X operation on qubits 0 and 2, and a Z operation on qubits 1 and 3.
341/// ```qsharp
342/// use qubits = Qubit[4];
343/// let bits = [true, false, true, false];
344/// // Apply when index in `bits` is `true`.
345/// ApplyPauliFromBitString(PauliX, true, bits, qubits);
346/// // Apply when index in `bits` is `false`.
347/// ApplyPauliFromBitString(PauliZ, false, bits, qubits);
348/// ```
349operation ApplyPauliFromBitString(pauli : Pauli, bitApply : Bool, bits : Bool[], qubits : Qubit[]) : Unit is Adj + Ctl {
350 let nBits = Length(bits);
351 Fact(nBits == Length(qubits), "Number of bits must be equal to number of qubits.");
352 for i in 0..nBits - 1 {
353 if bits[i] == bitApply {
354 ApplyP(pauli, qubits[i]);
355 }
356 }
357}
358
359/// # Summary
360/// Applies a Pauli operator on each qubit in an array if the corresponding
361/// bit of a Little-endian integer matches a given input.
362///
363/// # Input
364/// ## pauli
365/// Pauli operator to apply to `qubits[idx]` when bit of numberState
366/// in idx position is the same as bitApply.
367/// ## bitApply
368/// apply Pauli if bit is this value
369/// ## numberState
370/// Little-endian integer specifying which corresponding qubit in `qubits` should be operated on
371/// ## qubits
372/// Quantum register on which to selectively apply the specified Pauli operator
373///
374/// # Example
375/// The following applies an X operation on qubits 0 and 2, and a Z operation on qubits 1 and 3.
376/// ```qsharp
377/// use qubits = Qubit[4];
378/// let n = 5;
379/// // Apply when index in `bits` is `true`.
380/// ApplyPauliFromBitString(PauliX, true, n, qubits);
381/// // Apply when index in `bits` is `false`.
382/// ApplyPauliFromBitString(PauliZ, false, n, qubits);
383/// ```
384operation ApplyPauliFromInt(
385 pauli : Pauli,
386 bitApply : Bool,
387 numberState : Int,
388 qubits : Qubit[]
389) : Unit is Adj + Ctl {
390
391 let length = Length(qubits);
392 Fact(numberState >= 0, "number must be non-negative");
393 Fact(BitSizeI(numberState) <= length, "Bit size of numberState must not exceed qubits length");
394
395 for i in 0..length - 1 {
396 // If we assume loop unrolling, 2^i will be optimized to a constant.
397 if ((numberState &&& (1 <<< i)) != 0) == bitApply {
398 ApplyP(pauli, qubits[i]);
399 }
400 }
401}
402
403/// # Summary
404/// Maps a Pauli axis from one direction to another by applying an appropriate Clifford transformation.
405/// For example, use `within MapPauliAxis(PauliZ, PauliX, q)` and perform Z rotation when X rotation is desired.
406///
407/// # Description
408/// This function applies single-qubit Clifford transformations that remap Pauli axes on a Bloch sphere.
409/// These mappings are useful to apply operations known for one Pauli basis in different Pauli bases.
410/// Provide `from` and `to` parameters in terms of a passive transformation. For example,
411/// when a rotation around the X axis is desired and a rotation around the Z axis is available,
412/// the Z axis gets pointed in the direction of the X axis so that the rotation around Z axis can be used.
413/// Out of several transformations that achieve the requested mapping, the one with fewer gates is used.
414///
415/// # Input
416/// ## from
417/// The Pauli axis to map from. Perform subsequent operations on this axis.
418/// ## to
419/// The Pauli axis to map to. Subsequent operations on `from` axis will perform as if they act on this axis.
420/// ## q
421/// The qubit on which the transformation will be applied.
422///
423/// # Remarks
424/// The complete list of possible mappings and a list of gate sequences to achieve them.
425/// For example, a transformation of +X+Y+Z ↦ +X+Z-Y means that the bloch sphere is rotated so that
426/// the X axis remains unchanged, Y axis points in Z direction, and Z axis points in -Y direction.
427/// (Y with direction reversed). Such transformation could be used to achieve PauliZ to PauliY mapping.
428///
429/// +X+Y+Z ↦ +X+Y+Z: I (used when `from` == `to`) \
430/// +X+Y+Z ↦ +Z-Y+X: H (used when mapping Z to X and X to Z) \
431/// +X+Y+Z ↦ +Y+Z+X: S⁻¹H (used when mapping Z to Y) \
432/// +X+Y+Z ↦ +Z+X+Y: HS (used when mapping Y to Z) \
433/// +X+Y+Z ↦ +Y-X+Z: S (used when mapping Y to X) \
434/// +X+Y+Z ↦ -Y+X+Z: S⁻¹ (used when mapping X to Y) \
435/// +X+Y+Z ↦ -X+Z+Y: S⁻¹HS \
436/// +X+Y+Z ↦ -Y-Z+X: SH \
437/// +X+Y+Z ↦ +Y-Z-X: SHZ, S⁻¹HY, YSH, SXH, S⁻¹YH, XS⁻¹H \
438/// +X+Y+Z ↦ -X-Z-Y: SHS⁻¹ \
439/// +X+Y+Z ↦ +X-Y-Z: X \
440/// +X+Y+Z ↦ -Z+X-Y: HXS⁻¹, HSX, ZHS⁻¹, YHS, HYS, HS⁻¹Y \
441/// +X+Y+Z ↦ +X-Z+Y: SHS, HS⁻¹H \
442/// +X+Y+Z ↦ -Y+Z-X: SHY, S⁻¹HZ, YS⁻¹H, SYH, S⁻¹XH, XSH \
443/// +X+Y+Z ↦ -X+Y-Z: Y \
444/// +X+Y+Z ↦ -Z+Y+X: HX, ZH \
445/// +X+Y+Z ↦ -Y-X-Z: YS, SX, S⁻¹Y, XS⁻¹ \
446/// +X+Y+Z ↦ +Y+X-Z: YS⁻¹, SY, S⁻¹X, XS \
447/// +X+Y+Z ↦ +Z+Y-X: XH, HZ \
448/// +X+Y+Z ↦ +X+Z-Y: S⁻¹HS⁻¹, HSH \
449/// +X+Y+Z ↦ -Z-X+Y: HXS, HSY, ZHS, YHS⁻¹, HYS⁻¹, HS⁻¹X \
450/// +X+Y+Z ↦ -X-Y+Z: Z \
451/// +X+Y+Z ↦ -Z-Y-X: YH, HY \
452/// +X+Y+Z ↦ +Z-X-Y: HS⁻¹
453///
454/// # Example
455/// ```qsharp
456/// // The following implements Rx(0.1, q) via Rz.
457/// within {
458/// MapPauliAxis(PauliZ, PauliX, q);
459/// } apply {
460/// Rz(0.1, q);
461/// }
462/// ```
463///
464/// # References
465/// - [Wikipedia: Bloch sphere](https://wikipedia.org/wiki/Bloch_sphere)
466/// - [Wikipedia: Clifford group](https://wikipedia.org/wiki/Clifford_group)
467/// - [Wikipedia: Active and passive transformation](https://wikipedia.org/wiki/Active_and_passive_transformation)
468operation MapPauliAxis(from : Pauli, to : Pauli, q : Qubit) : Unit is Adj + Ctl {
469 if from == to {
470 // +X+Y+Z ↦ +X+Y+Z, No gates are needed.
471 } elif (from == PauliZ and to == PauliX) or (from == PauliX and to == PauliZ) {
472 // +X+Y+Z ↦ +Z-Y+X
473 H(q);
474 } elif from == PauliZ and to == PauliY {
475 // +X+Y+Z ↦ +Y+Z+X
476 Adjoint S(q);
477 H(q);
478 } elif from == PauliY and to == PauliZ {
479 // +X+Y+Z ↦ +Z+X+Y
480 H(q);
481 S(q);
482 } elif from == PauliY and to == PauliX {
483 // +X+Y+Z ↦ +Y-X+Z
484 S(q);
485 } elif from == PauliX and to == PauliY {
486 // +X+Y+Z ↦ -Y+X+Z
487 Adjoint S(q);
488 } else {
489 fail "Unsupported mapping of Pauli axes.";
490 }
491}
492
493/// # Summary
494/// Applies a unitary operation on the target if the control
495/// register state corresponds to a specified nonnegative integer.
496///
497/// # Input
498/// ## numberState
499/// A nonnegative integer on which the operation `oracle` should be
500/// controlled.
501/// ## oracle
502/// A unitary operation to be controlled.
503/// ## target
504/// A target on which to apply `oracle`.
505/// ## controlRegister
506/// A quantum register that controls application of `oracle`.
507///
508/// # Remarks
509/// The value of `numberState` is interpreted using a little-endian encoding.
510///
511/// `numberState` must be at most $2^\texttt{Length(controlRegister)} - 1$.
512/// For example, `numberState = 537` means that `oracle`
513/// is applied if and only if `controlRegister` is in the state $\ket{537}$.
514operation ApplyControlledOnInt<'T>(
515 numberState : Int,
516 oracle : ('T => Unit is Adj + Ctl),
517 controlRegister : Qubit[],
518 target : 'T
519) : Unit is Adj + Ctl {
520
521 within {
522 ApplyPauliFromInt(PauliX, false, numberState, controlRegister);
523 } apply {
524 Controlled oracle(controlRegister, target);
525 }
526}
527
528/// # Summary
529/// Applies `oracle` on `target` when `controlRegister`
530/// is in the state specified by `bits`.
531///
532/// # Description
533/// Applies a unitary operation `oracle` on the `target`, controlled
534/// on a state specified by a given bit mask `bits`.
535/// The bit at `bits[i]` corresponds to qubit at `controlRegister[i]`.
536/// The pattern given by `bits` may be shorter than `controlRegister`,
537/// in which case additional control qubits are ignored (that is, neither
538/// controlled on |0⟩ nor |1⟩).
539/// If `bits` is longer than `controlRegister`, an error is raised.
540///
541/// # Input
542/// ## bits
543/// The bit string to control the given unitary operation on.
544/// ## oracle
545/// The unitary operation to be applied on the target.
546/// ## target
547/// The target to be passed to `oracle` as an input.
548/// ## controlRegister
549/// A quantum register that controls application of `oracle`.
550///
551/// # Example
552/// ```qsharp
553/// // When bits = [1,0,0] oracle is applied if and only if controlRegister
554/// // is in the state |100⟩.
555/// use t = Qubit();
556/// use c = Qubit[3];
557/// X(c[0]);
558/// ApplyControlledOnBitString([true, false, false], X, c, t);
559/// Message($"{M(t)}"); // Prints `One` since oracle `X` was applied.
560/// ```
561operation ApplyControlledOnBitString<'T>(
562 bits : Bool[],
563 oracle : ('T => Unit is Adj + Ctl),
564 controlRegister : Qubit[],
565 target : 'T
566) : Unit is Adj + Ctl {
567
568 // The control register must have enough bits to implement the requested control.
569 Fact(Length(bits) <= Length(controlRegister), "Control register shorter than control pattern.");
570
571 // Use a subregister of the controlled register when
572 // bits is shorter than controlRegister.
573 let controlSubregister = controlRegister[...Length(bits) - 1];
574 within {
575 ApplyPauliFromBitString(PauliX, false, bits, controlSubregister);
576 } apply {
577 Controlled oracle(controlSubregister, target);
578 }
579}
580
581/// # Summary
582/// Applies the rotations of Quantum Fourier Transform (QFT) to a little-endian quantum register.
583///
584/// # Description
585/// Applies the rotations of QFT to a little-endian register `qs` of length n
586/// containing |x₁⟩⊗|x₂⟩⊗…⊗|xₙ⟩. The qs[0] initially contains the
587/// least significant bit xₙ. The state of qs[0] becomes
588/// (|0⟩+𝑒^(2π𝑖[0.xₙ])|1⟩)/sqrt(2) after the operation.
589///
590/// # Input
591/// ## qs
592/// Quantum register in a little-endian format to which the rotations are applied.
593///
594/// # Remarks
595/// Note that this operation applies only the rotations part of the QFT.
596/// To complete the transform, you need to reverse the order of qubits after this operation,
597/// for example, using the operation `SwapReverseRegister`.
598///
599/// # Reference
600/// - [Quantum Fourier transform](https://en.wikipedia.org/wiki/Quantum_Fourier_transform)
601operation ApplyQFT(qs : Qubit[]) : Unit is Adj + Ctl {
602 let length = Length(qs);
603 Fact(length >= 1, "ApplyQFT: Length(qs) must be at least 1.");
604 for i in length - 1..-1..0 {
605 H(qs[i]);
606 for j in 0..i - 1 {
607 Controlled R1Frac([qs[i]], (1, j + 1, qs[i - j - 1]));
608 }
609 }
610}
611
612/// # Summary
613/// Uses SWAP gates to reverse the order of the qubits in a register.
614///
615/// # Input
616/// ## register
617/// The qubits order of which should be reversed using SWAP gates
618operation SwapReverseRegister(register : Qubit[]) : Unit is Adj + Ctl {
619 let length = Length(register);
620 for i in 0..length / 2 - 1 {
621 SWAP(register[i], register[(length - i) - 1]);
622 }
623}
624
625/// # Summary
626/// Applies a bitwise-XOR operation between a classical integer and an
627/// integer represented by a register of qubits.
628///
629/// # Description
630/// Applies `X` operations to qubits in a little-endian register based on
631/// 1 bits in an integer.
632///
633/// Let us denote `value` by a and let y be an unsigned integer encoded in `target`,
634/// then `ApplyXorInPlace` performs an operation given by the following map:
635/// |y⟩ ↦ |y ⊕ a⟩, where ⊕ is the bitwise exclusive OR operator.
636operation ApplyXorInPlace(value : Int, target : Qubit[]) : Unit is Adj + Ctl {
637 body (...) {
638 Fact(value >= 0, "`value` must be non-negative.");
639 mutable runningValue = value;
640 for q in target {
641 if (runningValue &&& 1) != 0 {
642 X(q);
643 }
644 set runningValue >>>= 1;
645 }
646 Fact(runningValue == 0, "value is too large");
647 }
648 adjoint self;
649}
650
651/// # Summary
652/// Applies a bitwise-XOR operation between a classical integer and an
653/// integer represented by a register of qubits.
654///
655/// # Description
656/// Applies `X` operations to qubits in a little-endian register based on
657/// 1 bits in an integer.
658///
659/// Let us denote `value` by a and let y be an unsigned integer encoded in `target`,
660/// then `ApplyXorInPlace` performs an operation given by the following map:
661/// |y⟩ ↦ |y ⊕ a⟩, where ⊕ is the bitwise exclusive OR operator.
662operation ApplyXorInPlaceL(value : BigInt, target : Qubit[]) : Unit is Adj + Ctl {
663 body (...) {
664 Fact(value >= 0L, "`value` must be non-negative.");
665 mutable runningValue = value;
666 for q in target {
667 if (runningValue &&& 1L) != 0L {
668 X(q);
669 }
670 set runningValue >>>= 1;
671 }
672 Fact(runningValue == 0L, "`value` is too large.");
673 }
674 adjoint self;
675}
676
677/// # Summary
678/// Applies operation `op` to the `target` `power` times.
679/// If `power` is negative, the adjoint of `op` is used.
680/// If `power` is 0, the operation `op` is not applied.
681operation ApplyOperationPowerA<'T>(
682 power : Int,
683 op : 'T => Unit is Adj,
684 target : 'T
685) : Unit is Adj {
686 let u = if power >= 0 { op } else { Adjoint op };
687 for _ in 1..AbsI(power) {
688 u(target);
689 }
690}
691
692/// # Summary
693/// Applies operation `op` to the `target` `power` times.
694/// If `power` is negative, the adjoint of `op` is used.
695/// If `power` is 0, the operation `op` is not applied.
696operation ApplyOperationPowerCA<'T>(
697 power : Int,
698 op : 'T => Unit is Ctl + Adj,
699 target : 'T
700) : Unit is Ctl + Adj {
701 let u = if power >= 0 { op } else { Adjoint op };
702 for _ in 1..AbsI(power) {
703 u(target);
704 }
705}
706
707/// # Summary
708/// Performs the quantum phase estimation algorithm for a unitary U represented
709/// by `applyPowerOfU`, and a `targetState`. Returns the phase estimation
710/// in the range of [0, 2π) as a fraction of 2π in the little-endian register `phase`.
711///
712/// # Input
713/// ## applyPowerOfU
714/// An oracle implementing Uᵐ for a unitary U and a given integer power m.
715/// `ApplyOperationPowerCA(_, U, _)` can be used to implement this oracle,
716/// if no better performing implementation is available.
717/// ## targetState
718/// A quantum register acted on by U. When this `targetState` is the eigenstate
719/// of the operator U, the corresponding eigenvalue is estimated.
720/// ## phase
721/// A little-endian quantum register containing the phase estimation result. The phase is
722/// a fraction of 2π represented in binary with q[0] containing 2π/2=π bit, q[1] containing 2π/4=π/2 bit,
723/// q[2] containing 2π/8=π/4 bit, and so on. The length of the register indicates the desired precision.
724/// The phase register is assumed to be in the state |0...0⟩ when the operation is invoked.
725///
726/// # Remarks
727/// All eigenvalues of a unitary operator are of magnitude 1 and therefore can be represented as
728/// $e^{i\phi}$ for some $\phi \in [0, 2\pi)$. Finding the phase of an eigenvalue is therefore
729/// equivalent to finding the eigenvalue itself. Passing the eigenvector as `targetState`
730/// to the phase estimation operation allows finding the eigenvalue to the desired precision
731/// determined by the length of the `phase` register.
732///
733/// # Reference
734/// - [Quantum phase estimation algorithm](https://wikipedia.org/wiki/Quantum_phase_estimation_algorithm)
735///
736/// # See Also
737/// - [Std.Canon.ApplyOperationPowerCA](xref:Qdk.Std.Canon.ApplyOperationPowerCA)
738operation ApplyQPE(
739 applyPowerOfU : (Int, Qubit[]) => Unit is Adj + Ctl,
740 targetState : Qubit[],
741 phase : Qubit[]
742) : Unit is Adj + Ctl {
743
744 let nQubits = Length(phase);
745 ApplyToEachCA(H, phase);
746
747 for i in 0..nQubits - 1 {
748 let power = 2^((nQubits - i) - 1);
749 Controlled applyPowerOfU(
750 phase[i..i],
751 (power, targetState)
752 );
753 }
754
755 Adjoint ApplyQFT(phase);
756}
757
758/// # Summary
759/// Relabels the qubits in the `current` array with the qubits in the `updated` array. The `updated` array
760/// must be a valid permutation of the `current` array.
761///
762/// # Input
763/// ## current
764/// Array of qubits to be relabeled.
765/// ## updated
766/// Array of qubits with which to relabel the `current` array.
767///
768/// # Remarks
769/// This operation is useful when you need to relabel qubits in a way that does not incur any quantum operations.
770/// Note that when compiling for execution on hardware with limited qubit connectivity, this operation
771/// may not result in any changes to qubit adjacency and one or more `SWAP` gates may still be required.
772///
773/// # Example
774/// The following example demonstrates how to relabel qubits in a register:
775/// ```qsharp
776/// use qubits = Qubit[3];
777/// let newOrder = [qubits[2], qubits[0], qubits[1]];
778/// Relabel(qubits, newOrder);
779/// ```
780/// After this operation, any use of `qubits[0]` will refer to the qubit that was originally `qubits[2]`, and so on.
781/// To exchange the labels on two qubits, the virtual equivalent of a `SWAP` gate, you can use the following code:
782/// ```qsharp
783/// use (q0, q1) = (Qubit(), Qubit());
784/// Relabel([q0, q1], [q1, q0]);
785/// ```
786/// Note that the adjoint of this operation effectively changes the order of arguments, such that
787/// `Adjoint Relabel(qubits, newOrder)` is equivalent to `Relabel(newOrder, qubits)`.
788operation Relabel(current : Qubit[], updated : Qubit[]) : Unit is Adj {
789 body ... {
790 PermuteLabels(current, updated);
791 }
792 adjoint ... {
793 PermuteLabels(updated, current);
794 }
795}
796
797operation PermuteLabels(current : Qubit[], updated : Qubit[]) : Unit {
798 body intrinsic;
799}
800
801export
802 ApplyToEach,
803 ApplyToEachA,
804 ApplyToEachC,
805 ApplyToEachCA,
806 CX,
807 CY,
808 CZ,
809 Fst,
810 Snd,
811 ApplyCNOTChain,
812 ApplyP,
813 ApplyPauli,
814 ApplyPauliFromBitString,
815 ApplyPauliFromInt,
816 MapPauliAxis,
817 ApplyControlledOnInt,
818 ApplyControlledOnBitString,
819 ApplyQFT,
820 ApplyQPE,
821 SwapReverseRegister,
822 ApplyXorInPlace,
823 ApplyXorInPlaceL,
824 ApplyOperationPowerA,
825 ApplyOperationPowerCA,
826 Relabel;
827