microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fedimser/memory-re

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/std/src/Std/Intrinsic.qs

1216lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4
5import Std.Convert.*;
6import Std.Core.*;
7import Std.Diagnostics.*;
8import Std.Math.*;
9open QIR.Intrinsic;
10import Std.InternalHelpers.*;
11
12/// # Summary
13/// Applies the AND gate that is more efficient for use with decomposition of multi-controlled operations.
14/// Note that target qubit must be in |0⟩ state.
15///
16/// # Input
17/// ## control1
18/// First control qubit for the AND gate.
19/// ## control2
20/// Second control qubit for the AND gate.
21/// ## target
22/// Target qubit for the AND gate.
23///
24/// # Remarks
25/// Use the Adjoint only for uncomputation purposes.
26@Config(Adaptive)
27operation AND(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
28 body ... {
29 __quantum__qis__ccx__body(control1, control2, target);
30 }
31 adjoint ... {
32 __quantum__qis__h__body(target);
33 if MResetZ(target) == One {
34 __quantum__qis__cz__body(control1, control2);
35 }
36 }
37}
38
39/// # Summary
40/// Applies the AND gate that is more efficient for use with decomposition of multi-controlled operations.
41/// Note that target qubit must be in |0⟩ state.
42///
43/// # Input
44/// ## control1
45/// First control qubit for the AND gate.
46/// ## control2
47/// Second control qubit for the AND gate.
48/// ## target
49/// Target qubit for the AND gate.
50///
51/// # Remarks
52/// Use the Adjoint only for uncomputation purposes.
53@Config(not Adaptive)
54operation AND(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
55 PhaseCCX(control1, control2, target);
56}
57
58/// # Summary
59/// Applies the doubly controlled–NOT (CCNOT) gate to three qubits.
60///
61/// # Input
62/// ## control1
63/// First control qubit for the CCNOT gate.
64/// ## control2
65/// Second control qubit for the CCNOT gate.
66/// ## target
67/// Target qubit for the CCNOT gate.
68///
69/// # Remarks
70/// Equivalent to:
71/// ```qsharp
72/// Controlled X([control1, control2], target);
73/// ```
74operation CCNOT(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj + Ctl {
75 body ... {
76 __quantum__qis__ccx__body(control1, control2, target);
77 }
78 controlled (ctls, ...) {
79 Controlled X(ctls + [control1, control2], target);
80 }
81 adjoint self;
82}
83
84/// # Summary
85/// Applies the controlled-NOT (CNOT) gate to a pair of qubits.
86///
87/// # Input
88/// ## control
89/// Control qubit for the CNOT gate.
90/// ## target
91/// Target qubit for the CNOT gate.
92///
93/// # Remarks
94/// $$
95/// \begin{align}
96/// \operatorname{CNOT} \mathrel{:=}
97/// \begin{bmatrix}
98/// 1 & 0 & 0 & 0 \\\\
99/// 0 & 1 & 0 & 0 \\\\
100/// 0 & 0 & 0 & 1 \\\\
101/// 0 & 0 & 1 & 0
102/// \end{bmatrix},
103/// \end{align}
104/// $$
105///
106/// where rows and columns are ordered as in the quantum concepts guide.
107///
108/// Equivalent to:
109/// ```qsharp
110/// Controlled X([control], target);
111/// ```
112operation CNOT(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
113 body ... {
114 __quantum__qis__cx__body(control, target);
115 }
116 controlled (ctls, ...) {
117 Controlled X(ctls + [control], target);
118 }
119 adjoint self;
120}
121
122/// # Summary
123/// Applies the exponential of a multi-qubit Pauli operator.
124///
125/// # Input
126/// ## paulis
127/// Array of single-qubit Pauli values indicating the tensor product
128/// factors on each qubit.
129/// ## theta
130/// Angle about the given multi-qubit Pauli operator by which the
131/// target register is to be rotated.
132/// ## qubits
133/// Register to apply the given rotation to.
134///
135/// # Remarks
136/// $$
137/// \begin{align}
138/// e^{i \theta [P_0 \otimes P_1 \cdots P_{N-1}]},
139/// \end{align}
140/// $$
141/// where $P_i$ is the $i$-th element of `paulis`, and where
142/// $N = $`Length(paulis)`.
143operation Exp(paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit is Adj + Ctl {
144 body ... {
145 Fact(Length(paulis) == Length(qubits), "Arrays 'pauli' and 'qubits' must have the same length");
146 let (paulis, qubits) = RemovePauliI(paulis, qubits);
147 let angle = -2.0 * theta;
148 let len = Length(paulis);
149
150 if len == 0 {
151 ApplyGlobalPhase(theta);
152 } elif len == 1 {
153 R(paulis[0], angle, qubits[0]);
154 } elif len == 2 {
155 within {
156 MapPauliAxis(paulis[0], paulis[1], qubits[1]);
157 } apply {
158 if (paulis[0] == PauliX) {
159 Rxx(angle, qubits[0], qubits[1]);
160 } elif (paulis[0] == PauliY) {
161 Ryy(angle, qubits[0], qubits[1]);
162 } elif (paulis[0] == PauliZ) {
163 Rzz(angle, qubits[0], qubits[1]);
164 }
165 }
166 } else {
167 // len > 2
168 within {
169 for i in 0..Length(paulis) - 1 {
170 MapPauliAxis(PauliZ, paulis[i], qubits[i]);
171 }
172 } apply {
173 within {
174 SpreadZ(qubits[1], qubits[2..Length(qubits) - 1]);
175 } apply {
176 Rzz(angle, qubits[0], qubits[1]);
177 }
178 }
179 }
180 }
181 adjoint ... {
182 Exp(paulis, -theta, qubits);
183 }
184}
185
186/// # Summary
187/// Applies the Hadamard transformation to a single qubit.
188///
189/// # Input
190/// ## qubit
191/// Qubit to which the gate should be applied.
192///
193/// # Remarks
194/// $$
195/// \begin{align}
196/// H \mathrel{:=}
197/// \frac{1}{\sqrt{2}}
198/// \begin{bmatrix}
199/// 1 & 1 \\\\
200/// 1 & -1
201/// \end{bmatrix}
202/// \end{align}
203/// $$
204operation H(qubit : Qubit) : Unit is Adj + Ctl {
205 body ... {
206 __quantum__qis__h__body(qubit);
207 }
208 controlled (ctls, ...) {
209 if Length(ctls) == 0 {
210 __quantum__qis__h__body(qubit);
211 } elif Length(ctls) == 1 {
212 CH(ctls[0], qubit);
213 } elif Length(ctls) == 2 {
214 CCH(ctls[0], ctls[1], qubit);
215 } else {
216 use aux = Qubit[Length(ctls) - 1 - (Length(ctls) % 2)];
217 within {
218 CollectControls(ctls, aux, 0);
219 } apply {
220 if Length(ctls) % 2 != 0 {
221 CCH(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
222 } else {
223 CCH(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
224 }
225 }
226 }
227 }
228 adjoint self;
229}
230
231/// # Summary
232/// Performs the identity operation (no-op) on a single qubit.
233///
234/// # Remarks
235/// This is a no-op. It is provided for completeness and because
236/// sometimes it is useful to call the identity in an algorithm or to pass it as a parameter.
237operation I(target : Qubit) : Unit is Adj + Ctl {
238 body ... {}
239 adjoint self;
240}
241
242/// # Summary
243/// Performs a measurement of a single qubit in the
244/// Pauli _Z_ basis.
245///
246/// # Input
247/// ## qubit
248/// Qubit to be measured.
249///
250/// # Output
251/// `Zero` if the +1 eigenvalue is observed, and `One` if
252/// the -1 eigenvalue is observed.
253///
254/// # Remarks
255/// The output result is given by
256/// the distribution
257/// $$
258/// \begin{align}
259/// \Pr(\texttt{Zero} | \ket{\psi}) =
260/// \braket{\psi | 0} \braket{0 | \psi}.
261/// \end{align}
262/// $$
263///
264/// Equivalent to:
265/// ```qsharp
266/// Measure([PauliZ], [qubit]);
267/// ```
268operation M(qubit : Qubit) : Result {
269 Measure([PauliZ], [qubit])
270}
271
272/// # Summary
273/// Performs a joint measurement of one or more qubits in the
274/// specified Pauli bases.
275///
276/// If the basis array and qubit array are different lengths, then the
277/// operation will fail.
278///
279/// # Input
280/// ## bases
281/// Array of single-qubit Pauli values indicating the tensor product
282/// factors on each qubit.
283/// ## qubits
284/// Register of qubits to be measured.
285///
286/// # Output
287/// `Zero` if the +1 eigenvalue is observed, and `One` if
288/// the -1 eigenvalue is observed.
289///
290/// # Remarks
291/// The probability of getting `Zero` is
292/// $\bra{\psi} \frac{I + P_0 \otimes \ldots \otimes P_{N-1}}{2} \ket{\psi}$
293/// where $P_i$ is the $i$-th element of `bases`, and where
294/// $N$ is the `Length(bases)`.
295/// That is, measurement returns a `Result` $d$ such that the eigenvalue of the
296/// observed measurement effect is $(-1)^d$.
297operation Measure(bases : Pauli[], qubits : Qubit[]) : Result {
298 if Length(bases) != Length(qubits) {
299 fail "Arrays 'bases' and 'qubits' must be of the same length.";
300 }
301 if Length(bases) == 1 {
302 within {
303 MapPauliAxis(PauliZ, bases[0], qubits[0]);
304 } apply {
305 __quantum__qis__m__body(qubits[0])
306 }
307 } else {
308 use aux = Qubit();
309 within {
310 H(aux);
311 } apply {
312 for i in 0..Length(bases) - 1 {
313 EntangleForJointMeasure(bases[i], aux, qubits[i]);
314 }
315 }
316 __quantum__qis__mresetz__body(aux)
317 }
318}
319
320/// # Summary
321/// Applies a rotation about the given Pauli axis.
322///
323/// # Input
324/// ## pauli
325/// Pauli operator (μ) to be exponentiated to form the rotation.
326/// ## theta
327/// Angle in radians about which the qubit is to be rotated.
328/// ## qubit
329/// Qubit to which the gate should be applied.
330///
331/// # Remarks
332/// $$
333/// \begin{align}
334/// R_{\mu}(\theta) \mathrel{:=}
335/// e^{-i \theta \sigma_{\mu} / 2},
336/// \end{align}
337/// $$
338/// where $\mu \in \{I, X, Y, Z\}$.
339///
340/// When called with `pauli = PauliI`, this operation applies
341/// a *global phase*. This phase can be significant
342/// when used with the `Controlled` functor.
343operation R(pauli : Pauli, theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
344 if (pauli == PauliX) {
345 Rx(theta, qubit);
346 } elif (pauli == PauliY) {
347 Ry(theta, qubit);
348 } elif (pauli == PauliZ) {
349 Rz(theta, qubit);
350 } else {
351 // PauliI
352 ApplyGlobalPhase(-theta / 2.0);
353 }
354}
355
356/// # Summary
357/// Applies a rotation about the |1⟩ state by a given angle.
358///
359/// # Input
360/// ## theta
361/// Angle about which the qubit is to be rotated.
362/// ## qubit
363/// Qubit to which the gate should be applied.
364///
365/// # Remarks
366/// $$
367/// \begin{align}
368/// R_1(\theta) \mathrel{:=}
369/// \operatorname{diag}(1, e^{i\theta}).
370/// \end{align}
371/// $$
372///
373/// Equivalent to:
374/// ```qsharp
375/// R(PauliZ, theta, qubit);
376/// R(PauliI, -theta, qubit);
377/// ```
378operation R1(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
379 Rz(theta, qubit);
380 R(PauliI, -theta, qubit);
381}
382
383/// # Summary
384/// Applies a rotation about the |1⟩ state by an angle specified
385/// as a dyadic fraction.
386///
387/// WARNING:
388/// This operation uses the **opposite** sign convention from
389/// Std.Intrinsic.R.
390///
391/// # Input
392/// ## numerator
393/// Numerator in the dyadic fraction representation of the angle
394/// by which the qubit is to be rotated. This angle is expressed in radians.
395/// ## power
396/// Power of two specifying the denominator of the angle by which
397/// the qubit is to be rotated. This angle is expressed in radians.
398/// ## qubit
399/// Qubit to which the gate should be applied.
400///
401/// # Remarks
402/// $$
403/// \begin{align}
404/// R_1(n, k) \mathrel{:=}
405/// \operatorname{diag}(1, e^{i \pi n / 2^k}).
406/// \end{align}
407/// $$
408///
409/// Equivalent to:
410/// ```qsharp
411/// RFrac(PauliZ, -numerator, denominator + 1, qubit);
412/// RFrac(PauliI, numerator, denominator + 1, qubit);
413/// ```
414operation R1Frac(numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl {
415 RFrac(PauliZ, -numerator, power + 1, qubit);
416 RFrac(PauliI, numerator, power + 1, qubit);
417}
418
419/// # Summary
420/// Given a single qubit, measures it and ensures it is in the |0⟩ state
421/// such that it can be safely released.
422///
423/// # Input
424/// ## qubit
425/// The qubit whose state is to be reset to |0⟩.
426operation Reset(qubit : Qubit) : Unit {
427 __quantum__qis__reset__body(qubit);
428}
429
430/// # Summary
431/// Given an array of qubits, measure them and ensure they are in the |0⟩ state
432/// such that they can be safely released.
433///
434/// # Input
435/// ## qubits
436/// An array of qubits whose states are to be reset to |0⟩.
437operation ResetAll(qubits : Qubit[]) : Unit {
438 for q in qubits {
439 Reset(q);
440 }
441}
442
443/// # Summary
444/// Applies a rotation about the given Pauli axis by an angle specified
445/// as a dyadic fraction.
446///
447/// WARNING:
448/// This operation uses the **opposite** sign convention from
449/// Std.Intrinsic.R.
450///
451/// # Input
452/// ## pauli
453/// Pauli operator to be exponentiated to form the rotation.
454/// ## numerator
455/// Numerator in the dyadic fraction representation of the angle
456/// by which the qubit is to be rotated. This angle is expressed in radians.
457/// ## power
458/// Power of two specifying the denominator of the angle by which
459/// the qubit is to be rotated. This angle is expressed in radians.
460/// ## qubit
461/// Qubit to which the gate should be applied.
462///
463/// # Remarks
464/// $$
465/// \begin{align}
466/// R_{\mu}(n, k) \mathrel{:=}
467/// e^{i \pi n \sigma_{\mu} / 2^k},
468/// \end{align}
469/// $$
470/// where $\mu \in \{I, X, Y, Z\}$.
471///
472/// Equivalent to:
473/// ```qsharp
474/// // PI() is a Q# function that returns an approximation of π.
475/// R(pauli, -2.0 * PI() * IntAsDouble(numerator) / IntAsDouble(2 ^ (power - 1)), qubit);
476/// ```
477operation RFrac(pauli : Pauli, numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl {
478 // Note that power must be converted to a double and used with 2.0 instead of 2 to allow for
479 // negative exponents that result in a fractional denominator.
480 let angle = ((-2.0 * PI()) * IntAsDouble(numerator)) / (2.0^IntAsDouble(power));
481 R(pauli, angle, qubit);
482}
483
484/// # Summary
485/// Applies a rotation about the _x_-axis by a given angle.
486///
487/// # Input
488/// ## theta
489/// Angle about which the qubit is to be rotated.
490/// ## qubit
491/// Qubit to which the gate should be applied.
492///
493/// # Remarks
494/// $$
495/// \begin{align}
496/// R_x(\theta) \mathrel{:=}
497/// e^{-i \theta \sigma_x / 2} =
498/// \begin{bmatrix}
499/// \cos \frac{\theta}{2} & -i\sin \frac{\theta}{2} \\\\
500/// -i\sin \frac{\theta}{2} & \cos \frac{\theta}{2}
501/// \end{bmatrix}.
502/// \end{align}
503/// $$
504///
505/// Equivalent to:
506/// ```qsharp
507/// R(PauliX, theta, qubit);
508/// ```
509operation Rx(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
510 body ... {
511 __quantum__qis__rx__body(theta, qubit);
512 }
513 controlled (ctls, ...) {
514 if Length(ctls) == 0 {
515 __quantum__qis__rx__body(theta, qubit);
516 } else {
517 within {
518 MapPauliAxis(PauliZ, PauliX, qubit);
519 } apply {
520 Controlled Rz(ctls, (theta, qubit));
521 }
522 }
523 }
524 adjoint ... {
525 Rx(-theta, qubit);
526 }
527}
528
529/// # Summary
530/// Applies the two qubit Ising _XX_ rotation gate.
531///
532/// # Input
533/// ## theta
534/// The angle about which the qubits are rotated.
535/// ## qubit0
536/// The first qubit input to the gate.
537/// ## qubit1
538/// The second qubit input to the gate.
539///
540/// # Remarks
541/// $$
542/// \begin{align}
543/// R_{xx}(\theta) \mathrel{:=}
544/// \begin{bmatrix}
545/// \cos \theta & 0 & 0 & -i\sin \theta \\\\
546/// 0 & \cos \theta & -i\sin \theta & 0 \\\\
547/// 0 & -i\sin \theta & \cos \theta & 0 \\\\
548/// -i\sin \theta & 0 & 0 & \cos \theta
549/// \end{bmatrix}.
550/// \end{align}
551/// $$
552operation Rxx(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
553 body ... {
554 __quantum__qis__rxx__body(theta, qubit0, qubit1);
555 }
556 controlled (ctls, ...) {
557 if Length(ctls) == 0 {
558 __quantum__qis__rxx__body(theta, qubit0, qubit1);
559 } elif Length(ctls) == 1 {
560 CRxx(ctls[0], theta, qubit0, qubit1);
561 } else {
562 use aux = Qubit[Length(ctls) - 1];
563 within {
564 CollectControls(ctls, aux, 0);
565 AdjustForSingleControl(ctls, aux);
566 } apply {
567 CRxx(aux[Length(ctls) - 2], theta, qubit0, qubit1);
568 }
569 }
570 }
571 adjoint ... {
572 Rxx(-theta, qubit0, qubit1);
573 }
574}
575
576/// # Summary
577/// Applies a rotation about the _y_-axis by a given angle.
578///
579/// # Input
580/// ## theta
581/// Angle about which the qubit is to be rotated.
582/// ## qubit
583/// Qubit to which the gate should be applied.
584///
585/// # Remarks
586/// $$
587/// \begin{align}
588/// R_y(\theta) \mathrel{:=}
589/// e^{-i \theta \sigma_y / 2} =
590/// \begin{bmatrix}
591/// \cos \frac{\theta}{2} & -\sin \frac{\theta}{2} \\\\
592/// \sin \frac{\theta}{2} & \cos \frac{\theta}{2}
593/// \end{bmatrix}.
594/// \end{align}
595/// $$
596///
597/// Equivalent to:
598/// ```qsharp
599/// R(PauliY, theta, qubit);
600/// ```
601operation Ry(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
602 body ... {
603 __quantum__qis__ry__body(theta, qubit);
604 }
605 controlled (ctls, ...) {
606 if Length(ctls) == 0 {
607 __quantum__qis__ry__body(theta, qubit);
608 } else {
609 within {
610 MapPauliAxis(PauliZ, PauliY, qubit);
611 } apply {
612 Controlled Rz(ctls, (theta, qubit));
613 }
614 }
615 }
616 adjoint ... {
617 Ry(-theta, qubit);
618 }
619}
620
621/// # Summary
622/// Applies the two qubit Ising _YY_ rotation gate.
623///
624/// # Input
625/// ## theta
626/// The angle about which the qubits are rotated.
627/// ## qubit0
628/// The first qubit input to the gate.
629/// ## qubit1
630/// The second qubit input to the gate.
631///
632/// # Remarks
633/// $$
634/// \begin{align}
635/// R_{yy}(\theta) \mathrel{:=}
636/// \begin{bmatrix}
637/// \cos \theta & 0 & 0 & i\sin \theta \\\\
638/// 0 & \cos \theta & -i\sin \theta & 0 \\\\
639/// 0 & -i\sin \theta & \cos \theta & 0 \\\\
640/// i\sin \theta & 0 & 0 & \cos \theta
641/// \end{bmatrix}.
642/// \end{align}
643/// $$
644operation Ryy(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
645 body ... {
646 __quantum__qis__ryy__body(theta, qubit0, qubit1);
647 }
648 controlled (ctls, ...) {
649 if Length(ctls) == 0 {
650 __quantum__qis__ryy__body(theta, qubit0, qubit1);
651 } elif Length(ctls) == 1 {
652 CRyy(ctls[0], theta, qubit0, qubit1);
653 } else {
654 use aux = Qubit[Length(ctls) - 1];
655 within {
656 CollectControls(ctls, aux, 0);
657 AdjustForSingleControl(ctls, aux);
658 } apply {
659 CRyy(aux[Length(ctls) - 2], theta, qubit0, qubit1);
660 }
661 }
662 }
663 adjoint ... {
664 Ryy(-theta, qubit0, qubit1);
665 }
666}
667
668/// # Summary
669/// Applies a rotation about the _z_-axis by a given angle.
670///
671/// # Input
672/// ## theta
673/// Angle about which the qubit is to be rotated.
674/// ## qubit
675/// Qubit to which the gate should be applied.
676///
677/// # Remarks
678/// $$
679/// \begin{align}
680/// R_z(\theta) \mathrel{:=}
681/// e^{-i \theta \sigma_z / 2} =
682/// \begin{bmatrix}
683/// e^{-i \theta / 2} & 0 \\\\
684/// 0 & e^{i \theta / 2}
685/// \end{bmatrix}.
686/// \end{align}
687/// $$
688///
689/// Equivalent to:
690/// ```qsharp
691/// R(PauliZ, theta, qubit);
692/// ```
693operation Rz(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
694 body ... {
695 __quantum__qis__rz__body(theta, qubit);
696 }
697 controlled (ctls, ...) {
698 if Length(ctls) == 0 {
699 __quantum__qis__rz__body(theta, qubit);
700 } elif Length(ctls) == 1 {
701 CRz(ctls[0], theta, qubit);
702 } else {
703 use aux = Qubit[Length(ctls) - 1];
704 within {
705 CollectControls(ctls, aux, 0);
706 AdjustForSingleControl(ctls, aux);
707 } apply {
708 CRz(aux[Length(ctls) - 2], theta, qubit);
709 }
710 }
711 }
712 adjoint ... {
713 Rz(-theta, qubit);
714 }
715}
716
717/// # Summary
718/// Applies the two qubit Ising _ZZ_ rotation gate.
719///
720/// # Input
721/// ## theta
722/// The angle about which the qubits are rotated.
723/// ## qubit0
724/// The first qubit input to the gate.
725/// ## qubit1
726/// The second qubit input to the gate.
727///
728/// # Remarks
729/// $$
730/// \begin{align}
731/// R_{zz}(\theta) \mathrel{:=}
732/// \begin{bmatrix}
733/// e^{-i \theta / 2} & 0 & 0 & 0 \\\\
734/// 0 & e^{i \theta / 2} & 0 & 0 \\\\
735/// 0 & 0 & e^{i \theta / 2} & 0 \\\\
736/// 0 & 0 & 0 & e^{-i \theta / 2}
737/// \end{bmatrix}.
738/// \end{align}
739/// $$
740operation Rzz(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
741 body ... {
742 __quantum__qis__rzz__body(theta, qubit0, qubit1);
743 }
744 controlled (ctls, ...) {
745 if Length(ctls) == 0 {
746 __quantum__qis__rzz__body(theta, qubit0, qubit1);
747 } elif Length(ctls) == 1 {
748 CRzz(ctls[0], theta, qubit0, qubit1);
749 } else {
750 use aux = Qubit[Length(ctls) - 1];
751 within {
752 CollectControls(ctls, aux, 0);
753 AdjustForSingleControl(ctls, aux);
754 } apply {
755 CRzz(aux[Length(ctls) - 2], theta, qubit0, qubit1);
756 }
757 }
758 }
759 adjoint ... {
760 Rzz(-theta, qubit0, qubit1);
761 }
762}
763
764/// # Summary
765/// Applies the π/4 phase gate to a single qubit.
766///
767/// # Input
768/// ## qubit
769/// Qubit to which the gate should be applied.
770///
771/// # Remarks
772/// $$
773/// \begin{align}
774/// S \mathrel{:=}
775/// \begin{bmatrix}
776/// 1 & 0 \\\\
777/// 0 & i
778/// \end{bmatrix}.
779/// \end{align}
780/// $$
781operation S(qubit : Qubit) : Unit is Adj + Ctl {
782 body ... {
783 __quantum__qis__s__body(qubit);
784 }
785 adjoint ... {
786 __quantum__qis__s__adj(qubit);
787 }
788 controlled (ctls, ...) {
789 if Length(ctls) == 0 {
790 __quantum__qis__s__body(qubit);
791 } elif Length(ctls) == 1 {
792 CS(ctls[0], qubit);
793 } elif Length(ctls) == 2 {
794 Controlled CS([ctls[0]], (ctls[1], qubit));
795 } else {
796 use aux = Qubit[Length(ctls) - 2];
797 within {
798 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
799 } apply {
800 if Length(ctls) % 2 != 0 {
801 Controlled CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
802 } else {
803 Controlled CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
804 }
805 }
806 }
807 }
808 controlled adjoint (ctls, ...) {
809 if Length(ctls) == 0 {
810 __quantum__qis__s__adj(qubit);
811 } elif Length(ctls) == 1 {
812 Adjoint CS(ctls[0], qubit);
813 } elif Length(ctls) == 2 {
814 Controlled Adjoint CS([ctls[0]], (ctls[1], qubit));
815 } else {
816 use aux = Qubit[Length(ctls) - 2];
817 within {
818 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
819 } apply {
820 if Length(ctls) % 2 != 0 {
821 Controlled Adjoint CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
822 } else {
823 Controlled Adjoint CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
824 }
825 }
826 }
827 }
828}
829
830/// # Summary
831/// Applies the square root of X gate to a single qubit.
832///
833/// # Input
834/// ## qubit
835/// Qubit to which the gate should be applied.
836///
837/// # Remarks
838/// $$
839/// \begin{align}
840/// SX \mathrel{:=}
841/// \begin{bmatrix}
842/// \frac{1}{2} + \frac{i}{2} & \frac{1}{2} - \frac{i}{2} \\\\
843/// \frac{1}{2} - \frac{i}{2} & \frac{1}{2} + \frac{i}{2}
844/// \end{bmatrix}.
845/// \end{align}
846/// $$
847operation SX(qubit : Qubit) : Unit is Adj + Ctl {
848 body ... {
849 __quantum__qis__sx__body(qubit);
850 }
851 adjoint ... {
852 __quantum__qis__x__body(qubit);
853 __quantum__qis__sx__body(qubit);
854 }
855 controlled (ctls, ...) {
856 if Length(ctls) == 0 {
857 __quantum__qis__sx__body(qubit);
858 } elif Length(ctls) == 1 {
859 within {
860 H(qubit);
861 } apply {
862 CS(ctls[0], qubit);
863 }
864 } elif Length(ctls) == 2 {
865 within {
866 H(qubit);
867 } apply {
868 Controlled CS([ctls[0]], (ctls[1], qubit));
869 }
870 } else {
871 use aux = Qubit[Length(ctls) - 2];
872 within {
873 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
874 H(qubit);
875 } apply {
876 if Length(ctls) % 2 != 0 {
877 Controlled CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
878 } else {
879 Controlled CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
880 }
881 }
882 }
883 }
884 controlled adjoint (ctls, ...) {
885 if Length(ctls) == 0 {
886 __quantum__qis__x__body(qubit);
887 __quantum__qis__sx__body(qubit);
888 } elif Length(ctls) == 1 {
889 within {
890 H(qubit);
891 } apply {
892 Adjoint CS(ctls[0], qubit);
893 }
894 } elif Length(ctls) == 2 {
895 within {
896 H(qubit);
897 } apply {
898 Controlled Adjoint CS([ctls[0]], (ctls[1], qubit));
899 }
900 } else {
901 use aux = Qubit[Length(ctls) - 2];
902 within {
903 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
904 H(qubit);
905 } apply {
906 if Length(ctls) % 2 != 0 {
907 Controlled Adjoint CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
908 } else {
909 Controlled Adjoint CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
910 }
911 }
912 }
913 }
914}
915
916/// # Summary
917/// Applies the SWAP gate to a pair of qubits.
918///
919/// # Input
920/// ## qubit1
921/// First qubit to be swapped.
922/// ## qubit2
923/// Second qubit to be swapped.
924///
925/// # Remarks
926/// $$
927/// \begin{align}
928/// \operatorname{SWAP} \mathrel{:=}
929/// \begin{bmatrix}
930/// 1 & 0 & 0 & 0 \\\\
931/// 0 & 0 & 1 & 0 \\\\
932/// 0 & 1 & 0 & 0 \\\\
933/// 0 & 0 & 0 & 1
934/// \end{bmatrix},
935/// \end{align}
936/// $$
937///
938/// where rows and columns are ordered as in the quantum concepts guide.
939///
940/// Equivalent to:
941/// ```qsharp
942/// CNOT(qubit1, qubit2);
943/// CNOT(qubit2, qubit1);
944/// CNOT(qubit1, qubit2);
945/// ```
946operation SWAP(qubit1 : Qubit, qubit2 : Qubit) : Unit is Adj + Ctl {
947 body ... {
948 __quantum__qis__swap__body(qubit1, qubit2);
949 }
950 adjoint self;
951 controlled (ctls, ...) {
952 if (Length(ctls) == 0) {
953 __quantum__qis__swap__body(qubit1, qubit2);
954 } else {
955 within {
956 CNOT(qubit1, qubit2);
957 } apply {
958 Controlled CNOT(ctls, (qubit2, qubit1));
959 }
960 }
961 }
962}
963
964/// # Summary
965/// Applies the π/8 gate to a single qubit.
966///
967/// # Input
968/// ## qubit
969/// Qubit to which the gate should be applied.
970///
971/// # Remarks
972/// $$
973/// \begin{align}
974/// T \mathrel{:=}
975/// \begin{bmatrix}
976/// 1 & 0 \\\\
977/// 0 & e^{i \pi / 4}
978/// \end{bmatrix}.
979/// \end{align}
980/// $$
981operation T(qubit : Qubit) : Unit is Adj + Ctl {
982 body ... {
983 __quantum__qis__t__body(qubit);
984 }
985 adjoint ... {
986 __quantum__qis__t__adj(qubit);
987 }
988 controlled (ctls, ...) {
989 if Length(ctls) == 0 {
990 __quantum__qis__t__body(qubit);
991 } elif Length(ctls) == 1 {
992 CT(ctls[0], qubit);
993 } else {
994 use aux = Qubit[Length(ctls) - 1];
995 within {
996 CollectControls(ctls, aux, 0);
997 AdjustForSingleControl(ctls, aux);
998 } apply {
999 CT(aux[Length(ctls) - 2], qubit);
1000 }
1001 }
1002 }
1003 controlled adjoint (ctls, ...) {
1004 if Length(ctls) == 0 {
1005 __quantum__qis__t__adj(qubit);
1006 } elif Length(ctls) == 1 {
1007 Adjoint CT(ctls[0], qubit);
1008 } else {
1009 use aux = Qubit[Length(ctls) - 1];
1010 within {
1011 CollectControls(ctls, aux, 0);
1012 AdjustForSingleControl(ctls, aux);
1013 } apply {
1014 Adjoint CT(aux[Length(ctls) - 2], qubit);
1015 }
1016 }
1017 }
1018}
1019
1020/// # Summary
1021/// Applies the Pauli _X_ gate.
1022///
1023/// # Input
1024/// ## qubit
1025/// Qubit to which the gate should be applied.
1026///
1027/// # Remarks
1028/// $$
1029/// \begin{align}
1030/// \sigma_x \mathrel{:=}
1031/// \begin{bmatrix}
1032/// 0 & 1 \\\\
1033/// 1 & 0
1034/// \end{bmatrix}.
1035/// \end{align}
1036/// $$
1037operation X(qubit : Qubit) : Unit is Adj + Ctl {
1038 body ... {
1039 __quantum__qis__x__body(qubit);
1040 }
1041 controlled (ctls, ...) {
1042 if Length(ctls) == 0 {
1043 __quantum__qis__x__body(qubit);
1044 } elif Length(ctls) == 1 {
1045 __quantum__qis__cx__body(ctls[0], qubit);
1046 } elif Length(ctls) == 2 {
1047 __quantum__qis__ccx__body(ctls[0], ctls[1], qubit);
1048 } else {
1049 use aux = Qubit[Length(ctls) - 2];
1050 within {
1051 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
1052 } apply {
1053 if Length(ctls) % 2 != 0 {
1054 __quantum__qis__ccx__body(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
1055 } else {
1056 __quantum__qis__ccx__body(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
1057 }
1058 }
1059 }
1060 }
1061 adjoint self;
1062}
1063
1064/// # Summary
1065/// Applies the Pauli _Y_ gate.
1066///
1067/// # Input
1068/// ## qubit
1069/// Qubit to which the gate should be applied.
1070///
1071/// # Remarks
1072/// $$
1073/// \begin{align}
1074/// \sigma_y \mathrel{:=}
1075/// \begin{bmatrix}
1076/// 0 & -i \\\\
1077/// i & 0
1078/// \end{bmatrix}.
1079/// \end{align}
1080/// $$
1081operation Y(qubit : Qubit) : Unit is Adj + Ctl {
1082 body ... {
1083 __quantum__qis__y__body(qubit);
1084 }
1085 controlled (ctls, ...) {
1086 if (Length(ctls) == 0) {
1087 __quantum__qis__y__body(qubit);
1088 } elif (Length(ctls) == 1) {
1089 __quantum__qis__cy__body(ctls[0], qubit);
1090 } elif (Length(ctls) == 2) {
1091 CCY(ctls[0], ctls[1], qubit);
1092 } else {
1093 use aux = Qubit[Length(ctls) - 2];
1094 within {
1095 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
1096 } apply {
1097 if Length(ctls) % 2 != 0 {
1098 CCY(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
1099 } else {
1100 CCY(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
1101 }
1102 }
1103 }
1104 }
1105 adjoint self;
1106}
1107
1108/// # Summary
1109/// Applies the Pauli _Z_ gate.
1110///
1111/// # Input
1112/// ## qubit
1113/// Qubit to which the gate should be applied.
1114///
1115/// # Remarks
1116/// $$
1117/// \begin{align}
1118/// \sigma_z \mathrel{:=}
1119/// \begin{bmatrix}
1120/// 1 & 0 \\\\
1121/// 0 & -1
1122/// \end{bmatrix}.
1123/// \end{align}
1124/// $$
1125operation Z(qubit : Qubit) : Unit is Adj + Ctl {
1126 body ... {
1127 __quantum__qis__z__body(qubit);
1128 }
1129 controlled (ctls, ...) {
1130 if Length(ctls) == 0 {
1131 __quantum__qis__z__body(qubit);
1132 } elif Length(ctls) == 1 {
1133 __quantum__qis__cz__body(ctls[0], qubit);
1134 } elif Length(ctls) == 2 {
1135 CCZ(ctls[0], ctls[1], qubit);
1136 } else {
1137 use aux = Qubit[Length(ctls) - 2];
1138 within {
1139 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
1140 } apply {
1141 if Length(ctls) % 2 != 0 {
1142 CCZ(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
1143 } else {
1144 CCZ(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
1145 }
1146 }
1147 }
1148 }
1149 adjoint self;
1150}
1151
1152/// # Summary
1153/// Applies the given unitary matrix to the given qubits. The matrix is checked at runtime to ensure it's shape is square and that the matrix dimensions are `2 ^ Length(qubits)`.
1154/// This operation is simulator-only and is not supported on hardware.
1155///
1156/// # Input
1157/// ## matrix
1158/// The unitary matrix to apply.
1159/// ## qubits
1160/// The qubits to which the unitary matrix should be applied.
1161///
1162/// # Example
1163/// This performs a two qubit CNOT using the unitary matrix representation:
1164/// ```qsharp
1165/// import Std.Math.Complex;
1166/// use qs = Qubit[2];
1167/// let one = new Complex { Real = 1.0, Imag = 0.0 };
1168/// let zero = new Complex { Real = 0.0, Imag = 0.0 };
1169/// ApplyUnitary(
1170/// [
1171/// [one, zero, zero, zero],
1172/// [zero, one, zero, zero],
1173/// [zero, zero, zero, one],
1174/// [zero, zero, one, zero]
1175/// ],
1176/// qs
1177/// );
1178/// ```
1179@Config(Unrestricted)
1180operation ApplyUnitary(matrix : Complex[][], qubits : Qubit[]) : Unit {
1181 let num_rows = Length(matrix);
1182 for col in matrix {
1183 if Length(col) != num_rows {
1184 fail "matrix passed to ApplyUnitary must be square.";
1185 }
1186 }
1187
1188 let num_qubits = Length(qubits);
1189 if num_rows != 1 <<< num_qubits {
1190 fail "matrix passed to ApplyUnitary must have dimensions 2^Length(qubits).";
1191 }
1192
1193 Apply(matrix, qubits);
1194}
1195
1196@Config(Unrestricted)
1197operation Apply(matrix : Complex[][], qubits : Qubit[]) : Unit {
1198 body intrinsic;
1199}
1200
1201/// # Summary
1202/// Logs a message.
1203///
1204/// # Input
1205/// ## msg
1206/// The message to be reported.
1207///
1208/// # Remarks
1209/// The specific behavior of this function is simulator-dependent,
1210/// but in most cases the given message will be written to the console.
1211/// ```
1212function Message(msg : String) : Unit {
1213 body intrinsic;
1214}
1215
1216export AND, CCNOT, CNOT, Exp, H, I, M, Measure, R, R1, R1Frac, Reset, ResetAll, RFrac, Rx, Rxx, Ry, Ryy, Rz, Rzz, S, SWAP, SX, T, X, Y, Z, ApplyUnitary, Message;
1217