microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cc20343d1b34e43e1bd16a5450e986fec5e70d20

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/intrinsic.qs

993lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4namespace Microsoft.Quantum.Intrinsic {
5 open Microsoft.Quantum.Convert;
6 open Microsoft.Quantum.Core;
7 open Microsoft.Quantum.Math;
8 open QIR.Intrinsic;
9
10 /// # Summary
11 /// Applies the doubly controlled–NOT (CCNOT) gate to three qubits.
12 ///
13 /// # Input
14 /// ## control1
15 /// First control qubit for the CCNOT gate.
16 /// ## control2
17 /// Second control qubit for the CCNOT gate.
18 /// ## target
19 /// Target qubit for the CCNOT gate.
20 ///
21 /// # Remarks
22 /// Equivalent to:
23 /// ```qsharp
24 /// Controlled X([control1, control2], target);
25 /// ```
26 operation CCNOT(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj + Ctl {
27 body (...) {
28 __quantum__qis__ccx__body(control1, control2, target);
29 }
30 controlled (ctls, ...) {
31 Controlled X(ctls + [control1, control2], target);
32 }
33 adjoint self;
34 }
35
36 /// # Summary
37 /// Applies the controlled-NOT (CNOT) gate to a pair of qubits.
38 ///
39 /// # Description
40 /// \begin{align}
41 /// \operatorname{CNOT} \mathrel{:=}
42 /// \begin{bmatrix}
43 /// 1 & 0 & 0 & 0 \\\\
44 /// 0 & 1 & 0 & 0 \\\\
45 /// 0 & 0 & 0 & 1 \\\\
46 /// 0 & 0 & 1 & 0
47 /// \end{bmatrix},
48 /// \end{align}
49 ///
50 /// where rows and columns are ordered as in the quantum concepts guide.
51 ///
52 /// # Input
53 /// ## control
54 /// Control qubit for the CNOT gate.
55 /// ## target
56 /// Target qubit for the CNOT gate.
57 ///
58 /// # Remarks
59 /// Equivalent to:
60 /// ```qsharp
61 /// Controlled X([control], target);
62 /// ```
63 operation CNOT(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
64 body (...) {
65 __quantum__qis__cx__body(control, target);
66 }
67 controlled (ctls, ...) {
68 Controlled X(ctls + [control], target);
69 }
70 adjoint self;
71 }
72
73 /// # Summary
74 /// Applies the Hadamard transformation to a single qubit.
75 ///
76 /// # Description
77 /// \begin{align}
78 /// H \mathrel{:=}
79 /// \frac{1}{\sqrt{2}}
80 /// \begin{bmatrix}
81 /// 1 & 1 \\\\
82 /// 1 & -1
83 /// \end{bmatrix}.
84 /// \end{align}
85 ///
86 /// # Input
87 /// ## qubit
88 /// Qubit to which the gate should be applied.
89 operation H(qubit : Qubit) : Unit is Adj + Ctl {
90 body (...) {
91 __quantum__qis__h__body(qubit);
92 }
93 controlled (ctls, ...) {
94 if Length(ctls) == 0 {
95 __quantum__qis__h__body(qubit);
96 }
97 elif Length(ctls) == 1 {
98 CH(ctls[0], qubit);
99 }
100 elif Length(ctls) == 2 {
101 CCH(ctls[0], ctls[1], qubit);
102 }
103 else {
104 use aux = Qubit[Length(ctls) - 1 - (Length(ctls) % 2)];
105 within {
106 CollectControls(ctls, aux, 0);
107 }
108 apply {
109 if Length(ctls) % 2 != 0 {
110 CCH(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
111 }
112 else {
113 CCH(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
114 }
115 }
116 }
117 }
118 adjoint self;
119 }
120
121 /// # Summary
122 /// Performs the identity operation (no-op) on a single qubit.
123 ///
124 /// # Remarks
125 /// This is a no-op. It is provided for completeness and because
126 /// sometimes it is useful to call the identity in an algorithm or to pass it as a parameter.
127 operation I(target : Qubit) : Unit is Adj + Ctl {
128 body (...) { }
129 adjoint self;
130 }
131
132 /// # Summary
133 /// Performs a measurement of a single qubit in the
134 /// Pauli $Z$ basis.
135 ///
136 /// # Description
137 /// The output result is given by
138 /// the distribution
139 /// \begin{align}
140 /// \Pr(\texttt{Zero} | \ket{\psi}) =
141 /// \braket{\psi | 0} \braket{0 | \psi}.
142 /// \end{align}
143 ///
144 /// # Input
145 /// ## qubit
146 /// Qubit to be measured.
147 ///
148 /// # Output
149 /// `Zero` if the $+1$ eigenvalue is observed, and `One` if
150 /// the $-1$ eigenvalue is observed.
151 ///
152 /// # Remarks
153 /// Equivalent to:
154 /// ```qsharp
155 /// Measure([PauliZ], [qubit]);
156 /// ```
157 operation M(qubit : Qubit) : Result {
158 return __quantum__qis__m__body(qubit);
159 }
160
161 /// # Summary
162 /// Performs a joint measurement of one or more qubits in the
163 /// specified Pauli bases.
164 ///
165 /// # Description
166 /// The output result is given by the distribution:
167 /// \begin{align}
168 /// \Pr(\texttt{Zero} | \ket{\psi}) =
169 /// \frac12 \braket{
170 /// \psi \mid|
171 /// \left(
172 /// \boldone + P_0 \otimes P_1 \otimes \cdots \otimes P_{N-1}
173 /// \right) \mid|
174 /// \psi
175 /// },
176 /// \end{align}
177 /// where $P_i$ is the $i$th element of `bases`, and where
178 /// $N = \texttt{Length}(\texttt{bases})$.
179 /// That is, measurement returns a `Result` $d$ such that the eigenvalue of the
180 /// observed measurement effect is $(-1)^d$.
181 ///
182 /// # Input
183 /// ## bases
184 /// Array of single-qubit Pauli values indicating the tensor product
185 /// factors on each qubit.
186 /// ## qubits
187 /// Register of qubits to be measured.
188 ///
189 /// # Output
190 /// `Zero` if the $+1$ eigenvalue is observed, and `One` if
191 /// the $-1$ eigenvalue is observed.
192 ///
193 /// # Remarks
194 /// If the basis array and qubit array are different lengths, then the
195 /// operation will fail.
196 operation Measure(bases : Pauli[], qubits : Qubit[]) : Result {
197 mutable res = Zero;
198 if Length(bases) != Length(qubits) {
199 fail "Arrays 'bases' and 'qubits' must be of the same length.";
200 }
201 if Length(bases) == 1 {
202 within {
203 MapPauli(qubits[0], PauliZ, bases[0]);
204 }
205 apply {
206 set res = __quantum__qis__m__body(qubits[0]);
207 }
208 }
209 else {
210 use aux = Qubit();
211 within {
212 H(aux);
213 }
214 apply {
215 for i in 0..Length(bases)-1 {
216 EntangleForJointMeasure(bases[i], aux, qubits[i]);
217 }
218 }
219 set res = __quantum__qis__mresetz__body(aux);
220 }
221 return res;
222 }
223
224 /// # Summary
225 /// Applies a rotation about the given Pauli axis.
226 ///
227 /// # Description
228 /// \begin{align}
229 /// R_{\mu}(\theta) \mathrel{:=}
230 /// e^{-i \theta \sigma_{\mu} / 2},
231 /// \end{align}
232 /// where $\mu \in \{I, X, Y, Z\}$.
233 ///
234 /// # Input
235 /// ## pauli
236 /// Pauli operator ($\mu$) to be exponentiated to form the rotation.
237 /// ## theta
238 /// Angle in radians about which the qubit is to be rotated.
239 /// ## qubit
240 /// Qubit to which the gate should be applied.
241 ///
242 /// # Remarks
243 /// When called with `pauli = PauliI`, this operation applies
244 /// a *global phase*. This phase can be significant
245 /// when used with the `Controlled` functor.
246 operation R(pauli : Pauli, theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
247 if (pauli == PauliX) {
248 Rx(theta, qubit);
249 }
250 elif (pauli == PauliY) {
251 Ry(theta, qubit);
252 }
253 elif (pauli == PauliZ) {
254 Rz(theta, qubit);
255 }
256 else { // PauliI
257 ApplyGlobalPhase( - theta / 2.0 );
258 }
259 }
260
261 /// # Summary
262 /// Applies a rotation about the $\ket{1}$ state by a given angle.
263 ///
264 /// # Description
265 /// \begin{align}
266 /// R_1(\theta) \mathrel{:=}
267 /// \operatorname{diag}(1, e^{i\theta}).
268 /// \end{align}
269 ///
270 /// # Input
271 /// ## theta
272 /// Angle about which the qubit is to be rotated.
273 /// ## qubit
274 /// Qubit to which the gate should be applied.
275 ///
276 /// # Remarks
277 /// Equivalent to:
278 /// ```qsharp
279 /// R(PauliZ, theta, qubit);
280 /// R(PauliI, -theta, qubit);
281 /// ```
282 operation R1(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
283 body (...) {
284 Rz(theta, qubit);
285 }
286 controlled (ctls, ...) {
287 if Length(ctls) == 0 {
288 Rz(theta, qubit);
289 }
290 elif Length(ctls) == 1 {
291 CR1(theta, ctls[0], qubit);
292 }
293 else {
294 use aux = Qubit[Length(ctls) - 1];
295 within {
296 CollectControls(ctls, aux, 0);
297 AdjustForSingleControl(ctls, aux);
298 }
299 apply {
300 CR1(theta, aux[Length(ctls) - 2], qubit);
301 }
302 }
303 }
304 }
305
306 /// # Summary
307 /// Applies a rotation about the $\ket{1}$ state by an angle specified
308 /// as a dyadic fraction.
309 ///
310 /// # Description
311 /// \begin{align}
312 /// R_1(n, k) \mathrel{:=}
313 /// \operatorname{diag}(1, e^{i \pi k / 2^n}).
314 /// \end{align}
315 ///
316 /// > [!WARNING]
317 /// > This operation uses the **opposite** sign convention from
318 /// > @"microsoft.quantum.intrinsic.r", and does not include the
319 /// > factor of $1/ 2$ included by @"microsoft.quantum.intrinsic.r1".
320 ///
321 /// # Input
322 /// ## numerator
323 /// Numerator in the dyadic fraction representation of the angle
324 /// by which the qubit is to be rotated. This angle is expressed in radians.
325 /// ## power
326 /// Power of two specifying the denominator of the angle by which
327 /// the qubit is to be rotated. This angle is expressed in radians.
328 /// ## qubit
329 /// Qubit to which the gate should be applied.
330 ///
331 /// # Remarks
332 /// Equivalent to:
333 /// ```qsharp
334 /// RFrac(PauliZ, -numerator, denominator + 1, qubit);
335 /// RFrac(PauliI, numerator, denominator + 1, qubit);
336 /// ```
337 operation R1Frac(numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl {
338 RFrac(PauliZ, -numerator, power + 1, qubit);
339 RFrac(PauliI, numerator, power + 1, qubit);
340 }
341
342 /// # Summary
343 /// Applies a rotation about the given Pauli axis by an angle specified
344 /// as a dyadic fraction.
345 ///
346 /// # Description
347 /// \begin{align}
348 /// R_{\mu}(n, k) \mathrel{:=}
349 /// e^{i \pi n \sigma_{\mu} / 2^k},
350 /// \end{align}
351 /// where $\mu \in \{I, X, Y, Z\}$.
352 ///
353 /// > [!WARNING]
354 /// > This operation uses the **opposite** sign convention from
355 /// > @"microsoft.quantum.intrinsic.r".
356 ///
357 /// # Input
358 /// ## pauli
359 /// Pauli operator to be exponentiated to form the rotation.
360 /// ## numerator
361 /// Numerator in the dyadic fraction representation of the angle
362 /// by which the qubit is to be rotated. This angle is expressed in radians.
363 /// ## power
364 /// Power of two specifying the denominator of the angle by which
365 /// the qubit is to be rotated. This angle is expressed in radians.
366 /// ## qubit
367 /// Qubit to which the gate should be applied.
368 ///
369 /// # Remarks
370 /// Equivalent to:
371 /// ```qsharp
372 /// // PI() is a Q# function that returns an approximation of π.
373 /// R(pauli, -PI() * IntAsDouble(numerator) / IntAsDouble(2 ^ (power - 1)), qubit);
374 /// ```
375 operation RFrac(pauli : Pauli, numerator : Int, power : Int, qubit : Qubit) : Unit is Adj + Ctl {
376 // Note that power must be converted to a double and used with 2.0 instead of 2 to allow for
377 // negative exponents that result in a fractional denominator.
378 let angle = ((-2.0 * PI()) * IntAsDouble(numerator)) / (2.0 ^ IntAsDouble(power));
379 R(pauli, angle, qubit);
380 }
381
382 /// # Summary
383 /// Applies a rotation about the $x$-axis by a given angle.
384 ///
385 /// # Description
386 /// \begin{align}
387 /// R_x(\theta) \mathrel{:=}
388 /// e^{-i \theta \sigma_x / 2} =
389 /// \begin{bmatrix}
390 /// \cos \frac{\theta}{2} & -i\sin \frac{\theta}{2} \\\\
391 /// -i\sin \frac{\theta}{2} & \cos \frac{\theta}{2}
392 /// \end{bmatrix}.
393 /// \end{align}
394 ///
395 /// # Input
396 /// ## theta
397 /// Angle about which the qubit is to be rotated.
398 /// ## qubit
399 /// Qubit to which the gate should be applied.
400 ///
401 /// # Remarks
402 /// Equivalent to:
403 /// ```qsharp
404 /// R(PauliX, theta, qubit);
405 /// ```
406 operation Rx(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
407 body (...) {
408 __quantum__qis__rx__body(theta, qubit);
409 }
410 controlled (ctls, ...) {
411 if Length(ctls) == 0 {
412 __quantum__qis__rx__body(theta, qubit);
413 }
414 else {
415 within {
416 MapPauli(qubit, PauliZ, PauliX);
417 }
418 apply {
419 Controlled Rz(ctls, (theta, qubit));
420 }
421 }
422 }
423 adjoint (...) {
424 Rx(-theta, qubit);
425 }
426 }
427
428 /// # Summary
429 /// Applies the two qubit Ising $XX$ rotation gate.
430 ///
431 /// # Description
432 /// \begin{align}
433 /// R_xx(\theta) \mathrel{:=}
434 /// \begin{bmatrix}
435 /// \cos \theta & 0 & 0 & -i\sin \theta \\\\
436 /// 0 & \cos \theta & -i\sin \theta & 0 \\\\
437 /// 0 & -i\sin \theta & \cos \theta & 0 \\\\
438 /// -i\sin \theta & 0 & 0 & \cos \theta
439 /// \end{bmatrix}.
440 /// \end{align}
441 ///
442 /// # Input
443 /// ## theta
444 /// The angle about which the qubits are rotated.
445 /// ## qubit0
446 /// The first qubit input to the gate.
447 /// ## qubit1
448 /// The second qubit input to the gate.
449 operation Rxx(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
450 body (...) {
451 __quantum__qis__rxx__body(theta, qubit0, qubit1);
452 }
453 controlled (ctls, ...) {
454 if Length(ctls) == 0 {
455 __quantum__qis__rxx__body(theta, qubit0, qubit1);
456 }
457 elif Length(ctls) == 1 {
458 CRxx(ctls[0], theta, qubit0, qubit1);
459 }
460 else {
461 use aux = Qubit[Length(ctls) - 1];
462 within {
463 CollectControls(ctls, aux, 0);
464 AdjustForSingleControl(ctls, aux);
465 }
466 apply {
467 CRxx(aux[Length(ctls) - 2], theta, qubit0, qubit1);
468 }
469 }
470 }
471 adjoint (...) {
472 Rxx(-theta, qubit0, qubit1);
473 }
474 }
475
476 /// # Summary
477 /// Applies a rotation about the $y$-axis by a given angle.
478 ///
479 /// # Description
480 /// \begin{align}
481 /// R_y(\theta) \mathrel{:=}
482 /// e^{-i \theta \sigma_y / 2} =
483 /// \begin{bmatrix}
484 /// \cos \frac{\theta}{2} & -\sin \frac{\theta}{2} \\\\
485 /// \sin \frac{\theta}{2} & \cos \frac{\theta}{2}
486 /// \end{bmatrix}.
487 /// \end{align}
488 ///
489 /// # Input
490 /// ## theta
491 /// Angle about which the qubit is to be rotated.
492 /// ## qubit
493 /// Qubit to which the gate should be applied.
494 ///
495 /// # Remarks
496 /// Equivalent to:
497 /// ```qsharp
498 /// R(PauliY, theta, qubit);
499 /// ```
500 operation Ry(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
501 body (...) {
502 __quantum__qis__ry__body(theta, qubit);
503 }
504 controlled (ctls, ...) {
505 if Length(ctls) == 0 {
506 __quantum__qis__ry__body(theta, qubit);
507 }
508 else {
509 within {
510 MapPauli(qubit, PauliZ, PauliY);
511 }
512 apply {
513 Controlled Rz(ctls, (theta, qubit));
514 }
515 }
516 }
517 adjoint (...) {
518 Ry(-theta, qubit);
519 }
520 }
521
522 /// # Summary
523 /// Applies the two qubit Ising $YY$ rotation gate.
524 ///
525 /// # Description
526 /// \begin{align}
527 /// R_yy(\theta) \mathrel{:=}
528 /// \begin{bmatrix}
529 /// \cos \theta & 0 & 0 & i\sin \theta \\\\
530 /// 0 & \cos \theta & -i\sin \theta & 0 \\\\
531 /// 0 & -i\sin \theta & \cos \theta & 0 \\\\
532 /// i\sin \theta & 0 & 0 & \cos \theta
533 /// \end{bmatrix}.
534 /// \end{align}
535 ///
536 /// # Input
537 /// ## theta
538 /// The angle about which the qubits are rotated.
539 /// ## qubit0
540 /// The first qubit input to the gate.
541 /// ## qubit1
542 /// The second qubit input to the gate.
543 operation Ryy(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
544 body (...) {
545 __quantum__qis__ryy__body(theta, qubit0, qubit1);
546 }
547 controlled (ctls, ...) {
548 if Length(ctls) == 0 {
549 __quantum__qis__ryy__body(theta, qubit0, qubit1);
550 }
551 elif Length(ctls) == 1 {
552 CRyy(ctls[0], theta, qubit0, qubit1);
553 }
554 else {
555 use aux = Qubit[Length(ctls) - 1];
556 within {
557 CollectControls(ctls, aux, 0);
558 AdjustForSingleControl(ctls, aux);
559 }
560 apply {
561 CRyy(aux[Length(ctls) - 2], theta, qubit0, qubit1);
562 }
563 }
564 }
565 adjoint (...) {
566 Ryy(-theta, qubit0, qubit1);
567 }
568 }
569
570 /// # Summary
571 /// Applies a rotation about the $z$-axis by a given angle.
572 ///
573 /// # Description
574 /// \begin{align}
575 /// R_z(\theta) \mathrel{:=}
576 /// e^{-i \theta \sigma_z / 2} =
577 /// \begin{bmatrix}
578 /// e^{-i \theta / 2} & 0 \\\\
579 /// 0 & e^{i \theta / 2}
580 /// \end{bmatrix}.
581 /// \end{align}
582 ///
583 /// # Input
584 /// ## theta
585 /// Angle about which the qubit is to be rotated.
586 /// ## qubit
587 /// Qubit to which the gate should be applied.
588 ///
589 /// # Remarks
590 /// Equivalent to:
591 /// ```qsharp
592 /// R(PauliZ, theta, qubit);
593 /// ```
594 operation Rz(theta : Double, qubit : Qubit) : Unit is Adj + Ctl {
595 body (...) {
596 __quantum__qis__rz__body(theta, qubit);
597 }
598 controlled (ctls, ...) {
599 if Length(ctls) == 0 {
600 __quantum__qis__rz__body(theta, qubit);
601 }
602 elif Length(ctls) == 1 {
603 CRz(ctls[0], theta, qubit);
604 }
605 else {
606 use aux = Qubit[Length(ctls) - 1];
607 within {
608 CollectControls(ctls, aux, 0);
609 AdjustForSingleControl(ctls, aux);
610 }
611 apply {
612 CRz(aux[Length(ctls) - 2], theta, qubit);
613 }
614 }
615 }
616 adjoint (...) {
617 Rz(-theta, qubit);
618 }
619 }
620
621 /// # Summary
622 /// Applies the two qubit Ising $ZZ$ rotation gate.
623 ///
624 /// # Description
625 /// \begin{align}
626 /// R_zz(\theta) \mathrel{:=}
627 /// \begin{bmatrix}
628 /// e^{-i \theta / 2} & 0 & 0 & 0 \\\\
629 /// 0 & e^{i \theta / 2} & 0 & 0 \\\\
630 /// 0 & 0 & e^{i \theta / 2} & 0 \\\\
631 /// 0 & 0 & 0 & e^{-i \theta / 2}
632 /// \end{bmatrix}.
633 /// \end{align}
634 ///
635 /// # Input
636 /// ## theta
637 /// The angle about which the qubits are rotated.
638 /// ## qubit0
639 /// The first qubit input to the gate.
640 /// ## qubit1
641 /// The second qubit input to the gate.
642 operation Rzz(theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit is Adj + Ctl {
643 body (...) {
644 __quantum__qis__rzz__body(theta, qubit0, qubit1);
645 }
646 controlled (ctls, ...) {
647 if Length(ctls) == 0 {
648 __quantum__qis__rzz__body(theta, qubit0, qubit1);
649 }
650 elif Length(ctls) == 1 {
651 CRzz(ctls[0], theta, qubit0, qubit1);
652 }
653 else {
654 use aux = Qubit[Length(ctls) - 1];
655 within {
656 CollectControls(ctls, aux, 0);
657 AdjustForSingleControl(ctls, aux);
658 }
659 apply {
660 CRzz(aux[Length(ctls) - 2], theta, qubit0, qubit1);
661 }
662 }
663 }
664 adjoint (...) {
665 Rzz(-theta, qubit0, qubit1);
666 }
667 }
668
669 /// # Summary
670 /// Applies the π/4 phase gate to a single qubit.
671 ///
672 /// # Description
673 /// \begin{align}
674 /// S \mathrel{:=}
675 /// \begin{bmatrix}
676 /// 1 & 0 \\\\
677 /// 0 & i
678 /// \end{bmatrix}.
679 /// \end{align}
680 ///
681 /// # Input
682 /// ## qubit
683 /// Qubit to which the gate should be applied.
684 operation S(qubit : Qubit) : Unit is Adj + Ctl {
685 body (...) {
686 __quantum__qis__s__body(qubit);
687 }
688 adjoint (...) {
689 __quantum__qis__s__adj(qubit);
690 }
691 controlled (ctls, ...) {
692 if Length(ctls) == 0 {
693 __quantum__qis__s__body(qubit);
694 }
695 elif Length(ctls) == 1 {
696 CS(ctls[0], qubit);
697 }
698 elif Length(ctls) == 2 {
699 Controlled CS([ctls[0]], (ctls[1], qubit));
700 }
701 else {
702 use aux = Qubit[Length(ctls) - 2];
703 within {
704 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
705 }
706 apply {
707 if Length(ctls) % 2 != 0 {
708 Controlled CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
709 }
710 else {
711 Controlled CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
712 }
713 }
714 }
715 }
716 controlled adjoint (ctls, ...) {
717 if Length(ctls) == 0 {
718 __quantum__qis__s__adj(qubit);
719 }
720 elif Length(ctls) == 1 {
721 Adjoint CS(ctls[0], qubit);
722 }
723 elif Length(ctls) == 2 {
724 Controlled Adjoint CS([ctls[0]], (ctls[1], qubit));
725 }
726 else {
727 use aux = Qubit[Length(ctls) - 2];
728 within {
729 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
730 }
731 apply {
732 if Length(ctls) % 2 != 0 {
733 Controlled Adjoint CS([ctls[Length(ctls) - 1]], (aux[Length(ctls) - 3], qubit));
734 }
735 else {
736 Controlled Adjoint CS([aux[Length(ctls) - 3]], (aux[Length(ctls) - 4], qubit));
737 }
738 }
739 }
740 }
741 }
742
743 /// # Summary
744 /// Applies the SWAP gate to a pair of qubits.
745 ///
746 /// # Description
747 /// \begin{align}
748 /// \operatorname{SWAP} \mathrel{:=}
749 /// \begin{bmatrix}
750 /// 1 & 0 & 0 & 0 \\\\
751 /// 0 & 0 & 1 & 0 \\\\
752 /// 0 & 1 & 0 & 0 \\\\
753 /// 0 & 0 & 0 & 1
754 /// \end{bmatrix},
755 /// \end{align}
756 ///
757 /// where rows and columns are ordered as in the quantum concepts guide.
758 ///
759 /// # Input
760 /// ## qubit1
761 /// First qubit to be swapped.
762 /// ## qubit2
763 /// Second qubit to be swapped.
764 ///
765 /// # Remarks
766 /// Equivalent to:
767 /// ```qsharp
768 /// CNOT(qubit1, qubit2);
769 /// CNOT(qubit2, qubit1);
770 /// CNOT(qubit1, qubit2);
771 /// ```
772 operation SWAP(qubit1 : Qubit, qubit2 : Qubit) : Unit is Adj + Ctl {
773 body (...) {
774 __quantum__qis__swap__body(qubit1, qubit2);
775 }
776 adjoint self;
777 controlled (ctls, ...) {
778 if (Length(ctls) == 0) {
779 __quantum__qis__swap__body(qubit1, qubit2);
780 }
781 else {
782 within {
783 CNOT(qubit1, qubit2);
784 }
785 apply {
786 Controlled CNOT(ctls, (qubit2, qubit1));
787 }
788 }
789 }
790 }
791
792 /// # Summary
793 /// Applies the π/8 gate to a single qubit.
794 ///
795 /// # Description
796 /// \begin{align}
797 /// T \mathrel{:=}
798 /// \begin{bmatrix}
799 /// 1 & 0 \\\\
800 /// 0 & e^{i \pi / 4}
801 /// \end{bmatrix}.
802 /// \end{align}
803 ///
804 /// # Input
805 /// ## qubit
806 /// Qubit to which the gate should be applied.
807 operation T(qubit : Qubit) : Unit is Adj + Ctl {
808 body (...) {
809 __quantum__qis__t__body(qubit);
810 }
811 adjoint (...) {
812 __quantum__qis__t__adj(qubit);
813 }
814 controlled (ctls, ...) {
815 if Length(ctls) == 0 {
816 __quantum__qis__t__body(qubit);
817 }
818 elif Length(ctls) == 1 {
819 CT(ctls[0], qubit);
820 }
821 else {
822 use aux = Qubit[Length(ctls) - 1];
823 within {
824 CollectControls(ctls, aux, 0);
825 AdjustForSingleControl(ctls, aux);
826 }
827 apply {
828 CT(aux[Length(ctls) - 2], qubit);
829 }
830 }
831 }
832 controlled adjoint (ctls, ...) {
833 if Length(ctls) == 0 {
834 __quantum__qis__t__adj(qubit);
835 }
836 elif Length(ctls) == 1 {
837 Adjoint CT(ctls[0], qubit);
838 }
839 else {
840 use aux = Qubit[Length(ctls) - 1];
841 within {
842 CollectControls(ctls, aux, 0);
843 AdjustForSingleControl(ctls, aux);
844 }
845 apply {
846 Adjoint CT(aux[Length(ctls) - 2], qubit);
847 }
848 }
849 }
850 }
851
852 /// # Summary
853 /// Applies the Pauli $X$ gate.
854 ///
855 /// # Description
856 /// \begin{align}
857 /// \sigma_x \mathrel{:=}
858 /// \begin{bmatrix}
859 /// 0 & 1 \\\\
860 /// 1 & 0
861 /// \end{bmatrix}.
862 /// \end{align}
863 ///
864 /// # Input
865 /// ## qubit
866 /// Qubit to which the gate should be applied.
867 operation X(qubit : Qubit) : Unit is Adj + Ctl {
868 body (...) {
869 __quantum__qis__x__body(qubit);
870 }
871 controlled (ctls, ...) {
872 if Length(ctls) == 0 {
873 __quantum__qis__x__body(qubit);
874 }
875 elif Length(ctls) == 1 {
876 __quantum__qis__cx__body(ctls[0], qubit);
877 }
878 elif Length(ctls) == 2 {
879 __quantum__qis__ccx__body(ctls[0], ctls[1], qubit);
880 }
881 else {
882 use aux = Qubit[Length(ctls) - 2];
883 within {
884 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
885 }
886 apply {
887 if Length(ctls) % 2 != 0 {
888 __quantum__qis__ccx__body(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
889 }
890 else {
891 __quantum__qis__ccx__body(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
892 }
893 }
894 }
895 }
896 adjoint self;
897 }
898
899 /// # Summary
900 /// Applies the Pauli $Y$ gate.
901 ///
902 /// # Description
903 /// \begin{align}
904 /// \sigma_y \mathrel{:=}
905 /// \begin{bmatrix}
906 /// 0 & -i \\\\
907 /// i & 0
908 /// \end{bmatrix}.
909 /// \end{align}
910 ///
911 /// # Input
912 /// ## qubit
913 /// Qubit to which the gate should be applied.
914 operation Y(qubit : Qubit) : Unit is Adj + Ctl {
915 body (...) {
916 __quantum__qis__y__body(qubit);
917 }
918 controlled (ctls, ...) {
919 if (Length(ctls) == 0) {
920 __quantum__qis__y__body(qubit);
921 }
922 elif (Length(ctls) == 1) {
923 __quantum__qis__cy__body(ctls[0], qubit);
924 }
925 elif (Length(ctls) == 2) {
926 CCY(ctls[0], ctls[1], qubit);
927 }
928 else {
929 use aux = Qubit[Length(ctls) - 2];
930 within {
931 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
932 }
933 apply {
934 if Length(ctls) % 2 != 0 {
935 CCY(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
936 }
937 else {
938 CCY(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
939 }
940 }
941 }
942 }
943 adjoint self;
944 }
945
946 /// # Summary
947 /// Applies the Pauli $Z$ gate.
948 ///
949 /// # Description
950 /// \begin{align}
951 /// \sigma_z \mathrel{:=}
952 /// \begin{bmatrix}
953 /// 1 & 0 \\\\
954 /// 0 & -1
955 /// \end{bmatrix}.
956 /// \end{align}
957 ///
958 /// # Input
959 /// ## qubit
960 /// Qubit to which the gate should be applied.
961 operation Z(qubit : Qubit) : Unit is Adj + Ctl {
962 body (...) {
963 __quantum__qis__z__body(qubit);
964 }
965 controlled (ctls, ...) {
966 if Length(ctls) == 0 {
967 __quantum__qis__z__body(qubit);
968 }
969 elif Length(ctls) == 1 {
970 __quantum__qis__cz__body(ctls[0], qubit);
971 }
972 elif Length(ctls) == 2 {
973 CCZ(ctls[0], ctls[1], qubit);
974 }
975 else {
976 use aux = Qubit[Length(ctls) - 2];
977 within {
978 CollectControls(ctls, aux, 1 - (Length(ctls) % 2));
979 }
980 apply {
981 if Length(ctls) % 2 != 0 {
982 CCZ(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], qubit);
983 }
984 else {
985 CCZ(aux[Length(ctls) - 3], aux[Length(ctls) - 4], qubit);
986 }
987 }
988 }
989 }
990 adjoint self;
991 }
992
993}
994