microsoft/qdk

Public

mirrored fromhttps://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/internal.qs

241lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4namespace Microsoft.Quantum.Intrinsic {
5 open Microsoft.Quantum.Arrays;
6 open Microsoft.Quantum.Core;
7 open Microsoft.Quantum.Math;
8
9 internal operation CH(control : Qubit, target : Qubit) : Unit is Adj {
10 within {
11 S(target);
12 H(target);
13 T(target);
14 }
15 apply {
16 CNOT(control, target);
17 }
18 }
19
20 internal operation CCH(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
21 within {
22 S(target);
23 H(target);
24 T(target);
25 }
26 apply {
27 CCNOT(control1, control2, target);
28 }
29 }
30
31 internal operation ApplyGlobalPhase(theta : Double) : Unit is Ctl + Adj {
32 body ... {}
33 controlled (ctls, ...) {
34 if Length(ctls) == 0 {
35 // Noop
36 }
37 elif Length(ctls) == 1 {
38 Rz(theta, ctls[0]);
39 }
40 else {
41 Controlled R1(ctls[1..(Length(ctls) - 1)], (theta, ctls[0]));
42 }
43 }
44 }
45
46 internal operation CR1(theta : Double, control : Qubit, target : Qubit) : Unit is Adj {
47 Rz(theta/2.0, target);
48 Rz(theta/2.0, control);
49 CNOT(control,target);
50 Rz(-theta/2.0, target);
51 CNOT(control,target);
52 }
53
54 internal operation CRz(control : Qubit, theta : Double, target : Qubit) : Unit is Adj {
55 Rz(theta / 2.0, target);
56 CNOT(control, target);
57 Rz(-theta / 2.0, target);
58 CNOT(control, target);
59 }
60
61 internal operation CS(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
62 T(control);
63 T(target);
64 CNOT(control, target);
65 Adjoint T(target);
66 CNOT(control, target);
67 }
68
69 internal operation CT(control : Qubit, target : Qubit) : Unit is Adj {
70 let angle = PI() / 8.0;
71 Rz(angle, control);
72 Rz(angle, target);
73 CNOT(control, target);
74 Adjoint Rz(angle, target);
75 CNOT(control, target);
76 }
77
78 internal operation MapPauli(qubit : Qubit, from : Pauli, to : Pauli) : Unit is Adj {
79 if from == to {
80 }
81 elif (from == PauliZ and to == PauliX) or (from == PauliX and to == PauliZ) {
82 H(qubit);
83 }
84 elif from == PauliZ and to == PauliY {
85 H(qubit);
86 S(qubit);
87 H(qubit);
88 }
89 elif from == PauliY and to == PauliZ {
90 H(qubit);
91 Adjoint S(qubit);
92 H(qubit);
93 }
94 elif from == PauliY and to == PauliX {
95 S(qubit);
96 }
97 elif from == PauliX and to == PauliY {
98 Adjoint S(qubit);
99 }
100 else {
101 fail "Unsupported input";
102 }
103 }
104
105 internal operation EntangleForJointMeasure(basis : Pauli, aux : Qubit, qubit : Qubit) : Unit {
106 if basis == PauliX {
107 Controlled X([aux], qubit);
108 }
109 elif basis == PauliZ {
110 Controlled Z([aux], qubit);
111 }
112 elif basis == PauliY {
113 Controlled Y([aux], qubit);
114 }
115 }
116
117 /// Collects the given list of control qubits into one or two of the given auxiliarly qubits, using
118 /// all but the last qubits in the auxiliary list as scratch qubits. The auxiliary list must be
119 /// big enough to accomodate the data, so it is usually smaller than controls list by number of
120 /// qubits needed for the eventual controlled unitary application. The passed adjustment value is
121 /// used to ensure the right number of auxiliary qubits are processed.
122 ///
123 /// For example, if the controls list is 6 qubits, the auxiliary list must be 5 qubits, and the
124 /// state from the 6 control qubits will be collected into the last qubit of the auxiliary array.
125 internal operation CollectControls(ctls : Qubit[], aux : Qubit[], adjustment : Int) : Unit is Adj {
126 // First collect the controls into the first part of the auxiliary list.
127 for i in 0..2..(Length(ctls) - 2) {
128 PhaseCCX(ctls[i], ctls[i + 1], aux[i / 2]);
129 }
130 // Then collect the auxiliary qubits in the first part of the list forward into the last
131 // qubit of the auxiliary list. The adjustment is used to allow the caller to reduce or increase
132 // the number of times this is run based on the eventual number of control qubits needed.
133 for i in 0..((Length(ctls) / 2) - 2 - adjustment) {
134 PhaseCCX(aux[i * 2], aux[(i * 2) + 1], aux[i + Length(ctls) / 2]);
135 }
136 }
137
138 /// When collecting controls, if there is an uneven number of original control qubits then the
139 /// last control and the second to last auxiliary will be collected into the last auxiliary.
140 internal operation AdjustForSingleControl(ctls : Qubit[], aux : Qubit[]) : Unit is Adj {
141 if Length(ctls) % 2 != 0 {
142 PhaseCCX(ctls[Length(ctls) - 1], aux[Length(ctls) - 3], aux[Length(ctls) - 2]);
143 }
144 }
145
146 internal operation PhaseCCX(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
147 // https://arxiv.org/pdf/1210.0974.pdf#page=2
148 H(target);
149 CNOT(target,control1);
150 CNOT(control1,control2);
151 T(control2);
152 Adjoint T(control1);
153 T(target);
154 CNOT(target,control1);
155 CNOT(control1,control2);
156 Adjoint T(control2);
157 CNOT(target,control2);
158 H(target);
159 }
160
161 internal operation CCZ(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
162 // [Page 15 of arXiv:1206.0758v3](https://arxiv.org/pdf/1206.0758v3.pdf#page=15)
163 Adjoint T(control1);
164 Adjoint T(control2);
165 CNOT(target, control1);
166 T(control1);
167 CNOT(control2, target);
168 CNOT(control2, control1);
169 T(target);
170 Adjoint T(control1);
171 CNOT(control2, target);
172 CNOT(target, control1);
173 Adjoint T(target);
174 T(control1);
175 CNOT(control2, control1);
176 }
177
178 internal operation CCY(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
179 within {
180 MapPauli(target, PauliZ, PauliY);
181 }
182 apply {
183 CCZ(control1, control2, target);
184 }
185 }
186
187 internal operation CRxx(control : Qubit, theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit {
188 within {
189 CNOT(qubit1, qubit0);
190 }
191 apply {
192 Controlled Rx([control], (theta, qubit0));
193 }
194 }
195
196 internal operation CRyy(control : Qubit, theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit {
197 within {
198 CNOT(qubit1, qubit0);
199 }
200 apply {
201 Controlled Ry([control], (theta, qubit0));
202 }
203 }
204
205 internal operation CRzz(control : Qubit, theta : Double, qubit0 : Qubit, qubit1 : Qubit) : Unit {
206 within {
207 CNOT(qubit1, qubit0);
208 }
209 apply {
210 Controlled Rz([control], (theta, qubit0));
211 }
212 }
213
214 internal function IndicesOfNonIdentity (paulies : Pauli[]) : Int[] {
215 mutable indices = [];
216 for i in 0 .. Length(paulies) - 1 {
217 if (paulies[i] != PauliI) {
218 set indices += [i];
219 }
220 }
221 indices
222 }
223
224 internal function RemovePauliI (paulis : Pauli[], qubits : Qubit[]) : (Pauli[], Qubit[]) {
225 let indices = IndicesOfNonIdentity(paulis);
226 let newPaulis = Subarray(indices, paulis);
227 let newQubits = Subarray(indices, qubits);
228 return (newPaulis, newQubits);
229 }
230
231 internal operation SpreadZ (from : Qubit, to : Qubit[]) : Unit is Adj {
232 if (Length(to) > 0) {
233 if (Length(to) > 1) {
234 let half = Length(to) / 2;
235 SpreadZ(to[0], to[half + 1 .. Length(to) - 1]);
236 SpreadZ(from, to[1 .. half]);
237 }
238 CNOT(to[0], from);
239 }
240 }
241}
242